UNPKG

@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
'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 };