UNPKG

@wagmi/core

Version:

VanillaJS library for Ethereum

142 lines (130 loc) 4.07 kB
import type { Address, Hex } from 'viem' import { ContractFunctionExecutionError, formatUnits, hexToString, trim, } from 'viem' import type { Config } from '../createConfig.js' import type { ChainIdParameter } from '../types/properties.js' import type { Unit } from '../types/unit.js' import type { Compute } from '../types/utils.js' import { getUnit } from '../utils/getUnit.js' import { type ReadContractsErrorType, readContracts } from './readContracts.js' export type GetTokenParameters<config extends Config = Config> = Compute< ChainIdParameter<config> & { address: Address formatUnits?: Unit | undefined } > export type GetTokenReturnType = { address: Address decimals: number name: string | undefined symbol: string | undefined totalSupply: { formatted: string value: bigint } } export type GetTokenErrorType = ReadContractsErrorType /** @deprecated */ export async function getToken<config extends Config>( config: config, parameters: GetTokenParameters<config>, ): Promise<GetTokenReturnType> { const { address, chainId, formatUnits: unit = 18 } = parameters function getAbi<type extends 'bytes32' | 'string'>(type: type) { return [ { type: 'function', name: 'decimals', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint8' }], }, { type: 'function', name: 'name', stateMutability: 'view', inputs: [], outputs: [{ type }], }, { type: 'function', name: 'symbol', stateMutability: 'view', inputs: [], outputs: [{ type }], }, { type: 'function', name: 'totalSupply', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }], }, ] as const } try { const abi = getAbi('string') const contractConfig = { address, abi, chainId } as const const [decimals, name, symbol, totalSupply] = await readContracts(config, { allowFailure: true, contracts: [ { ...contractConfig, functionName: 'decimals' }, { ...contractConfig, functionName: 'name' }, { ...contractConfig, functionName: 'symbol' }, { ...contractConfig, functionName: 'totalSupply' }, ] as const, }) // throw if `name` or `symbol` failed if (name.error instanceof ContractFunctionExecutionError) throw name.error if (symbol.error instanceof ContractFunctionExecutionError) throw symbol.error // `decimals` and `totalSupply` are required if (decimals.error) throw decimals.error if (totalSupply.error) throw totalSupply.error return { address, decimals: decimals.result, name: name.result, symbol: symbol.result, totalSupply: { formatted: formatUnits(totalSupply.result!, getUnit(unit)), value: totalSupply.result, }, } } catch (error) { // In the chance that there is an error upon decoding the contract result, // it could be likely that the contract data is represented as bytes32 instead // of a string. if (error instanceof ContractFunctionExecutionError) { const abi = getAbi('bytes32') const contractConfig = { address, abi, chainId } as const const [decimals, name, symbol, totalSupply] = await readContracts( config, { allowFailure: false, contracts: [ { ...contractConfig, functionName: 'decimals' }, { ...contractConfig, functionName: 'name' }, { ...contractConfig, functionName: 'symbol' }, { ...contractConfig, functionName: 'totalSupply' }, ] as const, }, ) return { address, decimals, name: hexToString(trim(name as Hex, { dir: 'right' })), symbol: hexToString(trim(symbol as Hex, { dir: 'right' })), totalSupply: { formatted: formatUnits(totalSupply, getUnit(unit)), value: totalSupply, }, } } throw error } }