From f1008692fc5d5070188fc07e6e801f5cb037b577 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Fri, 5 Apr 2024 10:06:59 +0200 Subject: [PATCH] feat(batch): make batching great again --- README.md | 3 +++ test/multicall-provider.spec.ts | 42 +++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 49f00b1..f906131 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,9 @@ With multicall, batch these queries into a single, on-chain query, without addit ### Using ethers-v6 +> [!WARNING] +> Ethers made changes to their `Provider` & `Signer` classes throughout v6, that are breaking types. For versions `v6.7` to `v6.10`, use `ethers-multicall-provider@6.2.0`. For later versions, use `ethers-multicall-provider@6.3.0`. + ```bash npm install ethers-multicall-provider ``` diff --git a/test/multicall-provider.spec.ts b/test/multicall-provider.spec.ts index e09b10b..f01b10c 100644 --- a/test/multicall-provider.spec.ts +++ b/test/multicall-provider.spec.ts @@ -110,7 +110,7 @@ describe("ethers-multicall-provider", () => { const result = await Promise.all([uni.name(), uni.symbol(), uni.decimals()]); expect(result).toEqual(["Uniswap", "UNI", 18n]); - expect(provider.send).toHaveBeenCalledTimes(1); + expect(provider.send).toHaveBeenCalledTimes(2); expect(provider.send).toHaveBeenNthCalledWith(1, "eth_call", [ { data: "0xbce38bd7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001600000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000406fdde03000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000495d89b41000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f98400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004313ce56700000000000000000000000000000000000000000000000000000000", @@ -118,6 +118,7 @@ describe("ethers-multicall-provider", () => { }, "latest", ]); + expect(provider.send).toHaveBeenNthCalledWith(2, "eth_chainId", []); }); it("should batch UNI calls without Promise.all", async () => { @@ -125,7 +126,7 @@ describe("ethers-multicall-provider", () => { expect(uni.symbol()).resolves.toEqual("UNI"); expect(await uni.decimals()).toEqual(18n); - expect(provider.send).toHaveBeenCalledTimes(1); + expect(provider.send).toHaveBeenCalledTimes(2); expect(provider.send).toHaveBeenNthCalledWith(1, "eth_call", [ { data: "0xbce38bd7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001600000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000406fdde03000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000495d89b41000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f98400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004313ce56700000000000000000000000000000000000000000000000000000000", @@ -133,6 +134,7 @@ describe("ethers-multicall-provider", () => { }, "latest", ]); + expect(provider.send).toHaveBeenNthCalledWith(2, "eth_chainId", []); }); it("should batch calls using Multicall2 at block 14_000_000", async () => { @@ -145,7 +147,7 @@ describe("ethers-multicall-provider", () => { ]); expect(result).toEqual(["Uniswap", "UNI", 18n]); - expect(provider.send).toHaveBeenCalledTimes(1); + expect(provider.send).toHaveBeenCalledTimes(2); expect(provider.send).toHaveBeenNthCalledWith(1, "eth_call", [ { data: "0xbce38bd7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001600000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000406fdde03000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000495d89b41000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f98400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004313ce56700000000000000000000000000000000000000000000000000000000", @@ -153,6 +155,7 @@ describe("ethers-multicall-provider", () => { }, "0xd59f80", ]); + expect(provider.send).toHaveBeenNthCalledWith(2, "eth_chainId", []); }); it("should not batch calls at block 12_000_000", async () => { @@ -165,7 +168,8 @@ describe("ethers-multicall-provider", () => { ]); expect(result).toEqual(["Uniswap", "UNI", 18n]); - expect(provider.send).toHaveBeenCalledTimes(3); + expect(provider.send).toHaveBeenCalledTimes(4); + expect(provider.send).toHaveBeenCalledWith("eth_chainId", []); }); it("should not batch calls at earliest block", async () => { @@ -178,13 +182,14 @@ describe("ethers-multicall-provider", () => { ]); expect(result).toEqual(["Uniswap", "UNI", 18]); - expect(provider.send).toHaveBeenCalledTimes(3); + expect(provider.send).toHaveBeenCalledTimes(4); + expect(provider.send).toHaveBeenCalledWith("eth_chainId", []); }); it("should throw a descriptive Error when querying unknown contract", async () => { await expect(unknownUni.symbol()).rejects.toEqual( new Error( - `could not decode result data (value="0x", info={ "method": "symbol", "signature": "symbol()" }, code=BAD_DATA, version=6.7.1)` + `could not decode result data (value="0x", info={ "method": "symbol", "signature": "symbol()" }, code=BAD_DATA, version=6.11.1)` ) ); }); @@ -200,7 +205,7 @@ describe("ethers-multicall-provider", () => { expect(unknownUni.symbol().catch(() => "UNI")).resolves.toEqual("UNI"); await expect(unknownUni.symbol()).rejects.toEqual( new Error( - `could not decode result data (value="0x", info={ "method": "symbol", "signature": "symbol()" }, code=BAD_DATA, version=6.7.1)` + `could not decode result data (value="0x", info={ "method": "symbol", "signature": "symbol()" }, code=BAD_DATA, version=6.11.1)` ) ); }); @@ -212,7 +217,7 @@ describe("ethers-multicall-provider", () => { expect(uni.symbol(overrides).catch(() => "UNI")).resolves.toEqual("UNI"); await expect(unknownUni.symbol(overrides)).rejects.toEqual( new Error( - `could not decode result data (value="0x", info={ "method": "symbol", "signature": "symbol()" }, code=BAD_DATA, version=6.7.1)` + `could not decode result data (value="0x", info={ "method": "symbol", "signature": "symbol()" }, code=BAD_DATA, version=6.11.1)` ) ); }); @@ -221,7 +226,16 @@ describe("ethers-multicall-provider", () => { const range = _range(1_000); const result: bigint[] = await Promise.all(range.map(() => uni.balanceOf(ZeroAddress))); - expect(provider.send).toHaveBeenCalledTimes(1); + expect(provider.send).toHaveBeenCalledTimes(2); + expect(provider.send).toHaveBeenNthCalledWith(1, "eth_call", [ + { + data: "0xbce38bd700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a08231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + to: multicall3Address.toLowerCase(), + }, + "latest", + ]); + expect(provider.send).toHaveBeenNthCalledWith(2, "eth_chainId", []); + expect(result).toEqual(range.map(() => 0n)); }); @@ -232,18 +246,19 @@ describe("ethers-multicall-provider", () => { _range(1, 25).map((i) => uni.balanceOf("0x" + i.toString(16).padStart(40, "0"))) ); - expect(provider.send).toHaveBeenCalledTimes(2); + expect(provider.send).toHaveBeenCalledTimes(3); expect(provider.send).toHaveBeenNthCalledWith(1, "eth_call", [ { data: "0xbce38bd700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000074000000000000000000000000000000000000000000000000000000000000007e0000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000009200000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a08231000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a08231000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a08231000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a08231000000000000000000000000000000000000000000000000000000000000000d00000000000000000000000000000000000000000000000000000000", - to: "0xca11bde05977b3631167028862be2a173976ca11", + to: multicall3Address.toLowerCase(), }, "latest", ]); - expect(provider.send).toHaveBeenNthCalledWith(2, "eth_call", [ + expect(provider.send).toHaveBeenNthCalledWith(2, "eth_chainId", []); + expect(provider.send).toHaveBeenNthCalledWith(3, "eth_call", [ { data: "0xbce38bd700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000005c00000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a08231000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a08231000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000015000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a082310000000000000000000000000000000000000000000000000000000000000017000000000000000000000000000000000000000000000000000000000000000000000000000000001f9840a85d5af5bf1d1762f925bdaddc4201f9840000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002470a08231000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000", - to: "0xca11bde05977b3631167028862be2a173976ca11", + to: multicall3Address.toLowerCase(), }, "latest", ]); @@ -257,6 +272,7 @@ describe("ethers-multicall-provider", () => { ); expect(provider.send).toHaveBeenCalledTimes(4); + expect(provider.send).toHaveBeenCalledWith("eth_chainId", []); }); it("should not cache latest request", async () => {