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