@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.
- package/CHANGELOG.md +2 -3
- package/package.json +2 -1
- package/src/codegen/schema.js +58 -49
- package/src/codegen/schema.test.js +27 -32
- package/src/codegen/template.js +2 -1
- package/src/codegen/types/conversions.js +14 -43
- package/src/codegen/types/index.js +23 -20
- package/src/codegen/typescript.js +3 -0
- package/src/command-helpers/abi.js +3 -2
- package/src/command-helpers/data-sources.js +4 -3
- package/src/command-helpers/scaffold.js +14 -18
- package/src/command-helpers/spinner.js +1 -0
- package/src/commands/add.js +25 -42
- package/src/compiler/index.js +13 -12
- package/src/protocols/arweave/subgraph.js +7 -2
- package/src/protocols/cosmos/subgraph.js +9 -2
- package/src/protocols/ethereum/abi.js +7 -6
- package/src/protocols/ethereum/codegen/abi.js +223 -217
- package/src/protocols/ethereum/codegen/abi.test.js +16 -15
- package/src/protocols/ethereum/subgraph.js +67 -55
- package/src/protocols/ethereum/type-generator.js +25 -16
- package/src/protocols/index.js +6 -5
- package/src/protocols/near/subgraph.js +5 -3
- package/src/protocols/substreams/subgraph.js +4 -2
- package/src/scaffold/cosmos.test.js +1 -0
- package/src/scaffold/ethereum.test.js +3 -2
- package/src/scaffold/index.js +1 -1
- package/src/scaffold/near.test.js +1 -0
- package/src/schema.js +2 -1
- package/src/subgraph.js +53 -44
- package/src/type-generator.js +7 -6
- package/src/validation/contract.js +11 -6
- package/src/validation/manifest.js +84 -77
- package/src/validation/schema.js +294 -284
|
@@ -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(
|
|
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
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
|
157
|
-
|
|
158
|
-
|
|
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
|
|
172
|
-
|
|
173
|
-
|
|
179
|
+
events = events
|
|
180
|
+
.map(event => {
|
|
181
|
+
let eventClassName = event.get('_alias')
|
|
182
|
+
let tupleClasses = []
|
|
174
183
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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
|
+
}
|
|
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
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
|
|
282
|
-
|
|
286
|
+
return [klass, paramsClass, ...tupleClasses]
|
|
287
|
+
})
|
|
283
288
|
|
|
284
|
-
return events
|
|
285
|
-
|
|
286
|
-
|
|
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
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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
|
-
|
|
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',
|
|
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
|
-
(
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
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',
|
|
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
|
|