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

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,14 +1,13 @@
1
- const immutable = require('immutable')
2
1
  const fs = require('fs')
3
2
  const yaml = require('yaml')
4
3
  const request = require('sync-request')
5
- const Web3EthAbi = require('web3-eth-abi');
4
+ const Web3EthAbi = require('web3-eth-abi')
6
5
 
7
6
  const tsCodegen = require('../../../codegen/typescript')
8
7
  const typesCodegen = require('../../../codegen/types')
9
8
  const util = require('../../../codegen/util')
10
9
 
11
- const doFixtureCodegen = fs.existsSync('./fixtures.yaml');
10
+ const doFixtureCodegen = fs.existsSync('./fixtures.yaml')
12
11
 
13
12
  module.exports = class AbiCodeGenerator {
14
13
  constructor(abi) {
@@ -33,17 +32,12 @@ module.exports = class AbiCodeGenerator {
33
32
  'BigInt',
34
33
  ],
35
34
  '@graphprotocol/graph-ts',
36
- )
35
+ ),
37
36
  ]
38
37
 
39
38
  if (doFixtureCodegen) {
40
39
  imports.push(
41
- tsCodegen.moduleImports(
42
- [
43
- 'newMockEvent',
44
- ],
45
- 'matchstick-as/assembly/index',
46
- )
40
+ tsCodegen.moduleImports(['newMockEvent'], 'matchstick-as/assembly/index'),
47
41
  )
48
42
  }
49
43
 
@@ -66,106 +60,104 @@ module.exports = class AbiCodeGenerator {
66
60
  setName: (fn, name) => fn.set('_alias', name),
67
61
  })
68
62
 
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
- )
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 = []
87
67
 
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
- )
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
+ )
119
80
 
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
- })
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
+ })
138
99
 
139
- // Then, generate the event class itself
140
- let klass = tsCodegen.klass(fnClassName, {
141
- export: true,
142
- extends: 'ethereum.Call',
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
+ )
112
+
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)
143
130
  })
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]
161
- })
162
131
 
163
- return callFunctions
164
- .reduce(
165
- // flatten the array
166
- (array, classes) => array.concat(classes),
167
- [],
132
+ // Then, generate the event class itself
133
+ let klass = tsCodegen.klass(fnClassName, {
134
+ export: true,
135
+ extends: 'ethereum.Call',
136
+ })
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
+ ),
168
152
  )
153
+ return [klass, inputsClass, outputsClass, ...tupleClasses]
154
+ })
155
+
156
+ return callFunctions.reduce(
157
+ // flatten the array
158
+ (array, classes) => array.concat(classes),
159
+ [],
160
+ )
169
161
  }
170
162
 
171
163
  _generateEventTypes() {
@@ -176,122 +168,124 @@ module.exports = class AbiCodeGenerator {
176
168
  setName: (event, name) => event.set('_alias', name),
177
169
  })
178
170
 
179
- events = events
180
- .map(event => {
181
- let eventClassName = event.get('_alias')
182
- let tupleClasses = []
171
+ events = events.map(event => {
172
+ let eventClassName = event.get('_alias')
173
+ let tupleClasses = []
183
174
 
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
- )
196
-
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
- })
203
-
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
- }
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
+ )
224
187
 
225
- tupleClasses.push(...paramObject.classes)
226
- })
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
+ })
227
194
 
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
- ),
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`,
240
204
  )
205
+ paramsClass.addMethod(paramObject.getter)
241
206
 
242
207
  // Fixture generation
243
208
  if (doFixtureCodegen) {
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)
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'
255
215
  }
216
+ namesAndTypes.push({ name: paramObject.getter.name.slice(4), type: ethType })
217
+ }
218
+
219
+ tupleClasses.push(...paramObject.classes)
220
+ })
256
221
 
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`)
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})`
270
258
  }
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
+ }
271
266
 
272
- klass.addMethod(
273
- tsCodegen.staticMethod(
274
- `mock${eventClassName}`,
275
- [],
276
- tsCodegen.namedType(eventClassName),
277
- `
267
+ klass.addMethod(
268
+ tsCodegen.staticMethod(
269
+ `mock${eventClassName}`,
270
+ [],
271
+ tsCodegen.namedType(eventClassName),
272
+ `
278
273
  let event = changetype<${eventClassName}>(newMockEvent());
279
274
  ${stmnts}
280
275
  return event;
281
276
  `,
282
- )
283
- )
284
- }
277
+ ),
278
+ )
279
+ }
285
280
 
286
- return [klass, paramsClass, ...tupleClasses]
287
- })
281
+ return [klass, paramsClass, ...tupleClasses]
282
+ })
288
283
 
289
- return events
290
- .reduce(
291
- // flatten the array
292
- (array, classes) => array.concat(classes),
293
- [],
294
- )
284
+ return events.reduce(
285
+ // flatten the array
286
+ (array, classes) => array.concat(classes),
287
+ [],
288
+ )
295
289
  }
296
290
 
