UNPKG

@reown/appkit-controllers

Version:

The full stack toolkit to build onchain app UX.

123 lines 5.54 kB
import { erc20Abi, formatUnits } from 'viem'; import { ConstantsUtil, ParseUtil } from '@reown/appkit-common'; import { BlockchainApiController } from '../controllers/BlockchainApiController.js'; import { ChainController } from '../controllers/ChainController.js'; import { ConnectionController } from '../controllers/ConnectionController.js'; import { ConnectorController } from '../controllers/ConnectorController.js'; import { ERC7811Utils } from './ERC7811Util.js'; import { StorageUtil } from './StorageUtil.js'; import { ViemUtil } from './ViemUtil.js'; // -- Controller ---------------------------------------- // export const BalanceUtil = { /** * Get the balances of the user's tokens. If user connected with Auth provider or and on the EIP155 network, * it'll use the `wallet_getAssets` and `wallet_getCapabilities` calls to fetch the balance rather than Blockchain API * @param forceUpdate - If true, the balances will be fetched from the server * @returns The balances of the user's tokens */ async getMyTokensWithBalance(params = { forceUpdate: undefined, caipNetwork: ChainController.state.activeCaipNetwork, address: ChainController.getAccountData()?.address }) { const { forceUpdate, caipNetwork, address } = params; const isAuthConnector = ConnectorController.getConnectorId('eip155') === ConstantsUtil.CONNECTOR_ID.AUTH; if (!address) { return []; } const caipAddress = caipNetwork ? `${caipNetwork.caipNetworkId}:${address}` : address; const cachedBalance = StorageUtil.getBalanceCacheForCaipAddress(caipAddress); if (cachedBalance) { return cachedBalance.balances; } // Extract EIP-155 specific logic if (caipNetwork && caipNetwork.chainNamespace === ConstantsUtil.CHAIN.EVM && isAuthConnector) { const eip155Balances = await this.getEIP155Balances(address, caipNetwork); if (eip155Balances) { return this.filterLowQualityTokens(eip155Balances); } } // Fallback to 1Inch API const response = await BlockchainApiController.getBalance(address, caipNetwork?.caipNetworkId, forceUpdate); return this.filterLowQualityTokens(response.balances); }, /** * Get the balances of the user's tokens on the EIP155 network using native `wallet_getAssets` and `wallet_getCapabilities` calls * @param address - The address of the user * @param caipNetwork - The CAIP network * @returns The balances of the user's tokens on the EIP155 network */ async getEIP155Balances(address, caipNetwork) { try { const chainIdHex = ERC7811Utils.getChainIdHexFromCAIP2ChainId(caipNetwork.caipNetworkId); const walletCapabilities = (await ConnectionController.getCapabilities(address)); if (!walletCapabilities?.[chainIdHex]?.['assetDiscovery']?.supported) { return null; } const walletGetAssetsResponse = await ConnectionController.walletGetAssets({ account: address, chainFilter: [chainIdHex] }); if (!ERC7811Utils.isWalletGetAssetsResponse(walletGetAssetsResponse)) { return null; } const assets = walletGetAssetsResponse[chainIdHex] || []; const filteredAssets = assets.map(asset => ERC7811Utils.createBalance(asset, caipNetwork.caipNetworkId)); StorageUtil.updateBalanceCache({ caipAddress: `${caipNetwork.caipNetworkId}:${address}`, balance: { balances: filteredAssets }, timestamp: Date.now() }); return filteredAssets; } catch (error) { return null; } }, /** * The 1Inch API includes many low-quality tokens in the balance response, * which appear inconsistently. This filter prevents them from being displayed. */ filterLowQualityTokens(balances) { return balances.filter(balance => balance.quantity.decimals !== '0'); }, async fetchERC20Balance({ caipAddress, assetAddress, caipNetwork }) { const publicClient = await ViemUtil.createViemPublicClient(caipNetwork); const { address } = ParseUtil.parseCaipAddress(caipAddress); const [{ result: name }, { result: symbol }, { result: balance }, { result: decimals }] = await publicClient.multicall({ contracts: [ { address: assetAddress, functionName: 'name', args: [], abi: erc20Abi }, { address: assetAddress, functionName: 'symbol', args: [], abi: erc20Abi }, { address: assetAddress, functionName: 'balanceOf', args: [address], abi: erc20Abi }, { address: assetAddress, functionName: 'decimals', args: [], abi: erc20Abi } ] }); return { name, symbol, decimals, balance: balance && decimals ? formatUnits(balance, decimals) : '0' }; } }; //# sourceMappingURL=BalanceUtil.js.map