@graphprotocol/graph-cli 0.37.4 → 0.37.5

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.
Files changed (100) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/bin.js +6 -0
  3. package/dist/cli.js +26 -0
  4. package/dist/codegen/schema.js +244 -0
  5. package/dist/codegen/schema.test.js +455 -0
  6. package/dist/codegen/template.js +66 -0
  7. package/dist/codegen/types/conversions.js +335 -0
  8. package/dist/codegen/types/index.js +71 -0
  9. package/dist/codegen/types/index.test.js +563 -0
  10. package/dist/codegen/typescript.js +200 -0
  11. package/dist/codegen/util.js +40 -0
  12. package/dist/codegen/util.test.js +93 -0
  13. package/dist/command-helpers/abi.js +76 -0
  14. package/dist/command-helpers/auth.js +76 -0
  15. package/dist/command-helpers/compiler.js +66 -0
  16. package/dist/command-helpers/data-sources.js +29 -0
  17. package/dist/command-helpers/fs.js +9 -0
  18. package/dist/command-helpers/gluegun.js +48 -0
  19. package/dist/command-helpers/ipfs.js +5 -0
  20. package/dist/command-helpers/jsonrpc.js +27 -0
  21. package/dist/command-helpers/network.js +90 -0
  22. package/dist/command-helpers/network.test.js +86 -0
  23. package/dist/command-helpers/node.js +40 -0
  24. package/dist/command-helpers/scaffold.js +110 -0
  25. package/dist/command-helpers/spinner.js +80 -0
  26. package/dist/command-helpers/studio.js +14 -0
  27. package/dist/command-helpers/studio.test.js +41 -0
  28. package/dist/command-helpers/subgraph.js +22 -0
  29. package/dist/command-helpers/version.js +66 -0
  30. package/dist/command-helpers/version.test.js +186 -0
  31. package/dist/commands/add.js +187 -0
  32. package/dist/commands/auth.js +122 -0
  33. package/dist/commands/build.js +136 -0
  34. package/dist/commands/codegen.js +128 -0
  35. package/dist/commands/create.js +94 -0
  36. package/dist/commands/deploy.js +335 -0
  37. package/dist/commands/init.js +800 -0
  38. package/dist/commands/local.js +380 -0
  39. package/dist/commands/remove.js +95 -0
  40. package/dist/commands/test.js +293 -0
  41. package/dist/compiler/asc.js +83 -0
  42. package/dist/compiler/index.js +466 -0
  43. package/dist/debug.js +16 -0
  44. package/dist/migrations/mapping_api_version_0_0_1.js +83 -0
  45. package/dist/migrations/mapping_api_version_0_0_2.js +83 -0
  46. package/dist/migrations/mapping_api_version_0_0_3.js +83 -0
  47. package/dist/migrations/mapping_api_version_0_0_4.js +85 -0
  48. package/dist/migrations/mapping_api_version_0_0_5.js +85 -0
  49. package/dist/migrations/spec_version_0_0_2.js +45 -0
  50. package/dist/migrations/spec_version_0_0_3.js +50 -0
  51. package/dist/migrations/util/load-manifest.js +16 -0
  52. package/dist/migrations/util/versions.js +28 -0
  53. package/dist/migrations.js +54 -0
  54. package/dist/protocols/arweave/manifest.graphql +57 -0
  55. package/dist/protocols/arweave/scaffold/manifest.js +18 -0
  56. package/dist/protocols/arweave/scaffold/mapping.js +52 -0
  57. package/dist/protocols/arweave/subgraph.js +23 -0
  58. package/dist/protocols/contract.js +2 -0
  59. package/dist/protocols/cosmos/manifest.graphql +76 -0
  60. package/dist/protocols/cosmos/scaffold/manifest.js +15 -0
  61. package/dist/protocols/cosmos/scaffold/mapping.js +38 -0
  62. package/dist/protocols/cosmos/subgraph.js +28 -0
  63. package/dist/protocols/ethereum/abi.js +138 -0
  64. package/dist/protocols/ethereum/codegen/abi.js +474 -0
  65. package/dist/protocols/ethereum/codegen/abi.test.js +325 -0
  66. package/dist/protocols/ethereum/codegen/template.js +52 -0
  67. package/dist/protocols/ethereum/contract.js +22 -0
  68. package/dist/protocols/ethereum/manifest.graphql +94 -0
  69. package/dist/protocols/ethereum/scaffold/manifest.js +32 -0
  70. package/dist/protocols/ethereum/scaffold/mapping.js +65 -0
  71. package/dist/protocols/ethereum/subgraph.js +172 -0
  72. package/dist/protocols/ethereum/type-generator.js +123 -0
  73. package/dist/protocols/index.js +266 -0
  74. package/dist/protocols/ipfs/codegen/file_template.js +53 -0
  75. package/dist/protocols/near/contract.js +41 -0
  76. package/dist/protocols/near/manifest.graphql +64 -0
  77. package/dist/protocols/near/scaffold/manifest.js +16 -0
  78. package/dist/protocols/near/scaffold/mapping.js +38 -0
  79. package/dist/protocols/near/subgraph.js +23 -0
  80. package/dist/protocols/subgraph.js +2 -0
  81. package/dist/protocols/substreams/manifest.graphql +45 -0
  82. package/dist/protocols/substreams/scaffold/manifest.js +12 -0
  83. package/dist/protocols/substreams/subgraph.js +23 -0
  84. package/dist/scaffold/cosmos.test.js +82 -0
  85. package/dist/scaffold/ethereum.test.js +496 -0
  86. package/dist/scaffold/index.js +133 -0
  87. package/dist/scaffold/mapping.js +57 -0
  88. package/dist/scaffold/near.test.js +85 -0
  89. package/dist/scaffold/schema.js +86 -0
  90. package/dist/scaffold/tests.js +179 -0
  91. package/dist/schema.js +54 -0
  92. package/dist/subgraph.js +243 -0
  93. package/dist/type-generator.js +225 -0
  94. package/dist/validation/contract.js +44 -0
  95. package/dist/validation/index.js +10 -0
  96. package/dist/validation/manifest.js +266 -0
  97. package/dist/validation/schema.js +768 -0
  98. package/dist/validation/schema.test.js +35 -0
  99. package/dist/watcher.js +79 -0
  100. package/package.json +1 -1