297
291
  _generateInputOrOutput(inputOrOutput, index, parentClass, parentType, parentField) {
@@ -363,10 +357,10 @@ module.exports = class AbiCodeGenerator {
363
357
  `get ${name}`,
364
358
  [],
365
359
  util.isTupleMatrixType(type)
366
- ? `Array<Array<${tupleClassName}>>`
367
- : util.isTupleArrayType(type)
368
- ? `Array<${tupleClassName}>`
369
- : tupleClassName,
360
+ ? `Array<Array<${tupleClassName}>>`
361
+ : util.isTupleArrayType(type)
362
+ ? `Array<${tupleClassName}>`
363
+ : tupleClassName,
370
364
  `
371
365
  return ${
372
366
  isTupleType ? `changetype<${tupleClassName}>(${returnValue})` : `${returnValue}`
@@ -408,14 +402,12 @@ module.exports = class AbiCodeGenerator {
408
402
  export: true,
409
403
  extends: 'ethereum.SmartContract',
410
404
  })
411
- let types = immutable.List()
405
+ let types = []
412
406
 
413
407
  klass.addMethod(
414
408
  tsCodegen.staticMethod(
415
409
  'bind',
416
- immutable.List([
417
- tsCodegen.param('address', typesCodegen.ascTypeForEthereum('address')),
418
- ]),
410
+ [tsCodegen.param('address', typesCodegen.ascTypeForEthereum('address'))],
419
411
  tsCodegen.namedType(this.abi.name),
420
412
  `
421
413
  return new ${this.abi.name}('${this.abi.name}', address);
@@ -445,12 +437,12 @@ module.exports = class AbiCodeGenerator {
445
437
 
446
438
  // Disambiguate outputs with duplicate names
447
439
  let outputs = util.disambiguateNames({
448
- values: member.get('outputs', immutable.List()),
440
+ values: member.get('outputs', []),
449
441
  getName: (input, index) => input.get('name') || `value${index}`,
450
442
  setName: (input, name) => input.set('name', name),
451
443
  })
452
444
 
453
- if (member.get('outputs', immutable.List()).size > 1) {
445
+ if (member.get('outputs', []).size > 1) {
454
446
  simpleReturnType = false
455
447
 
456
448
  // Create a type dedicated to holding the return values
@@ -506,16 +498,18 @@ module.exports = class AbiCodeGenerator {
506
498
  ),
507
499
  )
508
500
  .forEach(member => returnType.addMember(member))
509
-
501
+
510
502
  // Add getters to the type
511
503
  outputs
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
- )
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
+ ),
519
513
  )
520
514
  .forEach(method => !!method && returnType.addMethod(method))
521
515
 
@@ -560,7 +554,7 @@ module.exports = class AbiCodeGenerator {
560
554
 
561
555
  // Disambiguate inputs with duplicate names
562
556
  let inputs = util.disambiguateNames({
563
- values: member.get('inputs', immutable.List()),
557
+ values: member.get('inputs', []),
564
558
  getName: (input, index) => input.get('name') || `param${index}`,
565
559
  setName: (input, name) => input.set('name', name),
566
560
  })
@@ -729,7 +723,7 @@ module.exports = class AbiCodeGenerator {
729
723
  return this.abi.data.filter(
730
724
  member =>
731
725
  member.get('type') === 'function' &&
732
- member.get('outputs', immutable.List()).size !== 0 &&
726
+ member.get('outputs', []).size !== 0 &&
733
727
  (allowedMutability.includes(member.get('stateMutability')) ||
734
728
  (member.get('stateMutability') === undefined && !member.get('payable', false))),
735
729
  )
@@ -1,6 +1,5 @@
1
1
  const fs = require('fs-extra')
2
2
  const path = require('path')
3
- const immutable = require('immutable')
4
3
 
5
4
  const ABI = require('../abi')
6
5
  const ts = require('../../../codegen/typescript')
@@ -216,31 +215,31 @@ describe('ABI code generation', () => {
216
215
  test('Have correct parameters', () => {
217
216
  let contract = generatedTypes.find(type => type.name === 'Contract')
218
217
  expect(contract.methods.map(method => [method.name, method.params])).toEqual([
219
- ['bind', immutable.List([ts.param('address', 'Address')])],
220
- ['read', immutable.List()],
221
- ['try_read', immutable.List()],
218
+ ['bind', [ts.param('address', 'Address')]],
219
+ ['read', []],
220
+ ['try_read', []],
222
221
  [
223
222
  'getProposal',
224
- immutable.List([
223
+ [
225
224
  ts.param('proposalId', 'BigInt'),
226
225
  ts.param('param1', 'Contract__getProposalInputParam1Struct'),
227
- ]),
226
+ ],
228
227
  ],
229
228
  [
230
229
  'try_getProposal',
231
- immutable.List([
230
+ [
232
231
  ts.param('proposalId', 'BigInt'),
233
232
  ts.param('param1', 'Contract__getProposalInputParam1Struct'),
234
- ]),
233
+ ],
235
234
  ],
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')])],
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')]],
244
243
  ])
245
244
  })
246
245