@graphprotocol/graph-cli 0.26.0 → 0.27.0
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/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/chain/ethereum.ts +1 -1
- package/examples/basic-event-handlers/node_modules/@graphprotocol/graph-ts/package.json +1 -1
- package/examples/basic-event-handlers/package.json +4 -4
- package/examples/basic-event-handlers/yarn.lock +8 -8
- package/package.json +27 -24
- package/src/commands/deploy.js +3 -1
- package/src/commands/init.js +2 -0
- package/src/commands/test.js +82 -59
- package/src/protocols/ethereum/codegen/abi.js +72 -2
- package/src/protocols/ethereum/manifest.graphql +92 -0
- package/src/protocols/index.js +17 -7
- package/src/protocols/near/manifest.graphql +57 -0
- package/src/subgraph.js +18 -13
- package/src/validation/manifest.js +12 -8
- package/tests/cli/validation/example-values-found.stderr +2 -2
- package/tests/cli/validation/invalid-manifest/subgraph.yaml +2 -1
- package/tests/cli/validation/invalid-manifest-cannot-infer-protocol/subgraph.yaml +12 -0
- package/tests/cli/validation/invalid-manifest-cannot-infer-protocol.stderr +5 -0
- package/tests/cli/validation/invalid-manifest.stderr +0 -3
- package/tests/cli/validation.test.js +8 -0
- package/manifest-schema.graphql +0 -122
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
"apollo-fetch": "^0.7.0"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"babel-polyfill": "
|
|
17
|
-
"babel-register": "
|
|
18
|
-
"truffle": "
|
|
19
|
-
"truffle-hdwallet-provider": "
|
|
16
|
+
"babel-polyfill": "6.26.0",
|
|
17
|
+
"babel-register": "6.26.0",
|
|
18
|
+
"truffle": "5.0.12",
|
|
19
|
+
"truffle-hdwallet-provider": "1.0.6"
|
|
20
20
|
},
|
|
21
21
|
"resolutions": {
|
|
22
22
|
"assemblyscript": "0.19.10"
|
|
@@ -112,18 +112,18 @@ babel-messages@^6.23.0:
|
|
|
112
112
|
dependencies:
|
|
113
113
|
babel-runtime "^6.22.0"
|
|
114
114
|
|
|
115
|
-
babel-polyfill
|
|
115
|
+
babel-polyfill@6.26.0:
|
|
116
116
|
version "6.26.0"
|
|
117
|
-
resolved "https://registry.
|
|
117
|
+
resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153"
|
|
118
118
|
integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=
|
|
119
119
|
dependencies:
|
|
120
120
|
babel-runtime "^6.26.0"
|
|
121
121
|
core-js "^2.5.0"
|
|
122
122
|
regenerator-runtime "^0.10.5"
|
|
123
123
|
|
|
124
|
-
babel-register@^6.26.0:
|
|
124
|
+
babel-register@6.26.0, babel-register@^6.26.0:
|
|
125
125
|
version "6.26.0"
|
|
126
|
-
resolved "https://registry.
|
|
126
|
+
resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
|
|
127
127
|
integrity sha1-btAhFz4vy0htestFxgCahW9kcHE=
|
|
128
128
|
dependencies:
|
|
129
129
|
babel-core "^6.26.0"
|
|
@@ -920,18 +920,18 @@ trim-right@^1.0.1:
|
|
|
920
920
|
resolved "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
|
|
921
921
|
integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
|
|
922
922
|
|
|
923
|
-
truffle-hdwallet-provider
|
|
923
|
+
truffle-hdwallet-provider@1.0.6:
|
|
924
924
|
version "1.0.6"
|
|
925
|
-
resolved "https://registry.
|
|
925
|
+
resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-1.0.6.tgz#7cda437c9a25bda6bbc5f4ed018e932254ecc867"
|
|
926
926
|
integrity sha512-cYTG0t9XouLLEBLMjkfHe3s2JO9wrFFVeXEgpW5Ay+8S56isf3LkrAUh0ws9bcYCJ0l7jho9xkaNnakeDqq//Q==
|
|
927
927
|
dependencies:
|
|
928
928
|
any-promise "^1.3.0"
|
|
929
929
|
bindings "^1.3.1"
|
|
930
930
|
websocket "^1.0.28"
|
|
931
931
|
|
|
932
|
-
truffle
|
|
932
|
+
truffle@5.0.12:
|
|
933
933
|
version "5.0.12"
|
|
934
|
-
resolved "https://registry.
|
|
934
|
+
resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.12.tgz#05ab7d2561a3ee4fd5e026dcc4b91b8f3c6e3795"
|
|
935
935
|
integrity sha512-dqnDmtTGNcnL29PHQwPE/CVmFFeGLuTFeb4TS3VY/vbASefu118IKXcadOWzkCPPwktv/njwylHSPhwoS00F2A==
|
|
936
936
|
dependencies:
|
|
937
937
|
app-module-path "^2.2.0"
|
package/package.json
CHANGED
|
@@ -1,41 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphprotocol/graph-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
|
+
"license": "(Apache-2.0 OR MIT)",
|
|
4
5
|
"description": "CLI for building for and deploying to The Graph",
|
|
5
6
|
"dependencies": {
|
|
6
7
|
"assemblyscript": "0.19.10",
|
|
7
8
|
"binary-install-raw": "0.0.13",
|
|
8
|
-
"chalk": "
|
|
9
|
-
"chokidar": "
|
|
10
|
-
"debug": "
|
|
11
|
-
"docker-compose": "
|
|
12
|
-
"dockerode": "
|
|
13
|
-
"fs-extra": "
|
|
14
|
-
"glob": "
|
|
9
|
+
"chalk": "3.0.0",
|
|
10
|
+
"chokidar": "3.5.1",
|
|
11
|
+
"debug": "4.1.1",
|
|
12
|
+
"docker-compose": "0.23.4",
|
|
13
|
+
"dockerode": "2.5.8",
|
|
14
|
+
"fs-extra": "9.0.0",
|
|
15
|
+
"glob": "7.1.6",
|
|
15
16
|
"gluegun": "https://github.com/edgeandnode/gluegun#v4.3.1-pin-colors-dep",
|
|
16
|
-
"graphql": "
|
|
17
|
-
"immutable": "
|
|
18
|
-
"ipfs-http-client": "
|
|
19
|
-
"jayson": "
|
|
20
|
-
"js-yaml": "
|
|
21
|
-
"node-fetch": "
|
|
22
|
-
"pkginfo": "
|
|
23
|
-
"prettier": "
|
|
24
|
-
"request": "
|
|
17
|
+
"graphql": "15.5.0",
|
|
18
|
+
"immutable": "3.8.2",
|
|
19
|
+
"ipfs-http-client": "34.0.0",
|
|
20
|
+
"jayson": "3.2.0",
|
|
21
|
+
"js-yaml": "3.13.1",
|
|
22
|
+
"node-fetch": "2.6.0",
|
|
23
|
+
"pkginfo": "0.4.1",
|
|
24
|
+
"prettier": "1.19.1",
|
|
25
|
+
"request": "2.88.2",
|
|
25
26
|
"semver": "7.3.5",
|
|
26
|
-
"
|
|
27
|
+
"sync-request": "6.1.0",
|
|
28
|
+
"tmp-promise": "3.0.2",
|
|
29
|
+
"web3-eth-abi": "1.7.0",
|
|
27
30
|
"which": "2.0.2",
|
|
28
|
-
"yaml": "
|
|
31
|
+
"yaml": "1.9.2"
|
|
29
32
|
},
|
|
30
33
|
"bin": {
|
|
31
34
|
"graph": "bin/graph"
|
|
32
35
|
},
|
|
33
36
|
"devDependencies": {
|
|
34
|
-
"eslint": "
|
|
35
|
-
"jest": "
|
|
36
|
-
"spawn-command": "
|
|
37
|
-
"strip-ansi": "
|
|
38
|
-
"tern": "
|
|
37
|
+
"eslint": "6.8.0",
|
|
38
|
+
"jest": "26.0.0",
|
|
39
|
+
"spawn-command": "0.0.2-1",
|
|
40
|
+
"strip-ansi": "6.0.0",
|
|
41
|
+
"tern": "0.24.3"
|
|
39
42
|
},
|
|
40
43
|
"scripts": {
|
|
41
44
|
"test": "jest --verbose",
|
package/src/commands/deploy.js
CHANGED
|
@@ -30,6 +30,7 @@ Options:
|
|
|
30
30
|
-l --version-label <label> Version label used for the deployment
|
|
31
31
|
-h, --help Show usage information
|
|
32
32
|
-i, --ipfs <node> Upload build results to an IPFS node (default: ${DEFAULT_IPFS_URL})
|
|
33
|
+
--debug-fork ID of a remote subgraph whose store will be GraphQL queried
|
|
33
34
|
-o, --output-dir <path> Output directory for build results (default: build/)
|
|
34
35
|
--skip-migrations Skip subgraph migrations (default: false)
|
|
35
36
|
-w, --watch Regenerate types when subgraph files change (default: false)
|
|
@@ -96,6 +97,7 @@ module.exports = {
|
|
|
96
97
|
skipMigrations,
|
|
97
98
|
w,
|
|
98
99
|
watch,
|
|
100
|
+
debugFork,
|
|
99
101
|
} = toolbox.parameters.options
|
|
100
102
|
|
|
101
103
|
// Support both long and short option variants
|
|
@@ -264,7 +266,7 @@ module.exports = {
|
|
|
264
266
|
// `Failed to deploy to Graph node ${requestUrl}`,
|
|
265
267
|
client.request(
|
|
266
268
|
'subgraph_deploy',
|
|
267
|
-
{ name: subgraphName, ipfs_hash: ipfsHash, version_label: versionLabel },
|
|
269
|
+
{ name: subgraphName, ipfs_hash: ipfsHash, version_label: versionLabel, debug_fork: debugFork },
|
|
268
270
|
async (requestError, jsonRpcError, res) => {
|
|
269
271
|
if (jsonRpcError) {
|
|
270
272
|
spinner.fail(
|
package/src/commands/init.js
CHANGED
|
@@ -283,6 +283,8 @@ const getEtherscanLikeAPIUrl = (network) => {
|
|
|
283
283
|
case "bsc": return `https://api.bscscan.com/api`;
|
|
284
284
|
case "matic": return `https://api.polygonscan.com/api`;
|
|
285
285
|
case "mumbai": return `https://api-testnet.polygonscan.com/api`;
|
|
286
|
+
case "aurora": return `https://api.aurorascan.dev/api`;
|
|
287
|
+
case "aurora-testnet": return `https://api-testnet.aurorascan.dev/api`;
|
|
286
288
|
default: return `https://api-${network}.etherscan.io/api`;
|
|
287
289
|
}
|
|
288
290
|
}
|
package/src/commands/test.js
CHANGED
|
@@ -2,8 +2,9 @@ const { Binary } = require('binary-install-raw')
|
|
|
2
2
|
const os = require('os')
|
|
3
3
|
const chalk = require('chalk')
|
|
4
4
|
const fetch = require('node-fetch')
|
|
5
|
-
const { filesystem, print } = require('gluegun')
|
|
5
|
+
const { filesystem, patching, print, system } = require('gluegun')
|
|
6
6
|
const { fixParameters } = require('../command-helpers/gluegun')
|
|
7
|
+
const path = require('path')
|
|
7
8
|
const semver = require('semver')
|
|
8
9
|
const { spawn, exec } = require('child_process')
|
|
9
10
|
const yaml = require('js-yaml')
|
|
@@ -102,7 +103,7 @@ async function runBinary(datasource, opts) {
|
|
|
102
103
|
let latestVersion = opts.get("latestVersion")
|
|
103
104
|
let recompileOpt = opts.get("recompile")
|
|
104
105
|
|
|
105
|
-
const platform = getPlatform(logsOpt)
|
|
106
|
+
const platform = await getPlatform(logsOpt)
|
|
106
107
|
|
|
107
108
|
const url = `https://github.com/LimeChain/matchstick/releases/download/${versionOpt || latestVersion}/${platform}`
|
|
108
109
|
|
|
@@ -120,19 +121,21 @@ async function runBinary(datasource, opts) {
|
|
|
120
121
|
args.length > 0 ? binary.run(...args) : binary.run()
|
|
121
122
|
}
|
|
122
123
|
|
|
123
|
-
function getPlatform(logsOpt) {
|
|
124
|
+
async function getPlatform(logsOpt) {
|
|
124
125
|
const type = os.type()
|
|
125
126
|
const arch = os.arch()
|
|
126
|
-
const release = os.release()
|
|
127
127
|
const cpuCore = os.cpus()[0]
|
|
128
|
-
const
|
|
129
|
-
const
|
|
128
|
+
const isM1 = (arch === 'arm64' && /Apple (M1|processor)/.test(cpuCore.model))
|
|
129
|
+
const linuxInfo = type === 'Linux' ? await getLinuxInfo() : new Map()
|
|
130
|
+
const linuxDistro = linuxInfo.get('name')
|
|
131
|
+
const release = linuxInfo.get('version') || os.release()
|
|
132
|
+
const majorVersion = parseInt(linuxInfo.get('version'), 10) || semver.major(release)
|
|
130
133
|
|
|
131
134
|
if (logsOpt) {
|
|
132
|
-
print.info(`OS type: ${type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`)
|
|
135
|
+
print.info(`OS type: ${linuxDistro || type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`)
|
|
133
136
|
}
|
|
134
137
|
|
|
135
|
-
if (arch === 'x64' ||
|
|
138
|
+
if (arch === 'x64' || isM1) {
|
|
136
139
|
if (type === 'Darwin') {
|
|
137
140
|
if (majorVersion === 19) {
|
|
138
141
|
return 'binary-macos-10.15'
|
|
@@ -145,8 +148,9 @@ function getPlatform(logsOpt) {
|
|
|
145
148
|
} else if (type === 'Linux') {
|
|
146
149
|
if (majorVersion === 18) {
|
|
147
150
|
return 'binary-linux-18'
|
|
151
|
+
} else {
|
|
152
|
+
return 'binary-linux-20'
|
|
148
153
|
}
|
|
149
|
-
return 'binary-linux-20'
|
|
150
154
|
} else if (type === 'Windows_NT') {
|
|
151
155
|
return 'binary-windows'
|
|
152
156
|
}
|
|
@@ -155,6 +159,23 @@ function getPlatform(logsOpt) {
|
|
|
155
159
|
throw new Error(`Unsupported platform: ${type} ${arch} ${majorVersion}`)
|
|
156
160
|
}
|
|
157
161
|
|
|
162
|
+
async function getLinuxInfo() {
|
|
163
|
+
try {
|
|
164
|
+
let result = await system.run("cat /etc/*-release | grep -E '(^VERSION|^NAME)='", {trim: true})
|
|
165
|
+
let infoArray = result.replace(/['"]+/g, '').split('\n').map(p => p.split('='))
|
|
166
|
+
let infoMap = new Map();
|
|
167
|
+
|
|
168
|
+
infoArray.forEach((val) => {
|
|
169
|
+
infoMap.set(val[0].toLowerCase(), val[1])
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
return infoMap
|
|
173
|
+
} catch (error) {
|
|
174
|
+
print.error(`Error fetching the Linux version:\n ${error}`)
|
|
175
|
+
process.exit(1)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
158
179
|
async function runDocker(datasource, opts) {
|
|
159
180
|
let coverageOpt = opts.get("coverage")
|
|
160
181
|
let forceOpt = opts.get("force")
|
|
@@ -169,27 +190,34 @@ async function runDocker(datasource, opts) {
|
|
|
169
190
|
// Get current working directory
|
|
170
191
|
let current_folder = await filesystem.cwd()
|
|
171
192
|
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
let dockerDir = ""
|
|
193
|
+
// Declate dockerfilePath with default location
|
|
194
|
+
let dockerfilePath = "./tests/.docker/Dockerfile"
|
|
175
195
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
196
|
+
// Check if matchstick.yaml config exists
|
|
197
|
+
if(filesystem.exists('matchstick.yaml')) {
|
|
198
|
+
try {
|
|
199
|
+
// Load the config
|
|
200
|
+
let config = await yaml.load(filesystem.read('matchstick.yaml', 'utf8'))
|
|
201
|
+
|
|
202
|
+
// Check if matchstick.yaml is not empty
|
|
203
|
+
if(config != null) {
|
|
204
|
+
// If a custom tests folder is declared update dockerfilePath
|
|
205
|
+
dockerfilePath = path.join(config.testsFolder || 'tests', '.docker/Dockerfile')
|
|
206
|
+
}
|
|
207
|
+
} catch (error) {
|
|
208
|
+
print.info('A problem occurred while reading matchstick.yaml. Please attend to the errors below:')
|
|
209
|
+
print.error(error.message)
|
|
210
|
+
process.exit(1)
|
|
211
|
+
}
|
|
183
212
|
}
|
|
184
213
|
|
|
185
|
-
//
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
return
|
|
214
|
+
// Check if the Dockerfil already exists
|
|
215
|
+
let dockerfileExists = filesystem.exists(dockerfilePath)
|
|
216
|
+
|
|
217
|
+
// Generate the Dockerfile only if it doesn't exists,
|
|
218
|
+
// version flag and/or force flag is passed.
|
|
219
|
+
if(!dockerfileExists || versionOpt || forceOpt) {
|
|
220
|
+
await dockerfile(dockerfilePath, versionOpt, latestVersion)
|
|
193
221
|
}
|
|
194
222
|
|
|
195
223
|
// Run a command to check if matchstick image already exists
|
|
@@ -212,10 +240,10 @@ async function runDocker(datasource, opts) {
|
|
|
212
240
|
|
|
213
241
|
// If a matchstick image does not exists, the command returns an empty string,
|
|
214
242
|
// else it'll return the image ID. Skip `docker build` if an image already exists
|
|
215
|
-
//
|
|
243
|
+
// Delete current image(if any) and rebuild.
|
|
216
244
|
// Use spawn() and {stdio: 'inherit'} so we can see the logs in real time.
|
|
217
|
-
if(stdout === '' || versionOpt || forceOpt) {
|
|
218
|
-
if (
|
|
245
|
+
if(!dockerfileExists || stdout === '' || versionOpt || forceOpt) {
|
|
246
|
+
if (stdout !== '') {
|
|
219
247
|
exec('docker image rm matchstick', (error, stdout, stderr) => {
|
|
220
248
|
print.info(chalk.bold(`Removing matchstick image\n${stdout}`))
|
|
221
249
|
})
|
|
@@ -224,7 +252,7 @@ async function runDocker(datasource, opts) {
|
|
|
224
252
|
// run a container from that image.
|
|
225
253
|
spawn(
|
|
226
254
|
'docker',
|
|
227
|
-
['build', '
|
|
255
|
+
['build', '-f', dockerfilePath, '-t', 'matchstick', '.'],
|
|
228
256
|
{ stdio: 'inherit' }
|
|
229
257
|
).on('close', code => {
|
|
230
258
|
if (code === 0) {
|
|
@@ -239,37 +267,32 @@ async function runDocker(datasource, opts) {
|
|
|
239
267
|
})
|
|
240
268
|
}
|
|
241
269
|
|
|
242
|
-
//
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
ENV ARGS=""
|
|
247
|
-
|
|
248
|
-
# Install necessary packages
|
|
249
|
-
RUN apt update
|
|
250
|
-
RUN apt install -y nodejs
|
|
251
|
-
RUN apt install -y npm
|
|
252
|
-
RUN apt install -y git
|
|
253
|
-
RUN apt install -y postgresql
|
|
254
|
-
RUN apt install -y curl
|
|
255
|
-
RUN apt install -y cmake
|
|
256
|
-
RUN npm install -g @graphprotocol/graph-cli
|
|
270
|
+
// Downloads Dockerfile template from the demo-subgraph repo
|
|
271
|
+
// Replaces the placeholders with their respective values
|
|
272
|
+
async function dockerfile(dockerfilePath, versionOpt, latestVersion) {
|
|
273
|
+
let spinner = print.spin("Generating Dockerfile...")
|
|
257
274
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
275
|
+
try {
|
|
276
|
+
// Fetch the Dockerfile template content from the demo-subgraph repo
|
|
277
|
+
let content = await fetch('https://raw.githubusercontent.com/LimeChain/demo-subgraph/main/Dockerfile')
|
|
278
|
+
.then((response) => {
|
|
279
|
+
if (response.ok) {
|
|
280
|
+
return response.text()
|
|
281
|
+
} else {
|
|
282
|
+
throw new Error(`Status Code: ${response.status}, with error: ${response.statusText}`);
|
|
283
|
+
}
|
|
284
|
+
})
|
|
263
285
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
WORKDIR matchstick
|
|
286
|
+
// Write the Dockerfile
|
|
287
|
+
await filesystem.write(dockerfilePath, content)
|
|
267
288
|
|
|
268
|
-
|
|
269
|
-
|
|
289
|
+
// Replaces the version placeholders
|
|
290
|
+
await patching.replace(dockerfilePath, '<MATCHSTICK_VERSION>', versionOpt || latestVersion)
|
|
270
291
|
|
|
271
|
-
|
|
272
|
-
|
|
292
|
+
} catch (error) {
|
|
293
|
+
spinner.fail(`A problem occurred while generating the Dockerfile. Please attend to the errors below:\n ${error.message}`)
|
|
294
|
+
process.exit(1)
|
|
295
|
+
}
|
|
273
296
|
|
|
274
|
-
|
|
297
|
+
spinner.succeed('Successfully generated Dockerfile.')
|
|
275
298
|
}
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
const immutable = require('immutable')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const yaml = require('yaml')
|
|
4
|
+
const request = require('sync-request')
|
|
5
|
+
const Web3EthAbi = require('web3-eth-abi');
|
|
2
6
|
|
|
3
7
|
const tsCodegen = require('../../../codegen/typescript')
|
|
4
8
|
const typesCodegen = require('../../../codegen/types')
|
|
5
9
|
const util = require('../../../codegen/util')
|
|
6
10
|
|
|
11
|
+
const doFixtureCodegen = fs.existsSync('./fixtures.yaml');
|
|
12
|
+
|
|
7
13
|
module.exports = class AbiCodeGenerator {
|
|
8
14
|
constructor(abi) {
|
|
9
15
|
this.abi = abi
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
generateModuleImports() {
|
|
13
|
-
|
|
19
|
+
let imports = [
|
|
14
20
|
tsCodegen.moduleImports(
|
|
15
21
|
[
|
|
16
22
|
// Ethereum integration
|
|
@@ -27,8 +33,21 @@ module.exports = class AbiCodeGenerator {
|
|
|
27
33
|
'BigInt',
|
|
28
34
|
],
|
|
29
35
|
'@graphprotocol/graph-ts',
|
|
30
|
-
)
|
|
36
|
+
)
|
|
31
37
|
]
|
|
38
|
+
|
|
39
|
+
if (doFixtureCodegen) {
|
|
40
|
+
imports.push(
|
|
41
|
+
tsCodegen.moduleImports(
|
|
42
|
+
[
|
|
43
|
+
'newMockEvent',
|
|
44
|
+
],
|
|
45
|
+
'matchstick-as/assembly/index',
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return imports
|
|
32
51
|
}
|
|
33
52
|
|
|
34
53
|
generateTypes() {
|
|
@@ -182,6 +201,7 @@ module.exports = class AbiCodeGenerator {
|
|
|
182
201
|
setName: (input, name) => input.set('name', name),
|
|
183
202
|
})
|
|
184
203
|
|
|
204
|
+
let namesAndTypes = []
|
|
185
205
|
inputs.forEach((input, index) => {
|
|
186
206
|
// Generate getters and classes for event params
|
|
187
207
|
let paramObject = this._generateInputOrOutput(
|
|
@@ -192,6 +212,11 @@ module.exports = class AbiCodeGenerator {
|
|
|
192
212
|
`parameters`,
|
|
193
213
|
)
|
|
194
214
|
paramsClass.addMethod(paramObject.getter)
|
|
215
|
+
let ethType = typesCodegen.ethereumTypeForAsc(paramObject.getter.returnType)
|
|
216
|
+
if (typeof ethType === typeof {} && (ethType.test("int256") || ethType.test("uint256"))) {
|
|
217
|
+
ethType = "int32"
|
|
218
|
+
}
|
|
219
|
+
namesAndTypes.push({name: paramObject.getter.name.slice(4), type: ethType})
|
|
195
220
|
tupleClasses.push(...paramObject.classes)
|
|
196
221
|
})
|
|
197
222
|
|
|
@@ -208,6 +233,51 @@ module.exports = class AbiCodeGenerator {
|
|
|
208
233
|
`return new ${paramsClassName}(this)`,
|
|
209
234
|
),
|
|
210
235
|
)
|
|
236
|
+
|
|
237
|
+
// Fixture generation
|
|
238
|
+
if (doFixtureCodegen) {
|
|
239
|
+
const args = yaml.parse(fs.readFileSync('./fixtures.yaml', 'utf8'))
|
|
240
|
+
const blockNumber = args['blockNumber']
|
|
241
|
+
const contractAddr = args['contractAddr']
|
|
242
|
+
const topic0 = args['topic0']
|
|
243
|
+
const apiKey = args['apiKey']
|
|
244
|
+
const url = `https://api.etherscan.io/api?module=logs&action=getLogs&fromBlock=${blockNumber}&toBlock=${blockNumber}&address=${contractAddr}&${topic0}=topic0&apikey=${apiKey}`;
|
|
245
|
+
|
|
246
|
+
let resp = request("GET", url)
|
|
247
|
+
let body = JSON.parse(resp.getBody("utf8"))
|
|
248
|
+
if (body.status === '0') {
|
|
249
|
+
throw new Error(body.result)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
let res = Web3EthAbi.decodeLog(
|
|
253
|
+
namesAndTypes,
|
|
254
|
+
body.result[0].data,
|
|
255
|
+
[]
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
let stmnts = ""
|
|
259
|
+
for (let i = 0; i < namesAndTypes.length; i++) {
|
|
260
|
+
let code = '"' + res[i] + '"'
|
|
261
|
+
if (namesAndTypes[i].type.toString() == "address") {
|
|
262
|
+
code = `Address.fromString(${code})`
|
|
263
|
+
}
|
|
264
|
+
stmnts = stmnts.concat(`event.parameters.push(new ethereum.EventParam(\"${namesAndTypes[i].name}\", ${typesCodegen.ethereumFromAsc(code, namesAndTypes[i].type)}));`, `\n`)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
klass.addMethod(
|
|
268
|
+
tsCodegen.staticMethod(
|
|
269
|
+
`mock${eventClassName}`,
|
|
270
|
+
[],
|
|
271
|
+
tsCodegen.namedType(eventClassName),
|
|
272
|
+
`
|
|
273
|
+
let event = changetype<${eventClassName}>(newMockEvent());
|
|
274
|
+
${stmnts}
|
|
275
|
+
return event;
|
|
276
|
+
`,
|
|
277
|
+
)
|
|
278
|
+
)
|
|
279
|
+
}
|
|
280
|
+
|
|
211
281
|
return [klass, paramsClass, ...tupleClasses]
|
|
212
282
|
})
|
|
213
283
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Each referenced type's in any of the types below must be listed
|
|
2
|
+
# here either as `scalar` or `type` for the validation code to work
|
|
3
|
+
# properly.
|
|
4
|
+
#
|
|
5
|
+
# That's why `String` is listed as a scalar even though it's built-in
|
|
6
|
+
# GraphQL basic types.
|
|
7
|
+
scalar String
|
|
8
|
+
scalar File
|
|
9
|
+
scalar BigInt
|
|
10
|
+
|
|
11
|
+
type SubgraphManifest {
|
|
12
|
+
specVersion: String!
|
|
13
|
+
features: [String!]
|
|
14
|
+
schema: Schema!
|
|
15
|
+
description: String
|
|
16
|
+
repository: String
|
|
17
|
+
graft: Graft
|
|
18
|
+
dataSources: [DataSource!]!
|
|
19
|
+
templates: [DataSourceTemplate!]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type Schema {
|
|
23
|
+
file: File!
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type DataSource {
|
|
27
|
+
kind: String!
|
|
28
|
+
name: String!
|
|
29
|
+
network: String
|
|
30
|
+
source: ContractSource!
|
|
31
|
+
mapping: ContractMapping!
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type ContractSource {
|
|
35
|
+
address: String
|
|
36
|
+
abi: String!
|
|
37
|
+
startBlock: BigInt
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type ContractMapping {
|
|
41
|
+
kind: String
|
|
42
|
+
apiVersion: String!
|
|
43
|
+
language: String!
|
|
44
|
+
file: File!
|
|
45
|
+
entities: [String!]!
|
|
46
|
+
abis: [ContractAbi!]!
|
|
47
|
+
blockHandlers: [BlockHandler!]
|
|
48
|
+
callHandlers: [CallHandler!]
|
|
49
|
+
eventHandlers: [ContractEventHandler!]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type ContractAbi {
|
|
53
|
+
name: String!
|
|
54
|
+
file: File!
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
type BlockHandler {
|
|
58
|
+
handler: String!
|
|
59
|
+
filter: BlockFilter
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
type BlockFilter {
|
|
63
|
+
kind: String!
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type CallHandler {
|
|
67
|
+
function: String!
|
|
68
|
+
handler: String!
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
type ContractEventHandler {
|
|
72
|
+
event: String!
|
|
73
|
+
topic0: String
|
|
74
|
+
handler: String!
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
type Graft {
|
|
78
|
+
base: String!
|
|
79
|
+
block: BigInt!
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
type DataSourceTemplate {
|
|
83
|
+
kind: String!
|
|
84
|
+
name: String!
|
|
85
|
+
network: String
|
|
86
|
+
source: ContractSourceTemplate!
|
|
87
|
+
mapping: ContractMapping!
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
type ContractSourceTemplate {
|
|
91
|
+
abi: String!
|
|
92
|
+
}
|
package/src/protocols/index.js
CHANGED
|
@@ -60,10 +60,7 @@ module.exports = class Protocol {
|
|
|
60
60
|
'aurora',
|
|
61
61
|
'aurora-testnet',
|
|
62
62
|
],
|
|
63
|
-
near: [
|
|
64
|
-
'near-mainnet',
|
|
65
|
-
'near-testnet'
|
|
66
|
-
],
|
|
63
|
+
near: ['near-mainnet', 'near-testnet'],
|
|
67
64
|
})
|
|
68
65
|
}
|
|
69
66
|
|
|
@@ -108,6 +105,15 @@ module.exports = class Protocol {
|
|
|
108
105
|
}
|
|
109
106
|
}
|
|
110
107
|
|
|
108
|
+
hasTemplates() {
|
|
109
|
+
switch (this.name) {
|
|
110
|
+
case 'ethereum':
|
|
111
|
+
return true
|
|
112
|
+
case 'near':
|
|
113
|
+
return false
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
111
117
|
getTypeGenerator(options) {
|
|
112
118
|
switch (this.name) {
|
|
113
119
|
case 'ethereum':
|
|
@@ -118,13 +124,17 @@ module.exports = class Protocol {
|
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
getTemplateCodeGen(template) {
|
|
127
|
+
if (!this.hasTemplates()) {
|
|
128
|
+
throw new Error(
|
|
129
|
+
`Template data sources with kind '${this.name}' are not supported yet`,
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
|
|
121
133
|
switch (this.name) {
|
|
122
134
|
case 'ethereum':
|
|
123
135
|
return new EthereumTemplateCodeGen(template)
|
|
124
136
|
default:
|
|
125
|
-
throw new Error(
|
|
126
|
-
`Template data sources with kind '${this.name}' are not supported yet`,
|
|
127
|
-
)
|
|
137
|
+
throw new Error(`Template data sources with kind '${this.name}' is unknown`)
|
|
128
138
|
}
|
|
129
139
|
}
|
|
130
140
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Each referenced type's in any of the types below must be listed
|
|
2
|
+
# here either as `scalar` or `type` for the validation code to work
|
|
3
|
+
# properly.
|
|
4
|
+
#
|
|
5
|
+
# That's why `String` is listed as a scalar even though it's built-in
|
|
6
|
+
# GraphQL basic types.
|
|
7
|
+
scalar String
|
|
8
|
+
scalar File
|
|
9
|
+
scalar BigInt
|
|
10
|
+
|
|
11
|
+
type SubgraphManifest {
|
|
12
|
+
specVersion: String!
|
|
13
|
+
schema: Schema!
|
|
14
|
+
description: String
|
|
15
|
+
repository: String
|
|
16
|
+
graft: Graft
|
|
17
|
+
dataSources: [DataSource!]!
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type Schema {
|
|
21
|
+
file: File!
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type DataSource {
|
|
25
|
+
kind: String!
|
|
26
|
+
name: String!
|
|
27
|
+
network: String
|
|
28
|
+
source: ContractSource!
|
|
29
|
+
mapping: ContractMapping!
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type ContractSource {
|
|
33
|
+
account: String
|
|
34
|
+
startBlock: BigInt
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type ContractMapping {
|
|
38
|
+
apiVersion: String!
|
|
39
|
+
language: String!
|
|
40
|
+
file: File!
|
|
41
|
+
entities: [String!]!
|
|
42
|
+
blockHandlers: [BlockHandler!]
|
|
43
|
+
receiptHandlers: [ReceiptHandler!]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type BlockHandler {
|
|
47
|
+
handler: String!
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
type ReceiptHandler {
|
|
51
|
+
handler: String!
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
type Graft {
|
|
55
|
+
base: String!
|
|
56
|
+
block: BigInt!
|
|
57
|
+
}
|
package/src/subgraph.js
CHANGED
|
@@ -27,7 +27,7 @@ const buildCombinedWarning = (filename, warnings) =>
|
|
|
27
27
|
? warnings.reduce(
|
|
28
28
|
(msg, w) =>
|
|
29
29
|
`${msg}
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
Path: ${w.get('path').size === 0 ? '/' : w.get('path').join(' > ')}
|
|
32
32
|
${w
|
|
33
33
|
.get('message')
|
|
@@ -39,9 +39,21 @@ const buildCombinedWarning = (filename, warnings) =>
|
|
|
39
39
|
|
|
40
40
|
module.exports = class Subgraph {
|
|
41
41
|
static async validate(data, protocol, { resolveFile }) {
|
|
42
|
+
if (protocol.name == null) {
|
|
43
|
+
return immutable.fromJS([
|
|
44
|
+
{
|
|
45
|
+
path: [],
|
|
46
|
+
message: `Unable to determine for which protocol manifest file is built for. Ensure you have at least one 'dataSources' and/or 'templates' elements defined in your subgraph.`,
|
|
47
|
+
},
|
|
48
|
+
])
|
|
49
|
+
}
|
|
50
|
+
|
|
42
51
|
// Parse the default subgraph schema
|
|
43
52
|
let schema = graphql.parse(
|
|
44
|
-
await fs.readFile(
|
|
53
|
+
await fs.readFile(
|
|
54
|
+
path.join(__dirname, 'protocols', protocol.name, `manifest.graphql`),
|
|
55
|
+
'utf-8',
|
|
56
|
+
),
|
|
45
57
|
)
|
|
46
58
|
|
|
47
59
|
// Obtain the root `SubgraphManifest` type from the schema
|
|
@@ -146,10 +158,7 @@ At least one such handler must be defined.`,
|
|
|
146
158
|
}
|
|
147
159
|
|
|
148
160
|
static validateContractValues(manifest, protocol) {
|
|
149
|
-
return validation.validateContractValues(
|
|
150
|
-
manifest,
|
|
151
|
-
protocol,
|
|
152
|
-
)
|
|
161
|
+
return validation.validateContractValues(manifest, protocol)
|
|
153
162
|
}
|
|
154
163
|
|
|
155
164
|
// Validate that data source names are unique, so they don't overwrite each other.
|
|
@@ -200,17 +209,13 @@ More than one template named '${name}', template names must be unique.`,
|
|
|
200
209
|
return yaml.stringify(manifest.toJS())
|
|
201
210
|
}
|
|
202
211
|
|
|
203
|
-
static async load(
|
|
204
|
-
filename,
|
|
205
|
-
{ protocol, skipValidation } = { skipValidation: false }
|
|
206
|
-
) {
|
|
212
|
+
static async load(filename, { protocol, skipValidation } = { skipValidation: false }) {
|
|
207
213
|
// Load and validate the manifest
|
|
208
214
|
let data = null
|
|
209
215
|
|
|
210
|
-
if(filename.match(/.js$/)) {
|
|
216
|
+
if (filename.match(/.js$/)) {
|
|
211
217
|
data = require(path.resolve(filename))
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
218
|
+
} else {
|
|
214
219
|
data = yaml.parse(await fs.readFile(filename, 'utf-8'))
|
|
215
220
|
}
|
|
216
221
|
|
|
@@ -52,8 +52,7 @@ const validators = immutable.fromJS({
|
|
|
52
52
|
validators.get(ctx.getIn(['type', 'name', 'value']))(value, ctx),
|
|
53
53
|
|
|
54
54
|
UnionTypeDefinition: (value, ctx) => {
|
|
55
|
-
const unionVariants = ctx
|
|
56
|
-
.getIn(['type', 'types'])
|
|
55
|
+
const unionVariants = ctx.getIn(['type', 'types'])
|
|
57
56
|
|
|
58
57
|
let errors = List()
|
|
59
58
|
|
|
@@ -78,7 +77,10 @@ const validators = immutable.fromJS({
|
|
|
78
77
|
|
|
79
78
|
NonNullType: (value, ctx) =>
|
|
80
79
|
value !== null && value !== undefined
|
|
81
|
-
? validateValue(
|
|
80
|
+
? validateValue(
|
|
81
|
+
value,
|
|
82
|
+
ctx.update('type', type => type.get('type')),
|
|
83
|
+
)
|
|
82
84
|
: immutable.fromJS([
|
|
83
85
|
{
|
|
84
86
|
path: ctx.get('path'),
|
|
@@ -126,7 +128,7 @@ const validators = immutable.fromJS({
|
|
|
126
128
|
),
|
|
127
129
|
)
|
|
128
130
|
: errors.push(
|
|
129
|
-
key == 'templates'
|
|
131
|
+
key == 'templates' && ctx.get('protocol').hasTemplates()
|
|
130
132
|
? immutable.fromJS({
|
|
131
133
|
path: ctx.get('path'),
|
|
132
134
|
message:
|
|
@@ -211,7 +213,8 @@ const validateValue = (value, ctx) => {
|
|
|
211
213
|
}
|
|
212
214
|
|
|
213
215
|
const validateDataSourceForNetwork = (dataSources, protocol) =>
|
|
214
|
-
dataSources
|
|
216
|
+
dataSources
|
|
217
|
+
.filter(dataSource => protocol.isValidKindName(dataSource.kind))
|
|
215
218
|
.reduce(
|
|
216
219
|
(networks, dataSource) =>
|
|
217
220
|
networks.update(dataSource.network, dataSources =>
|
|
@@ -235,11 +238,11 @@ const validateDataSourceNetworks = (value, protocol) => {
|
|
|
235
238
|
${networks
|
|
236
239
|
.map(
|
|
237
240
|
(dataSources, network) =>
|
|
238
|
-
|
|
241
|
+
` ${
|
|
239
242
|
network === undefined
|
|
240
243
|
? 'Data sources and templates having no network set'
|
|
241
|
-
|
|
242
|
-
|
|
244
|
+
: `Data sources and templates using '${network}'`
|
|
245
|
+
}:\n${dataSources.map(ds => ` - ${ds}`).join('\n')}`,
|
|
243
246
|
)
|
|
244
247
|
.join('\n')}
|
|
245
248
|
Recommendation: Make all data sources and templates use the same network name.`,
|
|
@@ -262,6 +265,7 @@ const validateManifest = (value, type, schema, protocol, { resolveFile }) => {
|
|
|
262
265
|
path: [],
|
|
263
266
|
errors: [],
|
|
264
267
|
resolveFile,
|
|
268
|
+
protocol,
|
|
265
269
|
}),
|
|
266
270
|
)
|
|
267
271
|
: immutable.fromJS([
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
- Load subgraph from subgraph.yaml
|
|
2
2
|
⚠ Warnings while loading subgraph from subgraph.yaml: Warnings in subgraph.yaml:
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
Path: repository
|
|
5
5
|
The repository is still set to https://github.com/graphprotocol/example-subgraph.
|
|
6
6
|
Please replace it with a link to your subgraph source code.
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
Path: description
|
|
9
9
|
The description is still the one from the example subgraph.
|
|
10
10
|
Please update it to tell users more about your subgraph.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
- Load subgraph from subgraph.yaml
|
|
2
|
+
✖ Failed to load subgraph from subgraph.yaml: Error in subgraph.yaml:
|
|
3
|
+
|
|
4
|
+
Path: /
|
|
5
|
+
Unable to determine for which protocol manifest file is built for. Ensure you have at least one 'dataSources' and/or 'templates' elements defined in your subgraph.
|
|
@@ -9,6 +9,14 @@ describe('Validation', () => {
|
|
|
9
9
|
exitCode: 1,
|
|
10
10
|
},
|
|
11
11
|
)
|
|
12
|
+
cliTest(
|
|
13
|
+
'Invalid subgraph manifest (cannot infer protocol)',
|
|
14
|
+
['codegen', '--skip-migrations'],
|
|
15
|
+
'validation/invalid-manifest-cannot-infer-protocol',
|
|
16
|
+
{
|
|
17
|
+
exitCode: 1,
|
|
18
|
+
},
|
|
19
|
+
)
|
|
12
20
|
cliTest(
|
|
13
21
|
'ABI not found in data source',
|
|
14
22
|
['codegen', '--skip-migrations'],
|
package/manifest-schema.graphql
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
scalar String
|
|
2
|
-
scalar File
|
|
3
|
-
scalar BigInt
|
|
4
|
-
|
|
5
|
-
type Schema {
|
|
6
|
-
file: File!
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
union DataSource =
|
|
10
|
-
EthereumContractDataSource |
|
|
11
|
-
NearContractDataSource
|
|
12
|
-
|
|
13
|
-
union DataSourceTemplate = EthereumContractDataSourceTemplate
|
|
14
|
-
|
|
15
|
-
type EthereumContractDataSource {
|
|
16
|
-
kind: String!
|
|
17
|
-
name: String!
|
|
18
|
-
network: String
|
|
19
|
-
source: EthereumContractSource!
|
|
20
|
-
mapping: EthereumContractMapping!
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
type NearContractDataSource {
|
|
24
|
-
kind: String!
|
|
25
|
-
name: String!
|
|
26
|
-
network: String
|
|
27
|
-
source: NearContractSource!
|
|
28
|
-
mapping: NearContractMapping!
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
type EthereumContractSource {
|
|
32
|
-
address: String
|
|
33
|
-
abi: String!
|
|
34
|
-
startBlock: BigInt
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
type NearContractSource {
|
|
38
|
-
account: String
|
|
39
|
-
startBlock: BigInt
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
type EthereumContractMapping {
|
|
43
|
-
kind: String
|
|
44
|
-
apiVersion: String!
|
|
45
|
-
language: String!
|
|
46
|
-
file: File!
|
|
47
|
-
entities: [String!]!
|
|
48
|
-
abis: [EthereumContractAbi!]!
|
|
49
|
-
blockHandlers: [EthereumBlockHandler!]
|
|
50
|
-
callHandlers: [EthereumCallHandler!]
|
|
51
|
-
eventHandlers: [EthereumContractEventHandler!]
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
type NearContractMapping {
|
|
55
|
-
apiVersion: String!
|
|
56
|
-
language: String!
|
|
57
|
-
file: File!
|
|
58
|
-
entities: [String!]!
|
|
59
|
-
blockHandlers: [NearBlockHandler!]
|
|
60
|
-
receiptHandlers: [NearReceiptHandler!]
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
type EthereumContractAbi {
|
|
64
|
-
name: String!
|
|
65
|
-
file: File!
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
type EthereumBlockHandler {
|
|
69
|
-
handler: String!
|
|
70
|
-
filter: EthereumBlockFilter
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
type EthereumBlockFilter {
|
|
74
|
-
kind: String!
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
type NearBlockHandler {
|
|
78
|
-
handler: String!
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
type EthereumCallHandler {
|
|
82
|
-
function: String!
|
|
83
|
-
handler: String!
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
type NearReceiptHandler {
|
|
87
|
-
handler: String!
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
type EthereumContractEventHandler {
|
|
91
|
-
event: String!
|
|
92
|
-
topic0: String
|
|
93
|
-
handler: String!
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
type Graft {
|
|
97
|
-
base: String!
|
|
98
|
-
block: BigInt!
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
type SubgraphManifest {
|
|
102
|
-
specVersion: String!
|
|
103
|
-
features: [String!]
|
|
104
|
-
schema: Schema!
|
|
105
|
-
description: String
|
|
106
|
-
repository: String
|
|
107
|
-
graft: Graft
|
|
108
|
-
dataSources: [DataSource!]!
|
|
109
|
-
templates: [DataSourceTemplate!]
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
type EthereumContractDataSourceTemplate {
|
|
113
|
-
kind: String!
|
|
114
|
-
name: String!
|
|
115
|
-
network: String
|
|
116
|
-
source: EthereumContractSourceTemplate!
|
|
117
|
-
mapping: EthereumContractMapping!
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
type EthereumContractSourceTemplate {
|
|
121
|
-
abi: String!
|
|
122
|
-
}
|