Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/rename-multicall-same-contract-helper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@uniswap/uniswapx-sdk': minor
---

Rename `multicallSameContractManyFunctions` to `multicallSameContractManyCalls`. The old name is still exported as a deprecated alias, so no existing import breaks.

The helper resolves `functionName` to a single fragment once, then encodes one call per entry in `functionParams` — it varies the arguments of one function, not the function itself. `functionName` living in the shared `MulticallParams` base type already makes "many functions" impossible: its sibling `multicallSameFunctionManyContracts` extends the same base and varies the address instead, and that one is named accurately.

No capability was missing. `multicall` is exported and takes arbitrary `{target, callData}` pairs, so heterogeneous functions and contracts were always reachable through it; these two helpers are narrow conveniences over it, one of them mislabeled.
38 changes: 37 additions & 1 deletion sdks/uniswapx-sdk/src/utils/multicall.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { ethers } from "ethers";
import multicall2Abi from "../../abis/multicall2.json";
import { BlockOverrides } from "../order";

import { multicallOrdersPreservingOrder } from "./multicall";
import {
multicallOrdersPreservingOrder,
multicallSameContractManyCalls,
multicallSameContractManyFunctions,
} from "./multicall";

const multicall2Interface = new Interface(multicall2Abi);
// Stand-in for the real quoter: one string param per order so each call can be
Expand Down Expand Up @@ -91,6 +95,38 @@ async function quoteIds(
);
}

describe("multicallSameContractManyCalls", () => {
it("calls one function once per entry in functionParams", async () => {
const sent: SentCall[] = [];
const results = await multicallSameContractManyCalls(mockProvider(sent), {
address: QUOTER_ADDRESS,
contractInterface: quoterInterface,
functionName: "quote",
functionParams: [["a"], ["b"], ["c"]],
});

expect(sent).toEqual([{ ids: ["a", "b", "c"], blockOverrides: undefined }]);
expect(results).toHaveLength(3);
});

it("is still exported under its deprecated name", async () => {
expect(multicallSameContractManyFunctions).toBe(
multicallSameContractManyCalls
);

// the old name has to keep working for consumers that have not migrated
const sent: SentCall[] = [];
await multicallSameContractManyFunctions(mockProvider(sent), {
address: QUOTER_ADDRESS,
contractInterface: quoterInterface,
functionName: "quote",
functionParams: [["a"]],
});

expect(sent).toEqual([{ ids: ["a"], blockOverrides: undefined }]);
});
});

describe("multicallOrdersPreservingOrder", () => {
describe("results line up with the input orders", () => {
// Orders carrying block overrides are dispatched on separate eth_calls, so
Expand Down
19 changes: 14 additions & 5 deletions sdks/uniswapx-sdk/src/utils/multicall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ type Call = {
callData: string;
};

// Perform multiple on-chain calls in a single http request
// return all results including errors
// Call one function on one contract once per entry in `functionParams`, in a
// single http request, returning all results including errors.
// Uses deployless method to function properly even on chains with no multicall contract deployed
export async function multicallSameContractManyFunctions<
export async function multicallSameContractManyCalls<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
TFunctionParams extends any[] | undefined
>(
Expand Down Expand Up @@ -74,6 +74,15 @@ export async function multicallSameContractManyFunctions<
return multicall(provider, calls, stateOverrrides, blockOverrides);
}

/**
* @deprecated Renamed to {@link multicallSameContractManyCalls}. This helper calls a
* single function once per entry in `functionParams` -- it varies the arguments, not
* the function, which `functionName` being a lone string already implies. To call
* different functions in one request, build the calls yourself and use {@link multicall}.
*/
export const multicallSameContractManyFunctions =
multicallSameContractManyCalls;

/// Structurally matches the SignedOrder / SignedV4Order shapes without importing
/// them, which would create a cycle with OrderQuoter
export type OrderWithBlockOverrides = {
Expand Down Expand Up @@ -106,7 +115,7 @@ export async function multicallOrdersPreservingOrder<

const batches: Promise<{ indices: number[]; results: MulticallResult[] }>[] =
overrideIndices.map((i) =>
multicallSameContractManyFunctions(
multicallSameContractManyCalls(
provider,
{ ...params, functionParams: [buildParams(orders[i])] },
undefined,
Expand All @@ -118,7 +127,7 @@ export async function multicallOrdersPreservingOrder<
// otherwise it costs a round trip to quote nothing
if (plainIndices.length > 0) {
batches.push(
multicallSameContractManyFunctions(provider, {
multicallSameContractManyCalls(provider, {
...params,
functionParams: plainIndices.map((i) => buildParams(orders[i])),
}).then((results) => ({ indices: plainIndices, results }))
Expand Down
Loading