@reown/appkit-controllers
Version:
The full stack toolkit to build onchain app UX.
159 lines • 7.81 kB
JavaScript
import { HelpersUtil } from '@reown/appkit-common';
import { ApiController } from '../controllers/ApiController.js';
import { ConnectionController } from '../controllers/ConnectionController.js';
import { ConnectorController } from '../controllers/ConnectorController.js';
import { OptionsController } from '../controllers/OptionsController.js';
import { ConnectorUtil } from './ConnectorUtil.js';
import { ConstantsUtil } from './ConstantsUtil.js';
import { CoreHelperUtil } from './CoreHelperUtil.js';
import { StorageUtil } from './StorageUtil.js';
export const WalletUtil = {
filterOutDuplicatesByRDNS(wallets) {
const connectors = ConnectorController.state.connectors;
const recent = StorageUtil.getRecentWallets();
const connectorRDNSs = connectors
.map(connector => connector.info?.rdns)
.filter(Boolean);
const recentRDNSs = recent.map(wallet => wallet.rdns).filter(Boolean);
const allRDNSs = connectorRDNSs.concat(recentRDNSs);
if (allRDNSs.includes('io.metamask.mobile') && CoreHelperUtil.isMobile()) {
const index = allRDNSs.indexOf('io.metamask.mobile');
allRDNSs[index] = 'io.metamask';
}
const filtered = wallets.filter(wallet => {
// Check RDNS match first
if (wallet?.rdns && allRDNSs.includes(String(wallet.rdns))) {
return false;
}
// Some wallets don't have RDNS, so we need to check if the name matches a connector name
if (!wallet?.rdns) {
const hasMatchingConnectorName = connectors.some(connector => connector.name === wallet.name);
if (hasMatchingConnectorName) {
return false;
}
}
return true;
});
return filtered;
},
filterOutDuplicatesByIds(wallets) {
const connectors = ConnectorController.state.connectors.filter(connector => connector.type === 'ANNOUNCED' ||
connector.type === 'INJECTED' ||
connector.type === 'MULTI_CHAIN');
const recent = StorageUtil.getRecentWallets();
const connectorIds = connectors.map(connector => connector.explorerId || connector.explorerWallet?.id || connector.id);
const recentIds = recent.map(wallet => wallet.id);
const allIds = connectorIds.concat(recentIds);
const filtered = wallets.filter(wallet => !allIds.includes(wallet?.id));
return filtered;
},
filterOutDuplicateWallets(wallets) {
const uniqueByRDNS = this.filterOutDuplicatesByRDNS(wallets);
const uniqueWallets = this.filterOutDuplicatesByIds(uniqueByRDNS);
return uniqueWallets;
},
/**
* Marks wallets as installed based on available connectors and sorts them
* according to both installation status and featuredWalletIds order.
*
* @param wallets - Array of wallets to process
* @returns Array of wallets marked as installed and sorted by priority
*/
markWalletsAsInstalled(wallets) {
const { connectors } = ConnectorController.state;
const { featuredWalletIds } = OptionsController.state;
const installedWalletRdnsMap = connectors
.filter(connector => connector.type === 'ANNOUNCED')
.reduce((rdnsMap, connector) => {
if (!connector.info?.rdns) {
return rdnsMap;
}
rdnsMap[connector.info.rdns] = true;
return rdnsMap;
}, {});
// Mark each wallet as installed if its RDNS exists in the installed connectors
const walletsWithInstallationStatus = wallets.map(wallet => ({
...wallet,
installed: Boolean(wallet.rdns) && Boolean(installedWalletRdnsMap[wallet.rdns ?? ''])
}));
const sortedWallets = walletsWithInstallationStatus.sort((walletA, walletB) => {
const installationComparison = Number(walletB.installed) - Number(walletA.installed);
if (installationComparison !== 0) {
return installationComparison;
}
if (featuredWalletIds?.length) {
const walletAFeaturedIndex = featuredWalletIds.indexOf(walletA.id);
const walletBFeaturedIndex = featuredWalletIds.indexOf(walletB.id);
if (walletAFeaturedIndex !== -1 && walletBFeaturedIndex !== -1) {
return walletAFeaturedIndex - walletBFeaturedIndex;
}
// WalletA is featured, place it first
if (walletAFeaturedIndex !== -1) {
return -1;
}
// WalletB is featured, place it first
if (walletBFeaturedIndex !== -1) {
return 1;
}
}
return 0;
});
return sortedWallets;
},
getConnectOrderMethod(_features, _connectors) {
const connectMethodOrder = _features?.connectMethodsOrder || OptionsController.state.features?.connectMethodsOrder;
const connectors = _connectors || ConnectorController.state.connectors;
if (connectMethodOrder) {
return connectMethodOrder;
}
const { injected, announced } = ConnectorUtil.getConnectorsByType(connectors, ApiController.state.recommended, ApiController.state.featured);
const shownInjected = injected.filter(ConnectorUtil.showConnector);
const shownAnnounced = announced.filter(ConnectorUtil.showConnector);
if (shownInjected.length || shownAnnounced.length) {
return ['wallet', 'email', 'social'];
}
return ConstantsUtil.DEFAULT_CONNECT_METHOD_ORDER;
},
isExcluded(wallet) {
const isRDNSExcluded = Boolean(wallet.rdns) && ApiController.state.excludedWallets.some(w => w.rdns === wallet.rdns);
const isNameExcluded = Boolean(wallet.name) &&
ApiController.state.excludedWallets.some(w => HelpersUtil.isLowerCaseMatch(w.name, wallet.name));
return isRDNSExcluded || isNameExcluded;
},
markWalletsWithDisplayIndex(wallets) {
return wallets.map((w, index) => ({ ...w, display_index: index }));
},
/**
* Filters wallets based on WalletConnect support and platform requirements.
*
* On mobile only wallets with WalletConnect support and some mandatory wallets are shown.
* On desktop with Appkit Core only wallets with WalletConnect support are shown.
* On desktop with Appkit all wallets are shown.
*
* @param wallets - Array of wallets to filter
* @returns Filtered array of wallets based on WalletConnect support and platform
*/
filterWalletsByWcSupport(wallets) {
if (ConnectionController.state.wcBasic) {
return wallets.filter(wallet => wallet.supports_wc);
}
if (CoreHelperUtil.isMobile()) {
return wallets.filter(wallet => wallet.supports_wc || ConstantsUtil.MANDATORY_WALLET_IDS_ON_MOBILE.includes(wallet.id));
}
return wallets;
},
getWalletConnectWallets(allWallets) {
const wallets = [...ApiController.state.featured, ...ApiController.state.recommended];
if (ApiController.state.filteredWallets?.length > 0) {
wallets.push(...ApiController.state.filteredWallets);
}
else {
wallets.push(...allWallets);
}
const uniqueWallets = CoreHelperUtil.uniqueBy(wallets, 'id');
const walletsWithInstalled = WalletUtil.markWalletsAsInstalled(uniqueWallets);
const walletsByWcSupport = WalletUtil.filterWalletsByWcSupport(walletsWithInstalled);
return WalletUtil.markWalletsWithDisplayIndex(walletsByWcSupport);
}
};
//# sourceMappingURL=WalletUtil.js.map