@subsquid/evm-typegen 4.5.1 → 5.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/lib/abi.support.d.ts +3 -0
- package/lib/abi.support.d.ts.map +1 -0
- package/lib/abi.support.js +9 -0
- package/lib/abi.support.js.map +1 -0
- package/lib/chainIds.d.ts +3 -0
- package/lib/chainIds.d.ts.map +1 -0
- package/lib/chainIds.js +268 -0
- package/lib/chainIds.js.map +1 -0
- package/lib/description.d.ts +76 -0
- package/lib/description.d.ts.map +1 -0
- package/lib/description.js +156 -0
- package/lib/description.js.map +1 -0
- package/lib/main.js +68 -42
- package/lib/main.js.map +1 -1
- package/lib/multicall.d.ts +17 -13
- package/lib/multicall.d.ts.map +1 -1
- package/lib/multicall.js +9 -7
- package/lib/multicall.js.map +1 -1
- package/lib/typegen.d.ts +8 -23
- package/lib/typegen.d.ts.map +1 -1
- package/lib/typegen.js +267 -187
- package/lib/typegen.js.map +1 -1
- package/package.json +11 -10
- package/src/abi.support.ts +2 -0
- package/src/chainIds.ts +315 -0
- package/src/description.ts +221 -0
- package/src/main.ts +209 -174
- package/src/multicall.ts +171 -159
- package/src/typegen.ts +276 -227
- package/lib/util/types.d.ts +0 -3
- package/lib/util/types.d.ts.map +0 -1
- package/lib/util/types.js +0 -46
- package/lib/util/types.js.map +0 -1
- package/src/util/types.ts +0 -54
package/src/multicall.ts
CHANGED
|
@@ -1,174 +1,186 @@
|
|
|
1
1
|
import * as p from '@subsquid/evm-codec'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
2
|
+
import {func, ContractBase, type AbiFunction, type FunctionReturn, type FunctionArguments} from '@subsquid/evm-abi'
|
|
3
|
+
|
|
4
|
+
// aggregate((address,bytes)[])
|
|
5
|
+
const aggregate = func(
|
|
6
|
+
'0x252dba42',
|
|
7
|
+
{
|
|
8
|
+
calls: p.array(
|
|
9
|
+
p.struct({
|
|
10
|
+
target: p.address,
|
|
11
|
+
callData: p.bytes,
|
|
12
|
+
}),
|
|
13
|
+
),
|
|
14
|
+
},
|
|
15
|
+
p.struct({blockNumber: p.uint256, returnData: p.array(p.bytes)}),
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
// tryAggregate(bool,(address,bytes)[])
|
|
19
|
+
const tryAggregate = func(
|
|
20
|
+
'0xbce38bd7',
|
|
21
|
+
{
|
|
22
|
+
requireSuccess: p.bool,
|
|
23
|
+
calls: p.array(p.struct({target: p.address, callData: p.bytes})),
|
|
24
|
+
},
|
|
25
|
+
p.array(p.struct({success: p.bool, returnData: p.bytes})),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
export type MulticallResult<T extends AbiFunction<any, any>> =
|
|
29
|
+
| {
|
|
30
|
+
success: true
|
|
31
|
+
value: FunctionReturn<T>
|
|
32
|
+
}
|
|
33
|
+
| {
|
|
34
|
+
success: false
|
|
35
|
+
returnData?: string
|
|
36
|
+
value?: undefined
|
|
37
|
+
}
|
|
24
38
|
|
|
25
39
|
type AnyFunc = AbiFunction<any, any>
|
|
26
|
-
type AggregateTuple<T extends AnyFunc = AnyFunc> = [
|
|
27
|
-
|
|
40
|
+
type AggregateTuple<T extends AnyFunc = AnyFunc> = [
|
|
41
|
+
func: T,
|
|
42
|
+
address: string,
|
|
43
|
+
args: T extends AnyFunc ? FunctionArguments<T> : never,
|
|
44
|
+
]
|
|
45
|
+
type Call = {target: string; func: AnyFunc; callData: string}
|
|
28
46
|
|
|
29
47
|
export class Multicall extends ContractBase {
|
|
30
|
-
|
|
31
|
-
|
|
48
|
+
static aggregate = aggregate
|
|
49
|
+
static tryAggregate = tryAggregate
|
|
50
|
+
|
|
51
|
+
aggregate<TF extends AnyFunc>(
|
|
52
|
+
func: TF,
|
|
53
|
+
address: string,
|
|
54
|
+
calls: FunctionArguments<TF>[],
|
|
55
|
+
pageSize?: number,
|
|
56
|
+
): Promise<FunctionReturn<TF>[]>
|
|
57
|
+
|
|
58
|
+
aggregate<TF extends AnyFunc>(
|
|
59
|
+
func: TF,
|
|
60
|
+
calls: (readonly [address: string, args: FunctionArguments<TF>])[],
|
|
61
|
+
pageSize?: number,
|
|
62
|
+
): Promise<FunctionReturn<TF>[]>
|
|
63
|
+
|
|
64
|
+
aggregate(calls: AggregateTuple[], pageSize?: number): Promise<any[]>
|
|
65
|
+
|
|
66
|
+
async aggregate(...args: any[]): Promise<any[]> {
|
|
67
|
+
let [calls, pageSize] = this.makeCalls(args)
|
|
68
|
+
if (calls.length === 0) return []
|
|
69
|
+
|
|
70
|
+
const pages = Array.from(splitArray(pageSize, calls))
|
|
71
|
+
const results = await Promise.all(
|
|
72
|
+
pages.map(async (page) => {
|
|
73
|
+
const {returnData} = await this.eth_call(aggregate, {calls: page})
|
|
74
|
+
return returnData.map((data, i) => page[i].func.decodeResult(data))
|
|
75
|
+
}),
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return results.flat()
|
|
79
|
+
}
|
|
32
80
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
const pages = Array.from(splitArray(pageSize, calls))
|
|
89
|
-
const results = await Promise.all(
|
|
90
|
-
pages.map(async (page) => {
|
|
91
|
-
const response = await this.eth_call(tryAggregate, {
|
|
92
|
-
requireSuccess: false,
|
|
93
|
-
calls: page,
|
|
94
|
-
})
|
|
95
|
-
return response.map((res, i) => {
|
|
96
|
-
if (res.success) {
|
|
97
|
-
try {
|
|
98
|
-
return {
|
|
99
|
-
success: true,
|
|
100
|
-
value: page[i].func.decodeResult(res.returnData)
|
|
101
|
-
}
|
|
102
|
-
} catch (err: any) {
|
|
103
|
-
return {success: false, returnData: res.returnData}
|
|
81
|
+
tryAggregate<TF extends AnyFunc>(
|
|
82
|
+
func: TF,
|
|
83
|
+
address: string,
|
|
84
|
+
calls: FunctionArguments<TF>[],
|
|
85
|
+
pageSize?: number,
|
|
86
|
+
): Promise<MulticallResult<TF>[]>
|
|
87
|
+
|
|
88
|
+
tryAggregate<TF extends AnyFunc>(
|
|
89
|
+
func: TF,
|
|
90
|
+
calls: (readonly [address: string, args: FunctionArguments<TF>])[],
|
|
91
|
+
pageSize?: number,
|
|
92
|
+
): Promise<MulticallResult<TF>[]>
|
|
93
|
+
|
|
94
|
+
tryAggregate(calls: AggregateTuple[], pageSize?: number): Promise<MulticallResult<any>[]>
|
|
95
|
+
|
|
96
|
+
async tryAggregate(...args: any[]): Promise<any[]> {
|
|
97
|
+
let [calls, pageSize] = this.makeCalls(args)
|
|
98
|
+
if (calls.length === 0) return []
|
|
99
|
+
|
|
100
|
+
const pages = Array.from(splitArray(pageSize, calls))
|
|
101
|
+
const results = await Promise.all(
|
|
102
|
+
pages.map(async (page) => {
|
|
103
|
+
const response = await this.eth_call(tryAggregate, {
|
|
104
|
+
requireSuccess: false,
|
|
105
|
+
calls: page,
|
|
106
|
+
})
|
|
107
|
+
return response.map((res, i) => {
|
|
108
|
+
if (res.success) {
|
|
109
|
+
try {
|
|
110
|
+
return {
|
|
111
|
+
success: true,
|
|
112
|
+
value: page[i].func.decodeResult(res.returnData),
|
|
113
|
+
}
|
|
114
|
+
} catch (err: any) {
|
|
115
|
+
return {success: false, returnData: res.returnData}
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
return {success: false}
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
}),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
return results.flat()
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private makeCalls(args: any[]): [calls: Call[], page: number] {
|
|
128
|
+
let page = typeof args[args.length - 1] == 'number' ? args.pop()! : Number.MAX_SAFE_INTEGER
|
|
129
|
+
switch (args.length) {
|
|
130
|
+
case 1: {
|
|
131
|
+
let list: AggregateTuple[] = args[0]
|
|
132
|
+
let calls: Call[] = new Array(list.length)
|
|
133
|
+
for (let i = 0; i < list.length; i++) {
|
|
134
|
+
let [func, address, args] = list[i]
|
|
135
|
+
calls[i] = {target: address, callData: func.encode(args), func}
|
|
104
136
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
let calls: Call[] = new Array(list.length)
|
|
131
|
-
for (let i = 0; i < list.length; i++) {
|
|
132
|
-
let [address, args] = list[i]
|
|
133
|
-
calls[i] = {target: address, callData: func.encode(args), func}
|
|
134
|
-
}
|
|
135
|
-
return [calls, 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
|
-
for (let i = 0; i < list.length; i++) {
|
|
143
|
-
let args = list[i]
|
|
144
|
-
calls[i] = {target: address, callData: func.encode(args), func}
|
|
137
|
+
return [calls, page]
|
|
138
|
+
}
|
|
139
|
+
case 2: {
|
|
140
|
+
let func: AnyFunc = args[0]
|
|
141
|
+
let list: [address: string, args: any][] = args[1]
|
|
142
|
+
let calls: Call[] = new Array(list.length)
|
|
143
|
+
for (let i = 0; i < list.length; i++) {
|
|
144
|
+
let [address, args] = list[i]
|
|
145
|
+
calls[i] = {target: address, callData: func.encode(args), func}
|
|
146
|
+
}
|
|
147
|
+
return [calls, page]
|
|
148
|
+
}
|
|
149
|
+
case 3: {
|
|
150
|
+
let func: AnyFunc = args[0]
|
|
151
|
+
let address: string = args[1]
|
|
152
|
+
let list: any = args[2]
|
|
153
|
+
let calls: Call[] = new Array(list.length)
|
|
154
|
+
for (let i = 0; i < list.length; i++) {
|
|
155
|
+
let args = list[i]
|
|
156
|
+
calls[i] = {target: address, callData: func.encode(args), func}
|
|
157
|
+
}
|
|
158
|
+
return [calls, page]
|
|
159
|
+
}
|
|
160
|
+
default:
|
|
161
|
+
throw new Error(`Unexpected number of arguments: ${args.length}`)
|
|
145
162
|
}
|
|
146
|
-
return [calls, page]
|
|
147
|
-
}
|
|
148
|
-
default:
|
|
149
|
-
throw new Error(`Unexpected number of arguments: ${args.length}`)
|
|
150
163
|
}
|
|
151
|
-
}
|
|
152
164
|
}
|
|
153
165
|
|
|
154
166
|
function* splitSlice(maxSize: number, beg: number, end?: number): Iterable<[beg: number, end: number]> {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
167
|
+
maxSize = Math.max(1, maxSize)
|
|
168
|
+
end = end ?? Number.MAX_SAFE_INTEGER
|
|
169
|
+
while (beg < end) {
|
|
170
|
+
let left = end - beg
|
|
171
|
+
let splits = Math.ceil(left / maxSize)
|
|
172
|
+
let step = Math.round(left / splits)
|
|
173
|
+
yield [beg, beg + step]
|
|
174
|
+
beg += step
|
|
175
|
+
}
|
|
164
176
|
}
|
|
165
177
|
|
|
166
178
|
function* splitArray<T>(maxSize: number, arr: T[]): Iterable<T[]> {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
179
|
+
if (arr.length <= maxSize) {
|
|
180
|
+
yield arr
|
|
181
|
+
} else {
|
|
182
|
+
for (let [beg, end] of splitSlice(maxSize, 0, arr.length)) {
|
|
183
|
+
yield arr.slice(beg, end)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|