@graphprotocol/graph-cli 0.37.2-alpha-20221219142030-0cf2a37 → 0.37.2

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.
@@ -1,13 +1,14 @@
1
+ const immutable = require('immutable')
1
2
  const fs = require('fs')
2
3
  const yaml = require('yaml')
3
4
  const request = require('sync-request')
4
- const Web3EthAbi = require('web3-eth-abi')
5
+ const Web3EthAbi = require('web3-eth-abi');
5
6
 
6
7
  const tsCodegen = require('../../../codegen/typescript')
7
8
  const typesCodegen = require('../../../codegen/types')
8
9
  const util = require('../../../codegen/util')
9
10
 
10
- const doFixtureCodegen = fs.existsSync('./fixtures.yaml')
11
+ const doFixtureCodegen = fs.existsSync('./fixtures.yaml');
11
12
 
12
13
  module.exports = class AbiCodeGenerator {
13
14
  constructor(abi) {
@@ -32,12 +33,17 @@ module.exports = class AbiCodeGenerator {
32
33
  'BigInt',
33
34
  ],
34
35
  '@graphprotocol/graph-ts',
35
- ),
36
+ )
36
37
  ]
37
38
 
38
39
  if (doFixtureCodegen) {
39
40
  imports.push(
40
- tsCodegen.moduleImports(['newMockEvent'], 'matchstick-as/assembly/index'),
41
+ tsCodegen.moduleImports(
42
+ [
43
+ 'newMockEvent',
44
+ ],
45
+ 'matchstick-as/assembly/index',
46
+ )
41
47
  )
42
48
  }
43
49
 
@@ -60,104 +66,106 @@ module.exports = class AbiCodeGenerator {
60
66
  setName: (fn, name) => fn.set('_alias', name),
61
67
  })
62
68
 
