@pancakeswap/multicall 2.0.0 → 3.0.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.
package/dist/index.mjs CHANGED
@@ -1,328 +1,298 @@
1
- import { Interface } from '@ethersproject/abi';
2
- import { Contract } from '@ethersproject/contracts';
3
1
  import { ChainId } from '@pancakeswap/sdk';
2
+ import { getContract } from 'viem';
4
3
 
5
- // index.ts
4
+ // ../utils/toBigInt.ts
5
+ function toBigInt(num) {
6
+ return BigInt(num.toString());
7
+ }
8
+ var MULTICALL_ADDRESS = {
9
+ [ChainId.ZKSYNC]: "0x95071cBD09184083E7F732a710c2e30c9882Fd5f",
10
+ [ChainId.BSC]: "0x39eecaE833c944ebb94942Fa44CaE46e87a8Da17",
11
+ [ChainId.ETHEREUM]: "0xC0916D7E360c31D5F6D0c497E6a36B7B0E80e3cf",
12
+ [ChainId.ARBITRUM_ONE]: "0xbFfE39cDD04f0183e0493c1Deb6E275c5cf84AdF",
13
+ [ChainId.POLYGON_ZKEVM]: "0xe05b539447B17630Cb087473F6b50E5c5f73FDeb",
14
+ [ChainId.LINEA]: "0x6E6B30d65D605DAa4CaC65eB270100Ecca36b140",
15
+ [ChainId.BASE]: "0x3EFaAb8D7A631cfF5ccF5f149d1Bbb3B5bfda2C0",
16
+ // Testnets
17
+ [ChainId.BSC_TESTNET]: "0xeeF6ff30cF5D5b8aBA0DE16A01d17A0697a275b5",
18
+ [ChainId.GOERLI]: "0xD55CAFAB2Ffa1139Be46bc5C0b8259c620050dFC",
19
+ [ChainId.ARBITRUM_GOERLI]: "0xe12a5c707Fb528acbE6117b20AF1f7c20b0A8077",
20
+ [ChainId.POLYGON_ZKEVM_TESTNET]: "0x236e713bFF45adb30e25D1c29A887aBCb0Ea7E21",
21
+ [ChainId.ZKSYNC_TESTNET]: "0x8A23CB45E5F4d5a1b2DB673663Ea2aAedc48acff",
22
+ [ChainId.LINEA_TESTNET]: "0x990010b6DBA3e7faa025790bC0433A9f690c65F3",
23
+ [ChainId.BASE_TESTNET]: "0x6F7f93D929d6FBaF16c245e42846EF21aee23437",
24
+ [ChainId.OPBNB_TESTNET]: "0x6A70ED893D85cf6D4059e1CF3e63a48e4D204D32",
25
+ [ChainId.SCROLL_SEPOLIA]: "0x052a99849Ef2e13a5CB28275862991671D4b6fF5"
26
+ };
27
+ var DEFAULT_BLOCK_CONFLICT_TOLERANCE = 0;
28
+ var BLOCK_CONFLICT_TOLERANCE = {
29
+ [ChainId.BSC]: 3,
30
+ [ChainId.ETHEREUM]: 1,
31
+ [ChainId.ARBITRUM_ONE]: 5,
32
+ [ChainId.POLYGON_ZKEVM]: 1,
33
+ [ChainId.ZKSYNC]: 3,
34
+ [ChainId.LINEA]: 3,
35
+ [ChainId.BASE]: 3,
36
+ // Testnets
37
+ [ChainId.BSC_TESTNET]: 3,
38
+ [ChainId.GOERLI]: 1,
39
+ [ChainId.ARBITRUM_GOERLI]: 5,
40
+ [ChainId.POLYGON_ZKEVM_TESTNET]: 1,
41
+ [ChainId.ZKSYNC_TESTNET]: 3,
42
+ [ChainId.LINEA_TESTNET]: 3,
43
+ [ChainId.OPBNB_TESTNET]: 3,
44
+ [ChainId.BASE_TESTNET]: 3,
45
+ [ChainId.SCROLL_SEPOLIA]: 3
46
+ };
47
+ var DEFAULT_GAS_LIMIT = 150000000n;
48
+ var DEFAULT_GAS_LIMIT_BY_CHAIN = {
49
+ [ChainId.BSC]: 100000000n,
50
+ [ChainId.ZKSYNC]: 500000000n,
51
+ [ChainId.POLYGON_ZKEVM]: 1500000n
52
+ };
53
+ var DEFAULT_GAS_BUFFER = 3000000n;
54
+ var DEFAULT_GAS_BUFFER_BY_CHAIN = {
55
+ [ChainId.BSC]: DEFAULT_GAS_BUFFER,
56
+ [ChainId.POLYGON_ZKEVM]: 0n
57
+ };
6
58
 
