import { ApiPromise, WsProvider } from '@polkadot/api' import { WalletName, WalletReadyState } from '@solana/wallet-adapter-base' import { Wallet } from '@solana/wallet-adapter-react' import { ethers } from 'ethers' import { getPolkadotExtensionModule } from '../core' import { Chain, ChainType, Chains, PolkadotExtensionState, ProviderConfigs, SolanaWalletAdapterState } from '../core/interfaces' export const userCanceledError = new Error('user canceled') /** * @param account * @param prefix * @param suffix * @returns */ export function truncateString(str: string, headNumber = 4, tailNumber = 4, replacement = '...') { const head = str.slice(0, headNumber) const tail = str.slice(str.length - tailNumber) return head + replacement + tail } /** * @param u8a * @returns */ export const u8aToHex = (u8a: number[]) => { return `0x${new Uint8Array(u8a)}` as const } /** * @param u8 * @returns */ export const u8ToHex = (u8: number) => { return `0x${u8.toString(16)}` as const } const cacheWalletKey = 'ATA_WALLET_CACHE' interface ConnectedWalletCache { providerLabel: string chainId: string } export function setConnectedWalletCache(data: ConnectedWalletCache) { localStorage.setItem(cacheWalletKey, JSON.stringify(data)) } export function getConnectedWalletCache(): ConnectedWalletCache | null { const cache = localStorage.getItem(cacheWalletKey) return cache ? JSON.parse(cache) : null } export function clearConnectedWalletCache() { localStorage.removeItem(cacheWalletKey) } export async function constructPolkadotApi(options: { chainId: string; chains: Chains }) { const { chainId, chains } = options const chain = chains.find((item) => item.chainId === chainId) if (!chain) { return } const wsProvider = new WsProvider(chain.rpcUrls[0]) const api = await ApiPromise.create({ provider: wsProvider }) return api } export async function getPolkadotExtensionStateByExtensionLabel(options: { appName?: string label: string providerConfigs: ProviderConfigs }): Promise { const { appName, label, providerConfigs } = options const extensionModules = getPolkadotExtensionModule(providerConfigs) const extensionModule = extensionModules.find((item) => item.label === label) const result = extensionModule && extensionModule.isEnabled() ? await extensionModule.getInjected(appName || '') : undefined const accounts = result ? await result.injected.accounts.get() : [] return extensionModule && result ? { label: extensionModule.label, icon: extensionModule.getIcon(), injected: result.injected, accounts: accounts.map((item) => item.address) } : undefined } export async function switchEvmChain(options: { ethersProvider: ethers.providers.Web3Provider chain: Chain }) { const { ethersProvider, chain } = options const { chainId, chainName, nativeCurrency, rpcUrls, blockExplorerUrls } = chain const chainIdParsed = hexlifyChainId(chainId) try { await ethersProvider.send('wallet_switchEthereumChain', [{ chainId: chainIdParsed }]) } catch (switchError: any) { if (switchError.code === 4902) { // eslint-disable-next-line no-useless-catch await ethersProvider.send('wallet_addEthereumChain', [ { chainId: chainIdParsed, chainName, nativeCurrency: nativeCurrency ? { name: nativeCurrency.name, symbol: nativeCurrency.symbol, decimals: nativeCurrency.decimals } : undefined, rpcUrls, blockExplorerUrls } ]) } } } export function getWalletIcon(icon: string) { const isSvg = icon.indexOf(' Promise }): Promise { const { name, wallets, select, connect } = options const wallet = wallets.find((item) => { return item.adapter.name == name }) if (wallet) { const { name, icon, readyState } = wallet.adapter const enabled = readyState === WalletReadyState.Installed || readyState === WalletReadyState.Loadable if (enabled) { select(name) await connect() return { label: name, icon, adapter: wallet.adapter, accounts: wallet.adapter.publicKey ? [wallet.adapter.publicKey.toString()] : [] } } } } export function hexlifyChainId(chainId: number | string) { const chainIdParsed = typeof chainId === 'string' ? parseInt(chainId) : chainId return `0x${chainIdParsed.toString(16)}` } export function getAccountAddressExplorerUrl(chain: Chain, account: string) { const { type, blockExplorerUrls } = chain if (blockExplorerUrls && blockExplorerUrls.length) { const url = new URL(blockExplorerUrls[0]) if (type === ChainType.EVM) { url.pathname = `address/${account}` return url.toString() } else if (type === ChainType.Polkadot) { url.pathname = `account/${account}` return url.toString() } else if (type === ChainType.Solana) { url.pathname = `address/${account}` return url.toString() } } }