Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save daochild/2ccd5b642d23c6dc410f63b005e7889d to your computer and use it in GitHub Desktop.
Save daochild/2ccd5b642d23c6dc410f63b005e7889d to your computer and use it in GitHub Desktop.
Multicall3 Contract Client Class on Typescript
// Resolve 2 TODOs and use multicall batch client.
import type { Interface, Result, ethers } from "ethers";
import { type IMulticall3 } from "../../index.js"; // TODO: use your import (in this example I used typechain types with multicall3 contract)
export type Multicall3ContractCall = { target: string, allowFailure: boolean, callData: string };
export type Aggregate3Response = { success: boolean; returnData: string };
export type TxResultsConverter<T> = (result: Result, ...opt: any[]) => T;
/*
* @description Client to be inherited from to work with Multicall3 contract to perform batch calls.
* @dev For more info: https://github.com/mds1/multicall/tree/main.
*/
export abstract class Multicall3ContractClient {
_caller: ethers.Provider | ethers.Signer;
_multicall3Contract: IMulticall3;
constructor(caller: ethers.Provider | ethers.Signer, multicall3ContractAddress: string) {
this._caller = caller
const multicall3Abi = []; // TODO: add abi here
this._multicall3Contract = new ethers.Contract(multicall3ContractAddress, multicall3Abi, this._caller) as unknown as IMulticall3;
}
async _callBatch<ConvertTo>(
callsEncoded: Multicall3ContractCall[],
callResultsInterface: Interface,
contractMethod: string,
txResultsConverter: TxResultsConverter<ConvertTo>,
): Promise<Array<ConvertTo>> {
console.group("[_callBatch]");
console.info('Send batch request with callsEncoded = %s...', JSON.stringify(callsEncoded))
const multicallContractCallResults: Aggregate3Response[] = await this._multicall3Contract.aggregate3.staticCall(callsEncoded);
let decodedResults: Array<ConvertTo> = []
console.info("Decode and convert all results with converter %s", txResultsConverter.name)
for (const rawResult of multicallContractCallResults) {
console.info('Success status: %s', rawResult.success)
console.debug('Raw data: %s', rawResult.returnData)
const decoded = callResultsInterface.decodeFunctionResult(contractMethod, rawResult.returnData)
console.debug('Got after decoding: %s', decoded)
decodedResults.push(
txResultsConverter(decoded)
)
}
console.groupEnd();
return decodedResults
}
_decodeToString(result: Result, defaultNoResult: string = ""): string {
if (!result) {
return defaultNoResult;
}
return result.toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment