web3-mev-error-decoder 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +167 -2
  3. package/dist/error-decoder/constants.d.ts +5 -0
  4. package/dist/error-decoder/constants.js +19 -0
  5. package/dist/error-decoder/constants.js.map +1 -0
  6. package/dist/error-decoder/decoder.d.ts +43 -0
  7. package/dist/error-decoder/decoder.js +98 -0
  8. package/dist/error-decoder/decoder.js.map +1 -0
  9. package/dist/error-decoder/enums.d.ts +9 -0
  10. package/dist/error-decoder/enums.js +11 -0
  11. package/dist/error-decoder/enums.js.map +1 -0
  12. package/dist/error-decoder/handlers.d.ts +32 -0
  13. package/dist/error-decoder/handlers.js +131 -0
  14. package/dist/error-decoder/handlers.js.map +1 -0
  15. package/dist/error-decoder/index.d.ts +7 -0
  16. package/dist/error-decoder/index.js +7 -0
  17. package/dist/error-decoder/index.js.map +1 -0
  18. package/dist/error-decoder/results.d.ts +19 -0
  19. package/dist/error-decoder/results.js +53 -0
  20. package/dist/error-decoder/results.js.map +1 -0
  21. package/dist/error-decoder/types.d.ts +31 -0
  22. package/dist/error-decoder/types.js +2 -0
  23. package/dist/error-decoder/types.js.map +1 -0
  24. package/dist/error-decoder/viem.d.ts +19 -0
  25. package/dist/error-decoder/viem.js +47 -0
  26. package/dist/error-decoder/viem.js.map +1 -0
  27. package/dist/index.d.ts +5 -0
  28. package/dist/index.js +6 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/multicall/abi.d.ts +7 -0
  31. package/dist/multicall/abi.js +27 -0
  32. package/dist/multicall/abi.js.map +1 -0
  33. package/dist/multicall/ethers.d.ts +50 -0
  34. package/dist/multicall/ethers.js +78 -0
  35. package/dist/multicall/ethers.js.map +1 -0
  36. package/dist/multicall/index.d.ts +21 -0
  37. package/dist/multicall/index.js +33 -0
  38. package/dist/multicall/index.js.map +1 -0
  39. package/dist/multicall/viem.d.ts +14 -0
  40. package/dist/multicall/viem.js +32 -0
  41. package/dist/multicall/viem.js.map +1 -0
  42. package/dist/provider/fallback-full.d.ts +124 -0
  43. package/dist/provider/fallback-full.js +629 -0
  44. package/dist/provider/fallback-full.js.map +1 -0
  45. package/dist/provider/fallback.d.ts +37 -0
  46. package/dist/provider/fallback.js +120 -0
  47. package/dist/provider/fallback.js.map +1 -0
  48. package/dist/provider/index.d.ts +7 -0
  49. package/dist/provider/index.js +5 -0
  50. package/dist/provider/index.js.map +1 -0
  51. package/dist/provider/viem-fallback.d.ts +47 -0
  52. package/dist/provider/viem-fallback.js +69 -0
  53. package/dist/provider/viem-fallback.js.map +1 -0
  54. package/dist/transaction/ethers.d.ts +27 -0
  55. package/dist/transaction/ethers.js +97 -0
  56. package/dist/transaction/ethers.js.map +1 -0
  57. package/dist/transaction/index.d.ts +21 -0
  58. package/dist/transaction/index.js +31 -0
  59. package/dist/transaction/index.js.map +1 -0
  60. package/dist/transaction/types.d.ts +46 -0
  61. package/dist/transaction/types.js +21 -0
  62. package/dist/transaction/types.js.map +1 -0
  63. package/dist/transaction/viem.d.ts +29 -0
  64. package/dist/transaction/viem.js +86 -0
  65. package/dist/transaction/viem.js.map +1 -0
  66. package/dist/types.d.ts +18 -0
  67. package/dist/types.js +2 -0
  68. package/dist/types.js.map +1 -0
  69. package/dist/utils.d.ts +59 -0
  70. package/dist/utils.js +140 -0
  71. package/dist/utils.js.map +1 -0
  72. package/package.json +106 -4
