diff --git a/src/BroSDK.ts b/src/BroSDK.ts index c950c64..f6653be 100644 --- a/src/BroSDK.ts +++ b/src/BroSDK.ts @@ -316,6 +316,9 @@ export class BroSDK { evm: { routesConfigCache: new Map(), feeRateCache: new Map(), + tokenInfoCaches: { + decimals: new Map(), + }, onChainConfigCache, viemClients: { ...defaultEvmClients, diff --git a/src/evmUtils/contractHelpers.ts b/src/evmUtils/contractHelpers.ts index 4be2553..1b488df 100644 --- a/src/evmUtils/contractHelpers.ts +++ b/src/evmUtils/contractHelpers.ts @@ -11,6 +11,8 @@ import { nativeCurrencyAddress } from "./addressHelpers" import { getEVMOnChainConfig } from "./apiHelpers/getEVMOnChainConfig" import { getEVMSupportedRoutes } from "./apiHelpers/getEVMSupportedRoutes" import { EVMEndpointContract } from "./evmContractAddresses" +import { readContract } from "viem/actions" +import { ERC20Abi } from "./contractAbi/ERC20Abi" const CONTRACT_COMMON_NUMBER_SCALE = 18 export const numberFromSolidityContractNumber = ( @@ -113,3 +115,35 @@ export async function getEVMToken( r => r.evmTokenAddress.toLowerCase() === tokenAddress.toLowerCase(), )?.evmToken } + +export function getERC20TokenDecimals( + sdkContext: SDKGlobalContext, + chainId: KnownChainId.EVMChain, + tokenAddress: EVMAddress, +): Promise { + const cacheKey = `${chainId}:${tokenAddress}` + + const tokenInfoCache = sdkContext.evm.tokenInfoCaches.decimals.get(cacheKey) + if (tokenInfoCache != null) return tokenInfoCache + + const client = sdkContext.evm.viemClients[chainId] + if (client == null) return Promise.resolve(undefined) + + const resPromise = readContract(client, { + abi: ERC20Abi, + address: tokenAddress, + functionName: "decimals", + }).catch(err => { + queueMicrotask(() => { + if ( + sdkContext.evm.tokenInfoCaches.decimals.get(cacheKey) === resPromise + ) { + sdkContext.evm.tokenInfoCaches.decimals.delete(cacheKey) + } + }) + throw err + }) + sdkContext.evm.tokenInfoCaches.decimals.set(cacheKey, resPromise) + + return resPromise +} diff --git a/src/sdkUtils/types.internal.ts b/src/sdkUtils/types.internal.ts index 2ce8668..7321d0c 100644 --- a/src/sdkUtils/types.internal.ts +++ b/src/sdkUtils/types.internal.ts @@ -83,6 +83,9 @@ export interface SDKGlobalContext { string, Promise > + tokenInfoCaches: { + decimals: SDKGlobalContextCache> + } routesConfigCache?: SDKGlobalContextCache< "mainnet" | "testnet", Promise diff --git a/src/utils/swapHelpers/fetchDexAggregatorPossibleRoutes/helpers.ts b/src/utils/swapHelpers/fetchDexAggregatorPossibleRoutes/helpers.ts index f26118e..880f826 100644 --- a/src/utils/swapHelpers/fetchDexAggregatorPossibleRoutes/helpers.ts +++ b/src/utils/swapHelpers/fetchDexAggregatorPossibleRoutes/helpers.ts @@ -1,6 +1,9 @@ import { readContract } from "viem/actions" import { ERC20Abi } from "../../../evmUtils/contractAbi/ERC20Abi" -import { getEVMTokenContractInfo } from "../../../evmUtils/contractHelpers" +import { + getERC20TokenDecimals, + getEVMTokenContractInfo, +} from "../../../evmUtils/contractHelpers" import { evmChainIdFromKnownChainId } from "../../../evmUtils/evmClients" import { EVMAddress, @@ -68,23 +71,19 @@ export async function getQueryableRoutes( return } - const client = Object.values(sdkContext.evm.viemClients).find( - c => c.chain?.id === Number(chainId), - ) - if (client == null) return - const [fromTokenDecimals, toTokenDecimals] = await Promise.all([ - readContract(client, { - abi: ERC20Abi, - address: fromEVMToken.tokenContractAddress, - functionName: "decimals", - }), - readContract(client, { - abi: ERC20Abi, - address: toEVMToken.tokenContractAddress, - functionName: "decimals", - }), + getERC20TokenDecimals( + sdkContext, + info.evmChain, + fromEVMToken.tokenContractAddress, + ), + getERC20TokenDecimals( + sdkContext, + info.evmChain, + toEVMToken.tokenContractAddress, + ), ]) + if (fromTokenDecimals == null || toTokenDecimals == null) return return { chain: {