@subsquid/evm-typegen 4.0.1 → 4.1.1
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/lib/multicall.d.ts +48 -213
- package/lib/multicall.d.ts.map +1 -1
- package/lib/multicall.js +100 -178
- package/lib/multicall.js.map +1 -1
- package/package.json +3 -3
- package/src/multicall.ts +150 -199
package/lib/multicall.d.ts
CHANGED
|
@@ -1,216 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const abi = new ethers.Interface([
|
|
8
|
-
{
|
|
9
|
-
type: 'function',
|
|
10
|
-
name: 'aggregate',
|
|
11
|
-
stateMutability: 'nonpayable',
|
|
12
|
-
inputs: [
|
|
13
|
-
{
|
|
14
|
-
name: 'calls',
|
|
15
|
-
type: 'tuple[]',
|
|
16
|
-
components: [
|
|
17
|
-
{name: 'target', type: 'address'},
|
|
18
|
-
{name: 'callData', type: 'bytes'},
|
|
19
|
-
]
|
|
20
|
-
}
|
|
21
|
-
],
|
|
22
|
-
outputs: [
|
|
23
|
-
{name: 'blockNumber', type: 'uint256'},
|
|
24
|
-
{name: 'returnData', type: 'bytes[]'},
|
|
25
|
-
]
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: 'tryAggregate',
|
|
29
|
-
type: 'function',
|
|
30
|
-
stateMutability: 'nonpayable',
|
|
31
|
-
inputs: [
|
|
32
|
-
{name: 'requireSuccess', type: 'bool'},
|
|
33
|
-
{
|
|
34
|
-
name: 'calls',
|
|
35
|
-
type: 'tuple[]',
|
|
36
|
-
components: [
|
|
37
|
-
{name: 'target', type: 'address'},
|
|
38
|
-
{name: 'callData', type: 'bytes'},
|
|
39
|
-
]
|
|
40
|
-
}
|
|
41
|
-
],
|
|
42
|
-
outputs: [
|
|
43
|
-
{
|
|
44
|
-
name: 'returnData',
|
|
45
|
-
type: 'tuple[]',
|
|
46
|
-
components: [
|
|
47
|
-
{name: 'success', type: 'bool'},
|
|
48
|
-
{name: 'returnData', type: 'bytes'},
|
|
49
|
-
]
|
|
50
|
-
},
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
])
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
type AnyFunc = Func<any, {}, any>
|
|
57
|
-
type Call = [address: string, bytes: string]
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const aggregate = new Func<[calls: Call[]], {}, {blockNumber: bigint, returnData: string[]}>(
|
|
61
|
-
abi, abi.getFunction('aggregate')!.selector
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const try_aggregate = new Func<[requireSuccess: boolean, calls: Array<[target: string, callData: string]>], {}, Array<{success: boolean, returnData: string}>>(
|
|
66
|
-
abi, abi.getFunction('tryAggregate')!.selector
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
export type MulticallResult<T> = {
|
|
71
|
-
success: true
|
|
72
|
-
value: T
|
|
1
|
+
import * as p from '@subsquid/evm-codec';
|
|
2
|
+
import { ContractBase, type AbiFunction, type FunctionReturn, type FunctionArguments } from '@subsquid/evm-abi';
|
|
3
|
+
export type MulticallResult<T extends AbiFunction<any, any>> = {
|
|
4
|
+
success: true;
|
|
5
|
+
value: FunctionReturn<T>;
|
|
73
6
|
} | {
|
|
74
|
-
success: false
|
|
75
|
-
returnData?: string
|
|
76
|
-
value?: undefined
|
|
7
|
+
success: false;
|
|
8
|
+
returnData?: string;
|
|
9
|
+
value?: undefined;
|
|
10
|
+
};
|
|
11
|
+
type AnyFunc = AbiFunction<any, any>;
|
|
12
|
+
type AggregateTuple<T extends AnyFunc = AnyFunc> = [func: T, address: string, args: T extends AnyFunc ? FunctionArguments<T> : never];
|
|
13
|
+
export declare class Multicall extends ContractBase {
|
|
14
|
+
static aggregate: AbiFunction<{
|
|
15
|
+
readonly calls: p.Codec<{
|
|
16
|
+
readonly target: string;
|
|
17
|
+
readonly callData: string | Uint8Array;
|
|
18
|
+
}[], {
|
|
19
|
+
readonly target: string;
|
|
20
|
+
readonly callData: string;
|
|
21
|
+
}[]>;
|
|
22
|
+
}, {
|
|
23
|
+
readonly blockNumber: p.Codec<number | bigint, bigint>;
|
|
24
|
+
readonly returnData: p.Codec<(string | Uint8Array)[], string[]>;
|
|
25
|
+
}>;
|
|
26
|
+
static tryAggregate: AbiFunction<{
|
|
27
|
+
readonly requireSuccess: p.Codec<boolean, boolean>;
|
|
28
|
+
readonly calls: p.Codec<{
|
|
29
|
+
readonly target: string;
|
|
30
|
+
readonly callData: string | Uint8Array;
|
|
31
|
+
}[], {
|
|
32
|
+
readonly target: string;
|
|
33
|
+
readonly callData: string;
|
|
34
|
+
}[]>;
|
|
35
|
+
}, p.Codec<{
|
|
36
|
+
readonly success: boolean;
|
|
37
|
+
readonly returnData: string | Uint8Array;
|
|
38
|
+
}[], {
|
|
39
|
+
readonly success: boolean;
|
|
40
|
+
readonly returnData: string;
|
|
41
|
+
}[]>>;
|
|
42
|
+
aggregate<TF extends AnyFunc>(func: TF, address: string, calls: FunctionArguments<TF>[], paging?: number): Promise<FunctionReturn<TF>[]>;
|
|
43
|
+
aggregate<TF extends AnyFunc>(func: TF, calls: [address: string, args: FunctionArguments<TF>][], paging?: number): Promise<FunctionReturn<TF>[]>;
|
|
44
|
+
aggregate(calls: AggregateTuple[], paging?: number): Promise<any[]>;
|
|
45
|
+
tryAggregate<TF extends AnyFunc>(func: TF, address: string, calls: FunctionArguments<TF>[], paging?: number): Promise<MulticallResult<TF>[]>;
|
|
46
|
+
tryAggregate<TF extends AnyFunc>(func: TF, calls: [address: string, args: FunctionArguments<TF>][], paging?: number): Promise<MulticallResult<TF>[]>;
|
|
47
|
+
tryAggregate(calls: AggregateTuple[], paging?: number): Promise<MulticallResult<any>[]>;
|
|
48
|
+
private makeCalls;
|
|
77
49
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
export class Multicall extends ContractBase {
|
|
81
|
-
static aggregate = aggregate
|
|
82
|
-
static try_aggregate = try_aggregate
|
|
83
|
-
|
|
84
|
-
aggregate<Args extends any[], R>(
|
|
85
|
-
func: Func<Args, {}, R>,
|
|
86
|
-
address: string,
|
|
87
|
-
calls: Args[],
|
|
88
|
-
paging?: number
|
|
89
|
-
): Promise<R[]>
|
|
90
|
-
|
|
91
|
-
aggregate<Args extends any[], R>(
|
|
92
|
-
func: Func<Args, {}, R>,
|
|
93
|
-
calls: [address: string, args: Args][],
|
|
94
|
-
paging?: number
|
|
95
|
-
): Promise<R[]>
|
|
96
|
-
|
|
97
|
-
aggregate(
|
|
98
|
-
calls: [func: AnyFunc, address: string, args: any[]][],
|
|
99
|
-
paging?: number
|
|
100
|
-
): Promise<any[]>
|
|
101
|
-
|
|
102
|
-
async aggregate(...args: any[]): Promise<any[]> {
|
|
103
|
-
let [calls, funcs, page] = this.makeCalls(args)
|
|
104
|
-
let size = calls.length
|
|
105
|
-
let results = new Array(size)
|
|
106
|
-
for (let [from, to] of splitIntoPages(size, page)) {
|
|
107
|
-
let {returnData} = await this.eth_call(aggregate, [calls.slice(from, to)])
|
|
108
|
-
for (let i = from; i < to; i++) {
|
|
109
|
-
let data = returnData[i - from]
|
|
110
|
-
results[i] = funcs[i].decodeResult(data)
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return results
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
tryAggregate<Args extends any[], R>(
|
|
117
|
-
func: Func<Args, {}, R>,
|
|
118
|
-
address: string,
|
|
119
|
-
calls: Args[],
|
|
120
|
-
paging?: number
|
|
121
|
-
): Promise<MulticallResult<R>[]>
|
|
122
|
-
|
|
123
|
-
tryAggregate<Args extends any[], R>(
|
|
124
|
-
func: Func<Args, {}, R>,
|
|
125
|
-
calls: [address: string, args: Args][],
|
|
126
|
-
paging?: number
|
|
127
|
-
): Promise<MulticallResult<R>[]>
|
|
128
|
-
|
|
129
|
-
tryAggregate(
|
|
130
|
-
calls: [func: AnyFunc, address: string, args: any[]][],
|
|
131
|
-
paging?: number
|
|
132
|
-
): Promise<MulticallResult<any>[]>
|
|
133
|
-
|
|
134
|
-
async tryAggregate(...args: any[]): Promise<any[]> {
|
|
135
|
-
let [calls, funcs, page] = this.makeCalls(args)
|
|
136
|
-
let size = calls.length
|
|
137
|
-
let results = new Array(size)
|
|
138
|
-
for (let [from, to] of splitIntoPages(size, page)) {
|
|
139
|
-
let response = await this.eth_call(try_aggregate, [false, calls.slice(from, to)])
|
|
140
|
-
for (let i = from; i < to; i++) {
|
|
141
|
-
let res = response[i - from]
|
|
142
|
-
if (res.success) {
|
|
143
|
-
try {
|
|
144
|
-
results[i] = {
|
|
145
|
-
success: true,
|
|
146
|
-
value: funcs[i].decodeResult(res.returnData)
|
|
147
|
-
}
|
|
148
|
-
} catch(err: any) {
|
|
149
|
-
results[i] = {success: false, returnData: res.returnData}
|
|
150
|
-
}
|
|
151
|
-
} else {
|
|
152
|
-
results[i] = {success: false}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return results
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
private makeCalls(args: any[]): [calls: Call[], funcs: AnyFunc[], page: number] {
|
|
160
|
-
let page = typeof args[args.length-1] == 'number' ? args.pop()! : Number.MAX_SAFE_INTEGER
|
|
161
|
-
switch(args.length) {
|
|
162
|
-
case 1: {
|
|
163
|
-
let list: [func: AnyFunc, address: string, args: any[]][] = args[0]
|
|
164
|
-
let calls = new Array(list.length)
|
|
165
|
-
let funcs = new Array(list.length)
|
|
166
|
-
for (let i = 0; i < list.length; i++) {
|
|
167
|
-
let [func, address, args] = list[i]
|
|
168
|
-
calls[i] = [address, func.encode(args)]
|
|
169
|
-
funcs[i] = func
|
|
170
|
-
}
|
|
171
|
-
return [calls, funcs, page]
|
|
172
|
-
}
|
|
173
|
-
case 2: {
|
|
174
|
-
let func: AnyFunc = args[0]
|
|
175
|
-
let list: [address: string, args: any[]][] = args[1]
|
|
176
|
-
let calls = new Array(list.length)
|
|
177
|
-
let funcs = new Array(list.length)
|
|
178
|
-
for (let i = 0; i < list.length; i++) {
|
|
179
|
-
let [address, args] = list[i]
|
|
180
|
-
calls[i] = [address, func.encode(args)]
|
|
181
|
-
funcs[i] = func
|
|
182
|
-
}
|
|
183
|
-
return [calls, funcs, page]
|
|
184
|
-
}
|
|
185
|
-
case 3: {
|
|
186
|
-
let func: AnyFunc = args[0]
|
|
187
|
-
let address: string = args[1]
|
|
188
|
-
let list: any[][] = args[2]
|
|
189
|
-
let calls = new Array(list.length)
|
|
190
|
-
let funcs = new Array(list.length)
|
|
191
|
-
for (let i = 0; i < list.length; i++) {
|
|
192
|
-
let args = list[i]
|
|
193
|
-
calls[i] = [address, func.encode(args)]
|
|
194
|
-
funcs[i] = func
|
|
195
|
-
}
|
|
196
|
-
return [calls, funcs, page]
|
|
197
|
-
}
|
|
198
|
-
default:
|
|
199
|
-
throw new Error('unexpected number of arguments')
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
function* splitIntoPages(size: number, page: number): Iterable<[from: number, to: number]> {
|
|
206
|
-
let from = 0
|
|
207
|
-
while (size) {
|
|
208
|
-
let step = Math.min(page, size)
|
|
209
|
-
let to = from + step
|
|
210
|
-
yield [from, to]
|
|
211
|
-
size -= step
|
|
212
|
-
from = to
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
*/
|
|
50
|
+
export {};
|
|
216
51
|
//# sourceMappingURL=multicall.d.ts.map
|
package/lib/multicall.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multicall.d.ts","sourceRoot":"","sources":["../src/multicall.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"multicall.d.ts","sourceRoot":"","sources":["../src/multicall.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,qBAAqB,CAAA;AACxC,OAAO,EAAM,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,iBAAiB,EAAC,MAAM,mBAAmB,CAAA;AAclH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI;IAC7D,OAAO,EAAE,IAAI,CAAA;IACb,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,CAAA;CACzB,GAAG;IACF,OAAO,EAAE,KAAK,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB,CAAA;AAED,KAAK,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AACpC,KAAK,cAAc,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,SAAS,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAA;AAGrI,qBAAa,SAAU,SAAQ,YAAY;IACzC,MAAM,CAAC,SAAS;;;;;;;;;;;OAAY;IAC5B,MAAM,CAAC,YAAY;;;;;;;;;;;;;;;UAAe;IAElC,SAAS,CAAC,EAAE,SAAS,OAAO,EAC1B,IAAI,EAAE,EAAE,EACR,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAC9B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,CAAC;IAEhC,SAAS,CAAC,EAAE,SAAS,OAAO,EAC1B,IAAI,EAAE,EAAE,EACR,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC,EAAE,EACvD,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,CAAC;IAEhC,SAAS,CACP,KAAK,EAAE,cAAc,EAAE,EACvB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,GAAG,EAAE,CAAC;IAgBjB,YAAY,CAAC,EAAE,SAAS,OAAO,EAC7B,IAAI,EAAE,EAAE,EACR,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAC9B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE,CAAC;IAEjC,YAAY,CAAC,EAAE,SAAS,OAAO,EAC7B,IAAI,EAAE,EAAE,EACR,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC,EAAE,EACvD,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE,CAAC;IAEjC,YAAY,CACV,KAAK,EAAE,cAAc,EAAE,EACvB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;IA8BlC,OAAO,CAAC,SAAS;CA2ClB"}
|
package/lib/multicall.js
CHANGED
|
@@ -1,217 +1,139 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const abi = new ethers.Interface([
|
|
9
|
-
{
|
|
10
|
-
type: 'function',
|
|
11
|
-
name: 'aggregate',
|
|
12
|
-
stateMutability: 'nonpayable',
|
|
13
|
-
inputs: [
|
|
14
|
-
{
|
|
15
|
-
name: 'calls',
|
|
16
|
-
type: 'tuple[]',
|
|
17
|
-
components: [
|
|
18
|
-
{name: 'target', type: 'address'},
|
|
19
|
-
{name: 'callData', type: 'bytes'},
|
|
20
|
-
]
|
|
21
|
-
}
|
|
22
|
-
],
|
|
23
|
-
outputs: [
|
|
24
|
-
{name: 'blockNumber', type: 'uint256'},
|
|
25
|
-
{name: 'returnData', type: 'bytes[]'},
|
|
26
|
-
]
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
name: 'tryAggregate',
|
|
30
|
-
type: 'function',
|
|
31
|
-
stateMutability: 'nonpayable',
|
|
32
|
-
inputs: [
|
|
33
|
-
{name: 'requireSuccess', type: 'bool'},
|
|
34
|
-
{
|
|
35
|
-
name: 'calls',
|
|
36
|
-
type: 'tuple[]',
|
|
37
|
-
components: [
|
|
38
|
-
{name: 'target', type: 'address'},
|
|
39
|
-
{name: 'callData', type: 'bytes'},
|
|
40
|
-
]
|
|
41
|
-
}
|
|
42
|
-
],
|
|
43
|
-
outputs: [
|
|
44
|
-
{
|
|
45
|
-
name: 'returnData',
|
|
46
|
-
type: 'tuple[]',
|
|
47
|
-
components: [
|
|
48
|
-
{name: 'success', type: 'bool'},
|
|
49
|
-
{name: 'returnData', type: 'bytes'},
|
|
50
|
-
]
|
|
51
|
-
},
|
|
52
|
-
]
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
53
7
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
calls
|
|
89
|
-
|
|
90
|
-
): Promise<R[]>
|
|
91
|
-
|
|
92
|
-
aggregate<Args extends any[], R>(
|
|
93
|
-
func: Func<Args, {}, R>,
|
|
94
|
-
calls: [address: string, args: Args][],
|
|
95
|
-
paging?: number
|
|
96
|
-
): Promise<R[]>
|
|
97
|
-
|
|
98
|
-
aggregate(
|
|
99
|
-
calls: [func: AnyFunc, address: string, args: any[]][],
|
|
100
|
-
paging?: number
|
|
101
|
-
): Promise<any[]>
|
|
102
|
-
|
|
103
|
-
async aggregate(...args: any[]): Promise<any[]> {
|
|
104
|
-
let [calls, funcs, page] = this.makeCalls(args)
|
|
105
|
-
let size = calls.length
|
|
106
|
-
let results = new Array(size)
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.Multicall = void 0;
|
|
27
|
+
const p = __importStar(require("@subsquid/evm-codec"));
|
|
28
|
+
const evm_abi_1 = require("@subsquid/evm-abi");
|
|
29
|
+
const aggregate = (0, evm_abi_1.fun)('0x252dba42', {
|
|
30
|
+
calls: p.array(p.struct({
|
|
31
|
+
target: p.address,
|
|
32
|
+
callData: p.bytes
|
|
33
|
+
}))
|
|
34
|
+
}, { blockNumber: p.uint256, returnData: p.array(p.bytes) });
|
|
35
|
+
const tryAggregate = (0, evm_abi_1.fun)('0xbce38bd7', {
|
|
36
|
+
requireSuccess: p.bool,
|
|
37
|
+
calls: p.array(p.struct({ target: p.address, callData: p.bytes }))
|
|
38
|
+
}, p.array(p.struct({ success: p.bool, returnData: p.bytes })));
|
|
39
|
+
class Multicall extends evm_abi_1.ContractBase {
|
|
40
|
+
async aggregate(...args) {
|
|
41
|
+
let [calls, funcs, page] = this.makeCalls(args);
|
|
42
|
+
let size = calls.length;
|
|
43
|
+
let results = new Array(size);
|
|
107
44
|
for (let [from, to] of splitIntoPages(size, page)) {
|
|
108
|
-
let {returnData} = await this.eth_call(aggregate,
|
|
45
|
+
let { returnData } = await this.eth_call(aggregate, { calls: calls.slice(from, to) });
|
|
109
46
|
for (let i = from; i < to; i++) {
|
|
110
|
-
let data = returnData[i - from]
|
|
111
|
-
results[i] = funcs[i].decodeResult(data)
|
|
47
|
+
let data = returnData[i - from];
|
|
48
|
+
results[i] = funcs[i].decodeResult(data);
|
|
112
49
|
}
|
|
113
50
|
}
|
|
114
|
-
return results
|
|
51
|
+
return results;
|
|
115
52
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
calls: Args[],
|
|
121
|
-
paging?: number
|
|
122
|
-
): Promise<MulticallResult<R>[]>
|
|
123
|
-
|
|
124
|
-
tryAggregate<Args extends any[], R>(
|
|
125
|
-
func: Func<Args, {}, R>,
|
|
126
|
-
calls: [address: string, args: Args][],
|
|
127
|
-
paging?: number
|
|
128
|
-
): Promise<MulticallResult<R>[]>
|
|
129
|
-
|
|
130
|
-
tryAggregate(
|
|
131
|
-
calls: [func: AnyFunc, address: string, args: any[]][],
|
|
132
|
-
paging?: number
|
|
133
|
-
): Promise<MulticallResult<any>[]>
|
|
134
|
-
|
|
135
|
-
async tryAggregate(...args: any[]): Promise<any[]> {
|
|
136
|
-
let [calls, funcs, page] = this.makeCalls(args)
|
|
137
|
-
let size = calls.length
|
|
138
|
-
let results = new Array(size)
|
|
53
|
+
async tryAggregate(...args) {
|
|
54
|
+
let [calls, funcs, page] = this.makeCalls(args);
|
|
55
|
+
let size = calls.length;
|
|
56
|
+
let results = new Array(size);
|
|
139
57
|
for (let [from, to] of splitIntoPages(size, page)) {
|
|
140
|
-
let response = await this.eth_call(
|
|
58
|
+
let response = await this.eth_call(tryAggregate, {
|
|
59
|
+
requireSuccess: false,
|
|
60
|
+
calls: calls.slice(from, to)
|
|
61
|
+
});
|
|
141
62
|
for (let i = from; i < to; i++) {
|
|
142
|
-
let res = response[i - from]
|
|
63
|
+
let res = response[i - from];
|
|
143
64
|
if (res.success) {
|
|
144
65
|
try {
|
|
145
66
|
results[i] = {
|
|
146
67
|
success: true,
|
|
147
68
|
value: funcs[i].decodeResult(res.returnData)
|
|
148
|
-
}
|
|
149
|
-
} catch(err: any) {
|
|
150
|
-
results[i] = {success: false, returnData: res.returnData}
|
|
69
|
+
};
|
|
151
70
|
}
|
|
152
|
-
|
|
153
|
-
|
|
71
|
+
catch (err) {
|
|
72
|
+
results[i] = { success: false, returnData: res.returnData };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
results[i] = { success: false };
|
|
154
77
|
}
|
|
155
78
|
}
|
|
156
79
|
}
|
|
157
|
-
return results
|
|
80
|
+
return results;
|
|
158
81
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
switch(args.length) {
|
|
82
|
+
makeCalls(args) {
|
|
83
|
+
let page = typeof args[args.length - 1] == 'number' ? args.pop() : Number.MAX_SAFE_INTEGER;
|
|
84
|
+
switch (args.length) {
|
|
163
85
|
case 1: {
|
|
164
|
-
let list
|
|
165
|
-
let calls = new Array(list.length)
|
|
166
|
-
let funcs = new Array(list.length)
|
|
86
|
+
let list = args[0];
|
|
87
|
+
let calls = new Array(list.length);
|
|
88
|
+
let funcs = new Array(list.length);
|
|
167
89
|
for (let i = 0; i < list.length; i++) {
|
|
168
|
-
let [func, address, args] = list[i]
|
|
169
|
-
calls[i] =
|
|
170
|
-
funcs[i] = func
|
|
90
|
+
let [func, address, args] = list[i];
|
|
91
|
+
calls[i] = { target: address, callData: func.encode(args) };
|
|
92
|
+
funcs[i] = func;
|
|
171
93
|
}
|
|
172
|
-
return [calls, funcs, page]
|
|
94
|
+
return [calls, funcs, page];
|
|
173
95
|
}
|
|
174
96
|
case 2: {
|
|
175
|
-
let func
|
|
176
|
-
let list
|
|
177
|
-
let calls = new Array(list.length)
|
|
178
|
-
let funcs = new Array(list.length)
|
|
97
|
+
let func = args[0];
|
|
98
|
+
let list = args[1];
|
|
99
|
+
let calls = new Array(list.length);
|
|
100
|
+
let funcs = new Array(list.length);
|
|
179
101
|
for (let i = 0; i < list.length; i++) {
|
|
180
|
-
let [address, args] = list[i]
|
|
181
|
-
calls[i] =
|
|
182
|
-
funcs[i] = func
|
|
102
|
+
let [address, args] = list[i];
|
|
103
|
+
calls[i] = { target: address, callData: func.encode(args) };
|
|
104
|
+
funcs[i] = func;
|
|
183
105
|
}
|
|
184
|
-
return [calls, funcs, page]
|
|
106
|
+
return [calls, funcs, page];
|
|
185
107
|
}
|
|
186
108
|
case 3: {
|
|
187
|
-
let func
|
|
188
|
-
let address
|
|
189
|
-
let list
|
|
190
|
-
let calls = new Array(list.length)
|
|
191
|
-
let funcs = new Array(list.length)
|
|
109
|
+
let func = args[0];
|
|
110
|
+
let address = args[1];
|
|
111
|
+
let list = args[2];
|
|
112
|
+
let calls = new Array(list.length);
|
|
113
|
+
let funcs = new Array(list.length);
|
|
192
114
|
for (let i = 0; i < list.length; i++) {
|
|
193
|
-
let args = list[i]
|
|
194
|
-
calls[i] =
|
|
195
|
-
funcs[i] = func
|
|
115
|
+
let args = list[i];
|
|
116
|
+
calls[i] = { target: address, callData: func.encode(args) };
|
|
117
|
+
funcs[i] = func;
|
|
196
118
|
}
|
|
197
|
-
return [calls, funcs, page]
|
|
119
|
+
return [calls, funcs, page];
|
|
198
120
|
}
|
|
199
121
|
default:
|
|
200
|
-
throw new Error('unexpected number of arguments')
|
|
122
|
+
throw new Error('unexpected number of arguments');
|
|
201
123
|
}
|
|
202
124
|
}
|
|
203
125
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
126
|
+
exports.Multicall = Multicall;
|
|
127
|
+
Multicall.aggregate = aggregate;
|
|
128
|
+
Multicall.tryAggregate = tryAggregate;
|
|
129
|
+
function* splitIntoPages(size, page) {
|
|
130
|
+
let from = 0;
|
|
208
131
|
while (size) {
|
|
209
|
-
let step = Math.min(page, size)
|
|
210
|
-
let to = from + step
|
|
211
|
-
yield [from, to]
|
|
212
|
-
size -= step
|
|
213
|
-
from = to
|
|
132
|
+
let step = Math.min(page, size);
|
|
133
|
+
let to = from + step;
|
|
134
|
+
yield [from, to];
|
|
135
|
+
size -= step;
|
|
136
|
+
from = to;
|
|
214
137
|
}
|
|
215
138
|
}
|
|
216
|
-
*/
|
|
217
139
|
//# sourceMappingURL=multicall.js.map
|
package/lib/multicall.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multicall.js","sourceRoot":"","sources":["../src/multicall.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"multicall.js","sourceRoot":"","sources":["../src/multicall.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subsquid/evm-typegen",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1",
|
|
4
4
|
"description": "CLI for generating typescript types and decode implementations for evm logs",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"repository": "git@github.com:subsquid/squid.git",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"@subsquid/util-internal": "^3.2.0",
|
|
22
22
|
"@subsquid/util-internal-code-printer": "^1.2.2",
|
|
23
23
|
"@subsquid/util-internal-commander": "^1.4.0",
|
|
24
|
-
"@subsquid/evm-codec": "^0.
|
|
25
|
-
"@subsquid/evm-abi": "^0.2.
|
|
24
|
+
"@subsquid/evm-codec": "^0.2.0",
|
|
25
|
+
"@subsquid/evm-abi": "^0.2.1",
|
|
26
26
|
"commander": "^11.1.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
package/src/multicall.ts
CHANGED
|
@@ -1,215 +1,166 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
]
|
|
20
|
-
}
|
|
21
|
-
],
|
|
22
|
-
outputs: [
|
|
23
|
-
{name: 'blockNumber', type: 'uint256'},
|
|
24
|
-
{name: 'returnData', type: 'bytes[]'},
|
|
25
|
-
]
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: 'tryAggregate',
|
|
29
|
-
type: 'function',
|
|
30
|
-
stateMutability: 'nonpayable',
|
|
31
|
-
inputs: [
|
|
32
|
-
{name: 'requireSuccess', type: 'bool'},
|
|
33
|
-
{
|
|
34
|
-
name: 'calls',
|
|
35
|
-
type: 'tuple[]',
|
|
36
|
-
components: [
|
|
37
|
-
{name: 'target', type: 'address'},
|
|
38
|
-
{name: 'callData', type: 'bytes'},
|
|
39
|
-
]
|
|
40
|
-
}
|
|
41
|
-
],
|
|
42
|
-
outputs: [
|
|
43
|
-
{
|
|
44
|
-
name: 'returnData',
|
|
45
|
-
type: 'tuple[]',
|
|
46
|
-
components: [
|
|
47
|
-
{name: 'success', type: 'bool'},
|
|
48
|
-
{name: 'returnData', type: 'bytes'},
|
|
49
|
-
]
|
|
50
|
-
},
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
])
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
type AnyFunc = Func<any, {}, any>
|
|
57
|
-
type Call = [address: string, bytes: string]
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const aggregate = new Func<[calls: Call[]], {}, {blockNumber: bigint, returnData: string[]}>(
|
|
61
|
-
abi, abi.getFunction('aggregate')!.selector
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const try_aggregate = new Func<[requireSuccess: boolean, calls: Array<[target: string, callData: string]>], {}, Array<{success: boolean, returnData: string}>>(
|
|
66
|
-
abi, abi.getFunction('tryAggregate')!.selector
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
export type MulticallResult<T> = {
|
|
71
|
-
success: true
|
|
72
|
-
value: T
|
|
1
|
+
import * as p from '@subsquid/evm-codec'
|
|
2
|
+
import {fun, ContractBase, type AbiFunction, type FunctionReturn, type FunctionArguments} from '@subsquid/evm-abi'
|
|
3
|
+
|
|
4
|
+
const aggregate = fun('0x252dba42', {
|
|
5
|
+
calls: p.array(p.struct({
|
|
6
|
+
target: p.address,
|
|
7
|
+
callData: p.bytes
|
|
8
|
+
}))
|
|
9
|
+
}, {blockNumber: p.uint256, returnData: p.array(p.bytes)})
|
|
10
|
+
|
|
11
|
+
const tryAggregate = fun('0xbce38bd7', {
|
|
12
|
+
requireSuccess: p.bool,
|
|
13
|
+
calls: p.array(p.struct({target: p.address, callData: p.bytes}))
|
|
14
|
+
}, p.array(p.struct({success: p.bool, returnData: p.bytes})))
|
|
15
|
+
|
|
16
|
+
export type MulticallResult<T extends AbiFunction<any, any>> = {
|
|
17
|
+
success: true
|
|
18
|
+
value: FunctionReturn<T>
|
|
73
19
|
} | {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
20
|
+
success: false
|
|
21
|
+
returnData?: string
|
|
22
|
+
value?: undefined
|
|
77
23
|
}
|
|
78
24
|
|
|
25
|
+
type AnyFunc = AbiFunction<any, any>
|
|
26
|
+
type AggregateTuple<T extends AnyFunc = AnyFunc> = [func: T, address: string, args: T extends AnyFunc ? FunctionArguments<T> : never]
|
|
27
|
+
type Call = {target: string, callData: string}
|
|
79
28
|
|
|
80
29
|
export class Multicall extends ContractBase {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
return results
|
|
30
|
+
static aggregate = aggregate
|
|
31
|
+
static tryAggregate = tryAggregate
|
|
32
|
+
|
|
33
|
+
aggregate<TF extends AnyFunc>(
|
|
34
|
+
func: TF,
|
|
35
|
+
address: string,
|
|
36
|
+
calls: FunctionArguments<TF>[],
|
|
37
|
+
paging?: number
|
|
38
|
+
): Promise<FunctionReturn<TF>[]>
|
|
39
|
+
|
|
40
|
+
aggregate<TF extends AnyFunc>(
|
|
41
|
+
func: TF,
|
|
42
|
+
calls: [address: string, args: FunctionArguments<TF>][],
|
|
43
|
+
paging?: number
|
|
44
|
+
): Promise<FunctionReturn<TF>[]>
|
|
45
|
+
|
|
46
|
+
aggregate(
|
|
47
|
+
calls: AggregateTuple[],
|
|
48
|
+
paging?: number
|
|
49
|
+
): Promise<any[]>
|
|
50
|
+
|
|
51
|
+
async aggregate(...args: any[]): Promise<any[]> {
|
|
52
|
+
let [calls, funcs, page] = this.makeCalls(args)
|
|
53
|
+
let size = calls.length
|
|
54
|
+
let results = new Array(size)
|
|
55
|
+
for (let [from, to] of splitIntoPages(size, page)) {
|
|
56
|
+
let {returnData} = await this.eth_call(aggregate, {calls: calls.slice(from, to)})
|
|
57
|
+
for (let i = from; i < to; i++) {
|
|
58
|
+
let data = returnData[i - from]
|
|
59
|
+
results[i] = funcs[i].decodeResult(data)
|
|
60
|
+
}
|
|
114
61
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
results[i] = {success: false}
|
|
153
|
-
}
|
|
62
|
+
return results
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
tryAggregate<TF extends AnyFunc>(
|
|
66
|
+
func: TF,
|
|
67
|
+
address: string,
|
|
68
|
+
calls: FunctionArguments<TF>[],
|
|
69
|
+
paging?: number
|
|
70
|
+
): Promise<MulticallResult<TF>[]>
|
|
71
|
+
|
|
72
|
+
tryAggregate<TF extends AnyFunc>(
|
|
73
|
+
func: TF,
|
|
74
|
+
calls: [address: string, args: FunctionArguments<TF>][],
|
|
75
|
+
paging?: number
|
|
76
|
+
): Promise<MulticallResult<TF>[]>
|
|
77
|
+
|
|
78
|
+
tryAggregate(
|
|
79
|
+
calls: AggregateTuple[],
|
|
80
|
+
paging?: number
|
|
81
|
+
): Promise<MulticallResult<any>[]>
|
|
82
|
+
|
|
83
|
+
async tryAggregate(...args: any[]): Promise<any[]> {
|
|
84
|
+
let [calls, funcs, page] = this.makeCalls(args)
|
|
85
|
+
let size = calls.length
|
|
86
|
+
let results = new Array(size)
|
|
87
|
+
for (let [from, to] of splitIntoPages(size, page)) {
|
|
88
|
+
let response = await this.eth_call(tryAggregate, {
|
|
89
|
+
requireSuccess: false,
|
|
90
|
+
calls: calls.slice(from, to)
|
|
91
|
+
})
|
|
92
|
+
for (let i = from; i < to; i++) {
|
|
93
|
+
let res = response[i - from]
|
|
94
|
+
if (res.success) {
|
|
95
|
+
try {
|
|
96
|
+
results[i] = {
|
|
97
|
+
success: true,
|
|
98
|
+
value: funcs[i].decodeResult(res.returnData)
|
|
154
99
|
}
|
|
100
|
+
} catch (err: any) {
|
|
101
|
+
results[i] = {success: false, returnData: res.returnData}
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
results[i] = {success: false}
|
|
155
105
|
}
|
|
156
|
-
|
|
106
|
+
}
|
|
157
107
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
case 3: {
|
|
186
|
-
let func: AnyFunc = args[0]
|
|
187
|
-
let address: string = args[1]
|
|
188
|
-
let list: any[][] = args[2]
|
|
189
|
-
let calls = new Array(list.length)
|
|
190
|
-
let funcs = new Array(list.length)
|
|
191
|
-
for (let i = 0; i < list.length; i++) {
|
|
192
|
-
let args = list[i]
|
|
193
|
-
calls[i] = [address, func.encode(args)]
|
|
194
|
-
funcs[i] = func
|
|
195
|
-
}
|
|
196
|
-
return [calls, funcs, page]
|
|
197
|
-
}
|
|
198
|
-
default:
|
|
199
|
-
throw new Error('unexpected number of arguments')
|
|
108
|
+
return results
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private makeCalls(args: any[]): [calls: Call[], funcs: AnyFunc[], page: number] {
|
|
112
|
+
let page = typeof args[args.length - 1] == 'number' ? args.pop()! : Number.MAX_SAFE_INTEGER
|
|
113
|
+
switch (args.length) {
|
|
114
|
+
case 1: {
|
|
115
|
+
let list: AggregateTuple[] = args[0]
|
|
116
|
+
let calls: Call[] = new Array(list.length)
|
|
117
|
+
let funcs = new Array(list.length)
|
|
118
|
+
for (let i = 0; i < list.length; i++) {
|
|
119
|
+
let [func, address, args] = list[i]
|
|
120
|
+
calls[i] = {target: address, callData: func.encode(args)}
|
|
121
|
+
funcs[i] = func
|
|
122
|
+
}
|
|
123
|
+
return [calls, funcs, page]
|
|
124
|
+
}
|
|
125
|
+
case 2: {
|
|
126
|
+
let func: AnyFunc = args[0]
|
|
127
|
+
let list: [address: string, args: any][] = args[1]
|
|
128
|
+
let calls: Call[] = new Array(list.length)
|
|
129
|
+
let funcs = new Array(list.length)
|
|
130
|
+
for (let i = 0; i < list.length; i++) {
|
|
131
|
+
let [address, args] = list[i]
|
|
132
|
+
calls[i] = {target: address, callData: func.encode(args)}
|
|
133
|
+
funcs[i] = func
|
|
200
134
|
}
|
|
135
|
+
return [calls, funcs, page]
|
|
136
|
+
}
|
|
137
|
+
case 3: {
|
|
138
|
+
let func: AnyFunc = args[0]
|
|
139
|
+
let address: string = args[1]
|
|
140
|
+
let list: any = args[2]
|
|
141
|
+
let calls: Call[] = new Array(list.length)
|
|
142
|
+
let funcs = new Array(list.length)
|
|
143
|
+
for (let i = 0; i < list.length; i++) {
|
|
144
|
+
let args = list[i]
|
|
145
|
+
calls[i] = {target: address, callData: func.encode(args)}
|
|
146
|
+
funcs[i] = func
|
|
147
|
+
}
|
|
148
|
+
return [calls, funcs, page]
|
|
149
|
+
}
|
|
150
|
+
default:
|
|
151
|
+
throw new Error('unexpected number of arguments')
|
|
201
152
|
}
|
|
153
|
+
}
|
|
202
154
|
}
|
|
203
155
|
|
|
204
156
|
|
|
205
157
|
function* splitIntoPages(size: number, page: number): Iterable<[from: number, to: number]> {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
158
|
+
let from = 0
|
|
159
|
+
while (size) {
|
|
160
|
+
let step = Math.min(page, size)
|
|
161
|
+
let to = from + step
|
|
162
|
+
yield [from, to]
|
|
163
|
+
size -= step
|
|
164
|
+
from = to
|
|
165
|
+
}
|
|
214
166
|
}
|
|
215
|
-
*/
|