import { Erc20__factory, MultiCall, MultiCall__factory } from './abi/types' import { Signer } from 'ethers' import { JsonRpcProvider, Provider } from '@ethersproject/providers' import { BigNumber } from '@ethersproject/bignumber' class MultiCallContract { private contract: MultiCall constructor(address: string, signerOrProvider: string | Signer | Provider) { if (typeof signerOrProvider !== 'string') { this.contract = MultiCall__factory.connect(address, signerOrProvider) } else { const provider = new JsonRpcProvider(signerOrProvider) this.contract = MultiCall__factory.connect(address, provider) } } async getTokenBalance(address: string, contract: string[]): Promise { const erc20 = Erc20__factory.createInterface() const calls = contract.map((item): MultiCall.CallStruct => { return { target: item, callData: erc20.encodeFunctionData('balanceOf', [address]), } }) return await this.tryAggregate(false, calls, (data) => { return erc20.decodeFunctionResult('balanceOf', data.returnData)[0] as BigNumber }) } async tryAggregate( requireSuccess: boolean, calls: MultiCall.CallStruct[], decodeFunc: (item: MultiCall.ResultStructOutput) => T, ) { const data = await this.contract.callStatic.tryAggregate(requireSuccess, calls) const result: T[] = [] data.map((item) => { result.push(decodeFunc(item) as T) }) return result } } export default MultiCallContract