63
- callFunctions = callFunctions.map(fn => {
64
- let fnAlias = fn.get('_alias')
65
- let fnClassName = `${fnAlias.charAt(0).toUpperCase()}${fnAlias.slice(1)}Call`
66
- let tupleClasses = []
67
-
68
- // First, generate a class with the input getters
69
- let inputsClassName = fnClassName + '__Inputs'
70
- let inputsClass = tsCodegen.klass(inputsClassName, { export: true })
71
- inputsClass.addMember(tsCodegen.klassMember('_call', fnClassName))
72
- inputsClass.addMethod(
73
- tsCodegen.method(
74
- `constructor`,
75
- [tsCodegen.param(`call`, fnClassName)],
76
- null,
77
- `this._call = call`,
78
- ),
79
- )
69
+ callFunctions = callFunctions
70
+ .map(fn => {
71
+ let fnAlias = fn.get('_alias')
72
+ let fnClassName = `${fnAlias.charAt(0).toUpperCase()}${fnAlias.slice(1)}Call`
73
+ let tupleClasses = []
74
+
75
+ // First, generate a class with the input getters
76
+ let inputsClassName = fnClassName + '__Inputs'
77
+ let inputsClass = tsCodegen.klass(inputsClassName, { export: true })
78
+ inputsClass.addMember(tsCodegen.klassMember('_call', fnClassName))
79
+ inputsClass.addMethod(
80
+ tsCodegen.method(
81
+ `constructor`,
82
+ [tsCodegen.param(`call`, fnClassName)],
83
+ null,
84
+ `this._call = call`,
85
+ ),
86
+ )
80
87
 
81
- // Generate getters and classes for function inputs
82
- util
83
- .disambiguateNames({
84
- values: fn.get('inputs', []),
85
- getName: (input, index) => input.get('name') || `value${index}`,
86
- setName: (input, name) => input.set('name', name),
87
- })
88
- .forEach((input, index) => {
89
- let callInput = this._generateInputOrOutput(
90
- input,
91
- index,
92
- fnClassName,
93
- `call`,
94
- `inputValues`,
95
- )
96
- inputsClass.addMethod(callInput.getter)
97
- tupleClasses.push(...callInput.classes)
98
- })
88
+ // Generate getters and classes for function inputs
89
+ util
90
+ .disambiguateNames({
91
+ values: fn.get('inputs', immutable.List()),
92
+ getName: (input, index) => input.get('name') || `value${index}`,
93
+ setName: (input, name) => input.set('name', name),
94
+ })
95
+ .forEach((input, index) => {
96
+ let callInput = this._generateInputOrOutput(
97
+ input,
98
+ index,
99
+ fnClassName,
100
+ `call`,
101
+ `inputValues`,
102
+ )
103
+ inputsClass.addMethod(callInput.getter)
104
+ tupleClasses.push(...callInput.classes)
105
+ })
106
+
107
+ // Second, generate a class with the output getters
108
+ let outputsClassName = fnClassName + '__Outputs'
109
+ let outputsClass = tsCodegen.klass(outputsClassName, { export: true })
110
+ outputsClass.addMember(tsCodegen.klassMember('_call', fnClassName))
111
+ outputsClass.addMethod(
112
+ tsCodegen.method(
113
+ `constructor`,
114
+ [tsCodegen.param(`call`, fnClassName)],
115
+ null,
116
+ `this._call = call`,
117
+ ),
118
+ )
99
119
 
100
- // Second, generate a class with the output getters
101
- let outputsClassName = fnClassName + '__Outputs'
102
- let outputsClass = tsCodegen.klass(outputsClassName, { export: true })
103
- outputsClass.addMember(tsCodegen.klassMember('_call', fnClassName))
104
- outputsClass.addMethod(
105
- tsCodegen.method(
106
- `constructor`,
107
- [tsCodegen.param(`call`, fnClassName)],
108
- null,
109
- `this._call = call`,
110
- ),
111
- )
120
+ // Generate getters and classes for function outputs
121
+ util
122
+ .disambiguateNames({
123
+ values: fn.get('outputs', immutable.List()),
124
+ getName: (output, index) => output.get('name') || `value${index}`,
125
+ setName: (output, name) => output.set('name', name),
126
+ })
127
+ .forEach((output, index) => {
128
+ let callInput = this._generateInputOrOutput(
129
+ output,
130
+ index,
131
+ fnClassName,
132
+ `call`,
133
+ `outputValues`,
134
+ )
135
+ outputsClass.addMethod(callInput.getter)
136
+ tupleClasses.push(...callInput.classes)
137
+ })
112
138
 
113
- // Generate getters and classes for function outputs
114
- util
115
- .disambiguateNames({
116
- values: fn.get('outputs', []),
117
- getName: (output, index) => output.get('name') || `value${index}`,
118
- setName: (output, name) => output.set('name', name),
119
- })
120
- .forEach((output, index) => {
121
- let callInput = this._generateInputOrOutput(
122
- output,
123
- index,
124
- fnClassName,
125
- `call`,
126
- `outputValues`,
127
- )
128
- outputsClass.addMethod(callInput.getter)
129
- tupleClasses.push(...callInput.classes)
139
+ // Then, generate the event class itself
140
+ let klass = tsCodegen.klass(fnClassName, {
141
+ export: true,
142
+ extends: 'ethereum.Call',
130
143
  })
131
-
132
- // Then, generate the event class itself
133
- let klass = tsCodegen.klass(fnClassName, {
134
- export: true,
135
- extends: 'ethereum.Call',
144
+ klass.addMethod(
145
+ tsCodegen.method(
146
+ `get inputs`,
147
+ [],
148
+ tsCodegen.namedType(inputsClassName),
149
+ `return new ${inputsClassName}(this)`,
150
+ ),
151
+ )
152
+ klass.addMethod(
153
+ tsCodegen.method(
154
+ `get outputs`,
155
+ [],
156
+ tsCodegen.namedType(outputsClassName),
157
+ `return new ${outputsClassName}(this)`,
158
+ ),
159
+ )
160
+ return [klass, inputsClass, outputsClass, ...tupleClasses]
136
161
  })
137
- klass.addMethod(
138
- tsCodegen.method(
139
- `get inputs`,
140
- [],
141
- tsCodegen.namedType(inputsClassName),
142
- `return new ${inputsClassName}(this)`,
143
- ),
144
- )
145
- klass.addMethod(
146
- tsCodegen.method(
147
- `get outputs`,
148
- [],
149
- tsCodegen.namedType(outputsClassName),
150
- `return new ${outputsClassName}(this)`,
151
- ),
152
- )
153
- return [klass, inputsClass, outputsClass, ...tupleClasses]
154
- })
155
162
 
156
- return callFunctions.reduce(
157
- // flatten the array
158
- (array, classes) => array.concat(classes),
159
- [],
160
- )
163
+ return callFunctions
164
+ .reduce(
165
+ // flatten the array
166
+ (array, classes) => array.concat(classes),
167
+ [],
168
+ )
161
169
  }
162
170
 
163
171
  _generateEventTypes() {
@@ -168,124 +176,122 @@ module.exports = class AbiCodeGenerator {
168
176
  setName: (event, name) => event.set('_alias', name),
169
177
  })
170
178
 
171
- events = events.map(event => {
172
- let eventClassName = event.get('_alias')
173
- let tupleClasses = []
179
+ events = events
180
+ .map(event => {
181
+ let eventClassName = event.get('_alias')
182
+ let tupleClasses = []
174
183
 
175
- // First, generate a class with the param getters
176
- let paramsClassName = eventClassName + '__Params'
177
- let paramsClass = tsCodegen.klass(paramsClassName, { export: true })
178
- paramsClass.addMember(tsCodegen.klassMember('_event', eventClassName))
179
- paramsClass.addMethod(
180
- tsCodegen.method(
181
- `constructor`,
182
- [tsCodegen.param(`event`, eventClassName)],
183
- null,
184
- `this._event = event`,
185
- ),
186
- )
184
+ // First, generate a class with the param getters
185
+ let paramsClassName = eventClassName + '__Params'
186
+ let paramsClass = tsCodegen.klass(paramsClassName, { export: true })
187
+ paramsClass.addMember(tsCodegen.klassMember('_event', eventClassName))
188
+ paramsClass.addMethod(
189
+ tsCodegen.method(
190
+ `constructor`,
191
+ [tsCodegen.param(`event`, eventClassName)],
192
+ null,
193
+ `this._event = event`,
194
+ ),
195
+ )
187
196
 
188
- // Enumerate inputs with duplicate names
189
- let inputs = util.disambiguateNames({
190
- values: event.get('inputs'),
191
- getName: (input, index) => input.get('name') || `param${index}`,
192
- setName: (input, name) => input.set('name', name),
193
- })
197
+ // Enumerate inputs with duplicate names
198
+ let inputs = util.disambiguateNames({
199
+ values: event.get('inputs'),
200
+ getName: (input, index) => input.get('name') || `param${index}`,
201
+ setName: (input, name) => input.set('name', name),
202
+ })
194
203
 
195
- let namesAndTypes = []
196
- inputs.forEach((input, index) => {
197
- // Generate getters and classes for event params
198
- let paramObject = this._generateInputOrOutput(
199
- input,
200
- index,
201
- eventClassName,
202
- `event`,
203
- `parameters`,
204
+ let namesAndTypes = []
205
+ inputs.forEach((input, index) => {
206
+ // Generate getters and classes for event params
207
+ let paramObject = this._generateInputOrOutput(
208
+ input,
209
+ index,
210
+ eventClassName,
211
+ `event`,
212
+ `parameters`,
213
+ )
214
+ paramsClass.addMethod(paramObject.getter)
215
+
216
+ // Fixture generation
217
+ if (doFixtureCodegen) {
218
+ let ethType = typesCodegen.ethereumTypeForAsc(paramObject.getter.returnType)
219
+ if (typeof ethType === typeof {} && (ethType.test("int256") || ethType.test("uint256"))) {
220
+ ethType = "int32"
221
+ }
222
+ namesAndTypes.push({name: paramObject.getter.name.slice(4), type: ethType})
223
+ }
224
+
225
+ tupleClasses.push(...paramObject.classes)
226
+ })
227
+
228
+ // Then, generate the event class itself
229
+ let klass = tsCodegen.klass(eventClassName, {
230
+ export: true,
231
+ extends: 'ethereum.Event',
232
+ })
233
+ klass.addMethod(
234
+ tsCodegen.method(
235
+ `get params`,
236
+ [],
237
+ tsCodegen.namedType(paramsClassName),
238
+ `return new ${paramsClassName}(this)`,
239
+ ),
204
240
  )
205
- paramsClass.addMethod(paramObject.getter)
206
241
 
207
242
  // Fixture generation
208
243
  if (doFixtureCodegen) {
209
- let ethType = typesCodegen.ethereumTypeForAsc(paramObject.getter.returnType)
210
- if (
211
- typeof ethType === typeof {} &&
212
- (ethType.test('int256') || ethType.test('uint256'))
213
- ) {
214
- ethType = 'int32'
244
+ const args = yaml.parse(fs.readFileSync('./fixtures.yaml', 'utf8'))
245
+ const blockNumber = args['blockNumber']
246
+ const contractAddr = args['contractAddr']
247
+ const topic0 = args['topic0']
248
+ const apiKey = args['apiKey']
249
+ const url = `https://api.etherscan.io/api?module=logs&action=getLogs&fromBlock=${blockNumber}&toBlock=${blockNumber}&address=${contractAddr}&${topic0}=topic0&apikey=${apiKey}`;
250
+
251
+ let resp = request("GET", url)
252
+ let body = JSON.parse(resp.getBody("utf8"))
253
+ if (body.status === '0') {
254
+ throw new Error(body.result)
215
255
  }
216
- namesAndTypes.push({ name: paramObject.getter.name.slice(4), type: ethType })
217
- }
218
-
219
- tupleClasses.push(...paramObject.classes)
220
- })
221
256
 
222
- // Then, generate the event class itself
223
- let klass = tsCodegen.klass(eventClassName, {
224
- export: true,
225
- extends: 'ethereum.Event',
226
- })
227
- klass.addMethod(
228
- tsCodegen.method(
229
- `get params`,
230
- [],
231
- tsCodegen.namedType(paramsClassName),
232
- `return new ${paramsClassName}(this)`,
233
- ),
234
- )
235
-
236
- // Fixture generation
237
- if (doFixtureCodegen) {
238
- const args = yaml.parse(fs.readFileSync('./fixtures.yaml', 'utf8'))
239
- const blockNumber = args['blockNumber']
240
- const contractAddr = args['contractAddr']
241
- const topic0 = args['topic0']
242
- const apiKey = args['apiKey']
243
- const url = `https://api.etherscan.io/api?module=logs&action=getLogs&fromBlock=${blockNumber}&toBlock=${blockNumber}&address=${contractAddr}&${topic0}=topic0&apikey=${apiKey}`
244
-
245
- let resp = request('GET', url)
246
- let body = JSON.parse(resp.getBody('utf8'))
247
- if (body.status === '0') {
248
- throw new Error(body.result)
249
- }
250
-
251
- let res = Web3EthAbi.decodeLog(namesAndTypes, body.result[0].data, [])
252
-
253
- let stmnts = ''
254
- for (let i = 0; i < namesAndTypes.length; i++) {
255
- let code = '"' + res[i] + '"'
256
- if (namesAndTypes[i].type.toString() == 'address') {
257
- code = `Address.fromString(${code})`
257
+ let res = Web3EthAbi.decodeLog(
258
+ namesAndTypes,
259
+ body.result[0].data,
260
+ []
261
+ );
262
+
263
+ let stmnts = ""
264
+ for (let i = 0; i < namesAndTypes.length; i++) {
265
+ let code = '"' + res[i] + '"'
266
+ if (namesAndTypes[i].type.toString() == "address") {
267
+ code = `Address.fromString(${code})`
268
+ }
269
+ stmnts = stmnts.concat(`event.parameters.push(new ethereum.EventParam(\"${namesAndTypes[i].name}\", ${typesCodegen.ethereumFromAsc(code, namesAndTypes[i].type)}));`, `\n`)
258
270
  }
259
- stmnts = stmnts.concat(
260
- `event.parameters.push(new ethereum.EventParam(\"${
261
- namesAndTypes[i].name
262
- }\", ${typesCodegen.ethereumFromAsc(code, namesAndTypes[i].type)}));`,
263
- `\n`,
264
- )
265
- }
266
271
 
267
- klass.addMethod(
268
- tsCodegen.staticMethod(
269
- `mock${eventClassName}`,
270
- [],
271
- tsCodegen.namedType(eventClassName),
272
- `
272
+ klass.addMethod(
273
+ tsCodegen.staticMethod(
274
+ `mock${eventClassName}`,
275
+ [],
276
+ tsCodegen.namedType(eventClassName),
277
+ `
273
278
  let event = changetype<${eventClassName}>(newMockEvent());
274
279
  ${stmnts}
275
280
  return event;
276
281
  `,
277
- ),
278
- )
279
- }
282
+ )
283
+ )
284
+ }
280
285
 
281
- return [klass, paramsClass, ...tupleClasses]
282
- })
286
+ return [klass, paramsClass, ...tupleClasses]
287
+ })
283
288
 
284
- return events.reduce(
285
- // flatten the array
286
- (array, classes) => array.concat(classes),
287
- [],
288
- )
289
+ return events
290
+ .reduce(
291
+ // flatten the array
292
+ (array, classes) => array.concat(classes),
293
+ [],
294
+ )
289
295
  }
290
296
 
291
297
  _generateInputOrOutput(inputOrOutput, index, parentClass, parentType, parentField) {
@@ -357,10 +363,10 @@ module.exports = class AbiCodeGenerator {
357
363
  `get ${name}`,
358
364
  [],
359
365
  util.isTupleMatrixType(type)
360
- ? `Array<Array<${tupleClassName}>>`
361
- : util.isTupleArrayType(type)
362
- ? `Array<${tupleClassName}>`
363
- : tupleClassName,
366
+ ? `Array<Array<${tupleClassName}>>`
367
+ : util.isTupleArrayType(type)
368
+ ? `Array<${tupleClassName}>`
369
+ : tupleClassName,
364
370
  `
365
371
  return ${
366
372
  isTupleType ? `changetype<${tupleClassName}>(${returnValue})` : `${returnValue}`
@@ -402,12 +408,14 @@ module.exports = class AbiCodeGenerator {
402
408
  export: true,
403
409
  extends: 'ethereum.SmartContract',
404
410
  })
405
- let types = []
411
+ let types = immutable.List()
406
412
 
407
413
  klass.addMethod(
408
414
  tsCodegen.staticMethod(
409
415
  'bind',
410
- [tsCodegen.param('address', typesCodegen.ascTypeForEthereum('address'))],
416
+ immutable.List([
417
+ tsCodegen.param('address', typesCodegen.ascTypeForEthereum('address')),
418
+ ]),
411
419
  tsCodegen.namedType(this.abi.name),
412
420
  `
413
421
  return new ${this.abi.name}('${this.abi.name}', address);
@@ -437,12 +445,12 @@ module.exports = class AbiCodeGenerator {
437
445
 
438
446
  // Disambiguate outputs with duplicate names
439
447
  let outputs = util.disambiguateNames({
440
- values: member.get('outputs', []),
448
+ values: member.get('outputs', immutable.List()),
441
449
  getName: (input, index) => input.get('name') || `value${index}`,
442
450
  setName: (input, name) => input.set('name', name),
443
451
  })
444
452
 
445
- if (member.get('outputs', []).size > 1) {
453
+ if (member.get('outputs', immutable.List()).size > 1) {
446
454
  simpleReturnType = false
447
455
 
448
456
  // Create a type dedicated to holding the return values
@@ -498,18 +506,16 @@ module.exports = class AbiCodeGenerator {
498
506
  ),
499
507
  )
500
508
  .forEach(member => returnType.addMember(member))
501
-
509
+
502
510
  // Add getters to the type
503
511
  outputs
504
- .map(
505
- (output, index) =>
506
- !!output.get('name') &&
507
- tsCodegen.method(
508
- `get${output.get('name')[0].toUpperCase()}${output.get('name').slice(1)}`,
509
- [],
510
- this._getTupleParamType(output, index, tupleResultParentType),
511
- `return this.value${index};`,
512
- ),
512
+ .map((output, index) =>
513
+ !!output.get('name') && tsCodegen.method(
514
+ `get${output.get('name')[0].toUpperCase()}${output.get('name').slice(1)}`,
515
+ [],
516
+ this._getTupleParamType(output, index, tupleResultParentType),
517
+ `return this.value${index};`
518
+ )
513
519
  )
514
520
  .forEach(method => !!method && returnType.addMethod(method))
515
521
 
@@ -554,7 +560,7 @@ module.exports = class AbiCodeGenerator {
554
560
 
555
561
  // Disambiguate inputs with duplicate names
556
562
  let inputs = util.disambiguateNames({
557
- values: member.get('inputs', []),
563
+ values: member.get('inputs', immutable.List()),
558
564
  getName: (input, index) => input.get('name') || `param${index}`,
559
565
  setName: (input, name) => input.set('name', name),
560
566
  })
@@ -723,7 +729,7 @@ module.exports = class AbiCodeGenerator {
723
729
  return this.abi.data.filter(
724
730
  member =>
725
731
  member.get('type') === 'function' &&
726
- member.get('outputs', []).size !== 0 &&
732
+ member.get('outputs', immutable.List()).size !== 0 &&
727
733
  (allowedMutability.includes(member.get('stateMutability')) ||
728
734
  (member.get('stateMutability') === undefined && !member.get('payable', false))),
729
735
  )
@@ -1,5 +1,6 @@
1
1
  const fs = require('fs-extra')
2
2
  const path = require('path')
3
+ const immutable = require('immutable')
3
4
 
4
5
  const ABI = require('../abi')
5
6
  const ts = require('../../../codegen/typescript')
@@ -215,31 +216,31 @@ describe('ABI code generation', () => {
215
216
  test('Have correct parameters', () => {
216
217
  let contract = generatedTypes.find(type => type.name === 'Contract')
217
218
  expect(contract.methods.map(method => [method.name, method.params])).toEqual([
218
- ['bind', [ts.param('address', 'Address')]],
219
- ['read', []],
220
- ['try_read', []],
219
+ ['bind', immutable.List([ts.param('address', 'Address')])],
220
+ ['read', immutable.List()],
221
+ ['try_read', immutable.List()],
221
222
  [
222
223
  'getProposal',
223
- [
224
+ immutable.List([
224
225
  ts.param('proposalId', 'BigInt'),
225
226
  ts.param('param1', 'Contract__getProposalInputParam1Struct'),
226
- ],
227
+ ]),
227
228
  ],
228
229
  [
229
230
  'try_getProposal',
230
- [
231
+ immutable.List([
231
232
  ts.param('proposalId', 'BigInt'),
232
233
  ts.param('param1', 'Contract__getProposalInputParam1Struct'),
233
- ],
234
+ ]),
234
235
  ],
235
- ['getProposals', []],
236
- ['try_getProposals', []],
237
- ['overloaded', [ts.param('param0', 'string')]],
238
- ['try_overloaded', [ts.param('param0', 'string')]],
239
- ['overloaded1', [ts.param('param0', 'BigInt')]],
240
- ['try_overloaded1', [ts.param('param0', 'BigInt')]],
241
- ['overloaded2', [ts.param('param0', 'Bytes')]],
242
- ['try_overloaded2', [ts.param('param0', 'Bytes')]],
236
+ ['getProposals', immutable.List()],
237
+ ['try_getProposals', immutable.List()],
238
+ ['overloaded', immutable.List([ts.param('param0', 'string')])],
239
+ ['try_overloaded', immutable.List([ts.param('param0', 'string')])],
240
+ ['overloaded1', immutable.List([ts.param('param0', 'BigInt')])],
241
+ ['try_overloaded1', immutable.List([ts.param('param0', 'BigInt')])],
242
+ ['overloaded2', immutable.List([ts.param('param0', 'Bytes')])],
243
+ ['try_overloaded2', immutable.List([ts.param('param0', 'Bytes')])],
243
244
  ])
244
245
  })
245
246