diff --git a/artifacts/ts/Add.ts b/artifacts/ts/Add.ts index e5014d2c6..0208281ea 100644 --- a/artifacts/ts/Add.ts +++ b/artifacts/ts/Add.ts @@ -381,14 +381,16 @@ export class AddInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: AddTypes.MultiCallResults; + }> { return (await multicallMethods( Add, this, - calls, + callss, getContractByCodeHash - )) as AddTypes.MultiCallResults; + )) as { [index in keyof Callss]: AddTypes.MultiCallResults }; } } diff --git a/artifacts/ts/DeprecatedNFTTest1.ts b/artifacts/ts/DeprecatedNFTTest1.ts index dc1a0d208..676664d4f 100644 --- a/artifacts/ts/DeprecatedNFTTest1.ts +++ b/artifacts/ts/DeprecatedNFTTest1.ts @@ -158,14 +158,22 @@ export class DeprecatedNFTTest1Instance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: DeprecatedNFTTest1Types.MultiCallResults< + Callss[index] + >; + }> { return (await multicallMethods( DeprecatedNFTTest1, this, - calls, + callss, getContractByCodeHash - )) as DeprecatedNFTTest1Types.MultiCallResults; + )) as { + [index in keyof Callss]: DeprecatedNFTTest1Types.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/DeprecatedNFTTest2.ts b/artifacts/ts/DeprecatedNFTTest2.ts index de5ae6f39..a480aad68 100644 --- a/artifacts/ts/DeprecatedNFTTest2.ts +++ b/artifacts/ts/DeprecatedNFTTest2.ts @@ -197,14 +197,22 @@ export class DeprecatedNFTTest2Instance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: DeprecatedNFTTest2Types.MultiCallResults< + Callss[index] + >; + }> { return (await multicallMethods( DeprecatedNFTTest2, this, - calls, + callss, getContractByCodeHash - )) as DeprecatedNFTTest2Types.MultiCallResults; + )) as { + [index in keyof Callss]: DeprecatedNFTTest2Types.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/DeprecatedNFTTest3.ts b/artifacts/ts/DeprecatedNFTTest3.ts index c4542a2bb..443928682 100644 --- a/artifacts/ts/DeprecatedNFTTest3.ts +++ b/artifacts/ts/DeprecatedNFTTest3.ts @@ -197,14 +197,22 @@ export class DeprecatedNFTTest3Instance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: DeprecatedNFTTest3Types.MultiCallResults< + Callss[index] + >; + }> { return (await multicallMethods( DeprecatedNFTTest3, this, - calls, + callss, getContractByCodeHash - )) as DeprecatedNFTTest3Types.MultiCallResults; + )) as { + [index in keyof Callss]: DeprecatedNFTTest3Types.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/DeprecatedNFTTest4.ts b/artifacts/ts/DeprecatedNFTTest4.ts index 403e2bc0f..f97acb18b 100644 --- a/artifacts/ts/DeprecatedNFTTest4.ts +++ b/artifacts/ts/DeprecatedNFTTest4.ts @@ -190,14 +190,22 @@ export class DeprecatedNFTTest4Instance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: DeprecatedNFTTest4Types.MultiCallResults< + Callss[index] + >; + }> { return (await multicallMethods( DeprecatedNFTTest4, this, - calls, + callss, getContractByCodeHash - )) as DeprecatedNFTTest4Types.MultiCallResults; + )) as { + [index in keyof Callss]: DeprecatedNFTTest4Types.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/DeprecatedNFTTest5.ts b/artifacts/ts/DeprecatedNFTTest5.ts index 9e559ea4f..e5182c9f3 100644 --- a/artifacts/ts/DeprecatedNFTTest5.ts +++ b/artifacts/ts/DeprecatedNFTTest5.ts @@ -204,14 +204,22 @@ export class DeprecatedNFTTest5Instance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: DeprecatedNFTTest5Types.MultiCallResults< + Callss[index] + >; + }> { return (await multicallMethods( DeprecatedNFTTest5, this, - calls, + callss, getContractByCodeHash - )) as DeprecatedNFTTest5Types.MultiCallResults; + )) as { + [index in keyof Callss]: DeprecatedNFTTest5Types.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/DeprecatedNFTTest6.ts b/artifacts/ts/DeprecatedNFTTest6.ts index fa48b83aa..3f57a17b7 100644 --- a/artifacts/ts/DeprecatedNFTTest6.ts +++ b/artifacts/ts/DeprecatedNFTTest6.ts @@ -190,14 +190,22 @@ export class DeprecatedNFTTest6Instance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: DeprecatedNFTTest6Types.MultiCallResults< + Callss[index] + >; + }> { return (await multicallMethods( DeprecatedNFTTest6, this, - calls, + callss, getContractByCodeHash - )) as DeprecatedNFTTest6Types.MultiCallResults; + )) as { + [index in keyof Callss]: DeprecatedNFTTest6Types.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/DeprecatedNFTTest7.ts b/artifacts/ts/DeprecatedNFTTest7.ts index a32cd2f59..2c5ab2c84 100644 --- a/artifacts/ts/DeprecatedNFTTest7.ts +++ b/artifacts/ts/DeprecatedNFTTest7.ts @@ -204,14 +204,22 @@ export class DeprecatedNFTTest7Instance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: DeprecatedNFTTest7Types.MultiCallResults< + Callss[index] + >; + }> { return (await multicallMethods( DeprecatedNFTTest7, this, - calls, + callss, getContractByCodeHash - )) as DeprecatedNFTTest7Types.MultiCallResults; + )) as { + [index in keyof Callss]: DeprecatedNFTTest7Types.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/FakeTokenTest.ts b/artifacts/ts/FakeTokenTest.ts index 3b752b58b..527805fe4 100644 --- a/artifacts/ts/FakeTokenTest.ts +++ b/artifacts/ts/FakeTokenTest.ts @@ -285,14 +285,20 @@ export class FakeTokenTestInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: FakeTokenTestTypes.MultiCallResults; + }> { return (await multicallMethods( FakeTokenTest, this, - calls, + callss, getContractByCodeHash - )) as FakeTokenTestTypes.MultiCallResults; + )) as { + [index in keyof Callss]: FakeTokenTestTypes.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/Greeter.ts b/artifacts/ts/Greeter.ts index 59dac1526..0c6dfc03e 100644 --- a/artifacts/ts/Greeter.ts +++ b/artifacts/ts/Greeter.ts @@ -160,14 +160,18 @@ export class GreeterInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: GreeterTypes.MultiCallResults; + }> { return (await multicallMethods( Greeter, this, - calls, + callss, getContractByCodeHash - )) as GreeterTypes.MultiCallResults; + )) as { + [index in keyof Callss]: GreeterTypes.MultiCallResults; + }; } } diff --git a/artifacts/ts/MapTest.ts b/artifacts/ts/MapTest.ts index 6f2b59669..8e95cc774 100644 --- a/artifacts/ts/MapTest.ts +++ b/artifacts/ts/MapTest.ts @@ -308,14 +308,18 @@ export class MapTestInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: MapTestTypes.MultiCallResults; + }> { return (await multicallMethods( MapTest, this, - calls, + callss, getContractByCodeHash - )) as MapTestTypes.MultiCallResults; + )) as { + [index in keyof Callss]: MapTestTypes.MultiCallResults; + }; } } diff --git a/artifacts/ts/NFTCollectionTest.ts b/artifacts/ts/NFTCollectionTest.ts index ce9ca677e..d26849471 100644 --- a/artifacts/ts/NFTCollectionTest.ts +++ b/artifacts/ts/NFTCollectionTest.ts @@ -314,14 +314,22 @@ export class NFTCollectionTestInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: NFTCollectionTestTypes.MultiCallResults< + Callss[index] + >; + }> { return (await multicallMethods( NFTCollectionTest, this, - calls, + callss, getContractByCodeHash - )) as NFTCollectionTestTypes.MultiCallResults; + )) as { + [index in keyof Callss]: NFTCollectionTestTypes.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/NFTCollectionWithRoyaltyTest.ts b/artifacts/ts/NFTCollectionWithRoyaltyTest.ts index 7dcb19e81..104f30feb 100644 --- a/artifacts/ts/NFTCollectionWithRoyaltyTest.ts +++ b/artifacts/ts/NFTCollectionWithRoyaltyTest.ts @@ -486,15 +486,23 @@ export class NFTCollectionWithRoyaltyTestInstance extends ContractInstance { }; async multicall< - Calls extends NFTCollectionWithRoyaltyTestTypes.MultiCallParams + Callss extends NFTCollectionWithRoyaltyTestTypes.MultiCallParams[] >( - calls: Calls - ): Promise> { + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: NFTCollectionWithRoyaltyTestTypes.MultiCallResults< + Callss[index] + >; + }> { return (await multicallMethods( NFTCollectionWithRoyaltyTest, this, - calls, + callss, getContractByCodeHash - )) as NFTCollectionWithRoyaltyTestTypes.MultiCallResults; + )) as { + [index in keyof Callss]: NFTCollectionWithRoyaltyTestTypes.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/NFTTest.ts b/artifacts/ts/NFTTest.ts index b2bd1eaaa..cf3552e2d 100644 --- a/artifacts/ts/NFTTest.ts +++ b/artifacts/ts/NFTTest.ts @@ -191,14 +191,18 @@ export class NFTTestInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: NFTTestTypes.MultiCallResults; + }> { return (await multicallMethods( NFTTest, this, - calls, + callss, getContractByCodeHash - )) as NFTTestTypes.MultiCallResults; + )) as { + [index in keyof Callss]: NFTTestTypes.MultiCallResults; + }; } } diff --git a/artifacts/ts/NFTTestStd.ts b/artifacts/ts/NFTTestStd.ts index 74bbd8e1f..d9a0783ea 100644 --- a/artifacts/ts/NFTTestStd.ts +++ b/artifacts/ts/NFTTestStd.ts @@ -228,14 +228,18 @@ export class NFTTestStdInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: NFTTestStdTypes.MultiCallResults; + }> { return (await multicallMethods( NFTTestStd, this, - calls, + callss, getContractByCodeHash - )) as NFTTestStdTypes.MultiCallResults; + )) as { + [index in keyof Callss]: NFTTestStdTypes.MultiCallResults; + }; } } diff --git a/artifacts/ts/Sub.ts b/artifacts/ts/Sub.ts index 1daed3122..dd5a1086c 100644 --- a/artifacts/ts/Sub.ts +++ b/artifacts/ts/Sub.ts @@ -167,14 +167,16 @@ export class SubInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: SubTypes.MultiCallResults; + }> { return (await multicallMethods( Sub, this, - calls, + callss, getContractByCodeHash - )) as SubTypes.MultiCallResults; + )) as { [index in keyof Callss]: SubTypes.MultiCallResults }; } } diff --git a/artifacts/ts/TokenTest.ts b/artifacts/ts/TokenTest.ts index cd4774301..228c80043 100644 --- a/artifacts/ts/TokenTest.ts +++ b/artifacts/ts/TokenTest.ts @@ -254,14 +254,18 @@ export class TokenTestInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: TokenTestTypes.MultiCallResults; + }> { return (await multicallMethods( TokenTest, this, - calls, + callss, getContractByCodeHash - )) as TokenTestTypes.MultiCallResults; + )) as { + [index in keyof Callss]: TokenTestTypes.MultiCallResults; + }; } } diff --git a/artifacts/ts/TokenTestStd.ts b/artifacts/ts/TokenTestStd.ts index a837474a0..a8a1f7f94 100644 --- a/artifacts/ts/TokenTestStd.ts +++ b/artifacts/ts/TokenTestStd.ts @@ -286,14 +286,20 @@ export class TokenTestStdInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: TokenTestStdTypes.MultiCallResults; + }> { return (await multicallMethods( TokenTestStd, this, - calls, + callss, getContractByCodeHash - )) as TokenTestStdTypes.MultiCallResults; + )) as { + [index in keyof Callss]: TokenTestStdTypes.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/artifacts/ts/UserAccount.ts b/artifacts/ts/UserAccount.ts index e7634fb70..68ea068f9 100644 --- a/artifacts/ts/UserAccount.ts +++ b/artifacts/ts/UserAccount.ts @@ -224,14 +224,18 @@ export class UserAccountInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: UserAccountTypes.MultiCallResults; + }> { return (await multicallMethods( UserAccount, this, - calls, + callss, getContractByCodeHash - )) as UserAccountTypes.MultiCallResults; + )) as { + [index in keyof Callss]: UserAccountTypes.MultiCallResults; + }; } } diff --git a/artifacts/ts/WrongNFTTest.ts b/artifacts/ts/WrongNFTTest.ts index 7704a01c8..cf2bb3d4b 100644 --- a/artifacts/ts/WrongNFTTest.ts +++ b/artifacts/ts/WrongNFTTest.ts @@ -201,14 +201,20 @@ export class WrongNFTTestInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: WrongNFTTestTypes.MultiCallResults; + }> { return (await multicallMethods( WrongNFTTest, this, - calls, + callss, getContractByCodeHash - )) as WrongNFTTestTypes.MultiCallResults; + )) as { + [index in keyof Callss]: WrongNFTTestTypes.MultiCallResults< + Callss[index] + >; + }; } } diff --git a/packages/cli/src/codegen.ts b/packages/cli/src/codegen.ts index 83254625d..b75979327 100644 --- a/packages/cli/src/codegen.ts +++ b/packages/cli/src/codegen.ts @@ -456,10 +456,10 @@ function genMulticall(contract: Contract): string { contract.publicFunctions().filter((functionSig) => functionSig.returnTypes.length > 0).length > 0 return supportMulticall ? ` - async multicall( - calls: Calls - ): Promise<${types}.MultiCallResults> { - return (await multicallMethods(${contract.name}, this, calls, getContractByCodeHash)) as ${types}.MultiCallResults + async multicall( + ...callss: Callss + ): Promise<{ [index in keyof Callss]: ${types}.MultiCallResults }> { + return (await multicallMethods(${contract.name}, this, callss, getContractByCodeHash)) as { [index in keyof Callss]: ${types}.MultiCallResults } } ` : '' diff --git a/packages/walletconnect/artifacts/ts/Greeter.ts b/packages/walletconnect/artifacts/ts/Greeter.ts index d94f04d31..e4d6bb2a9 100644 --- a/packages/walletconnect/artifacts/ts/Greeter.ts +++ b/packages/walletconnect/artifacts/ts/Greeter.ts @@ -102,14 +102,18 @@ export class GreeterInstance extends ContractInstance { }, }; - async multicall( - calls: Calls - ): Promise> { + async multicall( + ...callss: Callss + ): Promise<{ + [index in keyof Callss]: GreeterTypes.MultiCallResults; + }> { return (await multicallMethods( Greeter, this, - calls, + callss, getContractByCodeHash - )) as GreeterTypes.MultiCallResults; + )) as { + [index in keyof Callss]: GreeterTypes.MultiCallResults; + }; } } diff --git a/packages/web3/src/contract/contract.ts b/packages/web3/src/contract/contract.ts index 1f2a73a22..04347fecf 100644 --- a/packages/web3/src/contract/contract.ts +++ b/packages/web3/src/contract/contract.ts @@ -1921,35 +1921,42 @@ function toFieldsSig(contractName: string, functionSig: FunctionSig): FieldsSig export async function multicallMethods( contract: ContractFactory, instance: ContractInstance, - calls: Record, 'args'>>, + callss: Record, 'args'>>[], getContractByCodeHash: (codeHash: string) => Contract -): Promise>> { - const callEntries = Object.entries(calls) - const callsParams = callEntries.map((entry) => { - const [methodName, params] = entry - const methodIndex = contract.contract.getMethodIndex(methodName) - const txId = params?.txId ?? randomTxId() - return contract.contract.toApiCallContract( - { ...params, txId: txId, args: params.args === undefined ? {} : params.args }, - instance.groupIndex, - instance.address, - methodIndex - ) +): Promise>[]> { + const callEntries = callss.map((calls) => Object.entries(calls)) + const callsParams = callEntries.map((entries) => { + return entries.map((entry) => { + const [methodName, params] = entry + const methodIndex = contract.contract.getMethodIndex(methodName) + const txId = params?.txId ?? randomTxId() + return contract.contract.toApiCallContract( + { ...params, txId: txId, args: params.args === undefined ? {} : params.args }, + instance.groupIndex, + instance.address, + methodIndex + ) + }) }) - const result = await getCurrentNodeProvider().contracts.postContractsMulticallContract({ calls: callsParams }) - const callsResult: Record> = {} - callsParams.forEach((call, index) => { - const methodIndex = call.methodIndex - const callResult = result.results[`${index}`] - const methodName = callEntries[`${index}`][`0`] - callsResult[`${methodName}`] = contract.contract.fromApiCallContractResult( - callResult, - call.txId!, - methodIndex, - getContractByCodeHash - ) as CallContractResult + const result = await getCurrentNodeProvider().contracts.postContractsMulticallContract({ calls: callsParams.flat() }) + let callResultIndex = 0 + return callsParams.map((calls, index0) => { + const callsResult: Record> = {} + const entries = callEntries[`${index0}`] + calls.forEach((call, index1) => { + const methodIndex = call.methodIndex + const callResult = result.results[`${callResultIndex}`] + const methodName = entries[`${index1}`][`0`] + callsResult[`${methodName}`] = contract.contract.fromApiCallContractResult( + callResult, + call.txId!, + methodIndex, + getContractByCodeHash + ) as CallContractResult + callResultIndex += 1 + }) + return callsResult }) - return callsResult } export async function getContractEventsCurrentCount(contractAddress: Address): Promise { diff --git a/test/token.test.ts b/test/token.test.ts index 28509dff9..91b4e7ef1 100644 --- a/test/token.test.ts +++ b/test/token.test.ts @@ -76,16 +76,28 @@ describe('contract', function () { it('should multicall', async () => { const tokenTest = (await TokenTest.deploy(signer, { initialFields })).contractInstance - const result = await tokenTest.multicall({ + const result0 = await tokenTest.multicall({ getName: {}, getTotalSupply: {}, getDecimals: {}, getSymbol: {} }) - expect(result.getSymbol.returns).toEqual(symbol) - expect(result.getName.returns).toEqual(name) - expect(result.getDecimals.returns).toEqual(decimals) - expect(result.getTotalSupply.returns).toEqual(totalSupply) + expect(result0[0].getSymbol.returns).toEqual(symbol) + expect(result0[0].getName.returns).toEqual(name) + expect(result0[0].getDecimals.returns).toEqual(decimals) + expect(result0[0].getTotalSupply.returns).toEqual(totalSupply) + + const result1 = await tokenTest.multicall( + { getName: {} }, + { getName: {}, getSymbol: {} }, + { getName: {}, getSymbol: {}, getDecimals: {} } + ) + expect(result1[0].getName.returns).toEqual(name) + expect(result1[1].getName.returns).toEqual(name) + expect(result1[1].getSymbol.returns).toEqual(symbol) + expect(result1[2].getName.returns).toEqual(name) + expect(result1[2].getSymbol.returns).toEqual(symbol) + expect(result1[2].getDecimals.returns).toEqual(decimals) const tokenType = await web3.getCurrentNodeProvider().guessStdTokenType(tokenTest.contractId) expect(tokenType).toEqual('fungible')