@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.
- package/CHANGELOG.md +7 -0
- package/package.json +1 -2
- package/src/codegen/schema.js +49 -58
- package/src/codegen/schema.test.js +32 -27
- package/src/codegen/template.js +1 -2
- package/src/codegen/types/conversions.js +43 -14
- package/src/codegen/types/index.js +20 -23
- package/src/codegen/typescript.js +0 -3
- package/src/command-helpers/abi.js +2 -3
- package/src/command-helpers/data-sources.js +3 -4
- package/src/command-helpers/scaffold.js +18 -14
- package/src/command-helpers/spinner.js +0 -1
- package/src/commands/add.js +42 -25
- package/src/compiler/index.js +12 -13
- package/src/protocols/arweave/subgraph.js +2 -7
- package/src/protocols/cosmos/subgraph.js +2 -9
- package/src/protocols/ethereum/abi.js +6 -7
- package/src/protocols/ethereum/codegen/abi.js +217 -223
- package/src/protocols/ethereum/codegen/abi.test.js +15 -16
- package/src/protocols/ethereum/subgraph.js +55 -67
- package/src/protocols/ethereum/type-generator.js +16 -25
- package/src/protocols/index.js +5 -6
- package/src/protocols/near/subgraph.js +3 -5
- package/src/protocols/substreams/subgraph.js +2 -4
- package/src/scaffold/cosmos.test.js +0 -1
- package/src/scaffold/ethereum.test.js +2 -3
- package/src/scaffold/near.test.js +0 -1
- package/src/schema.js +1 -2
- package/src/subgraph.js +44 -53
- package/src/type-generator.js +6 -7
- package/src/validation/contract.js +6 -11
- package/src/validation/manifest.js +77 -84
- package/src/validation/schema.js +284 -294
|
@@ -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
|
-
.
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
164
|
-
.
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
.
|
|
181
|
-
|
|
182
|
-
let tupleClasses = []
|
|
171
|
+
events = events.map(event => {
|
|
172
|
+
let eventClassName = event.get('_alias')
|
|
173
|
+
let tupleClasses = []
|
|
183
174
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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
|
-
|
|
287
|
-
|
|
281
|
+
return [klass, paramsClass, ...tupleClasses]
|
|
282
|
+
})
|
|
288
283
|
|
|
289
|
-
return events
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
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
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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 =
|
|
405
|
+
let types = []
|
|
412
406
|
|
|
413
407
|
klass.addMethod(
|
|
414
408
|
tsCodegen.staticMethod(
|
|
415
409
|
'bind',
|
|
416
|
-
|
|
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',
|
|
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',
|
|
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(
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
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',
|
|
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',
|
|
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',
|
|
220
|
-
['read',
|
|
221
|
-
['try_read',
|
|
218
|
+
['bind', [ts.param('address', 'Address')]],
|
|
219
|
+
['read', []],
|
|
220
|
+
['try_read', []],
|
|
222
221
|
[
|
|
223
222
|
'getProposal',
|
|
224
|
-
|
|
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
|
-
|
|
230
|
+
[
|
|
232
231
|
ts.param('proposalId', 'BigInt'),
|
|
233
232
|
ts.param('param1', 'Contract__getProposalInputParam1Struct'),
|
|
234
|
-
]
|
|
233
|
+
],
|
|
235
234
|
],
|
|
236
|
-
['getProposals',
|
|
237
|
-
['try_getProposals',
|
|
238
|
-
['overloaded',
|
|
239
|
-
['try_overloaded',
|
|
240
|
-
['overloaded1',
|
|
241
|
-
['try_overloaded1',
|
|
242
|
-
['overloaded2',
|
|
243
|
-
['try_overloaded2',
|
|
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
|
|