@dynamic-labs/sdk-react-core
Version:
A React SDK for implementing wallet web3 authentication and authorization to your website.
187 lines (184 loc) • 7.89 kB
JavaScript
'use client'
import { isEmbeddedConnector } from '@dynamic-labs/wallet-connector-core';
import { getCalculatedOffset } from './utils/getCalculatedOffset/getCalculatedOffset.js';
import { groupWalletOptions } from './utils/groupWalletOptions/groupWalletOptions.js';
import { applyMultiWalletFilters } from './utils/applyMultiWalletFilters/applyMultiWalletFilters.js';
const PRIORITY_WALLET_LIST = [
'metamask',
'coinbase',
'walletconnect',
'phantom',
'argentx',
'blocto',
'solflare',
'braavos',
'trust',
'rainbow',
'dapper',
'glow',
'flowwalletflow',
];
const sortedInputList = (inputList, recommendedWalletKeys) => {
// Input is the unordered list of wallets we support
const unsortedRecommendedWallets = [];
const unsortedPriorityWallets = [];
const unsortedOtherWallets = [];
inputList.forEach((wallet) => {
const isRecommendedWallet = recommendedWalletKeys.includes(wallet.key);
if (isRecommendedWallet) {
unsortedRecommendedWallets.push(wallet);
}
else if (PRIORITY_WALLET_LIST.includes(wallet.key) &&
!isRecommendedWallet) {
unsortedPriorityWallets.push(wallet);
}
else {
unsortedOtherWallets.push(wallet);
}
});
const sortedPriorityWallets = unsortedPriorityWallets
.slice()
.sort((a, b) => PRIORITY_WALLET_LIST.indexOf(a.key) -
PRIORITY_WALLET_LIST.indexOf(b.key));
const sortedRecommendedWallets = unsortedRecommendedWallets
.slice()
.sort((a, b) => recommendedWalletKeys.indexOf(a.key) -
recommendedWalletKeys.indexOf(b.key));
return [
...sortedRecommendedWallets,
...sortedPriorityWallets,
...unsortedOtherWallets,
];
};
const walletListBuilder = ({ userWallets, multiWallet, numberOfWalletsToShow, inputList, isWalletConnectList, lastUsedWalletKey, searchFilter, walletsFilter, loginWithEmail, groupWallets, walletGroups, showMoreWalletsWithFilter, recommendedWallets, }) => {
let walletList = inputList;
if (isWalletConnectList) {
walletList = inputList.filter((wallet) => wallet.walletConnector.isWalletConnect &&
wallet.key !== 'walletconnect');
}
if (multiWallet) {
walletList = applyMultiWalletFilters({
userWallets,
walletOptions: walletList,
});
}
let lastUsedWallet;
const hasWalletFilter = Boolean(walletsFilter);
const recommendedWalletsList = [];
const installedWallets = [];
const otherWallets = [];
const recommendedWalletKeys = Array.from(new Set((recommendedWallets || []).map((w) => w.walletKey)));
const orderedInputList = orderAndFilterList(walletList, walletsFilter, isWalletConnectList, recommendedWalletKeys);
orderedInputList.forEach((wallet) => {
if (isEmbeddedConnector(wallet.walletConnector) ||
!wallet.walletConnector.isAvailable)
return;
if (recommendedWalletKeys === null || recommendedWalletKeys === void 0 ? void 0 : recommendedWalletKeys.includes(wallet.key)) {
recommendedWalletsList.push(wallet);
}
else if (lastUsedWalletKey === wallet.key) {
lastUsedWallet = wallet;
}
else if (wallet.isInstalledOnBrowser) {
installedWallets.push(wallet);
}
else {
otherWallets.push(wallet);
}
});
const firstPriorityWallets = [...(lastUsedWallet ? [lastUsedWallet] : [])];
const walletsList = [
...recommendedWalletsList,
...firstPriorityWallets,
...installedWallets,
...otherWallets,
];
const finalizedWalletList = groupWallets
? groupWalletOptions(walletGroups, walletsList)
: walletsList;
// If a filter has been applied we want to add an offset to the number of wallets
// to include the installed and last used wallets
const updatedNumberOfWalletsToShow = showMoreWalletsWithFilter && hasWalletFilter
? calculateWalletOffsetBasedOnInstalledAndLastUsedWallets(orderedInputList, firstPriorityWallets.concat(installedWallets), numberOfWalletsToShow)
: numberOfWalletsToShow;
return {
numberOfWallets: walletsList.length,
walletsList: listToDisplay(finalizedWalletList, searchFilter, isWalletConnectList, updatedNumberOfWalletsToShow, hasWalletFilter, loginWithEmail),
};
};
// We want to show the full list of wallets when we render the wallet connect list even
// if a filter was applied to the main page
const orderAndFilterList = (walletList, walletsFilter, isWalletConnectList, recommendedWalletKeys) => {
const sortedWalletList = sortedInputList(walletList, recommendedWalletKeys);
if (!isWalletConnectList && walletsFilter) {
return walletsFilter(sortedWalletList);
}
else {
return sortedWalletList;
}
};
const KEEP_WALLETS_NAME_LIST = ['walletconnect', 'bitcoin.com wallet'];
const applySearchFilterToWalletOptionList = (rawSearchFilter, walletOptionList) => {
const searchFilter = rawSearchFilter.trim().toLowerCase();
const cleanName = (name) => {
const trimmedLowerName = name.trim().toLowerCase();
if (KEEP_WALLETS_NAME_LIST.includes(trimmedLowerName)) {
return trimmedLowerName;
}
else {
return trimmedLowerName
.replace('wallet', '')
.replace('evm', '')
.replace('starknet', '')
.replace('solana', '')
.replace('flow', '')
.replace('bitcoin', '');
}
};
return walletOptionList.filter((walletOption) => {
var _a;
return cleanName(walletOption.name).includes(searchFilter) ||
(
// Validate nested wallets
(_a = walletOption.groupedWallets) === null || _a === void 0 ? void 0 : _a.some((nestedWalletOption) => cleanName(nestedWalletOption.name).includes(searchFilter)));
});
};
const listToDisplay = (finalizedList, searchFilter, isWalletConnectList, numberOfWalletsToShow, hasWalletFilter, loginWithEmail) => {
if (searchFilter) {
return applySearchFilterToWalletOptionList(searchFilter, finalizedList);
}
else if (isWalletConnectList) {
return finalizedList;
}
else if (loginWithEmail) {
return finalizedList.slice(0, numberOfWalletsToShow);
}
else {
const list = finalizedList.map((wallet) => wallet.name.toLowerCase());
const offset = getCalculatedOffset({
defaultOffset: numberOfWalletsToShow,
hasWalletFilter,
list,
priorityList: PRIORITY_WALLET_LIST,
});
return finalizedList.slice(0, offset);
}
};
/**
* This calculation adds an offset to numberOfWalletsToShow so we will show the
* intended wallets + installed and last used.
* We should would only apply the additonal offset if the installed wallets was not in the original list.
*
* For example:
* we want to show 4 wallets: ['metamask', 'rainbow', 'walletconnect', 'coinbase']
* and someone is using brave with installed phantom he should see
* [ 'brave injected', phantom ,'metamask', 'rainbow', 'walletconnect', 'coinbase',]
* And when someone is using metamask and coinbase they should see
* [ 'metamask', 'coinbase', 'rainbow', 'walletconnect']
*/
const calculateWalletOffsetBasedOnInstalledAndLastUsedWallets = (allWalletsOrdered, installedOrUsedWallets, numberOfWalletsToShow) => {
const filteredWallets = allWalletsOrdered.slice(0, numberOfWalletsToShow);
const offset = installedOrUsedWallets.filter((wallet) => !filteredWallets.includes(wallet)).length;
return numberOfWalletsToShow + offset;
};
export { PRIORITY_WALLET_LIST, calculateWalletOffsetBasedOnInstalledAndLastUsedWallets, walletListBuilder };