@subsquid/evm-typegen 1.2.0 → 1.3.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/main.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAOA,wBAAgB,GAAG,IAAI,IAAI,CAoB1B"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAKA,wBAAgB,GAAG,IAAI,IAAI,CA4B1B"}
package/lib/main.js CHANGED
@@ -4,12 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.run = void 0;
7
- const abi_1 = require("@ethersproject/abi");
8
- const util_internal_code_printer_1 = require("@subsquid/util-internal-code-printer");
9
7
  const commander_1 = require("commander");
10
- const fs_1 = __importDefault(require("fs"));
11
8
  const path_1 = __importDefault(require("path"));
12
9
  const process_1 = __importDefault(require("process"));
10
+ const typegen_1 = require("./typegen");
13
11
  function run() {
14
12
  commander_1.program.description(`
15
13
  Generates TypeScript definitions for evm log events
@@ -21,8 +19,14 @@ for use within substrate-processor mapping handlers.
21
19
  const options = commander_1.program.opts();
22
20
  const inputPath = options.abi;
23
21
  const outputPath = options.output;
22
+ if (path_1.default.parse(inputPath).ext !== ".json") {
23
+ throw new Error("invalid abi file extension");
24
+ }
25
+ if (path_1.default.parse(outputPath).ext !== ".ts") {
26
+ throw new Error("invalid output file extension");
27
+ }
24
28
  try {
25
- generateTsFromAbi(inputPath, outputPath);
29
+ new typegen_1.Typegen(inputPath, outputPath).generate();
26
30
  }
27
31
  catch (err) {
28
32
  console.error(`evm-typegen error: ${err.toString()}`);
@@ -30,219 +34,4 @@ for use within substrate-processor mapping handlers.
30
34
  }
31
35
  }
32
36
  exports.run = run;
33
- function generateTsFromAbi(inputPathRaw, outputPathRaw) {
34
- const inputPath = path_1.default.parse(inputPathRaw);
35
- const outputPath = path_1.default.parse(outputPathRaw);
36
- if (inputPath.ext !== ".json") {
37
- throw new Error("invalid abi file extension");
38
- }
39
- if (outputPath.ext !== ".ts") {
40
- throw new Error("invalid output file extension");
41
- }
42
- const rawABI = JSON.parse(fs_1.default.readFileSync(inputPathRaw, { encoding: "utf-8" }));
43
- const output = new util_internal_code_printer_1.Output();
44
- output.line("import * as ethers from \"ethers\";");
45
- output.line("import assert from \"assert\";");
46
- output.line();
47
- output.line("export const abi = new ethers.utils.Interface(getJsonAbi());");
48
- output.line();
49
- // validate the abi
50
- const abi = new abi_1.Interface(rawABI);
51
- const typeNames = {};
52
- const abiEvents = Object.values(abi.events).map((event) => {
53
- let eventTypeName = `${event.name}`;
54
- if (typeNames[event.name]) {
55
- eventTypeName += typeNames[event.name].toString();
56
- typeNames[event.name]++;
57
- }
58
- else {
59
- eventTypeName += "0";
60
- typeNames[event.name] = 1;
61
- }
62
- eventTypeName += 'Event';
63
- let signature = `${event.name}(`;
64
- if (event.inputs.length > 0) {
65
- signature += event.inputs[0].type;
66
- }
67
- for (let i = 1; i < event.inputs.length; ++i) {
68
- const input = event.inputs[i];
69
- signature += `,${input.type}`;
70
- }
71
- signature += ")";
72
- return {
73
- signature,
74
- eventTypeName,
75
- inputs: event.inputs,
76
- };
77
- });
78
- for (const decl of abiEvents) {
79
- output.line(`export type ${decl.eventTypeName} = ${getTupleType(decl.inputs)}`);
80
- output.line("");
81
- }
82
- output.block("export interface EvmEvent", () => {
83
- output.line("data: string;");
84
- output.line("topics: string[];");
85
- });
86
- output.line();
87
- output.block(`function decodeEvent(signature: string, data: EvmEvent): any`, () => {
88
- output.line(`return abi.decodeEventLog(`);
89
- output.indentation(() => {
90
- output.line(`abi.getEvent(signature),`);
91
- output.line(`data.data || "",`);
92
- output.line("data.topics");
93
- });
94
- output.line(");");
95
- });
96
- output.line();
97
- output.block("export const events =", () => {
98
- for (const decl of abiEvents) {
99
- output.block(`"${decl.signature}":`, () => {
100
- output.line(`topic: abi.getEventTopic("${decl.signature}"),`);
101
- output.block(`decode(data: EvmEvent): ${decl.eventTypeName}`, () => {
102
- output.line(`return decodeEvent("${decl.signature}", data)`);
103
- });
104
- });
105
- output.line(",");
106
- }
107
- });
108
- output.line();
109
- let abiFunctions = new Map();
110
- for (let func of Object.values(abi.functions)) {
111
- if (!func.constant || func.outputs == null)
112
- continue;
113
- let abiFunction = abiFunctions.get(func.name);
114
- if (abiFunction == null) {
115
- abiFunction = {
116
- name: func.name,
117
- overloads: []
118
- };
119
- abiFunctions.set(func.name, abiFunction);
120
- }
121
- let returnTypeName = func.outputs.length == 1 ? getType(func.outputs[0]) : getTupleType(func.outputs);
122
- abiFunction.overloads.push({
123
- inputs: func.inputs,
124
- outputs: func.outputs || [],
125
- returnTypeName
126
- });
127
- }
128
- output.block("interface ChainContext ", () => {
129
- output.line(`_chain: Chain`);
130
- });
131
- output.line();
132
- output.block("interface BlockContext ", () => {
133
- output.line(`_chain: Chain`);
134
- output.line(`block: Block`);
135
- });
136
- output.line();
137
- output.block("interface Block ", () => {
138
- output.line(`height: number`);
139
- });
140
- output.line();
141
- output.block("interface Chain ", () => {
142
- output.block("client: ", () => {
143
- output.line(`call: <T=any>(method: string, params?: unknown[]) => Promise<T>`);
144
- });
145
- });
146
- output.line();
147
- output.block("export class Contract ", () => {
148
- output.line(`private readonly _chain: Chain`);
149
- output.line(`private readonly blockHeight: number`);
150
- output.line(`readonly address: string`);
151
- output.line();
152
- output.line(`constructor(ctx: BlockContext, address: string)`);
153
- output.line(`constructor(ctx: ChainContext, block: Block, address: string)`);
154
- output.block(`constructor(ctx: BlockContext, blockOrAddress: Block | string, address?: string)`, () => {
155
- output.line(`this._chain = ctx._chain`);
156
- output.block(`if (typeof blockOrAddress === 'string') `, () => {
157
- output.line(`this.blockHeight = ctx.block.height`);
158
- output.line(`this.address = ethers.utils.getAddress(blockOrAddress)`);
159
- });
160
- output.block(`else `, () => {
161
- output.line(`assert(address != null)`);
162
- output.line(`this.blockHeight = blockOrAddress.height`);
163
- output.line(`this.address = ethers.utils.getAddress(address)`);
164
- });
165
- });
166
- output.line();
167
- for (const decl of abiFunctions.values()) {
168
- if (decl.overloads.length > 1) {
169
- for (let overload of decl.overloads) {
170
- const args = overload.inputs.map((i, n) => `${i.name || `arg${n}`}: ${getType(i)}`);
171
- const returnType = overload.returnTypeName;
172
- output.line(`async ${decl.name}(${args}): Promise<${returnType}>`);
173
- }
174
- output.block(`async ${decl.name}(...args: any[])`, () => {
175
- output.line(`return this.call("${decl.name}", args)`);
176
- });
177
- }
178
- else {
179
- const overload = decl.overloads[0];
180
- const params = overload.inputs.map((i, n) => `${i.name || `arg${n}`}: ${getType(i)}`);
181
- const returnType = overload.returnTypeName;
182
- output.block(`async ${decl.name}(${params.join(`, `)}): Promise<${returnType}>`, () => {
183
- output.line(`return this.call("${decl.name}", [${overload.inputs.map((i, n) => `${i.name || `arg${n}`}`).join(`, `)}])`);
184
- });
185
- }
186
- output.line();
187
- }
188
- output.block(`private async call(name: string, args: any[]) : Promise<any>`, () => {
189
- output.line(`const fragment = abi.getFunction(name)`);
190
- output.line(`const data = abi.encodeFunctionData(fragment, args)`);
191
- output.line(`const result = await this._chain.client.call('eth_call', [{to: this.address, data}, this.blockHeight])`);
192
- output.line(`const decoded = abi.decodeFunctionResult(fragment, result)`);
193
- output.line(`return decoded.length > 1 ? decoded : decoded[0]`);
194
- });
195
- });
196
- output.line();
197
- output.block("function getJsonAbi(): any", () => {
198
- `return ${JSON.stringify(rawABI, null, 2)}`.split('\n').forEach(line => {
199
- output.line(line);
200
- });
201
- });
202
- fs_1.default.writeFileSync(outputPathRaw, output.toString());
203
- }
204
- // taken from: https://github.com/ethers-io/ethers.js/blob/948f77050dae884fe88932fd88af75560aac9d78/packages/cli/src.ts/typescript.ts#L10
205
- function getType(param) {
206
- if (param.type === "address" || param.type === "string") {
207
- return "string";
208
- }
209
- if (param.type === "bool") {
210
- return "boolean";
211
- }
212
- if (param.type.substring(0, 5) === "bytes") {
213
- return "string";
214
- }
215
- let match = param.type.match(/^(u?int)([0-9]+)$/);
216
- if (match) {
217
- return parseInt(match[2]) < 53 ? 'number' : 'ethers.BigNumber';
218
- }
219
- if (param.baseType === "array") {
220
- return "Array<" + getType(param.arrayChildren) + ">";
221
- }
222
- if (param.baseType === "tuple") {
223
- return getTupleType(param.components);
224
- }
225
- throw new Error("unknown type");
226
- }
227
- function getTupleType(params) {
228
- let tuple = '[' + params.map(p => {
229
- return p.name ? `${p.name}: ${getType(p)}` : getType(p);
230
- }).join(', ') + ']';
231
- let fields = getStructFields(params);
232
- if (fields.length == 0)
233
- return tuple;
234
- let struct = '{' + fields.map(f => `${f.name}: ${getType(f)}`).join(', ') + '}';
235
- return `(${tuple} & ${struct})`;
236
- }
237
- // https://github.com/ethers-io/ethers.js/blob/948f77050dae884fe88932fd88af75560aac9d78/packages/abi/src.ts/coders/tuple.ts#L29
238
- function getStructFields(params) {
239
- let array = [];
240
- let counts = {};
241
- for (let p of params) {
242
- if (p.name && array[p.name] == null) {
243
- counts[p.name] = (counts[p.name] || 0) + 1;
244
- }
245
- }
246
- return params.filter(p => counts[p.name] == 1);
247
- }
248
37
  //# sourceMappingURL=main.js.map
package/lib/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAiC;AACjC,gDAAuB;AACvB,sDAA6B;AAC7B,uCAAiC;AAEjC,SAAgB,GAAG;IACf,mBAAO,CAAC,WAAW,CAAC;;;KAGnB,CAAC,IAAI,EAAE,CAAC;SACJ,cAAc,CAAC,cAAc,EAAE,yBAAyB,CAAC;SACzD,cAAc,CAAC,iBAAiB,EAAE,iCAAiC,CAAC,CAAC;IAE1E,mBAAO,CAAC,KAAK,EAAE,CAAC;IAEhB,MAAM,OAAO,GAAG,mBAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC;IAC9B,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAElC,IAAI,cAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE;QACvC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;KACjD;IAED,IAAI,cAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,KAAK,KAAK,EAAE;QACtC,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;KACpD;IAED,IAAI;QACA,IAAI,iBAAO,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAC;KACjD;IAAC,OAAO,GAAQ,EAAE;QACf,OAAO,CAAC,KAAK,CAAC,sBAAsB,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACtD,iBAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACnB;AACL,CAAC;AA5BD,kBA4BC"}
@@ -0,0 +1,14 @@
1
+ export declare class Typegen {
2
+ private rawAbi;
3
+ private abi;
4
+ private out;
5
+ constructor(abiFile: string, outPath: string);
6
+ generate(): void;
7
+ private generateEvents;
8
+ private generateFunctions;
9
+ private generateContract;
10
+ private getEvents;
11
+ private getFunctions;
12
+ private getCalls;
13
+ }
14
+ //# sourceMappingURL=typegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typegen.d.ts","sourceRoot":"","sources":["../src/typegen.ts"],"names":[],"mappings":"AAKA,qBAAa,OAAO;IAChB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,GAAG,CAAW;IACtB,OAAO,CAAC,GAAG,CAAY;gBAEX,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAM5C,QAAQ,IAAI,IAAI;IAoBhB,OAAO,CAAC,cAAc;IA0CtB,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,gBAAgB;IAyExB,OAAO,CAAC,SAAS;IAqBjB,OAAO,CAAC,YAAY;IAuBpB,OAAO,CAAC,QAAQ;CAsBnB"}
package/lib/typegen.js ADDED
@@ -0,0 +1,315 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.Typegen = void 0;
16
+ const abi_1 = require("@ethersproject/abi");
17
+ const util_internal_code_printer_1 = require("@subsquid/util-internal-code-printer");
18
+ const util_internal_1 = require("@subsquid/util-internal");
19
+ const fs_1 = __importDefault(require("fs"));
20
+ class Typegen {
21
+ constructor(abiFile, outPath) {
22
+ this.rawAbi = JSON.parse(fs_1.default.readFileSync(abiFile, { encoding: "utf-8" }));
23
+ this.abi = new abi_1.Interface(this.rawAbi);
24
+ this.out = new util_internal_code_printer_1.FileOutput(outPath);
25
+ }
26
+ generate() {
27
+ this.out.line("import * as ethers from \"ethers\";");
28
+ this.out.line("import assert from \"assert\";");
29
+ this.out.line();
30
+ this.out.line("export const abi = new ethers.utils.Interface(getJsonAbi());");
31
+ this.out.line();
32
+ this.generateEvents();
33
+ this.out.line();
34
+ this.generateFunctions();
35
+ this.out.line();
36
+ this.generateContract();
37
+ this.out.line();
38
+ this.out.block("function getJsonAbi(): any", () => {
39
+ `return ${JSON.stringify(this.rawAbi, null, 2)}`.split('\n').forEach(line => {
40
+ this.out.line(line);
41
+ });
42
+ });
43
+ this.out.write();
44
+ }
45
+ generateEvents() {
46
+ for (const decl of this.getEvents()) {
47
+ for (let i = 0; i < decl.overloads.length; i++) {
48
+ if (decl.overloads[i].inputs.length === 0)
49
+ continue;
50
+ this.out.line(`export type ${decl.name}${i}Event = ${getTupleType(decl.overloads[i].inputs)}`);
51
+ this.out.line();
52
+ }
53
+ }
54
+ this.out.block("export interface EvmLog", () => {
55
+ this.out.line("data: string;");
56
+ this.out.line("topics: string[];");
57
+ });
58
+ this.out.line();
59
+ this.out.block(`function decodeEvent(signature: string, data: EvmLog): any`, () => {
60
+ this.out.line(`return abi.decodeEventLog(`);
61
+ this.out.indentation(() => {
62
+ this.out.line(`abi.getEvent(signature),`);
63
+ this.out.line(`data.data || "",`);
64
+ this.out.line("data.topics");
65
+ });
66
+ this.out.line(");");
67
+ });
68
+ this.out.line();
69
+ this.out.block(`export const events =`, () => {
70
+ for (const event of this.getEvents()) {
71
+ for (let i = 0; i < event.overloads.length; i++) {
72
+ const overload = event.overloads[i];
73
+ const signature = createSignature(event.name, overload.inputs);
74
+ this.out.block(`"${signature}":`, () => {
75
+ this.out.line(`topic: abi.getEventTopic("${signature}"),`);
76
+ if (event.overloads[i].inputs.length > 0) {
77
+ this.out.block(`decode(data: EvmLog): ${event.name}${i}Event`, () => {
78
+ this.out.line(`return decodeEvent("${signature}", data)`);
79
+ });
80
+ }
81
+ });
82
+ this.out.line(",");
83
+ }
84
+ }
85
+ });
86
+ }
87
+ generateFunctions() {
88
+ for (const func of this.getFunctions()) {
89
+ for (let i = 0; i < func.overloads.length; i++) {
90
+ if (func.overloads[i].inputs.length === 0)
91
+ continue;
92
+ this.out.line(`export type ${upperCaseFirst(func.name)}${i}Function = ${getTupleType(func.overloads[i].inputs)}`);
93
+ this.out.line();
94
+ }
95
+ }
96
+ this.out.line();
97
+ this.out.block(`function decodeFunction(data: string): any`, () => {
98
+ this.out.line(`return abi.decodeFunctionData(data.slice(0, 10), data)`);
99
+ });
100
+ this.out.line();
101
+ this.out.block(`export const functions =`, () => {
102
+ for (const func of this.getFunctions()) {
103
+ for (let i = 0; i < func.overloads.length; i++) {
104
+ const overload = func.overloads[i];
105
+ const signature = createSignature(func.name, overload.inputs);
106
+ this.out.block(`"${signature}":`, () => {
107
+ this.out.line(`sighash: abi.getSighash("${signature}"),`);
108
+ if (func.overloads[i].inputs.length > 0)
109
+ this.out.block(`decode(input: string): ${upperCaseFirst(func.name)}${i}Function`, () => {
110
+ this.out.line(`return decodeFunction(input)`);
111
+ });
112
+ });
113
+ this.out.line(",");
114
+ }
115
+ }
116
+ });
117
+ }
118
+ generateContract() {
119
+ let abiCalls = this.getCalls();
120
+ this.out.block("interface ChainContext ", () => {
121
+ this.out.line(`_chain: Chain`);
122
+ });
123
+ this.out.line();
124
+ this.out.block("interface BlockContext ", () => {
125
+ this.out.line(`_chain: Chain`);
126
+ this.out.line(`block: Block`);
127
+ });
128
+ this.out.line();
129
+ this.out.block("interface Block ", () => {
130
+ this.out.line(`height: number`);
131
+ });
132
+ this.out.line();
133
+ this.out.block("interface Chain ", () => {
134
+ this.out.block("client: ", () => {
135
+ this.out.line(`call: <T=any>(method: string, params?: unknown[]) => Promise<T>`);
136
+ });
137
+ });
138
+ this.out.line();
139
+ this.out.block("export class Contract ", () => {
140
+ this.out.line(`private readonly _chain: Chain`);
141
+ this.out.line(`private readonly blockHeight: number`);
142
+ this.out.line(`readonly address: string`);
143
+ this.out.line();
144
+ this.out.line(`constructor(ctx: BlockContext, address: string)`);
145
+ this.out.line(`constructor(ctx: ChainContext, block: Block, address: string)`);
146
+ this.out.block(`constructor(ctx: BlockContext, blockOrAddress: Block | string, address?: string)`, () => {
147
+ this.out.line(`this._chain = ctx._chain`);
148
+ this.out.block(`if (typeof blockOrAddress === 'string') `, () => {
149
+ this.out.line(`this.blockHeight = ctx.block.height`);
150
+ this.out.line(`this.address = ethers.utils.getAddress(blockOrAddress)`);
151
+ });
152
+ this.out.block(`else `, () => {
153
+ this.out.line(`assert(address != null)`);
154
+ this.out.line(`this.blockHeight = blockOrAddress.height`);
155
+ this.out.line(`this.address = ethers.utils.getAddress(address)`);
156
+ });
157
+ });
158
+ this.out.line();
159
+ for (const decl of abiCalls) {
160
+ if (decl.overloads.length > 1) {
161
+ for (let overload of decl.overloads) {
162
+ const args = overload.inputs.map((i, n) => `${i.name || `arg${n}`}: ${getType(i)}`);
163
+ const returnType = overload.outputs.length == 1 ? getType(overload.outputs[0]) : getTupleType(overload.outputs);
164
+ this.out.line(`async ${decl.name}(${args}): Promise<${returnType}>`);
165
+ }
166
+ this.out.block(`async ${decl.name}(...args: any[])`, () => {
167
+ this.out.line(`return this.call("${decl.name}", args)`);
168
+ });
169
+ }
170
+ else {
171
+ const overload = decl.overloads[0];
172
+ const params = overload.inputs.map((i, n) => `${i.name || `arg${n}`}: ${getType(i)}`);
173
+ const returnType = overload.outputs.length == 1 ? getType(overload.outputs[0]) : getTupleType(overload.outputs);
174
+ this.out.block(`async ${decl.name}(${params.join(`, `)}): Promise<${returnType}>`, () => {
175
+ this.out.line(`return this.call("${decl.name}", [${overload.inputs.map((i, n) => `${i.name || `arg${n}`}`).join(`, `)}])`);
176
+ });
177
+ }
178
+ this.out.line();
179
+ }
180
+ this.out.block(`private async call(name: string, args: any[]) : Promise<any>`, () => {
181
+ this.out.line(`const fragment = abi.getFunction(name)`);
182
+ this.out.line(`const data = abi.encodeFunctionData(fragment, args)`);
183
+ this.out.line(`const result = await this._chain.client.call('eth_call', [{to: this.address, data}, this.blockHeight])`);
184
+ this.out.line(`const decoded = abi.decodeFunctionResult(fragment, result)`);
185
+ this.out.line(`return decoded.length > 1 ? decoded : decoded[0]`);
186
+ });
187
+ });
188
+ }
189
+ getEvents() {
190
+ let res = new Map();
191
+ for (let event of Object.values(this.abi.events)) {
192
+ let abiEvent = res.get(event.name);
193
+ if (abiEvent == null) {
194
+ abiEvent = {
195
+ name: event.name,
196
+ overloads: []
197
+ };
198
+ res.set(event.name, abiEvent);
199
+ }
200
+ abiEvent.overloads.push({
201
+ inputs: event.inputs || [],
202
+ });
203
+ }
204
+ return [...res.values()];
205
+ }
206
+ getFunctions() {
207
+ let res = new Map();
208
+ for (let func of Object.values(this.abi.functions)) {
209
+ if (func.constant)
210
+ continue;
211
+ let abiFunc = res.get(func.name);
212
+ if (abiFunc == null) {
213
+ abiFunc = {
214
+ name: func.name,
215
+ overloads: []
216
+ };
217
+ res.set(func.name, abiFunc);
218
+ }
219
+ abiFunc.overloads.push({
220
+ inputs: func.inputs || [],
221
+ });
222
+ }
223
+ return [...res.values()];
224
+ }
225
+ getCalls() {
226
+ let res = new Map();
227
+ for (let func of Object.values(this.abi.functions)) {
228
+ if (!func.constant || func.outputs == null)
229
+ continue;
230
+ let abiCall = res.get(func.name);
231
+ if (abiCall == null) {
232
+ abiCall = {
233
+ name: func.name,
234
+ overloads: []
235
+ };
236
+ res.set(func.name, abiCall);
237
+ }
238
+ abiCall.overloads.push({
239
+ inputs: func.inputs,
240
+ outputs: func.outputs || [],
241
+ });
242
+ }
243
+ return [...res.values()];
244
+ }
245
+ }
246
+ __decorate([
247
+ util_internal_1.def,
248
+ __metadata("design:type", Function),
249
+ __metadata("design:paramtypes", []),
250
+ __metadata("design:returntype", Array)
251
+ ], Typegen.prototype, "getEvents", null);
252
+ __decorate([
253
+ util_internal_1.def,
254
+ __metadata("design:type", Function),
255
+ __metadata("design:paramtypes", []),
256
+ __metadata("design:returntype", Array)
257
+ ], Typegen.prototype, "getFunctions", null);
258
+ __decorate([
259
+ util_internal_1.def,
260
+ __metadata("design:type", Function),
261
+ __metadata("design:paramtypes", []),
262
+ __metadata("design:returntype", Array)
263
+ ], Typegen.prototype, "getCalls", null);
264
+ exports.Typegen = Typegen;
265
+ // taken from: https://github.com/ethers-io/ethers.js/blob/948f77050dae884fe88932fd88af75560aac9d78/packages/cli/src.ts/typescript.ts#L10
266
+ function getType(param) {
267
+ if (param.type === "address" || param.type === "string") {
268
+ return "string";
269
+ }
270
+ if (param.type === "bool") {
271
+ return "boolean";
272
+ }
273
+ if (param.type.substring(0, 5) === "bytes") {
274
+ return "string";
275
+ }
276
+ let match = param.type.match(/^(u?int)([0-9]+)$/);
277
+ if (match) {
278
+ return parseInt(match[2]) < 53 ? 'number' : 'ethers.BigNumber';
279
+ }
280
+ if (param.baseType === "array") {
281
+ return "Array<" + getType(param.arrayChildren) + ">";
282
+ }
283
+ if (param.baseType === "tuple") {
284
+ return getTupleType(param.components);
285
+ }
286
+ throw new Error("unknown type");
287
+ }
288
+ function getTupleType(params) {
289
+ let tuple = '[' + params.map(p => {
290
+ return p.name ? `${p.name}: ${getType(p)}` : getType(p);
291
+ }).join(', ') + ']';
292
+ let fields = getStructFields(params);
293
+ if (fields.length == 0)
294
+ return tuple;
295
+ let struct = '{' + fields.map(f => `${f.name}: ${getType(f)}`).join(', ') + '}';
296
+ return `(${tuple} & ${struct})`;
297
+ }
298
+ // https://github.com/ethers-io/ethers.js/blob/948f77050dae884fe88932fd88af75560aac9d78/packages/abi/src.ts/coders/tuple.ts#L29
299
+ function getStructFields(params) {
300
+ let array = [];
301
+ let counts = {};
302
+ for (let p of params) {
303
+ if (p.name && array[p.name] == null) {
304
+ counts[p.name] = (counts[p.name] || 0) + 1;
305
+ }
306
+ }
307
+ return params.filter(p => counts[p.name] == 1);
308
+ }
309
+ function createSignature(name, inputs) {
310
+ return `${name}(${inputs.map((i) => i.type).join(`,`)})`;
311
+ }
312
+ function upperCaseFirst(s) {
313
+ return s[0].toUpperCase() + s.slice(1);
314
+ }
315
+ //# sourceMappingURL=typegen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typegen.js","sourceRoot":"","sources":["../src/typegen.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": "1.2.0",
3
+ "version": "1.3.0",
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",
@@ -18,7 +18,8 @@
18
18
  "dependencies": {
19
19
  "commander": "^9.3.0",
20
20
  "@ethersproject/abi": "^5.6.4",
21
- "@subsquid/util-internal-code-printer": "^0.0.2"
21
+ "@subsquid/util-internal-code-printer": "^0.0.2",
22
+ "@subsquid/util-internal": "^0.0.1"
22
23
  },
23
24
  "devDependencies": {
24
25
  "@types/node": "^16.11.41",
package/src/main.ts CHANGED
@@ -1,9 +1,7 @@
1
- import {EventFragment, Interface, ParamType} from "@ethersproject/abi"
2
- import {Output} from "@subsquid/util-internal-code-printer"
3
1
  import {program} from "commander"
4
- import fs from "fs"
5
2
  import path from "path"
6
3
  import process from "process"
4
+ import {Typegen} from "./typegen"
7
5
 
8
6
  export function run(): void {
9
7
  program.description(`
@@ -19,274 +17,18 @@ for use within substrate-processor mapping handlers.
19
17
  const inputPath = options.abi;
20
18
  const outputPath = options.output;
21
19
 
22
- try {
23
- generateTsFromAbi(inputPath, outputPath);
24
- } catch (err: any) {
25
- console.error(`evm-typegen error: ${err.toString()}`);
26
- process.exit(1);
27
- }
28
- }
29
-
30
- function generateTsFromAbi(inputPathRaw: string, outputPathRaw: string): void {
31
- const inputPath = path.parse(inputPathRaw);
32
- const outputPath = path.parse(outputPathRaw);
33
-
34
- if (inputPath.ext !== ".json") {
20
+ if (path.parse(inputPath).ext !== ".json") {
35
21
  throw new Error("invalid abi file extension");
36
22
  }
37
23
 
38
- if (outputPath.ext !== ".ts") {
24
+ if (path.parse(outputPath).ext !== ".ts") {
39
25
  throw new Error("invalid output file extension");
40
26
  }
41
27
 
42
- const rawABI = JSON.parse(fs.readFileSync(inputPathRaw, {encoding: "utf-8"}));
43
-
44
- const output = new Output();
45
-
46
- output.line("import * as ethers from \"ethers\";");
47
- output.line("import assert from \"assert\";");
48
- output.line();
49
- output.line("export const abi = new ethers.utils.Interface(getJsonAbi());");
50
- output.line();
51
-
52
- // validate the abi
53
- const abi = new Interface(rawABI);
54
-
55
- const typeNames: {[key: string]: number} = {};
56
-
57
- const abiEvents: Array<AbiEvent> = Object.values(abi.events).map((event: EventFragment): AbiEvent => {
58
- let eventTypeName = `${event.name}`;
59
- if (typeNames[event.name]) {
60
- eventTypeName += typeNames[event.name].toString();
61
- typeNames[event.name]++;
62
- } else {
63
- eventTypeName += "0";
64
- typeNames[event.name] = 1;
65
- }
66
- eventTypeName += 'Event'
67
-
68
- let signature = `${event.name}(`;
69
- if (event.inputs.length > 0) {
70
- signature += event.inputs[0].type;
71
- }
72
- for (let i = 1; i < event.inputs.length; ++i) {
73
- const input = event.inputs[i];
74
- signature += `,${input.type}`;
75
- }
76
- signature += ")";
77
-
78
- return {
79
- signature,
80
- eventTypeName,
81
- inputs: event.inputs,
82
- };
83
- });
84
-
85
- for (const decl of abiEvents) {
86
- output.line(`export type ${decl.eventTypeName} = ${getTupleType(decl.inputs)}`)
87
- output.line("");
88
- }
89
-
90
- output.block("export interface EvmEvent", () => {
91
- output.line("data: string;");
92
- output.line("topics: string[];");
93
- });
94
-
95
- output.line();
96
-
97
- output.block(`function decodeEvent(signature: string, data: EvmEvent): any`, () => {
98
- output.line(`return abi.decodeEventLog(`);
99
- output.indentation(() => {
100
- output.line(`abi.getEvent(signature),`);
101
- output.line(`data.data || "",`);
102
- output.line("data.topics");
103
- });
104
- output.line(");");
105
- });
106
-
107
- output.line();
108
-
109
- output.block("export const events =", () => {
110
- for (const decl of abiEvents) {
111
- output.block(`"${decl.signature}":`, () => {
112
- output.line(`topic: abi.getEventTopic("${decl.signature}"),`);
113
- output.block(`decode(data: EvmEvent): ${decl.eventTypeName}`, () => {
114
- output.line(`return decodeEvent("${decl.signature}", data)`);
115
- });
116
- });
117
- output.line(",");
118
- }
119
- });
120
-
121
- output.line();
122
-
123
- let abiFunctions: Map<string, AbiFunction> = new Map()
124
- for (let func of Object.values(abi.functions)) {
125
- if (!func.constant || func.outputs == null) continue
126
-
127
- let abiFunction = abiFunctions.get(func.name)
128
- if (abiFunction == null) {
129
- abiFunction = {
130
- name: func.name,
131
- overloads: []
132
- }
133
- abiFunctions.set(func.name, abiFunction)
134
- }
135
-
136
- let returnTypeName = func.outputs.length == 1 ? getType(func.outputs[0]) : getTupleType(func.outputs)
137
-
138
- abiFunction.overloads.push({
139
- inputs: func.inputs,
140
- outputs: func.outputs || [],
141
- returnTypeName
142
- })
143
- }
144
-
145
- output.block("interface ChainContext ", () => {
146
- output.line(`_chain: Chain`);
147
- })
148
- output.line();
149
- output.block("interface BlockContext ", () => {
150
- output.line(`_chain: Chain`);
151
- output.line(`block: Block`);
152
- })
153
- output.line();
154
- output.block("interface Block ", () => {
155
- output.line(`height: number`);
156
- })
157
- output.line();
158
- output.block("interface Chain ", () => {
159
- output.block("client: ", () => {
160
- output.line(`call: <T=any>(method: string, params?: unknown[]) => Promise<T>`);
161
- })
162
- })
163
- output.line();
164
- output.block("export class Contract ", () => {
165
- output.line(`private readonly _chain: Chain`);
166
- output.line(`private readonly blockHeight: number`);
167
- output.line(`readonly address: string`);
168
- output.line();
169
- output.line(`constructor(ctx: BlockContext, address: string)`);
170
- output.line(`constructor(ctx: ChainContext, block: Block, address: string)`);
171
- output.block(`constructor(ctx: BlockContext, blockOrAddress: Block | string, address?: string)`, () => {
172
- output.line(`this._chain = ctx._chain`);
173
- output.block(`if (typeof blockOrAddress === 'string') `, () => {
174
- output.line(`this.blockHeight = ctx.block.height`)
175
- output.line(`this.address = ethers.utils.getAddress(blockOrAddress)`)
176
- })
177
- output.block(`else `, () => {
178
- output.line(`assert(address != null)`)
179
- output.line(`this.blockHeight = blockOrAddress.height`)
180
- output.line(`this.address = ethers.utils.getAddress(address)`)
181
- })
182
- })
183
- output.line();
184
- for (const decl of abiFunctions.values()) {
185
- if (decl.overloads.length > 1) {
186
- for (let overload of decl.overloads) {
187
- const args = overload.inputs.map((i, n) => `${i.name || `arg${n}`}: ${getType(i)}`)
188
- const returnType = overload.returnTypeName
189
- output.line(`async ${decl.name}(${args}): Promise<${returnType}>`)
190
- }
191
- output.block(`async ${decl.name}(...args: any[])`, () => {
192
- output.line(`return this.call("${decl.name}", args)`);
193
- });
194
- } else {
195
- const overload = decl.overloads[0]
196
- const params = overload.inputs.map((i, n) => `${i.name || `arg${n}`}: ${getType(i)}`)
197
- const returnType = overload.returnTypeName
198
- output.block(`async ${decl.name}(${params.join(`, `)}): Promise<${returnType}>`, () => {
199
- output.line(`return this.call("${decl.name}", [${overload.inputs.map((i, n) => `${i.name || `arg${n}`}`).join(`, `)}])`);
200
- });
201
- }
202
- output.line();
203
- }
204
- output.block(`private async call(name: string, args: any[]) : Promise<any>`, () => {
205
- output.line(`const fragment = abi.getFunction(name)`);
206
- output.line(`const data = abi.encodeFunctionData(fragment, args)`);
207
- output.line(`const result = await this._chain.client.call('eth_call', [{to: this.address, data}, this.blockHeight])`);
208
- output.line(`const decoded = abi.decodeFunctionResult(fragment, result)`);
209
- output.line(`return decoded.length > 1 ? decoded : decoded[0]`);
210
- })
211
- })
212
-
213
- output.line();
214
-
215
- output.block("function getJsonAbi(): any", () => {
216
- `return ${JSON.stringify(rawABI, null, 2)}`.split('\n').forEach(line => {
217
- output.line(line)
218
- });
219
- });
220
-
221
- fs.writeFileSync(outputPathRaw, output.toString());
222
- }
223
-
224
- // taken from: https://github.com/ethers-io/ethers.js/blob/948f77050dae884fe88932fd88af75560aac9d78/packages/cli/src.ts/typescript.ts#L10
225
- function getType(param: ParamType): string {
226
- if (param.type === "address" || param.type === "string") {
227
- return "string"
228
- }
229
-
230
- if (param.type === "bool") {
231
- return "boolean"
232
- }
233
-
234
- if (param.type.substring(0, 5) === "bytes") {
235
- return "string"
236
- }
237
-
238
- let match = param.type.match(/^(u?int)([0-9]+)$/)
239
- if (match) {
240
- return parseInt(match[2]) < 53 ? 'number' : 'ethers.BigNumber'
241
- }
242
-
243
- if (param.baseType === "array") {
244
- return "Array<" + getType(param.arrayChildren) + ">";
245
- }
246
-
247
- if (param.baseType === "tuple") {
248
- return getTupleType(param.components);
249
- }
250
-
251
- throw new Error("unknown type");
252
- }
253
-
254
- function getTupleType(params: ParamType[]) {
255
- let tuple = '[' + params.map(p => {
256
- return p.name ? `${p.name}: ${getType(p)}` : getType(p)
257
- }).join(', ') + ']'
258
-
259
- let fields = getStructFields(params)
260
- if (fields.length == 0) return tuple
261
-
262
- let struct = '{' + fields.map(f => `${f.name}: ${getType(f)}`).join(', ') + '}'
263
-
264
- return `(${tuple} & ${struct})`
265
- }
266
-
267
- // https://github.com/ethers-io/ethers.js/blob/948f77050dae884fe88932fd88af75560aac9d78/packages/abi/src.ts/coders/tuple.ts#L29
268
- function getStructFields(params: ParamType[]): ParamType[] {
269
- let array: any = []
270
- let counts: Record<string, number> = {}
271
- for (let p of params) {
272
- if (p.name && array[p.name] == null) {
273
- counts[p.name] = (counts[p.name] || 0) + 1
274
- }
28
+ try {
29
+ new Typegen(inputPath, outputPath).generate();
30
+ } catch (err: any) {
31
+ console.error(`evm-typegen error: ${err.toString()}`);
32
+ process.exit(1);
275
33
  }
276
- return params.filter(p => counts[p.name] == 1)
277
- }
278
-
279
- interface AbiEvent {
280
- signature: string;
281
- eventTypeName: string;
282
- inputs: ParamType[];
283
- }
284
-
285
- interface AbiFunction {
286
- name: string;
287
- overloads: {
288
- inputs: ParamType[];
289
- outputs: ParamType[];
290
- returnTypeName?: string;
291
- }[]
292
34
  }
package/src/typegen.ts ADDED
@@ -0,0 +1,342 @@
1
+ import {Interface, ParamType} from "@ethersproject/abi"
2
+ import {FileOutput, Output} from "@subsquid/util-internal-code-printer"
3
+ import {def} from "@subsquid/util-internal"
4
+ import fs from "fs"
5
+
6
+ export class Typegen {
7
+ private rawAbi: any
8
+ private abi: Interface
9
+ private out: FileOutput
10
+
11
+ constructor(abiFile: string, outPath: string) {
12
+ this.rawAbi = JSON.parse(fs.readFileSync(abiFile, {encoding: "utf-8"}))
13
+ this.abi = new Interface(this.rawAbi)
14
+ this.out = new FileOutput(outPath)
15
+ }
16
+
17
+ generate(): void {
18
+ this.out.line("import * as ethers from \"ethers\";")
19
+ this.out.line("import assert from \"assert\";")
20
+ this.out.line()
21
+ this.out.line("export const abi = new ethers.utils.Interface(getJsonAbi());")
22
+ this.out.line()
23
+ this.generateEvents()
24
+ this.out.line()
25
+ this.generateFunctions()
26
+ this.out.line()
27
+ this.generateContract()
28
+ this.out.line()
29
+ this.out.block("function getJsonAbi(): any", () => {
30
+ `return ${JSON.stringify(this.rawAbi, null, 2)}`.split('\n').forEach(line => {
31
+ this.out.line(line)
32
+ })
33
+ })
34
+ this.out.write()
35
+ }
36
+
37
+ private generateEvents() {
38
+ for (const decl of this.getEvents()) {
39
+ for (let i = 0; i < decl.overloads.length; i++) {
40
+ if (decl.overloads[i].inputs.length === 0) continue
41
+ this.out.line(`export type ${decl.name}${i}Event = ${getTupleType(decl.overloads[i].inputs)}`)
42
+ this.out.line()
43
+ }
44
+ }
45
+ this.out.block("export interface EvmLog", () => {
46
+ this.out.line("data: string;")
47
+ this.out.line("topics: string[];")
48
+ })
49
+ this.out.line()
50
+ this.out.block(`function decodeEvent(signature: string, data: EvmLog): any`, () => {
51
+ this.out.line(`return abi.decodeEventLog(`)
52
+ this.out.indentation(() => {
53
+ this.out.line(`abi.getEvent(signature),`)
54
+ this.out.line(`data.data || "",`)
55
+ this.out.line("data.topics")
56
+ })
57
+ this.out.line(");")
58
+ })
59
+ this.out.line()
60
+ this.out.block(`export const events =`, () => {
61
+ for (const event of this.getEvents()) {
62
+ for (let i = 0; i < event.overloads.length; i++) {
63
+ const overload = event.overloads[i]
64
+ const signature = createSignature(event.name, overload.inputs)
65
+ this.out.block(`"${signature}":`, () => {
66
+ this.out.line(`topic: abi.getEventTopic("${signature}"),`)
67
+ if (event.overloads[i].inputs.length > 0) {
68
+ this.out.block(`decode(data: EvmLog): ${event.name}${i}Event`, () => {
69
+ this.out.line(`return decodeEvent("${signature}", data)`)
70
+ })
71
+ }
72
+ })
73
+ this.out.line(",")
74
+ }
75
+ }
76
+ })
77
+ }
78
+
79
+ private generateFunctions() {
80
+ for (const func of this.getFunctions()) {
81
+ for (let i = 0; i < func.overloads.length; i++) {
82
+ if (func.overloads[i].inputs.length === 0) continue
83
+ this.out.line(`export type ${upperCaseFirst(func.name)}${i}Function = ${getTupleType(func.overloads[i].inputs)}`)
84
+ this.out.line()
85
+ }
86
+ }
87
+ this.out.line()
88
+ this.out.block(`function decodeFunction(data: string): any`, () => {
89
+ this.out.line(`return abi.decodeFunctionData(data.slice(0, 10), data)`)
90
+ })
91
+ this.out.line()
92
+ this.out.block(`export const functions =`, () => {
93
+ for (const func of this.getFunctions()) {
94
+ for (let i = 0; i < func.overloads.length; i++) {
95
+ const overload = func.overloads[i]
96
+ const signature = createSignature(func.name, overload.inputs)
97
+ this.out.block(`"${signature}":`, () => {
98
+ this.out.line(`sighash: abi.getSighash("${signature}"),`)
99
+ if (func.overloads[i].inputs.length > 0)
100
+ this.out.block(`decode(input: string): ${upperCaseFirst(func.name)}${i}Function`, () => {
101
+ this.out.line(`return decodeFunction(input)`)
102
+ })
103
+ })
104
+ this.out.line(",")
105
+ }
106
+ }
107
+ })
108
+ }
109
+
110
+ private generateContract() {
111
+ let abiCalls = this.getCalls()
112
+
113
+ this.out.block("interface ChainContext ", () => {
114
+ this.out.line(`_chain: Chain`)
115
+ })
116
+ this.out.line()
117
+ this.out.block("interface BlockContext ", () => {
118
+ this.out.line(`_chain: Chain`)
119
+ this.out.line(`block: Block`)
120
+ })
121
+ this.out.line()
122
+ this.out.block("interface Block ", () => {
123
+ this.out.line(`height: number`)
124
+ })
125
+ this.out.line()
126
+ this.out.block("interface Chain ", () => {
127
+ this.out.block("client: ", () => {
128
+ this.out.line(`call: <T=any>(method: string, params?: unknown[]) => Promise<T>`)
129
+ })
130
+ })
131
+ this.out.line()
132
+ this.out.block("export class Contract ", () => {
133
+ this.out.line(`private readonly _chain: Chain`)
134
+ this.out.line(`private readonly blockHeight: number`)
135
+ this.out.line(`readonly address: string`)
136
+ this.out.line()
137
+ this.out.line(`constructor(ctx: BlockContext, address: string)`)
138
+ this.out.line(`constructor(ctx: ChainContext, block: Block, address: string)`)
139
+ this.out.block(`constructor(ctx: BlockContext, blockOrAddress: Block | string, address?: string)`, () => {
140
+ this.out.line(`this._chain = ctx._chain`)
141
+ this.out.block(`if (typeof blockOrAddress === 'string') `, () => {
142
+ this.out.line(`this.blockHeight = ctx.block.height`)
143
+ this.out.line(`this.address = ethers.utils.getAddress(blockOrAddress)`)
144
+ })
145
+ this.out.block(`else `, () => {
146
+ this.out.line(`assert(address != null)`)
147
+ this.out.line(`this.blockHeight = blockOrAddress.height`)
148
+ this.out.line(`this.address = ethers.utils.getAddress(address)`)
149
+ })
150
+ })
151
+ this.out.line()
152
+ for (const decl of abiCalls) {
153
+ if (decl.overloads.length > 1) {
154
+ for (let overload of decl.overloads) {
155
+ const args = overload.inputs.map((i, n) => `${i.name || `arg${n}`}: ${getType(i)}`)
156
+ const returnType = overload.outputs.length == 1 ? getType(overload.outputs[0]) : getTupleType(overload.outputs)
157
+ this.out.line(`async ${decl.name}(${args}): Promise<${returnType}>`)
158
+ }
159
+ this.out.block(`async ${decl.name}(...args: any[])`, () => {
160
+ this.out.line(`return this.call("${decl.name}", args)`)
161
+ })
162
+ } else {
163
+ const overload = decl.overloads[0]
164
+ const params = overload.inputs.map((i, n) => `${i.name || `arg${n}`}: ${getType(i)}`)
165
+ const returnType = overload.outputs.length == 1 ? getType(overload.outputs[0]) : getTupleType(overload.outputs)
166
+ this.out.block(`async ${decl.name}(${params.join(`, `)}): Promise<${returnType}>`, () => {
167
+ this.out.line(`return this.call("${decl.name}", [${overload.inputs.map((i, n) => `${i.name || `arg${n}`}`).join(`, `)}])`)
168
+ })
169
+ }
170
+ this.out.line()
171
+ }
172
+ this.out.block(`private async call(name: string, args: any[]) : Promise<any>`, () => {
173
+ this.out.line(`const fragment = abi.getFunction(name)`)
174
+ this.out.line(`const data = abi.encodeFunctionData(fragment, args)`)
175
+ this.out.line(`const result = await this._chain.client.call('eth_call', [{to: this.address, data}, this.blockHeight])`)
176
+ this.out.line(`const decoded = abi.decodeFunctionResult(fragment, result)`)
177
+ this.out.line(`return decoded.length > 1 ? decoded : decoded[0]`)
178
+ })
179
+ })
180
+ }
181
+
182
+ @def
183
+ private getEvents(): AbiEvent[] {
184
+ let res: Map<string, AbiEvent> = new Map()
185
+ for (let event of Object.values(this.abi.events)) {
186
+ let abiEvent = res.get(event.name)
187
+ if (abiEvent == null) {
188
+ abiEvent = {
189
+ name: event.name,
190
+ overloads: []
191
+ }
192
+ res.set(event.name, abiEvent)
193
+ }
194
+
195
+ abiEvent.overloads.push({
196
+ inputs: event.inputs || [],
197
+ })
198
+ }
199
+
200
+ return [...res.values()]
201
+ }
202
+
203
+ @def
204
+ private getFunctions(): AbiFunction[] {
205
+ let res: Map<string, AbiFunction> = new Map()
206
+ for (let func of Object.values(this.abi.functions)) {
207
+ if (func.constant) continue
208
+
209
+ let abiFunc = res.get(func.name)
210
+ if (abiFunc == null) {
211
+ abiFunc = {
212
+ name: func.name,
213
+ overloads: []
214
+ }
215
+ res.set(func.name, abiFunc)
216
+ }
217
+
218
+ abiFunc.overloads.push({
219
+ inputs: func.inputs || [],
220
+ })
221
+ }
222
+
223
+ return [...res.values()]
224
+ }
225
+
226
+ @def
227
+ private getCalls(): AbiCall[] {
228
+ let res: Map<string, AbiCall> = new Map()
229
+ for (let func of Object.values(this.abi.functions)) {
230
+ if (!func.constant || func.outputs == null) continue
231
+
232
+ let abiCall = res.get(func.name)
233
+ if (abiCall == null) {
234
+ abiCall = {
235
+ name: func.name,
236
+ overloads: []
237
+ }
238
+ res.set(func.name, abiCall)
239
+ }
240
+
241
+ abiCall.overloads.push({
242
+ inputs: func.inputs,
243
+ outputs: func.outputs || [],
244
+ })
245
+ }
246
+
247
+ return [...res.values()]
248
+ }
249
+ }
250
+
251
+
252
+ // taken from: https://github.com/ethers-io/ethers.js/blob/948f77050dae884fe88932fd88af75560aac9d78/packages/cli/src.ts/typescript.ts#L10
253
+ function getType(param: ParamType): string {
254
+ if (param.type === "address" || param.type === "string") {
255
+ return "string"
256
+ }
257
+
258
+ if (param.type === "bool") {
259
+ return "boolean"
260
+ }
261
+
262
+ if (param.type.substring(0, 5) === "bytes") {
263
+ return "string"
264
+ }
265
+
266
+ let match = param.type.match(/^(u?int)([0-9]+)$/)
267
+ if (match) {
268
+ return parseInt(match[2]) < 53 ? 'number' : 'ethers.BigNumber'
269
+ }
270
+
271
+ if (param.baseType === "array") {
272
+ return "Array<" + getType(param.arrayChildren) + ">"
273
+ }
274
+
275
+ if (param.baseType === "tuple") {
276
+ return getTupleType(param.components)
277
+ }
278
+
279
+ throw new Error("unknown type")
280
+ }
281
+
282
+
283
+ function getTupleType(params: ParamType[]) {
284
+ let tuple = '[' + params.map(p => {
285
+ return p.name ? `${p.name}: ${getType(p)}` : getType(p)
286
+ }).join(', ') + ']'
287
+
288
+ let fields = getStructFields(params)
289
+ if (fields.length == 0) return tuple
290
+
291
+ let struct = '{' + fields.map(f => `${f.name}: ${getType(f)}`).join(', ') + '}'
292
+
293
+ return `(${tuple} & ${struct})`
294
+ }
295
+
296
+
297
+ // https://github.com/ethers-io/ethers.js/blob/948f77050dae884fe88932fd88af75560aac9d78/packages/abi/src.ts/coders/tuple.ts#L29
298
+ function getStructFields(params: ParamType[]): ParamType[] {
299
+ let array: any = []
300
+ let counts: Record<string, number> = {}
301
+ for (let p of params) {
302
+ if (p.name && array[p.name] == null) {
303
+ counts[p.name] = (counts[p.name] || 0) + 1
304
+ }
305
+ }
306
+ return params.filter(p => counts[p.name] == 1)
307
+ }
308
+
309
+
310
+ function createSignature(name: string, inputs: ParamType[]) {
311
+ return `${name}(${inputs.map((i) => i.type).join(`,`)})`
312
+ }
313
+
314
+
315
+ interface AbiEvent {
316
+ name: string
317
+ overloads: {
318
+ inputs: ParamType[]
319
+ }[]
320
+ }
321
+
322
+
323
+ interface AbiFunction {
324
+ name: string
325
+ overloads: {
326
+ inputs: ParamType[]
327
+ }[]
328
+ }
329
+
330
+
331
+ interface AbiCall {
332
+ name: string
333
+ overloads: {
334
+ inputs: ParamType[]
335
+ outputs: ParamType[]
336
+ }[]
337
+ }
338
+
339
+
340
+ function upperCaseFirst(s: string): string {
341
+ return s[0].toUpperCase() + s.slice(1)
342
+ }