Multicall SDK
Typescript package used to batch smart contract read calls into a single tx through the use of a multicall contract.
Supported Networks
The following networks have a multicall contract already deployed and can be accessed by providing an RPC url which points to the proper network.
export const multicallContracts: Partial<Record<ChainId, string>> = {
[ChainId.BSC_MAINNET]: '0x7D82217018FAAcf81d4726134939C12300fF6B9E',
[ChainId.BSC_TESTNET]: '0x7b6838b362f05bA2a0CAA8F9c1B34F3D619e7413',
[ChainId.POLYGON_MAINNET]: '0x45b673A3a4bEa062e7cEF9149a0F2277B00c83b4',
[ChainId.POLYGON_MUMBAI_TESTNET]: '0xcda26CD17E52a29EDaE0D2A15633d85A4594eC10',
}
Installation
npm i @defifofum/multicall
yarn add @defifofum/multicall
Usage
Here is an example of how to use the multicall function.
Options
export interface MultiCallOptions {
maxCallsPerTx?: number;
chainId?: number;
tryAggregate?: boolean;
blockTag?: BlockTag;
customMulticallAddress?: string;
}
Dynamic ABI
See multicallDynamicAbi example for details on how to use multicall to make multiple calls with different ABIs. See the example output below.
To run the example: yarn example
import { multicallDynamicAbi, multicallDynamicAbiIndexedCalls, AbiCall } from '@defifofum/multicall';
multicallDynamicAbiIndexedCalls
is an extended function of multicallDynamicAbi
which allows batching related calls into separate arrays for easier decoding. Internally, the function combines all of the calls into a single call (up to the maxBatchPerCall
) and puts them back into their proper batch relation.
export interface AbiCall {
address: string
functionName: string
params?: any[]
abi: (any | Fragment)[]
}
export async function multicallDynamicAbi(
provider: string | providers.BaseProvider | providers.JsonRpcProvider,
calls: AbiCall[],
{ maxCallsPerTx = 1000, blockTag = 'latest', tryAggregate = false, chainId, customMulticallAddress }: MultiCallOptions = {}
): Promise<any[][] | undefined>
export async function multicallDynamicAbiIndexedCalls(
provider: string | providers.BaseProvider | providers.JsonRpcProvider,
indexedCalls: AbiCall[][],
{ maxCallsPerTx = 1000, blockTag = 'latest', tryAggregate = false, chainId, customMulticallAddress }: MultiCallOptions = {}
): Promise<any[][] | any[]>
Single ABI
import { multicall, Call } from '@defifofum/multicall';
const callDataArray: Call[] = [];
for (const address of contractAddresses) {
callDataArray.push({
address: address,
functionName: 'balanceOf',
params: [ addressToCheck ]
});
}
const returnedData = await multicall(
RPC_PROVIDER,
ERC20.abi,
callDataArray,
{
maxCallsPerTx: 1000,
}
);
const cleanedData = returnedData.map((dataArray, index) => {
return {
contractAddress: contractAddresses[index],
bscscanUrl: `https://bscscan.com/address/${contractAddresses[index]}#readContract`,
balance: dataArray[0].toString(),
}
});
Configuration
If you would like to deploy a multicall contract you will need to clone this repo and provide environment variables in a .env
file based on .env.example
. These variables are used to deploy and verify the contract.
Example Output
This example shows 5000 calls being made through this tool with two different ABIs mixed in. The run time is 8761ms.