@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/chainIds.ts
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import {closest} from 'fastest-levenshtein'
|
|
2
|
+
import * as validator from '@subsquid/util-internal-commander'
|
|
3
|
+
import {InvalidOptionArgumentError} from 'commander'
|
|
4
|
+
|
|
5
|
+
// ref: https://docs.etherscan.io/supported-chains
|
|
6
|
+
export const CHAIN_IDS: Record<string, number> = {
|
|
7
|
+
// Ethereum Mainnet
|
|
8
|
+
'ethereum-mainnet': 1,
|
|
9
|
+
'mainnet': 1,
|
|
10
|
+
'ethereum': 1,
|
|
11
|
+
'eth': 1,
|
|
12
|
+
|
|
13
|
+
// Sepolia Testnet
|
|
14
|
+
'sepolia-testnet': 11155111,
|
|
15
|
+
'sepolia': 11155111,
|
|
16
|
+
|
|
17
|
+
// Holesky Testnet
|
|
18
|
+
'holesky-testnet': 17000,
|
|
19
|
+
'holesky': 17000,
|
|
20
|
+
|
|
21
|
+
// Hoodi Testnet
|
|
22
|
+
'hoodi-testnet': 560048,
|
|
23
|
+
'hoodi': 560048,
|
|
24
|
+
|
|
25
|
+
// BNB Smart Chain Mainnet
|
|
26
|
+
'bnb-smart-chain-mainnet': 56,
|
|
27
|
+
'bsc': 56,
|
|
28
|
+
'bnb': 56,
|
|
29
|
+
|
|
30
|
+
// BNB Smart Chain Testnet
|
|
31
|
+
'bnb-smart-chain-testnet': 97,
|
|
32
|
+
'bsc-testnet': 97,
|
|
33
|
+
|
|
34
|
+
// Polygon Mainnet
|
|
35
|
+
'polygon-mainnet': 137,
|
|
36
|
+
'polygon': 137,
|
|
37
|
+
'matic': 137,
|
|
38
|
+
|
|
39
|
+
// Polygon Amoy Testnet
|
|
40
|
+
'polygon-amoy-testnet': 80002,
|
|
41
|
+
'amoy': 80002,
|
|
42
|
+
'polygon-amoy': 80002,
|
|
43
|
+
|
|
44
|
+
// Base Mainnet
|
|
45
|
+
'base-mainnet': 8453,
|
|
46
|
+
'base': 8453,
|
|
47
|
+
|
|
48
|
+
// Base Sepolia Testnet
|
|
49
|
+
'base-sepolia-testnet': 84532,
|
|
50
|
+
'base-sepolia': 84532,
|
|
51
|
+
|
|
52
|
+
// Arbitrum One Mainnet
|
|
53
|
+
'arbitrum-one-mainnet': 42161,
|
|
54
|
+
'arbitrum': 42161,
|
|
55
|
+
'arb': 42161,
|
|
56
|
+
'arbitrum-one': 42161,
|
|
57
|
+
|
|
58
|
+
// Arbitrum Nova Mainnet
|
|
59
|
+
'arbitrum-nova-mainnet': 42170,
|
|
60
|
+
'arbitrum-nova': 42170,
|
|
61
|
+
'nova': 42170,
|
|
62
|
+
|
|
63
|
+
// Arbitrum Sepolia Testnet
|
|
64
|
+
'arbitrum-sepolia-testnet': 421614,
|
|
65
|
+
'arbitrum-sepolia': 421614,
|
|
66
|
+
'arb-sepolia': 421614,
|
|
67
|
+
|
|
68
|
+
// Linea Mainnet
|
|
69
|
+
'linea-mainnet': 59144,
|
|
70
|
+
'linea': 59144,
|
|
71
|
+
|
|
72
|
+
// Linea Sepolia Testnet
|
|
73
|
+
'linea-sepolia-testnet': 59141,
|
|
74
|
+
'linea-sepolia': 59141,
|
|
75
|
+
|
|
76
|
+
// Blast Mainnet
|
|
77
|
+
'blast-mainnet': 81457,
|
|
78
|
+
'blast': 81457,
|
|
79
|
+
|
|
80
|
+
// Blast Sepolia Testnet
|
|
81
|
+
'blast-sepolia-testnet': 168587773,
|
|
82
|
+
'blast-sepolia': 168587773,
|
|
83
|
+
|
|
84
|
+
// OP Mainnet
|
|
85
|
+
'op-mainnet': 10,
|
|
86
|
+
'optimism': 10,
|
|
87
|
+
'op': 10,
|
|
88
|
+
|
|
89
|
+
// OP Sepolia Testnet
|
|
90
|
+
'op-sepolia-testnet': 11155420,
|
|
91
|
+
'op-sepolia': 11155420,
|
|
92
|
+
'optimism-sepolia': 11155420,
|
|
93
|
+
|
|
94
|
+
// Avalanche C-Chain
|
|
95
|
+
'avalanche-c-chain': 43114,
|
|
96
|
+
'avalanche': 43114,
|
|
97
|
+
'avax': 43114,
|
|
98
|
+
|
|
99
|
+
// Avalanche Fuji Testnet
|
|
100
|
+
'avalanche-fuji-testnet': 43113,
|
|
101
|
+
'fuji': 43113,
|
|
102
|
+
'avalanche-fuji': 43113,
|
|
103
|
+
|
|
104
|
+
// BitTorrent Chain Mainnet
|
|
105
|
+
'bittorrent-chain-mainnet': 199,
|
|
106
|
+
'bittorrent': 199,
|
|
107
|
+
'btt': 199,
|
|
108
|
+
|
|
109
|
+
// BitTorrent Chain Testnet
|
|
110
|
+
'bittorrent-chain-testnet': 1029,
|
|
111
|
+
'bittorrent-testnet': 1029,
|
|
112
|
+
'btt-testnet': 1029,
|
|
113
|
+
|
|
114
|
+
// Celo Mainnet
|
|
115
|
+
'celo-mainnet': 42220,
|
|
116
|
+
'celo': 42220,
|
|
117
|
+
|
|
118
|
+
// Celo Sepolia Testnet
|
|
119
|
+
'celo-sepolia-testnet': 11142220,
|
|
120
|
+
'celo-sepolia': 11142220,
|
|
121
|
+
|
|
122
|
+
// Fraxtal Mainnet
|
|
123
|
+
'fraxtal-mainnet': 252,
|
|
124
|
+
'fraxtal': 252,
|
|
125
|
+
|
|
126
|
+
// Fraxtal Hoodi Testnet
|
|
127
|
+
'fraxtal-hoodi-testnet': 2523,
|
|
128
|
+
'fraxtal-hoodi': 2523,
|
|
129
|
+
|
|
130
|
+
// Gnosis
|
|
131
|
+
'gnosis': 100,
|
|
132
|
+
'gno': 100,
|
|
133
|
+
'xdai': 100,
|
|
134
|
+
|
|
135
|
+
// Mantle Mainnet
|
|
136
|
+
'mantle-mainnet': 5000,
|
|
137
|
+
'mantle': 5000,
|
|
138
|
+
|
|
139
|
+
// Mantle Sepolia Testnet
|
|
140
|
+
'mantle-sepolia-testnet': 5003,
|
|
141
|
+
'mantle-sepolia': 5003,
|
|
142
|
+
|
|
143
|
+
// Memecore Mainnet
|
|
144
|
+
'memecore-mainnet': 4352,
|
|
145
|
+
'memecore': 4352,
|
|
146
|
+
|
|
147
|
+
// Memecore Testnet
|
|
148
|
+
'memecore-testnet': 43521,
|
|
149
|
+
|
|
150
|
+
// Moonbeam Mainnet
|
|
151
|
+
'moonbeam-mainnet': 1284,
|
|
152
|
+
'moonbeam': 1284,
|
|
153
|
+
|
|
154
|
+
// Moonriver Mainnet
|
|
155
|
+
'moonriver-mainnet': 1285,
|
|
156
|
+
'moonriver': 1285,
|
|
157
|
+
|
|
158
|
+
// Moonbase Alpha Testnet
|
|
159
|
+
'moonbase-alpha-testnet': 1287,
|
|
160
|
+
'moonbase': 1287,
|
|
161
|
+
'moonbase-alpha': 1287,
|
|
162
|
+
|
|
163
|
+
// opBNB Mainnet
|
|
164
|
+
'opbnb-mainnet': 204,
|
|
165
|
+
'opbnb': 204,
|
|
166
|
+
|
|
167
|
+
// opBNB Testnet
|
|
168
|
+
'opbnb-testnet': 5611,
|
|
169
|
+
|
|
170
|
+
// Scroll Mainnet
|
|
171
|
+
'scroll-mainnet': 534352,
|
|
172
|
+
'scroll': 534352,
|
|
173
|
+
|
|
174
|
+
// Scroll Sepolia Testnet
|
|
175
|
+
'scroll-sepolia-testnet': 534351,
|
|
176
|
+
'scroll-sepolia': 534351,
|
|
177
|
+
|
|
178
|
+
// Taiko Mainnet
|
|
179
|
+
'taiko-mainnet': 167000,
|
|
180
|
+
'taiko': 167000,
|
|
181
|
+
|
|
182
|
+
// Taiko Hoodi
|
|
183
|
+
'taiko-hoodi': 167013,
|
|
184
|
+
|
|
185
|
+
// XDC Mainnet
|
|
186
|
+
'xdc-mainnet': 50,
|
|
187
|
+
'xdc': 50,
|
|
188
|
+
|
|
189
|
+
// XDC Apothem Testnet
|
|
190
|
+
'xdc-apothem-testnet': 51,
|
|
191
|
+
'xdc-apothem': 51,
|
|
192
|
+
'apothem': 51,
|
|
193
|
+
|
|
194
|
+
// ApeChain Mainnet
|
|
195
|
+
'apechain-mainnet': 33139,
|
|
196
|
+
'apechain': 33139,
|
|
197
|
+
'ape': 33139,
|
|
198
|
+
|
|
199
|
+
// ApeChain Curtis Testnet
|
|
200
|
+
'apechain-curtis-testnet': 33111,
|
|
201
|
+
'apechain-curtis': 33111,
|
|
202
|
+
'curtis': 33111,
|
|
203
|
+
|
|
204
|
+
// World Mainnet
|
|
205
|
+
'world-mainnet': 480,
|
|
206
|
+
'world': 480,
|
|
207
|
+
|
|
208
|
+
// World Sepolia Testnet
|
|
209
|
+
'world-sepolia-testnet': 4801,
|
|
210
|
+
'world-sepolia': 4801,
|
|
211
|
+
|
|
212
|
+
// Sonic Mainnet
|
|
213
|
+
'sonic-mainnet': 146,
|
|
214
|
+
'sonic': 146,
|
|
215
|
+
|
|
216
|
+
// Sonic Testnet
|
|
217
|
+
'sonic-testnet': 14601,
|
|
218
|
+
|
|
219
|
+
// Unichain Mainnet
|
|
220
|
+
'unichain-mainnet': 130,
|
|
221
|
+
'unichain': 130,
|
|
222
|
+
|
|
223
|
+
// Unichain Sepolia Testnet
|
|
224
|
+
'unichain-sepolia-testnet': 1301,
|
|
225
|
+
'unichain-sepolia': 1301,
|
|
226
|
+
|
|
227
|
+
// Abstract Mainnet
|
|
228
|
+
'abstract-mainnet': 2741,
|
|
229
|
+
'abstract': 2741,
|
|
230
|
+
|
|
231
|
+
// Abstract Sepolia Testnet
|
|
232
|
+
'abstract-sepolia-testnet': 11124,
|
|
233
|
+
'abstract-sepolia': 11124,
|
|
234
|
+
|
|
235
|
+
// Berachain Mainnet
|
|
236
|
+
'berachain-mainnet': 80094,
|
|
237
|
+
'berachain': 80094,
|
|
238
|
+
'bera': 80094,
|
|
239
|
+
|
|
240
|
+
// Berachain Bepolia Testnet
|
|
241
|
+
'berachain-bepolia-testnet': 80069,
|
|
242
|
+
'berachain-bepolia': 80069,
|
|
243
|
+
'bepolia': 80069,
|
|
244
|
+
|
|
245
|
+
// Swellchain Mainnet
|
|
246
|
+
'swellchain-mainnet': 1923,
|
|
247
|
+
'swellchain': 1923,
|
|
248
|
+
'swell': 1923,
|
|
249
|
+
|
|
250
|
+
// Swellchain Testnet
|
|
251
|
+
'swellchain-testnet': 1924,
|
|
252
|
+
'swell-testnet': 1924,
|
|
253
|
+
|
|
254
|
+
// Monad Mainnet
|
|
255
|
+
'monad-mainnet': 143,
|
|
256
|
+
'monad': 143,
|
|
257
|
+
|
|
258
|
+
// Monad Testnet
|
|
259
|
+
'monad-testnet': 10143,
|
|
260
|
+
|
|
261
|
+
// HyperEVM Mainnet
|
|
262
|
+
'hyperevm-mainnet': 999,
|
|
263
|
+
'hyperevm': 999,
|
|
264
|
+
|
|
265
|
+
// Katana Mainnet
|
|
266
|
+
'katana-mainnet': 747474,
|
|
267
|
+
'katana': 747474,
|
|
268
|
+
|
|
269
|
+
// Katana Bokuto
|
|
270
|
+
'katana-bokuto': 737373,
|
|
271
|
+
'bokuto': 737373,
|
|
272
|
+
|
|
273
|
+
// Sei Mainnet
|
|
274
|
+
'sei-mainnet': 1329,
|
|
275
|
+
'sei': 1329,
|
|
276
|
+
|
|
277
|
+
// Sei Testnet
|
|
278
|
+
'sei-testnet': 1328,
|
|
279
|
+
|
|
280
|
+
// Stable Mainnet
|
|
281
|
+
'stable-mainnet': 988,
|
|
282
|
+
'stable': 988,
|
|
283
|
+
|
|
284
|
+
// Stable Testnet
|
|
285
|
+
'stable-testnet': 2201,
|
|
286
|
+
|
|
287
|
+
// Plasma Mainnet
|
|
288
|
+
'plasma-mainnet': 9745,
|
|
289
|
+
'plasma': 9745,
|
|
290
|
+
|
|
291
|
+
// Plasma Testnet
|
|
292
|
+
'plasma-testnet': 9746,
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function chainIdOption(chainId?: string): number | undefined {
|
|
296
|
+
if (chainId == null) {
|
|
297
|
+
return undefined
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// @ts-expect-error - chainId is a string
|
|
301
|
+
if (!isNaN(chainId)) {
|
|
302
|
+
return validator.positiveInt(chainId)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const normalizedChainId = chainId.toLowerCase()
|
|
306
|
+
|
|
307
|
+
if (normalizedChainId in CHAIN_IDS) {
|
|
308
|
+
return CHAIN_IDS[normalizedChainId]
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const suggestion = closest(normalizedChainId, Object.keys(CHAIN_IDS))
|
|
312
|
+
throw new InvalidOptionArgumentError(
|
|
313
|
+
`Unknown chain: "${chainId}". Did you mean "${suggestion}"? Alternatively, provide a numeric chain ID.`
|
|
314
|
+
)
|
|
315
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import {keccak256} from '@subsquid/evm-abi'
|
|
2
|
+
import type {Abi, AbiEvent, AbiFunction, AbiParameter} from 'abitype'
|
|
3
|
+
|
|
4
|
+
export interface ContractDef {
|
|
5
|
+
events: EventDef[]
|
|
6
|
+
functions: FunctionDef[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface DocDef {
|
|
10
|
+
notice?: string
|
|
11
|
+
dev?: string
|
|
12
|
+
params?: Record<string, string>
|
|
13
|
+
returns?: Record<string, string>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** NatSpec documentation extracted from a compilation artifact's userdoc/devdoc fields. */
|
|
17
|
+
export interface NatSpec {
|
|
18
|
+
userdoc?: {
|
|
19
|
+
methods?: Record<string, {notice?: string}>
|
|
20
|
+
events?: Record<string, {notice?: string}>
|
|
21
|
+
}
|
|
22
|
+
devdoc?: {
|
|
23
|
+
methods?: Record<string, {details?: string; params?: Record<string, string>; returns?: Record<string, string>}>
|
|
24
|
+
events?: Record<string, {details?: string; params?: Record<string, string>}>
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface EventDef {
|
|
29
|
+
name: string
|
|
30
|
+
signature: string
|
|
31
|
+
topic: string
|
|
32
|
+
inputs: FieldDef[]
|
|
33
|
+
key: string
|
|
34
|
+
typeName: string
|
|
35
|
+
docs?: DocDef
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface FunctionDef {
|
|
39
|
+
name: string
|
|
40
|
+
signature: string
|
|
41
|
+
selector: string
|
|
42
|
+
inputs: FieldDef[]
|
|
43
|
+
outputs: FieldDef[]
|
|
44
|
+
key: string
|
|
45
|
+
paramsTypeName: string
|
|
46
|
+
returnTypeName: string
|
|
47
|
+
docs?: DocDef
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface FieldDef {
|
|
51
|
+
name: string
|
|
52
|
+
type: TypeDef
|
|
53
|
+
indexed?: boolean
|
|
54
|
+
doc?: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type TypeDef =
|
|
58
|
+
| {kind: 'primitive'; name: string}
|
|
59
|
+
| {kind: 'array'; item: TypeDef}
|
|
60
|
+
| {kind: 'fixedArray'; item: TypeDef; size: number}
|
|
61
|
+
| {kind: 'tuple'; fields: FieldDef[]}
|
|
62
|
+
|
|
63
|
+
export function describe(abi: Abi, natspec?: NatSpec): ContractDef {
|
|
64
|
+
const rawEvents = abi.filter((x) => x.type === 'event') as AbiEvent[]
|
|
65
|
+
const rawFunctions = abi.filter((x) => x.type === 'function') as AbiFunction[]
|
|
66
|
+
|
|
67
|
+
const eventSuffix = overloadSuffixer(rawEvents)
|
|
68
|
+
const functionSuffix = overloadSuffixer(rawFunctions)
|
|
69
|
+
|
|
70
|
+
const events: EventDef[] = rawEvents.map((e) => {
|
|
71
|
+
const signature = eventSignature(e)
|
|
72
|
+
const docs = buildEventDocs(signature, natspec)
|
|
73
|
+
const inputs = e.inputs.map((p, i) => toFieldDef(p, i, true))
|
|
74
|
+
annotateParamDocs(inputs, docs?.params)
|
|
75
|
+
return {
|
|
76
|
+
name: e.name,
|
|
77
|
+
signature,
|
|
78
|
+
topic: `0x${keccak256(signature).toString('hex')}`,
|
|
79
|
+
inputs,
|
|
80
|
+
key: eventSuffix(e, e.name),
|
|
81
|
+
typeName: eventSuffix(e, `${capitalize(e.name)}EventArgs`),
|
|
82
|
+
docs,
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const functions: FunctionDef[] = rawFunctions.map((f) => {
|
|
87
|
+
const signature = fnSignature(f)
|
|
88
|
+
const docs = buildFunctionDocs(signature, natspec)
|
|
89
|
+
const inputs = f.inputs.map((p, i) => toFieldDef(p, i, false))
|
|
90
|
+
const outputs = (f.outputs ?? []).map((p, i) => toFieldDef(p, i, false))
|
|
91
|
+
annotateParamDocs(inputs, docs?.params)
|
|
92
|
+
annotateReturnDocs(outputs, docs?.returns)
|
|
93
|
+
return {
|
|
94
|
+
name: f.name,
|
|
95
|
+
signature,
|
|
96
|
+
selector: `0x${keccak256(signature).slice(0, 4).toString('hex')}`,
|
|
97
|
+
inputs,
|
|
98
|
+
outputs,
|
|
99
|
+
key: functionSuffix(f, f.name),
|
|
100
|
+
paramsTypeName: functionSuffix(f, `${capitalize(f.name)}Params`),
|
|
101
|
+
returnTypeName: functionSuffix(f, `${capitalize(f.name)}Return`),
|
|
102
|
+
docs,
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
return {events, functions}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function buildEventDocs(signature: string, natspec: NatSpec | undefined): DocDef | undefined {
|
|
110
|
+
const notice = natspec?.userdoc?.events?.[signature]?.notice
|
|
111
|
+
const devEntry = natspec?.devdoc?.events?.[signature]
|
|
112
|
+
if (!notice && !devEntry) return undefined
|
|
113
|
+
return filterEmptyDoc({
|
|
114
|
+
notice,
|
|
115
|
+
dev: devEntry?.details,
|
|
116
|
+
params: devEntry?.params,
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function buildFunctionDocs(signature: string, natspec: NatSpec | undefined): DocDef | undefined {
|
|
121
|
+
const notice = natspec?.userdoc?.methods?.[signature]?.notice
|
|
122
|
+
const devEntry = natspec?.devdoc?.methods?.[signature]
|
|
123
|
+
if (!notice && !devEntry) return undefined
|
|
124
|
+
return filterEmptyDoc({
|
|
125
|
+
notice,
|
|
126
|
+
dev: devEntry?.details,
|
|
127
|
+
params: devEntry?.params,
|
|
128
|
+
returns: devEntry?.returns,
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function filterEmptyDoc(doc: DocDef): DocDef | undefined {
|
|
133
|
+
const hasContent =
|
|
134
|
+
doc.notice != null ||
|
|
135
|
+
doc.dev != null ||
|
|
136
|
+
(doc.params != null && Object.keys(doc.params).length > 0) ||
|
|
137
|
+
(doc.returns != null && Object.keys(doc.returns).length > 0)
|
|
138
|
+
return hasContent ? doc : undefined
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function annotateParamDocs(fields: FieldDef[], params: Record<string, string> | undefined): void {
|
|
142
|
+
if (!params) return
|
|
143
|
+
for (const field of fields) {
|
|
144
|
+
const doc = params[field.name]
|
|
145
|
+
if (doc) field.doc = doc
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function annotateReturnDocs(fields: FieldDef[], returns: Record<string, string> | undefined): void {
|
|
150
|
+
if (!returns) return
|
|
151
|
+
for (let i = 0; i < fields.length; i++) {
|
|
152
|
+
const field = fields[i]
|
|
153
|
+
const doc = returns[field.name] ?? returns[`_${i}`]
|
|
154
|
+
if (doc) field.doc = doc
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function overloadSuffixer(items: readonly (AbiEvent | AbiFunction)[]) {
|
|
159
|
+
const counts = new Map<string, number>()
|
|
160
|
+
const indices = new Map<AbiEvent | AbiFunction, number>()
|
|
161
|
+
for (const item of items) {
|
|
162
|
+
const seen = counts.get(item.name) ?? 0
|
|
163
|
+
indices.set(item, seen)
|
|
164
|
+
counts.set(item.name, seen + 1)
|
|
165
|
+
}
|
|
166
|
+
return (item: AbiEvent | AbiFunction, base: string): string => {
|
|
167
|
+
if ((counts.get(item.name) ?? 1) <= 1) return base
|
|
168
|
+
const idx = indices.get(item)!
|
|
169
|
+
return idx === 0 ? base : `${base}_${idx}`
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function toFieldDef(p: AbiParameter, index: number, isEventInput: boolean): FieldDef {
|
|
174
|
+
const field: FieldDef = {
|
|
175
|
+
name: p.name || `_${index}`,
|
|
176
|
+
type: toTypeDef(p),
|
|
177
|
+
}
|
|
178
|
+
if (isEventInput && (p as any).indexed) field.indexed = true
|
|
179
|
+
return field
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function toTypeDef(p: AbiParameter): TypeDef {
|
|
183
|
+
const fixed = p.type.match(/\[(\d+)\]$/)
|
|
184
|
+
if (fixed) {
|
|
185
|
+
return {kind: 'fixedArray', size: Number(fixed[1]), item: toTypeDef(stripOuterArray(p))}
|
|
186
|
+
}
|
|
187
|
+
if (p.type.endsWith('[]')) {
|
|
188
|
+
return {kind: 'array', item: toTypeDef(stripOuterArray(p))}
|
|
189
|
+
}
|
|
190
|
+
if (p.type.startsWith('tuple')) {
|
|
191
|
+
const components = ((p as any).components || []) as AbiParameter[]
|
|
192
|
+
return {
|
|
193
|
+
kind: 'tuple',
|
|
194
|
+
fields: components.map((c, i) => toFieldDef(c, i, false)),
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return {kind: 'primitive', name: p.type}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function stripOuterArray(p: AbiParameter): AbiParameter {
|
|
201
|
+
return {...(p as any), type: p.type.replace(/\[\d*\]$/, '')} as AbiParameter
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function canonicalType(p: AbiParameter): string {
|
|
205
|
+
if (!p.type.startsWith('tuple')) return p.type
|
|
206
|
+
const arrayBrackets = p.type.slice(5)
|
|
207
|
+
const components = (p as any).components as AbiParameter[]
|
|
208
|
+
return `(${components.map(canonicalType).join(',')})${arrayBrackets}`
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function eventSignature(e: AbiEvent): string {
|
|
212
|
+
return `${e.name}(${e.inputs.map(canonicalType).join(',')})`
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function fnSignature(f: AbiFunction): string {
|
|
216
|
+
return `${f.name}(${f.inputs.map(canonicalType).join(',')})`
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function capitalize(s: string): string {
|
|
220
|
+
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
221
|
+
}
|