diff --git a/src/multicall-provider.ts b/src/multicall-provider.ts index 8cffafc..b175640 100644 --- a/src/multicall-provider.ts +++ b/src/multicall-provider.ts @@ -1,5 +1,12 @@ import DataLoader from "dataloader"; -import { BlockTag, BytesLike, AbstractProvider, PerformActionRequest, Network } from "ethers"; +import { + BlockTag, + BytesLike, + AbstractProvider, + PerformActionRequest, + Network, + isHexString, +} from "ethers"; import { multicallAddresses } from "./constants"; import { Multicall2, Multicall3 } from "./types"; @@ -48,7 +55,8 @@ export class MulticallWrapper { */ public static wrap( provider: T, - maxMulticallDataLength = 0 + maxMulticallDataLength = 0, + cache = true ): MulticallProvider { if (MulticallWrapper.isMulticallProvider(provider)) return provider; // Do not overwrap when given provider is already a multicall provider. @@ -157,7 +165,10 @@ export class MulticallWrapper { return results; }, - { cacheKeyFn: ({ call }) => (call.to + call.data + call.blockTag.toString()).toLowerCase() } + { + cache, + cacheKeyFn: ({ call }) => (call.to + call.data + call.blockTag.toString()).toLowerCase(), + } ); // Expose `Provider.fetchNetwork` to fetch & update the network cache when needed @@ -199,9 +210,15 @@ export class MulticallWrapper { if (multicall == null) return _perform(req); - return dataLoader.load({ + const request = { call: { to, data, blockTag }, multicall, + }; + + return dataLoader.load(request).then((value) => { + if (blockNumber == null) dataLoader.clear(request); + + return value; }); }; diff --git a/test/multicall-provider.spec.ts b/test/multicall-provider.spec.ts index 6ed6205..2770a55 100644 --- a/test/multicall-provider.spec.ts +++ b/test/multicall-provider.spec.ts @@ -1,5 +1,12 @@ import * as dotenv from "dotenv"; -import { JsonRpcProvider, WebSocketProvider, ZeroAddress, ethers } from "ethers"; +import { + AbiCoder, + JsonRpcProvider, + WebSocketProvider, + ZeroAddress, + ethers, + toUtf8Bytes, +} from "ethers"; import _range from "lodash/range"; import { multicall3Address, multicall2Address } from "../src/constants"; @@ -251,5 +258,37 @@ describe("ethers-multicall-provider", () => { expect(provider.send).toHaveBeenCalledTimes(4); }); + + it.only("should not cache latest request", async () => { + jest + .spyOn(provider, "send") + .mockImplementation(() => + Promise.resolve( + AbiCoder.defaultAbiCoder().encode( + ["(bool, bytes)[]"], + [[[true, AbiCoder.defaultAbiCoder().encode(["string"], ["UNI1"])]]] + ) + ) + ); + + const symbol1 = await uni.symbol(); + + jest + .spyOn(provider, "send") + .mockImplementation(() => + Promise.resolve( + AbiCoder.defaultAbiCoder().encode( + ["(bool, bytes)[]"], + [[[true, AbiCoder.defaultAbiCoder().encode(["string"], ["UNI2"])]]] + ) + ) + ); + + const symbol2 = await uni.symbol(); + + expect(symbol1).toEqual("UNI1"); + expect(symbol2).toEqual("UNI2"); + expect(provider.send).toHaveBeenCalledTimes(2); + }); }); });