@@ -0,0 +1,53 @@
1
+ import { ErrorType } from './enums.js';
2
+ const formatReason = (reason, defaultReason) => (reason && reason.trim() !== '' ? reason : defaultReason);
3
+ const baseErrorResult = (params) => {
4
+ const { type, data, reason, fragment, args, selector, name, signature } = params;
5
+ return {
6
+ type,
7
+ reason: formatReason(reason, null),
8
+ data: data ?? null,
9
+ name: name ?? null,
10
+ selector: selector ?? null,
11
+ signature: signature ?? null,
12
+ args: args ?? null,
13
+ fragment: fragment ?? null,
14
+ };
15
+ };
16
+ export const emptyErrorResult = ({ data, reason }) => baseErrorResult({
17
+ type: ErrorType.EmptyError,
18
+ data,
19
+ reason,
20
+ });
21
+ export const userRejectErrorResult = ({ data = null, reason, }) => baseErrorResult({
22
+ type: ErrorType.UserRejectError,
23
+ reason: formatReason(reason, 'User has rejected the transaction'),
24
+ data,
25
+ });
26
+ export const revertErrorResult = (params) => baseErrorResult({ type: ErrorType.RevertError, ...params });
27
+ export const unknownErrorResult = ({ data, reason, name, }) => baseErrorResult({
28
+ type: ErrorType.UnknownError,
29
+ reason: formatReason(reason, 'Unknown error'),
30
+ data,
31
+ name,
32
+ });
33
+ export const panicErrorResult = (params) => baseErrorResult({ type: ErrorType.PanicError, ...params });
34
+ export const customErrorResult = ({ data, reason, fragment, args, }) => {
35
+ const selector = data && data.length >= 10 ? data.slice(0, 10) : null;
36
+ return baseErrorResult({
37
+ type: ErrorType.CustomError,
38
+ reason: formatReason(reason, `No ABI for custom error ${selector}`),
39
+ data,
40
+ fragment,
41
+ args,
42
+ selector,
43
+ name: fragment?.name ?? selector,
44
+ signature: fragment?.format() ?? null,
45
+ });
46
+ };
47
+ export const rpcErrorResult = ({ reason, name }) => baseErrorResult({
48
+ type: ErrorType.RpcError,
49
+ reason: formatReason(reason, 'Error from JSON RPC provider'),
50
+ data: null,
51
+ name: name?.toString() ?? null,
52
+ });
53
+ //# sourceMappingURL=results.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results.js","sourceRoot":"","sources":["../../src/error-decoder/results.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { ErrorDescription, ErrorFragment, Interface, Result } from 'ethers';
2
+ import { ErrorType } from './enums.js';
3
+ /** Human-friendly decoded error, produced by `ErrorDecoder.decode` / `decodeError`. */
4
+ export type DecodedError = {
5
+ /** Classification of the error. */
6
+ type: ErrorType;
7
+ /** Human-readable reason (decoded string, panic description, or fallback message). */
8
+ reason: string | null;
9
+ /** Raw revert data (`0x...`), if present. */
10
+ data: string | null;
11
+ /** Error name (custom error name, RPC error code, or null). */
12
+ name: string | null;
13
+ /** 4-byte selector `0x........` for custom errors. */
14
+ selector: string | null;
15
+ /** Canonical signature, e.g. `MyError(uint256,address)`. */
16
+ signature: string | null;
17
+ /** Parsed error arguments, when the ABI is known. */
18
+ args: Result | null;
19
+ /** Matched error fragment, when the ABI is known. */
20
+ fragment: ErrorFragment | null;
21
+ /** Full ethers `ErrorDescription` fields when a fragment matched. */
22
+ description?: ErrorDescription;
23
+ };
24
+ export interface ErrorHandlerInput {
25
+ errorInterface?: Interface;
26
+ error: Error;
27
+ }
28
+ export interface ErrorHandler {
29
+ predicate: (data: string | undefined, error: Error) => boolean;
30
+ handle: (data: string | undefined, input: ErrorHandlerInput) => DecodedError;
31
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/error-decoder/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import type { PublicClient } from 'viem';
2
+ import type { AbiLike } from '../types.js';
3
+ import type { DecodedError } from './types.js';
4
+ /**
5
+ * Decode a viem-thrown error (e.g. from `simulateContract`, `readContract`,
6
+ * `call`, `waitForTransactionReceipt`).
7
+ *
8
+ * Unwraps `cause` chains (`CallExecutionError` -> `ContractFunctionRevertedError`),
9
+ * extracts revert data and decodes it with the provided ABIs. Errors without
10
+ * revert data are classified by message (user rejection / plain revert / RPC).
11
+ */
12
+ export declare function decodeViemError(error: unknown, opts?: {
13
+ abis?: ReadonlyArray<AbiLike>;
14
+ }): DecodedError;
15
+ /**
16
+ * Recover the revert reason of a mined reverted transaction for viem clients
17
+ * by replaying it via `publicClient.call`.
18
+ */
19
+ export declare function getRevertReasonViem(client: PublicClient, txHash: `0x${string}`, abis?: ReadonlyArray<AbiLike>): Promise<DecodedError>;
@@ -0,0 +1,47 @@
1
+ import { extractRevertData, getErrorMessage, callRequestFromViem } from '../utils.js';
2
+ import { ErrorDecoder, decodeRevertData } from './decoder.js';
3
+ import { unknownErrorResult } from './results.js';
4
+ /**
5
+ * Decode a viem-thrown error (e.g. from `simulateContract`, `readContract`,
6
+ * `call`, `waitForTransactionReceipt`).
7
+ *
8
+ * Unwraps `cause` chains (`CallExecutionError` -> `ContractFunctionRevertedError`),
9
+ * extracts revert data and decodes it with the provided ABIs. Errors without
10
+ * revert data are classified by message (user rejection / plain revert / RPC).
11
+ */
12
+ export function decodeViemError(error, opts = {}) {
13
+ const revertData = extractRevertData(error);
14
+ const synth = new Error(getErrorMessage(error));
15
+ const code = error?.code;
16
+ if (code != null) {
17
+ synth.code = code;
18
+ }
19
+ return new ErrorDecoder(opts.abis).decodeData(revertData, synth);
20
+ }
21
+ /**
22
+ * Recover the revert reason of a mined reverted transaction for viem clients
23
+ * by replaying it via `publicClient.call`.
24
+ */
25
+ export async function getRevertReasonViem(client, txHash, abis) {
26
+ const receipt = await client.getTransactionReceipt({ hash: txHash });
27
+ if (receipt && receipt.status === 'success') {
28
+ throw new Error('Transaction succeeded — there is no revert reason');
29
+ }
30
+ const tx = await client.getTransaction({ hash: txHash });
31
+ if (!tx) {
32
+ return unknownErrorResult({ reason: 'Transaction not found' });
33
+ }
34
+ const callRequest = callRequestFromViem(tx);
35
+ let data;
36
+ let callError;
37
+ try {
38
+ await client.call({ ...callRequest, blockNumber: receipt?.blockNumber });
39
+ await client.call({ ...callRequest });
40
+ }
41
+ catch (e) {
42
+ data = extractRevertData(e);
43
+ callError = e;
44
+ }
45
+ return decodeRevertData(data, abis, callError);
46
+ }
47
+ //# sourceMappingURL=viem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viem.js","sourceRoot":"","sources":["../../src/error-decoder/viem.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlD;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAc,EACd,OAA0C,EAAE;IAE5C,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,MAAM,IAAI,GAAI,KAAa,EAAE,IAAI,CAAC;IAClC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QAChB,KAAa,CAAC,IAAI,GAAG,IAAI,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AACnE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAoB,EACpB,MAAqB,EACrB,IAA6B;IAE7B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACrE,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,kBAAkB,CAAC,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,WAAW,GAAG,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAC5C,IAAI,IAAwB,CAAC;IAC7B,IAAI,SAA4B,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QACvE,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAC5B,SAAS,GAAG,CAAU,CAAC;IACzB,CAAC;IACD,OAAO,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './types.js';
2
+ export * from './error-decoder/index.js';
3
+ export * from './multicall/index.js';
4
+ export * from './transaction/index.js';
5
+ export * from './provider/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export * from './types.js';
2
+ export * from './error-decoder/index.js';
3
+ export * from './multicall/index.js';
4
+ export * from './transaction/index.js';
5
+ export * from './provider/index.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare const MULTICALL3_ABI: string[];
2
+ /**
3
+ * Multicall3 is deployed at the same deterministic address (CREATE2) on
4
+ * hundreds of chains: https://github.com/mds1/multicall
5
+ */
6
+ export declare const MULTICALL3_CANONICAL = "0xcA11bde05977b3631167028862bE2a173976CA11";
7
+ export declare function multicall3Address(_chainId?: number | bigint): string;
@@ -0,0 +1,27 @@
1
+ export const MULTICALL3_ABI = [
2
+ 'function aggregate((address target, bytes callData)[] calls) payable returns (uint256 blockNumber, bytes[] returnData)',
3
+ 'function tryAggregate(bool requireSuccess, (address target, bytes callData)[] calls) payable returns ((bool success, bytes returnData)[] returnData)',
4
+ 'function aggregate3((address target, bool allowFailure, bytes callData)[] calls) payable returns ((bool success, bytes returnData)[] returnData)',
5
+ 'function aggregate3Value((address target, bool allowFailure, uint256 value, bytes callData)[] calls) payable returns ((bool success, bytes returnData)[] returnData)',
6
+ 'function tryBlockAndAggregate(bool requireSuccess, (address target, bytes callData)[] calls) payable returns (uint256 blockNumber, (bool success, bytes returnData)[] returnData)',
7
+ 'function getBlockHash(uint256 blockNumber) view returns (bytes32 blockHash)',
8
+ 'function getLastBlockHash() view returns (bytes32 blockHash)',
9
+ 'function getCurrentBlockCoinbase() view returns (address coinbase)',
10
+ 'function getCurrentBlockDifficulty() view returns (uint256 difficulty)',
11
+ 'function getCurrentBlockGasLimit() view returns (uint256 gaslimit)',
12
+ 'function getCurrentBlockTimestamp() view returns (uint256 timestamp)',
13
+ 'function getEthBalance(address addr) view returns (uint256 balance)',
14
+ 'function getBasefee() view returns (uint256 basefee)',
15
+ 'function getChainId() view returns (uint256 chainid)',
16
+ ];
17
+ /**
18
+ * Multicall3 is deployed at the same deterministic address (CREATE2) on
19
+ * hundreds of chains: https://github.com/mds1/multicall
20
+ */
21
+ export const MULTICALL3_CANONICAL = '0xcA11bde05977b3631167028862bE2a173976CA11';
22
+ export function multicall3Address(_chainId) {
23
+ // Every known chain ships Multicall3 at the canonical address.
24
+ // Override via the `address` option if you use a custom deployment.
25
+ return MULTICALL3_CANONICAL;
26
+ }
27
+ //# sourceMappingURL=abi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abi.js","sourceRoot":"","sources":["../../src/multicall/abi.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,wHAAwH;IACxH,sJAAsJ;IACtJ,kJAAkJ;IAClJ,sKAAsK;IACtK,mLAAmL;IACnL,6EAA6E;IAC7E,8DAA8D;IAC9D,oEAAoE;IACpE,wEAAwE;IACxE,oEAAoE;IACpE,sEAAsE;IACtE,qEAAqE;IACrE,sDAAsD;IACtD,sDAAsD;CACvD,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,4CAA4C,CAAC;AAEjF,MAAM,UAAU,iBAAiB,CAAC,QAA0B;IAC1D,+DAA+D;IAC/D,oEAAoE;IACpE,OAAO,oBAAoB,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { Interface, type BlockTag, type Provider } from 'ethers';
2
+ import type { AbiLike, CallInput } from '../types.js';
3
+ export interface PreparedCall {
4
+ target: string;
5
+ data: string;
6
+ iface?: Interface;
7
+ method?: string;
8
+ abi?: AbiLike;
9
+ allowFailure?: boolean;
10
+ }
11
+ /** Encode + prepare one call for multicall execution. Shared by ethers/viem backends. */
12
+ export declare function prepareCall(call: CallInput, batchAllowFailure: boolean): PreparedCall;
13
+ /** Decode a per-call return/revert data item. */
14
+ export declare function decodeCallResult(call: PreparedCall, success: boolean, returnData: string): {
15
+ success: boolean;
16
+ returnData: string;
17
+ decoded: undefined;
18
+ error?: undefined;
19
+ } | {
20
+ success: boolean;
21
+ returnData: string;
22
+ decoded: any[];
23
+ error?: undefined;
24
+ } | {
25
+ success: boolean;
26
+ returnData: string;
27
+ error: import("../error-decoder/types.js").DecodedError;
28
+ decoded?: undefined;
29
+ };
30
+ export interface MulticallOptions {
31
+ provider: Provider;
32
+ calls: ReadonlyArray<CallInput>;
33
+ /** If true (default), individual call failures are returned instead of rejecting the whole batch. */
34
+ allowFailure?: boolean;
35
+ blockTag?: BlockTag;
36
+ /** Custom Multicall3 deployment address (defaults to canonical `0xcA11...CA11`). */
37
+ address?: string;
38
+ }
39
+ export interface MulticallResultItem {
40
+ success: boolean;
41
+ returnData: string | null;
42
+ decoded?: unknown;
43
+ error?: unknown;
44
+ }
45
+ export interface MulticallResponse {
46
+ blockNumber: bigint;
47
+ results: MulticallResultItem[];
48
+ }
49
+ /** Multicall for ethers v6 providers via the Multicall3 `aggregate3` entry point. */
50
+ export declare function multicallEth(opts: MulticallOptions): Promise<MulticallResponse>;
@@ -0,0 +1,78 @@
1
+ import { AbiCoder, Interface } from 'ethers';
2
+ import { toInterface } from '../utils.js';
3
+ import { decodeRevertData } from '../error-decoder/index.js';
4
+ import { multicall3Address } from './abi.js';
5
+ const AGGREGATE3 = new Interface([
6
+ 'function aggregate3((address target, bool allowFailure, bytes callData)[] calls) payable returns ((bool success, bytes returnData)[] returnData)',
7
+ ]);
8
+ /** Encode + prepare one call for multicall execution. Shared by ethers/viem backends. */
9
+ export function prepareCall(call, batchAllowFailure) {
10
+ if (call.data == null && !(call.abi != null && call.method != null)) {
11
+ throw new Error(`Call to ${call.target}: provide either "data" or "abi"+"method"`);
12
+ }
13
+ let data = call.data;
14
+ let iface;
15
+ if (call.abi != null && call.method != null) {
16
+ iface = toInterface(call.abi);
17
+ data = iface.encodeFunctionData(call.method, call.args ?? []);
18
+ }
19
+ return {
20
+ target: call.target,
21
+ data,
22
+ iface,
23
+ method: call.method,
24
+ abi: call.abi,
25
+ allowFailure: call.allowFailure ?? batchAllowFailure,
26
+ };
27
+ }
28
+ /** Decode a per-call return/revert data item. */
29
+ export function decodeCallResult(call, success, returnData) {
30
+ if (success) {
31
+ if (!call.iface || !call.method) {
32
+ return { success: true, returnData, decoded: undefined };
33
+ }
34
+ try {
35
+ const decoded = call.iface.decodeFunctionResult(call.method, returnData).toArray();
36
+ return { success: true, returnData, decoded };
37
+ }
38
+ catch {
39
+ // e.g. call to an EOA: success with empty (0x) data
40
+ return { success: true, returnData, decoded: undefined };
41
+ }
42
+ }
43
+ const error = decodeRevertData(returnData, call.abi ? [call.abi] : undefined);
44
+ return { success: false, returnData, error };
45
+ }
46
+ /** Multicall for ethers v6 providers via the Multicall3 `aggregate3` entry point. */
47
+ export async function multicallEth(opts) {
48
+ const { provider, calls, allowFailure = true, blockTag, address } = opts;
49
+ if (calls.length === 0) {
50
+ return { blockNumber: BigInt(await provider.getBlockNumber()), results: [] };
51
+ }
52
+ const prepared = calls.map((c) => prepareCall(c, allowFailure));
53
+ const data = AGGREGATE3.encodeFunctionData('aggregate3', [
54
+ prepared.map((c) => ({
55
+ target: c.target,
56
+ allowFailure: c.allowFailure,
57
+ callData: c.data,
58
+ })),
59
+ ]);
60
+ const resultData = await provider.call({
61
+ to: address ?? multicall3Address(),
62
+ data,
63
+ ...(blockTag != null ? { blockTag } : {}),
64
+ });
65
+ // aggregate3's wire format is canonical; tryBlockAndAggregate (3 outputs)
66
+ // is not reliably decoded by generic ABI decoders.
67
+ const decoded = AbiCoder.defaultAbiCoder().decode(['tuple(bool,bytes)[]'], resultData);
68
+ const items = decoded[0].toArray();
69
+ const results = prepared.map((call, i) => {
70
+ const [success, returnData] = items[i];
71
+ return { ...decodeCallResult(call, success, returnData) };
72
+ });
73
+ const blockNumber = typeof blockTag === 'number' || typeof blockTag === 'bigint'
74
+ ? BigInt(blockTag)
75
+ : BigInt(await provider.getBlockNumber());
76
+ return { blockNumber, results };
77
+ }
78
+ //# sourceMappingURL=ethers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ethers.js","sourceRoot":"","sources":["../../src/multicall/ethers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { Provider } from 'ethers';
2
+ import type { PublicClient as ViemPublicClient } from 'viem';
3
+ import { multicallEth, prepareCall, decodeCallResult, type MulticallOptions, type MulticallResponse, type MulticallResultItem } from './ethers.js';
4
+ import { multicallViem, type MulticallViemOptions } from './viem.js';
5
+ import { MULTICALL3_ABI, MULTICALL3_CANONICAL, multicall3Address } from './abi.js';
6
+ export interface MulticallUnifiedOptions {
7
+ /** ethers v6 provider. */
8
+ provider?: Provider;
9
+ /** viem public client. Takes precedence if both are given. */
10
+ client?: ViemPublicClient;
11
+ calls: ReadonlyArray<import('../types.js').CallInput>;
12
+ allowFailure?: boolean;
13
+ blockTag?: import('ethers').BlockTag;
14
+ blockNumber?: bigint;
15
+ address?: string;
16
+ }
17
+ export declare function isViemClient(x: unknown): x is ViemPublicClient;
18
+ /** Unified multicall entry point: works with an ethers provider or a viem client. */
19
+ export declare function multicall(opts: MulticallUnifiedOptions): Promise<MulticallResponse>;
20
+ export { multicallEth, multicallViem, multicall3Address, MULTICALL3_ABI, MULTICALL3_CANONICAL, prepareCall, decodeCallResult, };
21
+ export type { MulticallOptions, MulticallResponse, MulticallResultItem, MulticallViemOptions };
@@ -0,0 +1,33 @@
1
+ import { multicallEth, prepareCall, decodeCallResult, } from './ethers.js';
2
+ import { multicallViem } from './viem.js';
3
+ import { MULTICALL3_ABI, MULTICALL3_CANONICAL, multicall3Address } from './abi.js';
4
+ export function isViemClient(x) {
5
+ return (typeof x === 'object' &&
6
+ x !== null &&
7
+ 'readContract' in x &&
8
+ 'getTransactionReceipt' in x);
9
+ }
10
+ /** Unified multicall entry point: works with an ethers provider or a viem client. */
11
+ export async function multicall(opts) {
12
+ if (opts.client) {
13
+ return multicallViem({
14
+ client: opts.client,
15
+ calls: opts.calls,
16
+ allowFailure: opts.allowFailure,
17
+ blockNumber: opts.blockNumber,
18
+ address: opts.address,
19
+ });
20
+ }
21
+ if (opts.provider) {
22
+ return multicallEth({
23
+ provider: opts.provider,
24
+ calls: opts.calls,
25
+ allowFailure: opts.allowFailure,
26
+ blockTag: opts.blockTag,
27
+ address: opts.address,
28
+ });
29
+ }
30
+ throw new Error('multicall: provide either `provider` (ethers) or `client` (viem)');
31
+ }
32
+ export { multicallEth, multicallViem, multicall3Address, MULTICALL3_ABI, MULTICALL3_CANONICAL, prepareCall, decodeCallResult, };
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/multicall/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,WAAW,EACX,gBAAgB,GAIjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAA6B,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAcnF,MAAM,UAAU,YAAY,CAAC,CAAU;IACrC,OAAO,CACL,OAAO,CAAC,KAAK,QAAQ;QACrB,CAAC,KAAK,IAAI;QACV,cAAc,IAAI,CAAC;QACnB,uBAAuB,IAAI,CAAC,CAC7B,CAAC;AACJ,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAA6B;IAE7B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO,aAAa,CAAC;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;IACL,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,OAAO,YAAY,CAAC;YAClB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;AACtF,CAAC;AAED,OAAO,EACL,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,WAAW,EACX,gBAAgB,GACjB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { type PublicClient } from 'viem';
2
+ import type { CallInput } from '../types.js';
3
+ import { type MulticallResponse } from './ethers.js';
4
+ export interface MulticallViemOptions {
5
+ client: PublicClient;
6
+ calls: ReadonlyArray<CallInput>;
7
+ /** If true (default), individual call failures are returned instead of rejecting the whole batch. */
8
+ allowFailure?: boolean;
9
+ blockNumber?: bigint;
10
+ /** Custom Multicall3 deployment address (defaults to canonical `0xcA11...CA11`). */
11
+ address?: string;
12
+ }
13
+ /** Multicall for viem clients via the Multicall3 `aggregate3` entry point. */
14
+ export declare function multicallViem(opts: MulticallViemOptions): Promise<MulticallResponse>;
@@ -0,0 +1,32 @@
1
+ import { parseAbi } from 'viem';
2
+ import { decodeCallResult, prepareCall } from './ethers.js';
3
+ import { multicall3Address } from './abi.js';
4
+ const AGGREGATE3 = parseAbi([
5
+ 'function aggregate3((address target, bool allowFailure, bytes callData)[] calls) payable returns ((bool success, bytes returnData)[] returnData)',
6
+ ]);
7
+ /** Multicall for viem clients via the Multicall3 `aggregate3` entry point. */
8
+ export async function multicallViem(opts) {
9
+ const { client, calls, allowFailure = true, blockNumber, address } = opts;
10
+ if (calls.length === 0) {
11
+ return { blockNumber: await client.getBlockNumber(), results: [] };
12
+ }
13
+ const prepared = calls.map((c) => prepareCall(c, allowFailure));
14
+ const callsArg = prepared.map((c) => ({
15
+ target: c.target,
16
+ allowFailure: c.allowFailure,
17
+ callData: c.data,
18
+ }));
19
+ const items = (await client.readContract({
20
+ address: (address ?? multicall3Address()),
21
+ abi: AGGREGATE3,
22
+ functionName: 'aggregate3',
23
+ args: [callsArg],
24
+ blockNumber,
25
+ }));
26
+ const results = prepared.map((call, i) => {
27
+ const item = items[i];
28
+ return { ...decodeCallResult(call, item.success, item.returnData) };
29
+ });
30
+ return { blockNumber: blockNumber ?? (await client.getBlockNumber()), results };
31
+ }
32
+ //# sourceMappingURL=viem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viem.js","sourceRoot":"","sources":["../../src/multicall/viem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAA+B,MAAM,MAAM,CAAC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAoD,MAAM,aAAa,CAAC;AAC9G,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,UAAU,GAAG,QAAQ,CAAC;IAC1B,kJAAkJ;CACnJ,CAAC,CAAC;AAYH,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAA0B;IAC5D,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC1E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpC,MAAM,EAAE,CAAC,CAAC,MAAa;QACvB,YAAY,EAAE,CAAC,CAAC,YAAa;QAC7B,QAAQ,EAAE,CAAC,CAAC,IAAW;KACxB,CAAC,CAAC,CAAC;IAEJ,MAAM,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC;QACvC,OAAO,EAAE,CAAC,OAAO,IAAI,iBAAiB,EAAE,CAAQ;QAChD,GAAG,EAAE,UAAU;QACf,YAAY,EAAE,YAAY;QAC1B,IAAI,EAAE,CAAC,QAAQ,CAAC;QAChB,WAAW;KACZ,CAAC,CAA+D,CAAC;IAElE,MAAM,OAAO,GAA0B,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QAC9D,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,OAAO,EAAE,GAAG,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,EAAyB,CAAC;IAC7F,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,WAAW,EAAE,WAAW,IAAI,CAAC,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;AAClF,CAAC"}
@@ -0,0 +1,124 @@
1
+ import { JsonRpcApiProvider, Network, type JsonRpcApiProviderOptions, type JsonRpcError, type JsonRpcPayload, type JsonRpcResult, type Networkish } from 'ethers';
2
+ export declare enum FallbackProviderError {
3
+ NO_PROVIDER = "At least one provider must be provided",
4
+ CANNOT_DETECT_NETWORKS = "Could not detect providers networks",
5
+ INCONSISTENT_NETWORKS = "All providers must be connected to the same network",
6
+ DESTROYED = "Provider has been destroyed",
7
+ ALL_PROVIDERS_UNAVAILABLE = "All providers are unavailable",
8
+ HALTED = "Chain has halted",
9
+ INVALID_FALLBACK_OPTIONS = "Invalid fallback options",
10
+ BLOCK_NUMBER_STORAGE_CONFIG_ERROR = "Both getStoredBlockNumber and setStoredBlockNumber must be provided or neither",
11
+ FAILED_TO_GET_BLOCKNUMBER = "Failed to get block number"
12
+ }
13
+ export declare const DEFAULT_RETRIES = 0;
14
+ export declare const DEFAULT_TIMEOUT = 3000;
15
+ export declare const RETRY_DELAY = 100;
16
+ export declare const ALWAYS_SUPPORTED_METHODS: readonly string[];
17
+ export interface ProviderConfig {
18
+ provider: JsonRpcApiProvider;
19
+ retries?: number;
20
+ timeout?: number;
21
+ retryDelay?: number;
22
+ id?: string;
23
+ isMevProtected?: boolean;
24
+ /** The JSON-RPC methods this provider is allowed to serve, matched exactly. */
25
+ supportedMethods?: string[];
26
+ /** The JSON-RPC methods this provider must not serve (takes precedence over supportedMethods). */
27
+ unsupportedMethods?: string[];
28
+ /** Gets the stored block number when conducting a liveliness check (shared cache). */
29
+ getStoredBlockNumber?: () => Promise<number | null>;
30
+ /** Sets the stored block number when conducting a liveliness check. */
31
+ setStoredBlockNumber?: (blockNumber: number) => Promise<void>;
32
+ }
33
+ export interface LoggingOptions {
34
+ debug?: (message: string, metadata?: any) => void;
35
+ info?: (message: string, metadata?: any) => void;
36
+ notice?: (message: string, metadata?: any) => void;
37
+ warn?: (message: string, metadata?: any) => void;
38
+ error?: (message: string, metadata?: any) => void;
39
+ }
40
+ export type FallbackProviderOptions = {
41
+ /** Maximum block lag allowed for the provider to be considered valid, measured against the median block number. */
42
+ allowableBlockLag?: number;
43
+ /**
44
+ * If the median block number is not updated for this amount of time, the chain is considered halted and calls will
45
+ * throw. Denominated in seconds. 0 disables halt detection. Default: 300 (5 minutes).
46
+ */
47
+ haltDetectionTime?: number;
48
+ /** Interval for the liveliness check of the chain and providers, in ms. 0 disables. Default: 0. */
49
+ livelinessPollingInterval?: number;
50
+ /** Hook to get the time at which a block was first discovered (UNIX epoch seconds), or null if unknown. */
51
+ getBlockDiscoveryTime?: (blockNumber: number) => Promise<number | null>;
52
+ /** Hook to set the time at which a block was first discovered; null clears it. */
53
+ setBlockDiscoveryTime?: (blockNumber: number, currentTime: number | null) => Promise<void>;
54
+ /** If true, signed transactions are broadcast to all active providers. Default: false. */
55
+ broadcastToAll?: boolean;
56
+ broadcastToAllConfig?: {
57
+ /** Delay in ms between broadcasting to each provider. Default: 0. */
58
+ delay?: number;
59
+ /** Max random jitter (ms) added to the delay. Default: 0. */
60
+ delayJitter?: number;
61
+ };
62
+ /** If true, signed transactions are only broadcast to MEV-protected providers. Default: false. */
63
+ broadcastOnlyToMevProtected?: boolean;
64
+ /**
65
+ * If true, the provider throws on the first blockchain error it encounters
66
+ * (CALL_EXCEPTION, INSUFFICIENT_FUNDS, NONCE_EXPIRED, ...). Default: true.
67
+ */
68
+ throwOnFirstBlockchainError?: boolean;
69
+ };
70
+ export declare const DEFAULT_FALLBACK_OPTIONS: Required<Pick<FallbackProviderOptions, 'allowableBlockLag' | 'haltDetectionTime' | 'livelinessPollingInterval' | 'broadcastToAll' | 'broadcastOnlyToMevProtected' | 'throwOnFirstBlockchainError'>>;
71
+ export declare function isBlockchainError(e: any): boolean;
72
+ export declare function isAlreadyKnownError(e: any): boolean;
73
+ export declare const providerSupportsMethod: (config: ProviderConfig, method: string) => boolean;
74
+ export declare const filterProvidersByMethod: (providers: ProviderConfig[], method: string) => ProviderConfig[];
75
+ export declare const filterValidProviders: (providers: ProviderConfig[]) => Promise<{
76
+ network: Network;
77
+ providers: ProviderConfig[];
78
+ }>;
79
+ export declare function getBlockNumberWithTimeout(provider: JsonRpcApiProvider, timeout?: number): Promise<number>;
80
+ export declare function getBlockNumber(providerConfig: ProviderConfig): Promise<number>;
81
+ export declare const getBlockNumbersAndMedian: (providers: ProviderConfig[], logging?: LoggingOptions) => Promise<{
82
+ blockNumbers: ({
83
+ blockNumber: number;
84
+ fromCache: boolean;
85
+ } | null)[];
86
+ median: number;
87
+ }>;
88
+ /**
89
+ * Full-featured RPC fallback provider for ethers v6, ported from
90
+ * `ethers-v6-fallback-provider`.
91
+ *
92
+ * Features: per-provider retries/timeouts, provider failover, liveliness
93
+ * polling with median block-number lag filtering, chain halt detection,
94
+ * JSON-RPC method capability filtering, transaction broadcast to all /
95
+ * MEV-protected-only providers, and blockchain-vs-transport error
96
+ * classification (blockchain errors are never retried on another RPC).
97
+ */
98
+ export declare class FallbackProvider extends JsonRpcApiProvider {
99
+ #private;
100
+ constructor(providers: ProviderConfig[], network?: Networkish, options?: JsonRpcApiProviderOptions, loggingOptions?: LoggingOptions, fallbackOptions?: FallbackProviderOptions);
101
+ activeProvidersCount(): number;
102
+ activeProviderIds(): string[];
103
+ isHalted(): boolean;
104
+ /** Runs the liveliness check on demand (also runs automatically when polling is enabled). */
105
+ refreshLiveliness(): Promise<void>;
106
+ private _validateFallbackOptions;
107
+ private sendWithProvider;
108
+ send(method: string, params: {
109
+ [name: string]: any;
110
+ }): Promise<any>;
111
+ _send(payload: JsonRpcPayload | Array<JsonRpcPayload>): Promise<Array<JsonRpcResult | JsonRpcError>>;
112
+ _detectNetwork(): Promise<Network>;
113
+ /**
114
+ * Gets the time at which a block was first discovered.
115
+ */
116
+ private _getBlockDiscoveryTime;
117
+ /**
118
+ * Sets the time at which a block was first discovered.
119
+ */
120
+ private _setBlockDiscoveryTime;
121
+ private _livelinessCheck;
122
+ _start(): void;
123
+ destroy(): void;
124
+ }