7
- // Multicall.json
8
- var Multicall_default = [
9
- {
10
- inputs: [
11
- {
12
- components: [
13
- { internalType: "address", name: "target", type: "address" },
14
- { internalType: "bytes", name: "callData", type: "bytes" }
15
- ],
16
- internalType: "struct Multicall3.Call[]",
17
- name: "calls",
18
- type: "tuple[]"
19
- }
20
- ],
21
- name: "aggregate",
22
- outputs: [
23
- { internalType: "uint256", name: "blockNumber", type: "uint256" },
24
- { internalType: "bytes[]", name: "returnData", type: "bytes[]" }
25
- ],
26
- stateMutability: "payable",
27
- type: "function"
28
- },
29
- {
30
- inputs: [
31
- {
32
- components: [
33
- { internalType: "address", name: "target", type: "address" },
34
- { internalType: "bool", name: "allowFailure", type: "bool" },
35
- { internalType: "bytes", name: "callData", type: "bytes" }
36
- ],
37
- internalType: "struct Multicall3.Call3[]",
38
- name: "calls",
39
- type: "tuple[]"
40
- }
41
- ],
42
- name: "aggregate3",
43
- outputs: [
44
- {
45
- components: [
46
- { internalType: "bool", name: "success", type: "bool" },
47
- { internalType: "bytes", name: "returnData", type: "bytes" }
48
- ],
49
- internalType: "struct Multicall3.Result[]",
50
- name: "returnData",
51
- type: "tuple[]"
52
- }
53
- ],
54
- stateMutability: "payable",
55
- type: "function"
56
- },
57
- {
58
- inputs: [
59
- {
60
- components: [
61
- { internalType: "address", name: "target", type: "address" },
62
- { internalType: "bool", name: "allowFailure", type: "bool" },
63
- { internalType: "uint256", name: "value", type: "uint256" },
64
- { internalType: "bytes", name: "callData", type: "bytes" }
65
- ],
66
- internalType: "struct Multicall3.Call3Value[]",
67
- name: "calls",
68
- type: "tuple[]"
69
- }
70
- ],
71
- name: "aggregate3Value",
72
- outputs: [
73
- {
74
- components: [
75
- { internalType: "bool", name: "success", type: "bool" },
76
- { internalType: "bytes", name: "returnData", type: "bytes" }
77
- ],
78
- internalType: "struct Multicall3.Result[]",
79
- name: "returnData",
80
- type: "tuple[]"
81
- }
82
- ],
83
- stateMutability: "payable",
84
- type: "function"
85
- },
86
- {
87
- inputs: [
88
- {
89
- components: [
90
- { internalType: "address", name: "target", type: "address" },
91
- { internalType: "bytes", name: "callData", type: "bytes" }
92
- ],
93
- internalType: "struct Multicall3.Call[]",
94
- name: "calls",
95
- type: "tuple[]"
96
- }
97
- ],
98
- name: "blockAndAggregate",
99
- outputs: [
100
- { internalType: "uint256", name: "blockNumber", type: "uint256" },
101
- { internalType: "bytes32", name: "blockHash", type: "bytes32" },
102
- {
103
- components: [
104
- { internalType: "bool", name: "success", type: "bool" },
105
- { internalType: "bytes", name: "returnData", type: "bytes" }
106
- ],
107
- internalType: "struct Multicall3.Result[]",
108
- name: "returnData",
109
- type: "tuple[]"
110
- }
111
- ],
112
- stateMutability: "payable",
113
- type: "function"
114
- },
115
- {
116
- inputs: [],
117
- name: "getBasefee",
118
- outputs: [{ internalType: "uint256", name: "basefee", type: "uint256" }],
119
- stateMutability: "view",
120
- type: "function"
121
- },
122
- {
123
- inputs: [{ internalType: "uint256", name: "blockNumber", type: "uint256" }],
124
- name: "getBlockHash",
125
- outputs: [{ internalType: "bytes32", name: "blockHash", type: "bytes32" }],
126
- stateMutability: "view",
127
- type: "function"
128
- },
129
- {
130
- inputs: [],
131
- name: "getBlockNumber",
132
- outputs: [{ internalType: "uint256", name: "blockNumber", type: "uint256" }],
133
- stateMutability: "view",
134
- type: "function"
135
- },
136
- {
137
- inputs: [],
138
- name: "getChainId",
139
- outputs: [{ internalType: "uint256", name: "chainid", type: "uint256" }],
140
- stateMutability: "view",
141
- type: "function"
142
- },
143
- {
144
- inputs: [],
145
- name: "getCurrentBlockCoinbase",
146
- outputs: [{ internalType: "address", name: "coinbase", type: "address" }],
147
- stateMutability: "view",
148
- type: "function"
149
- },
150
- {
151
- inputs: [],
152
- name: "getCurrentBlockDifficulty",
153
- outputs: [{ internalType: "uint256", name: "difficulty", type: "uint256" }],
154
- stateMutability: "view",
155
- type: "function"
156
- },
157
- {
158
- inputs: [],
159
- name: "getCurrentBlockGasLimit",
160
- outputs: [{ internalType: "uint256", name: "gaslimit", type: "uint256" }],
161
- stateMutability: "view",
162
- type: "function"
163
- },
59
+ // src/abis/IMulticall.ts
60
+ var iMulticallABI = [
164
61
  {
165
62
  inputs: [],
166
- name: "getCurrentBlockTimestamp",
167
- outputs: [{ internalType: "uint256", name: "timestamp", type: "uint256" }],
168
- stateMutability: "view",
169
- type: "function"
170
- },
171
- {
172
- inputs: [{ internalType: "address", name: "addr", type: "address" }],
173
- name: "getEthBalance",
174
- outputs: [{ internalType: "uint256", name: "balance", type: "uint256" }],
63
+ name: "gasLeft",
64
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
175
65
  stateMutability: "view",
176
66
  type: "function"
177
67
  },
178
68
  {
179
69
  inputs: [],
180
- name: "getLastBlockHash",
181
- outputs: [{ internalType: "bytes32", name: "blockHash", type: "bytes32" }],
70
+ name: "gaslimit",
71
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
182
72
  stateMutability: "view",
183
73
  type: "function"
184
74
  },
185
75
  {
186
76
  inputs: [
187
- { internalType: "bool", name: "requireSuccess", type: "bool" },
188
77
  {
189
78
  components: [
190
79
  { internalType: "address", name: "target", type: "address" },
80
+ { internalType: "uint256", name: "gasLimit", type: "uint256" },
191
81
  { internalType: "bytes", name: "callData", type: "bytes" }
192
82
  ],
193
- internalType: "struct Multicall3.Call[]",
83
+ internalType: "struct MultiCallV2.Call[]",
194
84
  name: "calls",
195
85
  type: "tuple[]"
196
86
  }
197
87
  ],
198
- name: "tryAggregate",
88
+ name: "multicall",
199
89
  outputs: [
90
+ { internalType: "uint256", name: "blockNumber", type: "uint256" },
200
91
  {
201
92
  components: [
202
93
  { internalType: "bool", name: "success", type: "bool" },
94
+ { internalType: "uint256", name: "gasUsed", type: "uint256" },
203
95
  { internalType: "bytes", name: "returnData", type: "bytes" }
204
96
  ],
205
- internalType: "struct Multicall3.Result[]",
97
+ internalType: "struct MultiCallV2.Result[]",
206
98
  name: "returnData",
207
99
  type: "tuple[]"
208
100
  }
209
101
  ],
210
- stateMutability: "payable",
102
+ stateMutability: "nonpayable",
211
103
  type: "function"
212
104
  },
213
105
  {
214
106
  inputs: [
215
- { internalType: "bool", name: "requireSuccess", type: "bool" },
216
107
  {
217
108
  components: [
218
109
  { internalType: "address", name: "target", type: "address" },
110
+ { internalType: "uint256", name: "gasLimit", type: "uint256" },
219
111
  { internalType: "bytes", name: "callData", type: "bytes" }
220
112
  ],
221
- internalType: "struct Multicall3.Call[]",
113
+ internalType: "struct MultiCallV2.Call[]",
222
114
  name: "calls",
223
115
  type: "tuple[]"
224
- }
116
+ },
117
+ { internalType: "uint256", name: "gasBuffer", type: "uint256" }
225
118
  ],
226
- name: "tryBlockAndAggregate",
119
+ name: "multicallWithGasLimitation",
227
120
  outputs: [
228
121
  { internalType: "uint256", name: "blockNumber", type: "uint256" },
229
- { internalType: "bytes32", name: "blockHash", type: "bytes32" },
230
122
  {
231
123
  components: [
232
124
  { internalType: "bool", name: "success", type: "bool" },
125
+ { internalType: "uint256", name: "gasUsed", type: "uint256" },
233
126
  { internalType: "bytes", name: "returnData", type: "bytes" }
234
127
  ],
235
- internalType: "struct Multicall3.Result[]",
128
+ internalType: "struct MultiCallV2.Result[]",
236
129
  name: "returnData",
237
130
  type: "tuple[]"
238
- }
131
+ },
132
+ { internalType: "uint256", name: "lastSuccessIndex", type: "uint256" }
239
133
  ],
240
- stateMutability: "payable",
134
+ stateMutability: "nonpayable",
241
135
  type: "function"
242
136
  }