@@ -0,0 +1,474 @@
1
+ "use strict";
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]; } };
7
+ }
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const fs_1 = __importDefault(require("fs"));
30
+ const immutable_1 = __importDefault(require("immutable"));
31
+ const sync_request_1 = __importDefault(require("sync-request"));
32
+ const web3_eth_abi_1 = __importDefault(require("web3-eth-abi"));
33
+ const yaml_1 = __importDefault(require("yaml"));
34
+ const typesCodegen = __importStar(require("../../../codegen/types"));
35
+ const tsCodegen = __importStar(require("../../../codegen/typescript"));
36
+ const util = __importStar(require("../../../codegen/util"));
37
+ const doFixtureCodegen = fs_1.default.existsSync('./fixtures.yaml');
38
+ class AbiCodeGenerator {
39
+ abi;
40
+ constructor(abi) {
41
+ this.abi = abi;
42
+ this.abi = abi;
43
+ }
44
+ generateModuleImports() {
45
+ const imports = [
46
+ tsCodegen.moduleImports([
47
+ // Ethereum integration
48
+ 'ethereum',
49
+ // Base classes
50
+ 'JSONValue',
51
+ 'TypedMap',
52
+ 'Entity',
53
+ // AssemblyScript types
54
+ 'Bytes',
55
+ 'Address',
56
+ 'BigInt',
57
+ ], '@graphprotocol/graph-ts'),
58
+ ];
59
+ if (doFixtureCodegen) {
60
+ imports.push(tsCodegen.moduleImports(['newMockEvent'], 'matchstick-as/assembly/index'));
61
+ }
62
+ return imports;
63
+ }
64
+ generateTypes() {
65
+ return [
66
+ ...this._generateEventTypes(),
67
+ ...this._generateSmartContractClass(),
68
+ ...this._generateCallTypes(),
69
+ ];
70
+ }
71
+ _generateCallTypes() {
72
+ let callFunctions = util.disambiguateNames({
73
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
74
+ values: this.abi.callFunctions(),
75
+ getName: fn =>
76
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
77
+ fn.get('name') || (fn.get('type') === 'constructor' ? 'constructor' : 'default'),
78
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
79
+ setName: (fn, name) => fn.set('_alias', name),
80
+ });
81
+ callFunctions = callFunctions.map(fn => {
82
+ const fnAlias = fn.get('_alias');
83
+ const fnClassName = `${fnAlias.charAt(0).toUpperCase()}${fnAlias.slice(1)}Call`;
84
+ const tupleClasses = [];
85
+ // First, generate a class with the input getters
86
+ const inputsClassName = fnClassName + '__Inputs';
87
+ const inputsClass = tsCodegen.klass(inputsClassName, { export: true });
88
+ inputsClass.addMember(tsCodegen.klassMember('_call', fnClassName));
89
+ inputsClass.addMethod(tsCodegen.method(`constructor`, [tsCodegen.param(`call`, fnClassName)], null, `this._call = call`));
90
+ // Generate getters and classes for function inputs
91
+ util
92
+ .disambiguateNames({
93
+ values: fn.get('inputs', immutable_1.default.List()),
94
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
95
+ getName: (input, index) => input.get('name') || `value${index}`,
96
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
97
+ setName: (input, name) => input.set('name', name),
98
+ })
99
+ .forEach((input, index) => {
100
+ const callInput = this._generateInputOrOutput(input, index, fnClassName, `call`, `inputValues`);
101
+ inputsClass.addMethod(callInput.getter);
102
+ tupleClasses.push(...callInput.classes);
103
+ });
104
+ // Second, generate a class with the output getters
105
+ const outputsClassName = fnClassName + '__Outputs';
106
+ const outputsClass = tsCodegen.klass(outputsClassName, { export: true });
107
+ outputsClass.addMember(tsCodegen.klassMember('_call', fnClassName));
108
+ outputsClass.addMethod(tsCodegen.method(`constructor`, [tsCodegen.param(`call`, fnClassName)], null, `this._call = call`));
109
+ // Generate getters and classes for function outputs
110
+ util
111
+ .disambiguateNames({
112
+ values: fn.get('outputs', immutable_1.default.List()),
113
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
114
+ getName: (output, index) => output.get('name') || `value${index}`,
115
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
116
+ setName: (output, name) => output.set('name', name),
117
+ })
118
+ .forEach((output, index) => {
119
+ const callInput = this._generateInputOrOutput(output, index, fnClassName, `call`, `outputValues`);
120
+ outputsClass.addMethod(callInput.getter);
121
+ tupleClasses.push(...callInput.classes);
122
+ });
123
+ // Then, generate the event class itself
124
+ const klass = tsCodegen.klass(fnClassName, {
125
+ export: true,
126
+ extends: 'ethereum.Call',
127
+ });
128
+ klass.addMethod(tsCodegen.method(`get inputs`, [], tsCodegen.namedType(inputsClassName), `return new ${inputsClassName}(this)`));
129
+ klass.addMethod(tsCodegen.method(`get outputs`, [], tsCodegen.namedType(outputsClassName), `return new ${outputsClassName}(this)`));
130
+ return [klass, inputsClass, outputsClass, ...tupleClasses];
131
+ });
132
+ return callFunctions.reduce(
133
+ // flatten the array
134
+ (array, classes) => array.concat(classes), []);
135
+ }
136
+ _generateEventTypes() {
137
+ // Enumerate events with duplicate names
138
+ let events = util.disambiguateNames({
139
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
140
+ values: this.abi.data.filter(member => member.get('type') === 'event'),
141
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
142
+ getName: event => event.get('name'),
143
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
144
+ setName: (event, name) => event.set('_alias', name),
145
+ });
146
+ events = events.map(event => {
147
+ const eventClassName = event.get('_alias');
148
+ const tupleClasses = [];
149
+ // First, generate a class with the param getters
150
+ const paramsClassName = eventClassName + '__Params';
151
+ const paramsClass = tsCodegen.klass(paramsClassName, { export: true });
152
+ paramsClass.addMember(tsCodegen.klassMember('_event', eventClassName));
153
+ paramsClass.addMethod(tsCodegen.method(`constructor`, [tsCodegen.param(`event`, eventClassName)], null, `this._event = event`));
154
+ // Enumerate inputs with duplicate names
155
+ const inputs = util.disambiguateNames({
156
+ values: event.get('inputs'),
157
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
158
+ getName: (input, index) => input.get('name') || `param${index}`,
159
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
160
+ setName: (input, name) => input.set('name', name),
161
+ });
162
+ const namesAndTypes = [];
163
+ inputs.forEach((input, index) => {
164
+ // Generate getters and classes for event params
165
+ const paramObject = this._generateInputOrOutput(input, index, eventClassName, `event`, `parameters`);
166
+ paramsClass.addMethod(paramObject.getter);
167
+ // Fixture generation
168
+ if (doFixtureCodegen) {
169
+ let ethType = typesCodegen.ethereumTypeForAsc(String(paramObject.getter.returnType));
170
+ if (typeof ethType !== 'string' && (ethType.test('int256') || ethType.test('uint256'))) {
171
+ ethType = 'int32';
172
+ }
173
+ namesAndTypes.push({ name: paramObject.getter.name.slice(4), type: ethType });
174
+ }
175
+ tupleClasses.push(...paramObject.classes);
176
+ });
177
+ // Then, generate the event class itself
178
+ const klass = tsCodegen.klass(eventClassName, {
179
+ export: true,
180
+ extends: 'ethereum.Event',
181
+ });
182
+ klass.addMethod(tsCodegen.method(`get params`, [], tsCodegen.namedType(paramsClassName), `return new ${paramsClassName}(this)`));
183
+ // Fixture generation
184
+ if (doFixtureCodegen) {
185
+ const args = yaml_1.default.parse(fs_1.default.readFileSync('./fixtures.yaml', 'utf8'));
186
+ const blockNumber = args['blockNumber'];
187
+ const contractAddr = args['contractAddr'];
188
+ const topic0 = args['topic0'];
189
+ const apiKey = args['apiKey'];
190
+ const url = `https://api.etherscan.io/api?module=logs&action=getLogs&fromBlock=${blockNumber}&toBlock=${blockNumber}&address=${contractAddr}&${topic0}=topic0&apikey=${apiKey}`;
191
+ const resp = (0, sync_request_1.default)('GET', url);
192
+ const body = JSON.parse(resp.getBody('utf8'));
193
+ if (body.status === '0') {
194
+ throw new Error(body.result);
195
+ }
196
+ const res = web3_eth_abi_1.default
197
+ // @ts-expect-error decodeLog seems to exist on Web3EthAbi
198
+ .decodeLog(namesAndTypes, body.result[0].data, []);
199
+ let stmnts = '';
200
+ for (let i = 0; i < namesAndTypes.length; i++) {
201
+ let code = '"' + res[i] + '"';
202
+ if (namesAndTypes[i].type.toString() == 'address') {
203
+ code = `Address.fromString(${code})`;
204
+ }
205
+ stmnts = stmnts.concat(`event.parameters.push(new ethereum.EventParam("${namesAndTypes[i].name}", ${typesCodegen.ethereumFromAsc(code, namesAndTypes[i].type)}));`, `\n`);
206
+ }
207
+ klass.addMethod(tsCodegen.staticMethod(`mock${eventClassName}`, [], tsCodegen.namedType(eventClassName), `
208
+ let event = changetype<${eventClassName}>(newMockEvent());
209
+ ${stmnts}
210
+ return event;
211
+ `));
212
+ }
213
+ return [klass, paramsClass, ...tupleClasses];
214
+ });
215
+ return events.reduce(
216
+ // flatten the array
217
+ (array, classes) => array.concat(classes), []);
218
+ }
219
+ _generateInputOrOutput(inputOrOutput, index, parentClass, parentType, parentField) {
220
+ // Get name and type of the param, adjusting for indexed params and missing names
221
+ let name = inputOrOutput.get('name');
222
+ const valueType = parentType === 'event' && inputOrOutput.get('indexed')
223
+ ? this._indexedInputType(inputOrOutput.get('type'))
224
+ : inputOrOutput.get('type');
225
+ if (name === undefined || name === null || name === '') {
226
+ name = parentType === 'event' ? `param${index}` : `value${index}`;
227
+ }
228
+ // Generate getters and classes for the param (classes only created for Ethereum tuple types)
229
+ return util.containsTupleType(valueType)
230
+ ? this._generateTupleType(inputOrOutput, index, parentClass, parentType, parentField)
231
+ : {
232
+ name: [],
233
+ getter: tsCodegen.method(`get ${name}`, [], typesCodegen.ascTypeForEthereum(valueType), `
234
+ return ${typesCodegen.ethereumToAsc(util.isTupleType(parentType)
235
+ ? `this[${index}]`
236
+ : `this._${parentType}.${parentField}[${index}].value`, valueType)}
237
+ `),
238
+ classes: [],
239
+ };
240
+ }
241
+ _tupleTypeName(inputOrOutput, index, parentClass, parentType) {
242
+ return this._generateTupleType(inputOrOutput, index, parentClass, parentType, '').name;
243
+ }
244
+ _generateTupleType(inputOrOutput, index, parentClass, parentType, parentField) {
245
+ const type = inputOrOutput.get('type');
246
+ let name = inputOrOutput.get('name');
247
+ if (name === undefined || name === null || name === '') {
248
+ name = parentType === 'event' ? `param${index}` : `value${index}`;
249
+ }
250
+ const tupleIdentifier = parentClass + tsCodegen.namedType(name).capitalize();
251
+ const tupleClassName = tupleIdentifier + 'Struct';
252
+ let tupleClasses = [];
253
+ const isTupleType = util.isTupleType(type);
254
+ const returnValue = typesCodegen.ethereumToAsc(parentType === 'tuple'
255
+ ? `this[${index}]`
256
+ : `this._${parentType}.${parentField}[${index}].value`, type, tupleClassName);
257
+ // Generate getter for parent class
258
+ const tupleGetter = tsCodegen.method(`get ${name}`, [], util.isTupleMatrixType(type)
259
+ ? `Array<Array<${tupleClassName}>>`
260
+ : util.isTupleArrayType(type)
261
+ ? `Array<${tupleClassName}>`
262
+ : tupleClassName, `
263
+ return ${isTupleType ? `changetype<${tupleClassName}>(${returnValue})` : String(returnValue)}
264
+ `);
265
+ // Generate tuple class
266
+ const baseTupleClass = tsCodegen.klass(tupleClassName, {
267
+ export: true,
268
+ extends: 'ethereum.Tuple',
269
+ });
270
+ // Add param getters to tuple class and generate classes for each tuple parameter
271
+ inputOrOutput.get('components').forEach((component, index) => {
272
+ const paramObject = this._generateInputOrOutput(component, index, tupleIdentifier, `tuple`);
273
+ baseTupleClass.addMethod(paramObject.getter);
274
+ tupleClasses = tupleClasses.concat(paramObject.classes);
275
+ });
276
+ // Combine all tuple classes generated
277
+ tupleClasses.unshift(baseTupleClass);
278
+ return {
279
+ name: tupleClassName,
280
+ getter: tupleGetter,
281
+ classes: tupleClasses,
282
+ };
283
+ }
284
+ _generateSmartContractClass() {
285
+ const klass = tsCodegen.klass(this.abi.name, {
286
+ export: true,
287
+ extends: 'ethereum.SmartContract',
288
+ });
289
+ let types = immutable_1.default.List();
290
+ klass.addMethod(tsCodegen.staticMethod('bind',
291
+ // TODO: add support for iterable staticMethod params
292
+ immutable_1.default.List([
293
+ tsCodegen.param('address', typesCodegen.ascTypeForEthereum('address')),
294
+ ]), tsCodegen.namedType(this.abi.name), `
295
+ return new ${this.abi.name}('${this.abi.name}', address);
296
+ `));
297
+ // Get view/pure functions from the contract
298
+ let functions = this.callableFunctions();
299
+ // Disambiguate functions with duplicate names
300
+ functions = util.disambiguateNames({
301
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
302
+ values: functions,
303
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
304
+ getName: fn => fn.get('name'),
305
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
306
+ setName: (fn, name) => fn.set('_alias', name),
307
+ });
308
+ functions.forEach(member => {
309
+ const fnName = member.get('name');
310
+ const fnAlias = member.get('_alias');
311
+ const fnSignature = this.abi.functionSignature(member);
312
+ // Generate a type for the result of calling the function
313
+ let returnType = undefined;
314
+ let simpleReturnType = true;
315
+ const tupleResultParentType = this.abi.name + '__' + fnAlias + 'Result';
316
+ // Disambiguate outputs with duplicate names
317
+ const outputs = util.disambiguateNames({
318
+ values: member.get('outputs', immutable_1.default.List()),
319
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
320
+ getName: (input, index) => input.get('name') || `value${index}`,
321
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
322
+ setName: (input, name) => input.set('name', name),
323
+ });
324
+ if (member.get('outputs', immutable_1.default.List()).size > 1) {
325
+ simpleReturnType = false;
326
+ // Create a type dedicated to holding the return values
327
+ returnType = tsCodegen.klass(this.abi.name + '__' + fnAlias + 'Result', {
328
+ export: true,
329
+ });
330
+ // Add a constructor to this type
331
+ returnType.addMethod(tsCodegen.method('constructor', outputs.map((output, index) => tsCodegen.param(`value${index}`, this._getTupleParamType(output, index, tupleResultParentType))), null, outputs
332
+ .map((_output, index) => `this.value${index} = value${index}`)
333
+ .join('\n')));
334
+ // Add a `toMap(): TypedMap<string,ethereum.Value>` function to the return type
335
+ returnType.addMethod(tsCodegen.method('toMap', [], tsCodegen.namedType('TypedMap<string,ethereum.Value>'), `
336
+ let map = new TypedMap<string,ethereum.Value>();
337
+ ${outputs
338
+ .map((output, index) => `map.set('value${index}', ${typesCodegen.ethereumFromAsc(`this.value${index}`, output.get('type'))})`)
339
+ .join(';')}
340
+ return map;
341
+ `));
342
+ // Add value0, value1 etc. members to the type
343
+ outputs
344
+ .map((output, index) => tsCodegen.klassMember(`value${index}`, this._getTupleParamType(output, index, tupleResultParentType)))
345
+ .forEach((member) => returnType.addMember(member));
346
+ // Add getters to the type
347
+ outputs
348
+ .map((output, index) => !!output.get('name') &&
349
+ tsCodegen.method(`get${output.get('name')[0].toUpperCase()}${output.get('name').slice(1)}`, [], this._getTupleParamType(output, index, tupleResultParentType), `return this.value${index};`))
350
+ .forEach((method) => !!method && returnType.addMethod(method));
351
+ // Create types for Tuple outputs
352
+ outputs.forEach((output, index) => {
353
+ if (util.containsTupleType(output.get('type'))) {
354
+ types = types.concat(this._generateTupleType(output, index, tupleResultParentType, 'function', this.abi.name).classes);
355
+ }
356
+ });
357
+ // Add the type to the types we'll create
358
+ types = types.push(returnType);
359
+ returnType = tsCodegen.namedType(returnType.name);
360
+ }
361
+ else {
362
+ const type = outputs.get(0).get('type');
363
+ if (util.containsTupleType(type)) {
364
+ // Add the Tuple type to the types we'll create
365
+ const tuple = this._generateTupleType(outputs.get(0), 0, tupleResultParentType, 'function', this.abi.name);
366
+ types = types.concat(tuple.classes);
367
+ returnType = util.isTupleType(type)
368
+ ? tsCodegen.namedType(tuple.name)
369
+ : `Array<${tsCodegen.namedType(tuple.name)}>`;
370
+ }
371
+ else {
372
+ returnType = tsCodegen.namedType(typesCodegen.ascTypeForEthereum(type));
373
+ }
374
+ }
375
+ // Disambiguate inputs with duplicate names
376
+ const inputs = util.disambiguateNames({
377
+ values: member.get('inputs', immutable_1.default.List()),
378
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
379
+ getName: (input, index) => input.get('name') || `param${index}`,
380
+ // @ts-expect-error improve typings of disambiguateNames to handle iterables
381
+ setName: (input, name) => input.set('name', name),
382
+ });
383
+ // Generate a type prefix to identify the Tuple inputs to a function
384
+ const tupleInputParentType = this.abi.name + '__' + fnAlias + 'Input';
385
+ // Create types for Tuple inputs
386
+ inputs.forEach((input, index) => {
387
+ if (util.containsTupleType(input.get('type'))) {
388
+ types = types.concat(this._generateTupleType(input, index, tupleInputParentType, 'function', this.abi.name)
389
+ .classes);
390
+ }
391
+ });
392
+ // Generate and add a method that implements calling the function on
393
+ // the smart contract
394
+ const params = inputs.map((input, index) => tsCodegen.param(input.get('name'), this._getTupleParamType(input, index, tupleInputParentType)));
395
+ const superInputs = `
396
+ '${fnName}',
397
+ '${fnSignature}',
398
+ [${inputs.size > 0
399
+ ? inputs
400
+ .map((input) => typesCodegen.ethereumFromAsc(input.get('name'), input.get('type')))
401
+ .map((coercion) => coercion.toString())
402
+ .join(', ')
403
+ : ''}]`;
404
+ const methodCallBody = (isTry) => {
405
+ const methodBody = `
406
+ ${isTry
407
+ ? `
408
+ let result = super.tryCall(${superInputs})
409
+ if (result.reverted) {
410
+ return new ethereum.CallResult()
411
+ }
412
+ let value = result.value
413
+ return ethereum.CallResult.fromValue(`
414
+ : `
415
+ let result = super.call(${superInputs})
416
+
417
+ return (`}`;
418
+ const returnVal = simpleReturnType
419
+ ? typesCodegen.ethereumToAsc(isTry ? 'value[0]' : 'result[0]', outputs.get(0).get('type'), util.isTupleArrayType(outputs.get(0).get('type'))
420
+ ? this._tupleTypeName(outputs.get(0), 0, tupleResultParentType, this.abi.name)
421
+ : '')
422
+ : `new ${returnType.name}(
423
+ ${outputs
424
+ .map((output, index) => {
425
+ const val = typesCodegen.ethereumToAsc(isTry ? `value[${index}]` : `result[${index}]`, output.get('type'), util.isTupleArrayType(output.get('type'))
426
+ ? this._tupleTypeName(output, index, tupleResultParentType, this.abi.name)
427
+ : '');
428
+ return util.isTupleType(output.get('type'))
429
+ ? `changetype<${this._tupleTypeName(output, index, tupleResultParentType, this.abi.name)}>(${val})`
430
+ : val;
431
+ })
432
+ .join(', ')}
433
+ )`;
434
+ const isTuple = util.isTupleType(outputs.get(0).get('type'));
435
+ return `${methodBody} ${isTuple ? `changetype<${returnType}>(${returnVal})` : returnVal})`;
436
+ };
437
+ // Generate method with an without `try_`.
438
+ klass.addMethod(tsCodegen.method(fnAlias, params, returnType, methodCallBody(false)));
439
+ klass.addMethod(tsCodegen.method('try_' + fnAlias, params, 'ethereum.CallResult<' + returnType + '>', methodCallBody(true)));
440
+ });
441
+ return [...types, klass];
442
+ }
443
+ _getTupleParamType(inputOrOutput, index, tupleParentType) {
444
+ const type = inputOrOutput.get('type');
445
+ return util.isTupleType(type)
446
+ ? this._tupleTypeName(inputOrOutput, index, tupleParentType, this.abi.name)
447
+ : util.isTupleMatrixType(type)
448
+ ? `Array<Array<${this._tupleTypeName(inputOrOutput, index, tupleParentType, this.abi.name)}>>`
449
+ : util.isTupleArrayType(type)
450
+ ? `Array<${this._tupleTypeName(inputOrOutput, index, tupleParentType, this.abi.name)}>`
451
+ : typesCodegen.ascTypeForEthereum(type);
452
+ }
453
+ _indexedInputType(inputType) {
454
+ // strings, bytes and arrays are encoded and hashed to a bytes32 value
455
+ if (inputType === 'string' ||
456
+ inputType === 'bytes' ||
457
+ inputType === 'tuple' ||
458
+ // the following matches arrays of the forms `uint256[]` and `uint256[12356789]`;
459
+ // the value type name doesn't matter here, just that the type name ends with
460
+ // brackets and, optionally, a number inside the brackets
461
+ inputType.match(/\[[0-9]*\]$/g)) {
462
+ return 'bytes32';
463
+ }
464
+ return inputType;
465
+ }
466
+ callableFunctions() {
467
+ const allowedMutability = ['view', 'pure', 'nonpayable', 'constant'];
468
+ return this.abi.data.filter(member => member.get('type') === 'function' &&
469
+ member.get('outputs', immutable_1.default.List()).size !== 0 &&
470
+ (allowedMutability.includes(member.get('stateMutability')) ||
471
+ (member.get('stateMutability') === undefined && !member.get('payable', false))));
472
+ }
473
+ }
474
+ exports.default = AbiCodeGenerator;