243
137
  ];
244
138
 
245
- // index.ts
246
- var multicallAddresses = {
247
- 1: "0xcA11bde05977b3631167028862bE2a173976CA11",
248
- 4: "0xcA11bde05977b3631167028862bE2a173976CA11",
249
- 5: "0xcA11bde05977b3631167028862bE2a173976CA11",
250
- 56: "0xcA11bde05977b3631167028862bE2a173976CA11",
251
- 97: "0xcA11bde05977b3631167028862bE2a173976CA11"
252
- };
253
- var getMulticallContract = (chainId, provider) => {
254
- if (multicallAddresses[chainId]) {
255
- return new Contract(multicallAddresses[chainId], Multicall_default, provider);
139
+ // src/getMulticallContract.ts
140
+ function getMulticallContract({
141
+ chainId,
142
+ client
143
+ }) {
144
+ const address = MULTICALL_ADDRESS[chainId];
145
+ if (!address) {
146
+ throw new Error(`PancakeMulticall not supported on chain ${chainId}`);
256
147
  }
257
- return null;
258
- };
259
- function createMulticall(provider) {
260
- const multicall = async (abi, calls, chainId = ChainId.BSC) => {
261
- const multi = getMulticallContract(chainId, provider({ chainId }));
262
- if (!multi)
263
- throw new Error(`Multicall Provider missing for ${chainId}`);
264
- const itf = new Interface(abi);
265
- const calldata = calls.map((call) => ({
266
- target: call.address.toLowerCase(),
267
- callData: itf.encodeFunctionData(call.name, call.params)
268
- }));
269
- const { returnData } = await multi.callStatic.aggregate(calldata);
270
- const res = returnData.map((call, i) => itf.decodeFunctionResult(calls[i].name, call));
271
- return res;
272
- };
273
- const multicallv2 = async ({ abi, calls, chainId = ChainId.BSC, options, provider: _provider }) => {
274
- const { requireSuccess = true, ...overrides } = options || {};
275
- const multi = getMulticallContract(chainId, _provider || provider({ chainId }));
276
- if (!multi)
277
- throw new Error(`Multicall Provider missing for ${chainId}`);
278
- const itf = new Interface(abi);
279
- const calldata = calls.map((call) => ({
280
- target: call.address.toLowerCase(),
281
- callData: itf.encodeFunctionData(call.name, call.params)
282
- }));
283
- const returnData = await multi.callStatic.tryAggregate(requireSuccess, calldata, overrides);
284
- const res = returnData.map((call, i) => {
285
- const [result, data] = call;
286
- return result && data !== "0x" ? itf.decodeFunctionResult(calls[i].name, data) : null;
287
- });
288
- return res;
148
+ return getContract({ abi: iMulticallABI, address, publicClient: client });
149
+ }
150
+
151
+ // src/getGasLimit.ts
152
+ function getDefaultGasLimit(chainId) {
153
+ const gasLimitOnChain = chainId && DEFAULT_GAS_LIMIT_BY_CHAIN[chainId];
154
+ return gasLimitOnChain !== void 0 ? gasLimitOnChain : DEFAULT_GAS_LIMIT;
155
+ }
156
+ function getDefaultGasBuffer(chainId) {
157
+ const gasBufferOnChain = chainId && DEFAULT_GAS_BUFFER_BY_CHAIN[chainId];
158
+ return gasBufferOnChain !== void 0 ? gasBufferOnChain : DEFAULT_GAS_BUFFER;
159
+ }
160
+ async function getGasLimitOnChain({ chainId, client }) {
161
+ const multicall = getMulticallContract({ chainId, client });
162
+ const gasLeft = await multicall.read.gasLeft();
163
+ return gasLeft;
164
+ }
165
+ async function getGasLimit({
166
+ chainId,
167
+ gasLimit: gasLimitInput,
168
+ maxGasLimit: maxGasLimitInput = getDefaultGasLimit(chainId),
169
+ gasBuffer: gasBufferInput = getDefaultGasBuffer(chainId),
170
+ client
171
+ }) {
172
+ const gasLimitOverride = gasLimitInput && toBigInt(gasLimitInput);
173
+ const maxGasLimit = toBigInt(maxGasLimitInput);
174
+ const gasBuffer = toBigInt(gasBufferInput);
175
+ const gasLimit = gasLimitOverride || await getGasLimitOnChain({ chainId, client }) || maxGasLimit;
176
+ const minGasLimit = gasLimit < maxGasLimit ? gasLimit : maxGasLimit;
177
+ return minGasLimit - gasBuffer;
178
+ }
179
+
180
+ // src/getBlockConflictTolerance.ts
181
+ function getBlockConflictTolerance(chainId) {
182
+ return BLOCK_CONFLICT_TOLERANCE[chainId] || DEFAULT_BLOCK_CONFLICT_TOLERANCE;
183
+ }
184
+
185
+ // src/multicall.ts
186
+ async function multicallByGasLimit(calls, { chainId, gasBuffer = getDefaultGasBuffer(chainId), client, ...rest }) {
187
+ const gasLimit = await getGasLimit({
188
+ chainId,
189
+ gasBuffer,
190
+ client,
191
+ ...rest
192
+ });
193
+ const callChunks = splitCallsIntoChunks(calls, gasLimit);
194
+ return callByChunks(callChunks, { gasBuffer, client, chainId });
195
+ }
196
+ function formatCallReturn([blockNumber, results, successIndex]) {
197
+ const lastSuccessIndex = Number(successIndex);
198
+ return {
199
+ lastSuccessIndex,
200
+ blockNumber,
201
+ results: results.slice(0, lastSuccessIndex + 1).map(({ gasUsed, success, returnData }) => ({
202
+ gasUsed,
203
+ success,
204
+ result: returnData
205
+ }))
289
206
  };
290
- const multicallv3 = async ({ calls, chainId = ChainId.BSC, allowFailure, overrides }) => {
291
- const multi = getMulticallContract(chainId, provider({ chainId }));
292
- if (!multi)
293
- throw new Error(`Multicall Provider missing for ${chainId}`);
294
- const interfaceCache = /* @__PURE__ */ new WeakMap();
295
- const _calls = calls.map(({ abi, address, name, params, allowFailure: _allowFailure }) => {
296
- let itf = interfaceCache.get(abi);
297
- if (!itf) {
298
- itf = new Interface(abi);
299
- interfaceCache.set(abi, itf);
300
- }
301
- if (!itf.fragments.some((fragment) => fragment.name === name))
302
- console.error(`${name} missing on ${address}`);
303
- const callData = itf.encodeFunctionData(name, params ?? []);
304
- return {
305
- target: address.toLowerCase(),
306
- allowFailure: allowFailure || _allowFailure,
307
- callData
308
- };
309
- });
310
- const result = await multi.callStatic.aggregate3(_calls, ...overrides ? [overrides] : []);
311
- return result.map((call, i) => {
312
- const { returnData, success } = call;
313
- if (!success || returnData === "0x")
314
- return null;
315
- const { abi, name } = calls[i];
316
- const itf = interfaceCache.get(abi);
317
- const decoded = itf == null ? void 0 : itf.decodeFunctionResult(name, returnData);
318
- return decoded;
319
- });
207
+ }
208
+ async function call(calls, params) {
209
+ const {
210
+ chainId,
211
+ client,
212
+ gasBuffer = getDefaultGasBuffer(chainId),
213
+ blockConflictTolerance = getBlockConflictTolerance(chainId)
214
+ } = params;
215
+ if (!calls.length) {
216
+ return {
217
+ results: [],
218
+ blockNumber: 0n
219
+ };
220
+ }
221
+ const contract = getMulticallContract({ chainId, client });
222
+ const { result } = await contract.simulate.multicallWithGasLimitation([calls, gasBuffer]);
223
+ const { results, lastSuccessIndex, blockNumber } = formatCallReturn(result);
224
+ if (lastSuccessIndex === calls.length - 1) {
225
+ return {
226
+ results,
227
+ blockNumber
228
+ };
229
+ }
230
+ console.warn(
231
+ `Gas limit reached. Total num of ${calls.length} calls. First ${lastSuccessIndex + 1} calls executed. The remaining ${calls.length - lastSuccessIndex - 1} calls are not executed. Pls try adjust the gas limit per call.`
232
+ );
233
+ const { results: remainingResults, blockNumber: nextBlockNumber } = await call(
234
+ calls.slice(lastSuccessIndex + 1),
235
+ params
236
+ );
237
+ if (Number(nextBlockNumber - blockNumber) > blockConflictTolerance) {
238
+ throw new Error(
239
+ `Multicall failed because of block conflict. Latest calls are made at block ${nextBlockNumber} while last calls made at block ${blockNumber}. Block conflict tolerance is ${blockConflictTolerance}`
240
+ );
241
+ }
242
+ return {
243
+ results: [...results, ...remainingResults],
244
+ // Use the latest block number
245
+ blockNumber: nextBlockNumber
320
246
  };
247
+ }
248
+ async function callByChunks(chunks, params) {
249
+ const { blockConflictTolerance = getBlockConflictTolerance(params.chainId) } = params;
250
+ const callReturns = await Promise.all(chunks.map((chunk) => call(chunk, params)));
251
+ let minBlock = 0n;
252
+ let maxBlock = 0n;
253
+ let results = [];
254
+ for (const { results: callResults, blockNumber } of callReturns) {
255
+ if (minBlock === 0n || blockNumber < minBlock) {
256
+ minBlock = blockNumber;
257
+ }
258
+ if (blockNumber > maxBlock) {
259
+ maxBlock = blockNumber;
260
+ }
261
+ if (Number(maxBlock - minBlock) > blockConflictTolerance) {
262
+ throw new Error(
263
+ `Multicall failed because of block conflict. Min block is ${minBlock} while max block is ${maxBlock}. Block conflict tolerance is ${blockConflictTolerance}`
264
+ );
265
+ }
266
+ results = [...results, ...callResults];
267
+ }
321
268
  return {
322
- multicall,
323
- multicallv2,
324
- multicallv3
269
+ results,
270
+ blockNumber: maxBlock
325
271
  };
326
272
  }
273
+ function splitCallsIntoChunks(calls, gasLimit) {
274
+ const chunks = [[]];
275
+ let gasLeft = gasLimit;
276
+ for (const callRequest of calls) {
277
+ const { target, callData, gasLimit: gasCostLimit } = callRequest;
278
+ const singleGasLimit = toBigInt(gasCostLimit);
279
+ const currentChunk = chunks[chunks.length - 1];
280
+ if (singleGasLimit > gasLeft) {
281
+ chunks.push([callRequest]);
282
+ gasLeft = gasLimit - singleGasLimit;
283
+ if (gasLeft < 0n) {
284
+ console.warn(
285
+ `Multicall request may fail as the gas cost of a single call exceeds the gas limit ${gasLimit}. Gas cost: ${singleGasLimit}. To: ${target}. Data: ${callData}`
286
+ );
287
+ }
288
+ continue;
289
+ }
290
+ currentChunk.push(callRequest);
291
+ gasLeft -= singleGasLimit;
292
+ }
293
+ return chunks;
294
+ }
327
295
 
328
- export { createMulticall, getMulticallContract, multicallAddresses };
296
+ export { BLOCK_CONFLICT_TOLERANCE, DEFAULT_BLOCK_CONFLICT_TOLERANCE, DEFAULT_GAS_BUFFER, DEFAULT_GAS_BUFFER_BY_CHAIN, DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT_BY_CHAIN, MULTICALL_ADDRESS, getBlockConflictTolerance, getDefaultGasBuffer, getDefaultGasLimit, getGasLimit, getGasLimitOnChain, getMulticallContract, iMulticallABI, multicallByGasLimit };
297
+ //# sourceMappingURL=out.js.map
298
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../utils/toBigInt.ts","../src/constants/contracts.ts","../src/constants/blockConflictTolerance.ts","../src/constants/gasLimit.ts","../src/getMulticallContract.ts","../src/abis/IMulticall.ts","../src/getGasLimit.ts","../src/getBlockConflictTolerance.ts","../src/multicall.ts"],"names":["ChainId"],"mappings":"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","sourcesContent":["import { BigintIsh } from '@pancakeswap/sdk'\n\nexport function toBigInt(num: BigintIsh): bigint {\n return BigInt(num.toString())\n}\n","import { ChainId } from '@pancakeswap/sdk'\nimport { Address } from 'viem'\n\nexport const MULTICALL_ADDRESS: { [key in ChainId]?: Address } = {\n [ChainId.ZKSYNC]: '0x95071cBD09184083E7F732a710c2e30c9882Fd5f',\n [ChainId.BSC]: '0x39eecaE833c944ebb94942Fa44CaE46e87a8Da17',\n [ChainId.ETHEREUM]: '0xC0916D7E360c31D5F6D0c497E6a36B7B0E80e3cf',\n [ChainId.ARBITRUM_ONE]: '0xbFfE39cDD04f0183e0493c1Deb6E275c5cf84AdF',\n [ChainId.POLYGON_ZKEVM]: '0xe05b539447B17630Cb087473F6b50E5c5f73FDeb',\n [ChainId.LINEA]: '0x6E6B30d65D605DAa4CaC65eB270100Ecca36b140',\n [ChainId.BASE]: '0x3EFaAb8D7A631cfF5ccF5f149d1Bbb3B5bfda2C0',\n\n // Testnets\n [ChainId.BSC_TESTNET]: '0xeeF6ff30cF5D5b8aBA0DE16A01d17A0697a275b5',\n [ChainId.GOERLI]: '0xD55CAFAB2Ffa1139Be46bc5C0b8259c620050dFC',\n [ChainId.ARBITRUM_GOERLI]: '0xe12a5c707Fb528acbE6117b20AF1f7c20b0A8077',\n [ChainId.POLYGON_ZKEVM_TESTNET]: '0x236e713bFF45adb30e25D1c29A887aBCb0Ea7E21',\n [ChainId.ZKSYNC_TESTNET]: '0x8A23CB45E5F4d5a1b2DB673663Ea2aAedc48acff',\n [ChainId.LINEA_TESTNET]: '0x990010b6DBA3e7faa025790bC0433A9f690c65F3',\n [ChainId.BASE_TESTNET]: '0x6F7f93D929d6FBaF16c245e42846EF21aee23437',\n [ChainId.OPBNB_TESTNET]: '0x6A70ED893D85cf6D4059e1CF3e63a48e4D204D32',\n [ChainId.SCROLL_SEPOLIA]: '0x052a99849Ef2e13a5CB28275862991671D4b6fF5',\n}\n","import { ChainId } from '@pancakeswap/sdk'\n\nexport const DEFAULT_BLOCK_CONFLICT_TOLERANCE = 0\n\nexport const BLOCK_CONFLICT_TOLERANCE: { [key in ChainId]?: number } = {\n [ChainId.BSC]: 3,\n [ChainId.ETHEREUM]: 1,\n [ChainId.ARBITRUM_ONE]: 5,\n [ChainId.POLYGON_ZKEVM]: 1,\n [ChainId.ZKSYNC]: 3,\n [ChainId.LINEA]: 3,\n [ChainId.BASE]: 3,\n\n // Testnets\n [ChainId.BSC_TESTNET]: 3,\n [ChainId.GOERLI]: 1,\n [ChainId.ARBITRUM_GOERLI]: 5,\n [ChainId.POLYGON_ZKEVM_TESTNET]: 1,\n [ChainId.ZKSYNC_TESTNET]: 3,\n [ChainId.LINEA_TESTNET]: 3,\n [ChainId.OPBNB_TESTNET]: 3,\n [ChainId.BASE_TESTNET]: 3,\n [ChainId.SCROLL_SEPOLIA]: 3,\n}\n","import { ChainId } from '@pancakeswap/sdk'\n\nexport const DEFAULT_GAS_LIMIT = 150000000n\n\nexport const DEFAULT_GAS_LIMIT_BY_CHAIN: { [key in ChainId]?: bigint } = {\n [ChainId.BSC]: 100000000n,\n [ChainId.ZKSYNC]: 500000000n,\n [ChainId.POLYGON_ZKEVM]: 1500000n,\n}\n\nexport const DEFAULT_GAS_BUFFER = 3000000n\n\nexport const DEFAULT_GAS_BUFFER_BY_CHAIN: { [key in ChainId]?: bigint } = {\n [ChainId.BSC]: DEFAULT_GAS_BUFFER,\n [ChainId.POLYGON_ZKEVM]: 0n,\n}\n","import { ChainId } from '@pancakeswap/sdk'\nimport { GetContractReturnType, PublicClient, getContract } from 'viem'\n\nimport { MULTICALL_ADDRESS } from './constants/contracts'\nimport { iMulticallABI } from './abis/IMulticall'\n\ntype Params = {\n chainId: ChainId\n client?: PublicClient\n}\n\nexport function getMulticallContract({\n chainId,\n client,\n}: Params): GetContractReturnType<typeof iMulticallABI, PublicClient> {\n const address = MULTICALL_ADDRESS[chainId]\n if (!address) {\n throw new Error(`PancakeMulticall not supported on chain ${chainId}`)\n }\n\n return getContract({ abi: iMulticallABI, address, publicClient: client })\n}\n","export const iMulticallABI = [\n {\n inputs: [],\n name: 'gasLeft',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [],\n name: 'gaslimit',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n {\n components: [\n { internalType: 'address', name: 'target', type: 'address' },\n { internalType: 'uint256', name: 'gasLimit', type: 'uint256' },\n { internalType: 'bytes', name: 'callData', type: 'bytes' },\n ],\n internalType: 'struct MultiCallV2.Call[]',\n name: 'calls',\n type: 'tuple[]',\n },\n ],\n name: 'multicall',\n outputs: [\n { internalType: 'uint256', name: 'blockNumber', type: 'uint256' },\n {\n components: [\n { internalType: 'bool', name: 'success', type: 'bool' },\n { internalType: 'uint256', name: 'gasUsed', type: 'uint256' },\n { internalType: 'bytes', name: 'returnData', type: 'bytes' },\n ],\n internalType: 'struct MultiCallV2.Result[]',\n name: 'returnData',\n type: 'tuple[]',\n },\n ],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n {\n inputs: [\n {\n components: [\n { internalType: 'address', name: 'target', type: 'address' },\n { internalType: 'uint256', name: 'gasLimit', type: 'uint256' },\n { internalType: 'bytes', name: 'callData', type: 'bytes' },\n ],\n internalType: 'struct MultiCallV2.Call[]',\n name: 'calls',\n type: 'tuple[]',\n },\n { internalType: 'uint256', name: 'gasBuffer', type: 'uint256' },\n ],\n name: 'multicallWithGasLimitation',\n outputs: [\n { internalType: 'uint256', name: 'blockNumber', type: 'uint256' },\n {\n components: [\n { internalType: 'bool', name: 'success', type: 'bool' },\n { internalType: 'uint256', name: 'gasUsed', type: 'uint256' },\n { internalType: 'bytes', name: 'returnData', type: 'bytes' },\n ],\n internalType: 'struct MultiCallV2.Result[]',\n name: 'returnData',\n type: 'tuple[]',\n },\n { internalType: 'uint256', name: 'lastSuccessIndex', type: 'uint256' },\n ],\n stateMutability: 'nonpayable',\n type: 'function',\n },\n]\n","import { BigintIsh, ChainId } from '@pancakeswap/sdk'\nimport { toBigInt } from '@pancakeswap/utils/toBigInt'\nimport { PublicClient } from 'viem'\n\nimport {\n DEFAULT_GAS_BUFFER,\n DEFAULT_GAS_BUFFER_BY_CHAIN,\n DEFAULT_GAS_LIMIT,\n DEFAULT_GAS_LIMIT_BY_CHAIN,\n} from './constants'\nimport { getMulticallContract } from './getMulticallContract'\n\nexport type GetGasLimitParams = {\n chainId: ChainId\n client?: PublicClient\n\n // If provided then would override the gas limit got from on chain\n gasLimit?: BigintIsh\n\n // The gas limit should be whichever is smaller between gasLimit and maxGasLimit\n maxGasLimit?: BigintIsh\n\n gasBuffer?: BigintIsh\n}\n\nexport function getDefaultGasLimit(chainId?: ChainId) {\n const gasLimitOnChain = chainId && DEFAULT_GAS_LIMIT_BY_CHAIN[chainId]\n return gasLimitOnChain !== undefined ? gasLimitOnChain : DEFAULT_GAS_LIMIT\n}\n\nexport function getDefaultGasBuffer(chainId?: ChainId) {\n const gasBufferOnChain = chainId && DEFAULT_GAS_BUFFER_BY_CHAIN[chainId]\n return gasBufferOnChain !== undefined ? gasBufferOnChain : DEFAULT_GAS_BUFFER\n}\n\nexport type GetGasLimitOnChainParams = Pick<GetGasLimitParams, 'chainId' | 'client'>\n\nexport async function getGasLimitOnChain({ chainId, client }: GetGasLimitOnChainParams) {\n const multicall = getMulticallContract({ chainId, client })\n const gasLeft = (await multicall.read.gasLeft()) as bigint\n return gasLeft\n}\n\nexport async function getGasLimit({\n chainId,\n gasLimit: gasLimitInput,\n maxGasLimit: maxGasLimitInput = getDefaultGasLimit(chainId),\n gasBuffer: gasBufferInput = getDefaultGasBuffer(chainId),\n client,\n}: GetGasLimitParams) {\n const gasLimitOverride = gasLimitInput && toBigInt(gasLimitInput)\n const maxGasLimit = toBigInt(maxGasLimitInput)\n const gasBuffer = toBigInt(gasBufferInput)\n\n const gasLimit = gasLimitOverride || (await getGasLimitOnChain({ chainId, client })) || maxGasLimit\n const minGasLimit = gasLimit < maxGasLimit ? gasLimit : maxGasLimit\n return minGasLimit - gasBuffer\n}\n","import { ChainId } from '@pancakeswap/sdk'\n\nimport { BLOCK_CONFLICT_TOLERANCE, DEFAULT_BLOCK_CONFLICT_TOLERANCE } from './constants'\n\nexport function getBlockConflictTolerance(chainId: ChainId) {\n return BLOCK_CONFLICT_TOLERANCE[chainId] || DEFAULT_BLOCK_CONFLICT_TOLERANCE\n}\n","import { toBigInt } from '@pancakeswap/utils/toBigInt'\n\nimport { GetGasLimitParams, getDefaultGasBuffer, getGasLimit } from './getGasLimit'\nimport { MulticallRequestWithGas } from './types'\nimport { getMulticallContract } from './getMulticallContract'\nimport { getBlockConflictTolerance } from './getBlockConflictTolerance'\n\nexport type CallByGasLimitParams = GetGasLimitParams & {\n // Normally we expect to get quotes from within the same block\n // But for some chains like BSC the block time is quite short so need some extra tolerance\n // 0 means no block conflict and all the multicall results should be queried within the same block\n blockConflictTolerance?: number\n}\n\nexport async function multicallByGasLimit(\n calls: MulticallRequestWithGas[],\n { chainId, gasBuffer = getDefaultGasBuffer(chainId), client, ...rest }: CallByGasLimitParams,\n) {\n const gasLimit = await getGasLimit({\n chainId,\n gasBuffer,\n client,\n ...rest,\n })\n const callChunks = splitCallsIntoChunks(calls, gasLimit)\n return callByChunks(callChunks, { gasBuffer, client, chainId })\n}\n\ntype CallParams = Pick<CallByGasLimitParams, 'chainId' | 'client' | 'gasBuffer' | 'blockConflictTolerance'>\n\nexport type SingleCallResult = {\n result: string\n gasUsed: bigint\n success: boolean\n}\n\nexport type CallResult = {\n results: SingleCallResult[]\n // Will be the greatest block number if block conflict tolerance is not 0\n blockNumber: bigint\n}\n\nexport type MulticallReturn = CallResult & {\n lastSuccessIndex: number\n}\n\ntype CallReturnFromContract = [bigint, { success: boolean; gasUsed: bigint; returnData: string }[], bigint]\n\nfunction formatCallReturn([blockNumber, results, successIndex]: CallReturnFromContract): MulticallReturn {\n const lastSuccessIndex = Number(successIndex)\n return {\n lastSuccessIndex,\n blockNumber,\n results: results.slice(0, lastSuccessIndex + 1).map(({ gasUsed, success, returnData }) => ({\n gasUsed,\n success,\n result: returnData,\n })),\n }\n}\n\nasync function call(calls: MulticallRequestWithGas[], params: CallParams): Promise<CallResult> {\n const {\n chainId,\n client,\n gasBuffer = getDefaultGasBuffer(chainId),\n blockConflictTolerance = getBlockConflictTolerance(chainId),\n } = params\n if (!calls.length) {\n return {\n results: [],\n blockNumber: 0n,\n }\n }\n\n const contract = getMulticallContract({ chainId, client })\n const { result } = await contract.simulate.multicallWithGasLimitation([calls, gasBuffer])\n const { results, lastSuccessIndex, blockNumber } = formatCallReturn(result as CallReturnFromContract)\n if (lastSuccessIndex === calls.length - 1) {\n return {\n results,\n blockNumber,\n }\n }\n console.warn(\n `Gas limit reached. Total num of ${calls.length} calls. First ${\n lastSuccessIndex + 1\n } calls executed. The remaining ${\n calls.length - lastSuccessIndex - 1\n } calls are not executed. Pls try adjust the gas limit per call.`,\n )\n const { results: remainingResults, blockNumber: nextBlockNumber } = await call(\n calls.slice(lastSuccessIndex + 1),\n params,\n )\n if (Number(nextBlockNumber - blockNumber) > blockConflictTolerance) {\n throw new Error(\n `Multicall failed because of block conflict. Latest calls are made at block ${nextBlockNumber} while last calls made at block ${blockNumber}. Block conflict tolerance is ${blockConflictTolerance}`,\n )\n }\n return {\n results: [...results, ...remainingResults],\n // Use the latest block number\n blockNumber: nextBlockNumber,\n }\n}\n\nasync function callByChunks(chunks: MulticallRequestWithGas[][], params: CallParams): Promise<CallResult> {\n const { blockConflictTolerance = getBlockConflictTolerance(params.chainId) } = params\n const callReturns = await Promise.all(chunks.map((chunk) => call(chunk, params)))\n\n let minBlock = 0n\n let maxBlock = 0n\n let results: SingleCallResult[] = []\n for (const { results: callResults, blockNumber } of callReturns) {\n if (minBlock === 0n || blockNumber < minBlock) {\n minBlock = blockNumber\n }\n if (blockNumber > maxBlock) {\n maxBlock = blockNumber\n }\n if (Number(maxBlock - minBlock) > blockConflictTolerance) {\n throw new Error(\n `Multicall failed because of block conflict. Min block is ${minBlock} while max block is ${maxBlock}. Block conflict tolerance is ${blockConflictTolerance}`,\n )\n }\n results = [...results, ...callResults]\n }\n return {\n results,\n blockNumber: maxBlock,\n }\n}\n\nfunction splitCallsIntoChunks(calls: MulticallRequestWithGas[], gasLimit: bigint): MulticallRequestWithGas[][] {\n const chunks: MulticallRequestWithGas[][] = [[]]\n\n let gasLeft = gasLimit\n for (const callRequest of calls) {\n const { target, callData, gasLimit: gasCostLimit } = callRequest\n const singleGasLimit = toBigInt(gasCostLimit)\n const currentChunk = chunks[chunks.length - 1]\n if (singleGasLimit > gasLeft) {\n chunks.push([callRequest])\n gasLeft = gasLimit - singleGasLimit\n\n // Single call exceeds the gas limit\n if (gasLeft < 0n) {\n console.warn(\n `Multicall request may fail as the gas cost of a single call exceeds the gas limit ${gasLimit}. Gas cost: ${singleGasLimit}. To: ${target}. Data: ${callData}`,\n )\n }\n continue\n }\n\n currentChunk.push(callRequest)\n gasLeft -= singleGasLimit\n }\n\n return chunks\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import { GetGasLimitParams } from './getGasLimit';
2
+ import { MulticallRequestWithGas } from './types';
3
+ export type CallByGasLimitParams = GetGasLimitParams & {
4
+ blockConflictTolerance?: number;
5
+ };
6
+ export declare function multicallByGasLimit(calls: MulticallRequestWithGas[], { chainId, gasBuffer, client, ...rest }: CallByGasLimitParams): Promise<CallResult>;
7
+ export type SingleCallResult = {
8
+ result: string;
9
+ gasUsed: bigint;
10
+ success: boolean;
11
+ };
12
+ export type CallResult = {
13
+ results: SingleCallResult[];
14
+ blockNumber: bigint;
15
+ };
16
+ export type MulticallReturn = CallResult & {
17
+ lastSuccessIndex: number;
18
+ };
19
+ //# sourceMappingURL=multicall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multicall.d.ts","sourceRoot":"","sources":["../src/multicall.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAoC,MAAM,eAAe,CAAA;AACnF,OAAO,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAIjD,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAAG;IAIrD,sBAAsB,CAAC,EAAE,MAAM,CAAA;CAChC,CAAA;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,uBAAuB,EAAE,EAChC,EAAE,OAAO,EAAE,SAAwC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,oBAAoB,uBAU7F;AAID,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAE3B,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG;IACzC,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA"}
@@ -0,0 +1,10 @@
1
+ import type { Address } from 'viem';
2
+ import { BigintIsh } from '@pancakeswap/sdk';
3
+ export type MulticallRequest = {
4
+ target: Address;
5
+ callData: string;
6
+ };
7
+ export type MulticallRequestWithGas = MulticallRequest & {
8
+ gasLimit: BigintIsh;
9
+ };
10
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAE5C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG;IACvD,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA"}