@graphprotocol/graph-cli 0.24.1 → 0.25.3

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.
Files changed (105) hide show
  1. package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/index.js +50 -0
  2. package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/license +21 -0
  3. package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/package.json +49 -0
  4. package/examples/basic-event-handlers/node_modules/chalk/node_modules/supports-color/readme.md +36 -0
  5. package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/index.js +10 -0
  6. package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/license +9 -0
  7. package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/package.json +53 -0
  8. package/examples/basic-event-handlers/node_modules/cliui/node_modules/ansi-regex/readme.md +46 -0
  9. package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/index.js +4 -0
  10. package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/license +9 -0
  11. package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/package.json +52 -0
  12. package/examples/basic-event-handlers/node_modules/cliui/node_modules/strip-ansi/readme.md +39 -0
  13. package/examples/basic-event-handlers/node_modules/keccak/build/Makefile +342 -0
  14. package/examples/basic-event-handlers/node_modules/keccak/build/Release/.deps/Release/obj.target/keccak/src/addon.o.d.raw +27 -0
  15. package/examples/basic-event-handlers/node_modules/keccak/build/binding.Makefile +6 -0
  16. package/examples/basic-event-handlers/node_modules/keccak/build/config.gypi +207 -0
  17. package/examples/basic-event-handlers/node_modules/keccak/build/gyp-mac-tool +615 -0
  18. package/examples/basic-event-handlers/node_modules/keccak/build/keccak.target.mk +209 -0
  19. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/.coveralls.yml +1 -0
  20. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/.eslintrc +14 -0
  21. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/.travis.yml +20 -0
  22. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/CHANGELOG.md +395 -0
  23. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/LICENSE +19 -0
  24. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/Makefile +58 -0
  25. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/README.md +368 -0
  26. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/karma.conf.js +70 -0
  27. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/node.js +1 -0
  28. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/package.json +43 -0
  29. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/browser.js +195 -0
  30. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/debug.js +225 -0
  31. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/index.js +10 -0
  32. package/examples/basic-event-handlers/node_modules/mocha/node_modules/debug/src/node.js +186 -0
  33. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/LICENSE +15 -0
  34. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/README.md +368 -0
  35. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/changelog.md +67 -0
  36. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/common.js +240 -0
  37. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/glob.js +790 -0
  38. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/package.json +43 -0
  39. package/examples/basic-event-handlers/node_modules/rimraf/node_modules/glob/sync.js +486 -0
  40. package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/index.js +10 -0
  41. package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/license +9 -0
  42. package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/package.json +53 -0
  43. package/examples/basic-event-handlers/node_modules/string-width/node_modules/ansi-regex/readme.md +46 -0
  44. package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/index.js +4 -0
  45. package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/license +9 -0
  46. package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/package.json +52 -0
  47. package/examples/basic-event-handlers/node_modules/string-width/node_modules/strip-ansi/readme.md +39 -0
  48. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/index.js +46 -0
  49. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/license +21 -0
  50. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/package.json +45 -0
  51. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point/readme.md +39 -0
  52. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/index.js +37 -0
  53. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/license +21 -0
  54. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/package.json +56 -0
  55. package/examples/basic-event-handlers/node_modules/wrap-ansi/node_modules/string-width/readme.md +42 -0
  56. package/package.json +2 -2
  57. package/src/codegen/schema.js +15 -5
  58. package/src/codegen/schema.test.js +368 -0
  59. package/src/codegen/types/defaults.js +34 -0
  60. package/src/codegen/types/index.js +8 -1
  61. package/src/codegen/typescript.js +7 -11
  62. package/src/command-helpers/scaffold.js +66 -0
  63. package/src/command-helpers/version.js +1 -1
  64. package/src/command-helpers/version.test.js +1 -1
  65. package/src/commands/init.js +129 -92
  66. package/src/commands/test.js +210 -27
  67. package/src/protocols/ethereum/contract.js +22 -0
  68. package/src/protocols/ethereum/scaffold/manifest.js +32 -0
  69. package/src/protocols/ethereum/scaffold/mapping.js +76 -0
  70. package/src/protocols/ethereum/subgraph.js +0 -14
  71. package/src/protocols/index.js +94 -12
  72. package/src/protocols/near/contract.js +46 -0
  73. package/src/protocols/near/scaffold/manifest.js +16 -0
  74. package/src/protocols/near/scaffold/mapping.js +39 -0
  75. package/src/protocols/near/subgraph.js +1 -23
  76. package/src/{scaffold.test.js → scaffold/ethereum.test.js} +27 -19
  77. package/src/scaffold/index.js +149 -0
  78. package/src/scaffold/mapping.js +49 -0
  79. package/src/scaffold/near.test.js +89 -0
  80. package/src/scaffold/schema.js +62 -0
  81. package/src/subgraph.js +8 -0
  82. package/src/validation/contract.js +56 -0
  83. package/src/validation/index.js +2 -1
  84. package/src/validation/manifest.js +0 -29
  85. package/tests/cli/init/{abis → ethereum/abis}/Marketplace.json +0 -0
  86. package/tests/cli/init/{abis → ethereum/abis}/OverloadedElements.json +0 -0
  87. package/tests/cli/init/{abis → ethereum/abis}/SoloMargin.json +0 -0
  88. package/tests/cli/init/{from-contract-with-abi-and-structs.stderr → ethereum/from-contract-with-abi-and-structs.stderr} +1 -1
  89. package/tests/cli/init/{from-contract-with-abi-and-structs.stdout → ethereum/from-contract-with-abi-and-structs.stdout} +0 -0
  90. package/tests/cli/init/{from-contract-with-abi.stderr → ethereum/from-contract-with-abi.stderr} +1 -1
  91. package/tests/cli/init/{from-contract-with-abi.stdout → ethereum/from-contract-with-abi.stdout} +0 -0
  92. package/tests/cli/init/{from-contract-with-overloaded-elements.stderr → ethereum/from-contract-with-overloaded-elements.stderr} +1 -1
  93. package/tests/cli/init/{from-contract-with-overloaded-elements.stdout → ethereum/from-contract-with-overloaded-elements.stdout} +0 -0
  94. package/tests/cli/init/{from-contract.stderr → ethereum/from-contract.stderr} +1 -1
  95. package/tests/cli/init/{from-contract.stdout → ethereum/from-contract.stdout} +0 -0
  96. package/tests/cli/init/{from-example.stderr → ethereum/from-example.stderr} +0 -0
  97. package/tests/cli/init/{from-example.stdout → ethereum/from-example.stdout} +0 -0
  98. package/tests/cli/init/near/from-contract.stderr +12 -0
  99. package/tests/cli/init/near/from-contract.stdout +12 -0
  100. package/tests/cli/init.test.js +143 -112
  101. package/tests/cli/util.js +56 -41
  102. package/tests/cli/validation/near-is-valid/subgraph.yaml +1 -0
  103. package/examples/basic-event-handlers/node_modules/mocha/lib/reporters/base.js.orig +0 -498
  104. package/examples/basic-event-handlers/node_modules/node-fetch/lib/index.js +0 -1416
  105. package/src/scaffold.js +0 -364
@@ -2,61 +2,125 @@ 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')
6
+ const { fixParameters } = require('../command-helpers/gluegun')
5
7
  const semver = require('semver')
8
+ const { spawn, exec } = require('child_process')
9
+ const yaml = require('js-yaml')
6
10
 
7
11
  const HELP = `
8
12
  ${chalk.bold('graph test')} ${chalk.dim('[options]')} ${chalk.bold('<datasource>')}
9
13
 
10
14
  ${chalk.dim('Options:')}
11
-
12
- -f --force Overwrite folder + file when downloading
15
+ -c, --coverage Run the tests in coverage mode. Works with v0.2.1 and above
16
+ -d, --docker Run the tests in a docker container(Note: Please execute from the root folder of the subgraph)
17
+ -f --force Binary - overwrites folder + file when downloading. Docker - rebuilds the docker image
13
18
  -h, --help Show usage information
14
19
  -l, --logs Logs to the console information about the OS, CPU model and download url (debugging purposes)
20
+ -r, --recompile Force-recompile tests (Not available in 0.2.2 and earlier versions)
15
21
  -v, --version <tag> Choose the version of the rust binary that you want to be downloaded/used
16
22
  `
17
23
 
18
24
  module.exports = {
19
25
  description: 'Runs rust binary for subgraph testing',
20
26
  run: async toolbox => {
21
- // Obtain tools
22
- let { print } = toolbox
23
-
24
27
  // Read CLI parameters
25
- let { f, force, h, help, l, logs, v, version } = toolbox.parameters.options
26
- let datasource = toolbox.parameters.first
28
+ let {
29
+ c,
30
+ coverage,
31
+ d,
32
+ docker,
33
+ f,
34
+ force,
35
+ h,
36
+ help,
37
+ l,
38
+ logs,
39
+ r,
40
+ recompile,
41
+ v,
42
+ version,
43
+ } = toolbox.parameters.options
27
44
 
45
+ let opts = new Map()
28
46
  // Support both long and short option variants
29
- force = force || f
30
- help = help || h
31
- logs = logs || l
32
- version = version || v
47
+ opts.set("coverage", coverage || c)
48
+ opts.set("docker", docker || d)
49
+ opts.set("force", force || f)
50
+ opts.set("help", help || h)
51
+ opts.set("logs", logs || l)
52
+ opts.set("recompile", recompile || r)
53
+ opts.set("version", version || v)
54
+
55
+ // Fix if a boolean flag (e.g -c, --coverage) has an argument
56
+ try {
57
+ fixParameters(toolbox.parameters, {
58
+ h,
59
+ help,
60
+ c,
61
+ coverage,
62
+ d,
63
+ docker,
64
+ f,
65
+ force,
66
+ l,
67
+ logs,
68
+ r,
69
+ recompile
70
+ })
71
+ } catch (e) {
72
+ print.error(e.message)
73
+ process.exitCode = 1
74
+ return
75
+ }
76
+
77
+ let datasource = toolbox.parameters.first || toolbox.parameters.array[0]
33
78
 
34
79
  // Show help text if requested
35
- if (help) {
80
+ if (opts.get("help")) {
36
81
  print.info(HELP)
37
82
  return
38
83
  }
39
84
 
40
- const platform = getPlatform(logs)
41
- if (!version) {
42
- let result = await fetch('https://api.github.com/repos/LimeChain/matchstick/releases/latest')
43
- let json = await result.json()
44
- version = json.tag_name
85
+ let result = await fetch('https://api.github.com/repos/LimeChain/matchstick/releases/latest')
86
+ let json = await result.json()
87
+ opts.set("latestVersion", json.tag_name)
88
+
89
+ if(opts.get("docker")) {
90
+ runDocker(datasource, opts)
91
+ } else {
92
+ runBinary(datasource, opts)
45
93
  }
94
+ }
95
+ }
46
96
 
47
- const url = `https://github.com/LimeChain/matchstick/releases/download/${version}/${platform}`
97
+ async function runBinary(datasource, opts) {
98
+ let coverageOpt = opts.get("coverage")
99
+ let forceOpt = opts.get("force")
100
+ let logsOpt = opts.get("logs")
101
+ let versionOpt = opts.get("version")
102
+ let latestVersion = opts.get("latestVersion")
103
+ let recompileOpt = opts.get("recompile")
48
104
 
49
- if (logs) {
50
- console.log(`Download link: ${url}`)
51
- }
105
+ const platform = getPlatform(logsOpt)
52
106
 
53
- let binary = new Binary(platform, url, version)
54
- await binary.install(force)
55
- datasource ? binary.run(datasource) : binary.run()
107
+ const url = `https://github.com/LimeChain/matchstick/releases/download/${versionOpt || latestVersion}/${platform}`
108
+
109
+ if (logsOpt) {
110
+ print.info(`Download link: ${url}`)
56
111
  }
112
+
113
+ let binary = new Binary(platform, url, versionOpt || latestVersion)
114
+ forceOpt ? await binary.install(true) : await binary.install(false)
115
+ let args = new Array()
116
+
117
+ if (coverageOpt) args.push('-c')
118
+ if (recompileOpt) args.push('-r')
119
+ if (datasource) args.push(datasource)
120
+ args.length > 0 ? binary.run(...args) : binary.run()
57
121
  }
58
122
 
59
- function getPlatform(logs) {
123
+ function getPlatform(logsOpt) {
60
124
  const type = os.type()
61
125
  const arch = os.arch()
62
126
  const release = os.release()
@@ -64,8 +128,8 @@ function getPlatform(logs) {
64
128
  const majorVersion = semver.major(release)
65
129
  const isM1 = cpuCore.model.includes("Apple M1")
66
130
 
67
- if (logs) {
68
- console.log(`OS type: ${type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`)
131
+ if (logsOpt) {
132
+ print.info(`OS type: ${type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`)
69
133
  }
70
134
 
71
135
  if (arch === 'x64' || (arch === 'arm64' && isM1)) {
@@ -90,3 +154,122 @@ function getPlatform(logs) {
90
154
 
91
155
  throw new Error(`Unsupported platform: ${type} ${arch} ${majorVersion}`)
92
156
  }
157
+
158
+ async function runDocker(datasource, opts) {
159
+ let coverageOpt = opts.get("coverage")
160
+ let forceOpt = opts.get("force")
161
+ let versionOpt = opts.get("version")
162
+ let latestVersion = opts.get("latestVersion")
163
+ let recompileOpt = opts.get("recompile")
164
+
165
+ // Remove binary-install-raw binaries, because docker has permission issues
166
+ // when building the docker images
167
+ await filesystem.remove("./node_modules/binary-install-raw/bin")
168
+
169
+ // Get current working directory
170
+ let current_folder = await filesystem.cwd()
171
+
172
+ // Build the Dockerfile location. Defaults to ./tests/.docker if
173
+ // a custom testsFolder is not declared in the subgraph.yaml
174
+ let dockerDir = ""
175
+
176
+ try {
177
+ let doc = await yaml.load(filesystem.read('subgraph.yaml', 'utf8'))
178
+ testsFolder = doc.testsFolder || './tests'
179
+ dockerDir = testsFolder.endsWith('/') ? testsFolder + '.docker' : testsFolder + '/.docker'
180
+ } catch (error) {
181
+ print.error(error.message)
182
+ return
183
+ }
184
+
185
+ // Create the Dockerfile
186
+ try {
187
+ await filesystem.write(`${dockerDir}/Dockerfile`, dockerfile(versionOpt, latestVersion))
188
+ print.info('Successfully generated Dockerfile.')
189
+ } catch (error) {
190
+ print.info('A problem occurred while generating the Dockerfile. Please attend to the errors below:')
191
+ print.error(error.message)
192
+ return
193
+ }
194
+
195
+ // Run a command to check if matchstick image already exists
196
+ exec('docker images -q matchstick', (error, stdout, stderr) => {
197
+ // Collect all(if any) flags and options that have to be passed to the matchstick binary
198
+ let testArgs = ''
199
+ if (coverageOpt) testArgs = testArgs + ' -c'
200
+ if (recompileOpt) testArgs = testArgs + ' -r'
201
+ if (datasource) testArgs = testArgs + ' ' + datasource
202
+
203
+ // Build the `docker run` command options and flags
204
+ let dockerRunOpts = ['run', '-it', '--rm', '--mount', `type=bind,source=${current_folder},target=/matchstick`]
205
+
206
+ if(testArgs !== '') {
207
+ dockerRunOpts.push('-e')
208
+ dockerRunOpts.push(`ARGS=${testArgs.trim()}`)
209
+ }
210
+
211
+ dockerRunOpts.push('matchstick')
212
+
213
+ // If a matchstick image does not exists, the command returns an empty string,
214
+ // else it'll return the image ID. Skip `docker build` if an image already exists
215
+ // If `-v/--version` is specified, delete current image(if any) and rebuild.
216
+ // Use spawn() and {stdio: 'inherit'} so we can see the logs in real time.
217
+ if(stdout === '' || versionOpt || forceOpt) {
218
+ if ((stdout !== '' && versionOpt) || forceOpt) {
219
+ exec('docker image rm matchstick', (error, stdout, stderr) => {
220
+ print.info(chalk.bold(`Removing matchstick image\n${stdout}`))
221
+ })
222
+ }
223
+ // Build a docker image. If the process has executed successfully
224
+ // run a container from that image.
225
+ spawn(
226
+ 'docker',
227
+ ['build', '--no-cache', '-f', `${dockerDir}/Dockerfile`, '-t', 'matchstick', '.'],
228
+ { stdio: 'inherit' }
229
+ ).on('close', code => {
230
+ if (code === 0) {
231
+ spawn('docker', dockerRunOpts, { stdio: 'inherit' })
232
+ }
233
+ })
234
+ } else {
235
+ print.info("Docker image already exists. Skipping `docker build` command.")
236
+ // Run the container from the existing matchstick docker image
237
+ spawn('docker', dockerRunOpts, { stdio: 'inherit' })
238
+ }
239
+ })
240
+ }
241
+
242
+ // TODO: Move these in separate file (in a function maybe)
243
+ function dockerfile(versionOpt, latestVersion) {
244
+ return `
245
+ FROM ubuntu:20.04
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
257
+
258
+ # Download the latest linux binary
259
+ RUN curl -OL https://github.com/LimeChain/matchstick/releases/download/${versionOpt || latestVersion}/binary-linux-20
260
+
261
+ # Make it executable
262
+ RUN chmod a+x binary-linux-20
263
+
264
+ # Create a matchstick dir where the host will be copied
265
+ RUN mkdir matchstick
266
+ WORKDIR matchstick
267
+
268
+ # Copy host to /matchstick
269
+ COPY ../ .
270
+
271
+ RUN graph codegen
272
+ RUN graph build
273
+
274
+ CMD ../binary-linux-20 \${ARGS}`
275
+ }
@@ -0,0 +1,22 @@
1
+ module.exports = class EthereumContract {
2
+ static identifierName() {
3
+ return 'address'
4
+ }
5
+
6
+ constructor(address) {
7
+ this.address = address
8
+ }
9
+
10
+ validate() {
11
+ const pattern = /^(0x)?[0-9a-fA-F]{40}$/
12
+
13
+ const errorMessage = "Must be 40 hexadecimal characters, with an optional '0x' prefix."
14
+
15
+ const valid = pattern.test(this.address)
16
+
17
+ return {
18
+ valid,
19
+ error: valid ? null : errorMessage,
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,32 @@
1
+ const { abiEvents } = require('../../../scaffold/schema')
2
+ const ABI = require('../abi')
3
+
4
+ const source = ({ contract, contractName }) => `
5
+ address: '${contract}'
6
+ abi: ${contractName}`
7
+
8
+ const mapping = ({ abi, contractName }) => `
9
+ kind: ethereum/events
10
+ apiVersion: 0.0.5
11
+ language: wasm/assemblyscript
12
+ entities:
13
+ ${abiEvents(abi)
14
+ .map(event => `- ${event.get('_alias')}`)
15
+ .join('\n ')}
16
+ abis:
17
+ - name: ${contractName}
18
+ file: ./abis/${contractName}.json
19
+ eventHandlers:
20
+ ${abiEvents(abi)
21
+ .map(
22
+ event => `
23
+ - event: ${ABI.eventSignature(event)}
24
+ handler: handle${event.get('_alias')}`,
25
+ )
26
+ .join('')}
27
+ file: ./src/mapping.ts`
28
+
29
+ module.exports = {
30
+ source,
31
+ mapping,
32
+ }
@@ -0,0 +1,76 @@
1
+ const { generateEventFieldAssignments } = require('../../../scaffold/mapping')
2
+
3
+ const generatePlaceholderHandlers = ({ abi, events, contractName }) =>
4
+ `
5
+ import { BigInt } from '@graphprotocol/graph-ts'
6
+ import { ${contractName}, ${events.map(event => event._alias)} }
7
+ from '../generated/${contractName}/${contractName}'
8
+ import { ExampleEntity } from '../generated/schema'
9
+
10
+ ${events
11
+ .map((event, index) =>
12
+ index === 0
13
+ ? `
14
+ export function handle${event._alias}(event: ${event._alias}): void {
15
+ // Entities can be loaded from the store using a string ID; this ID
16
+ // needs to be unique across all entities of the same type
17
+ let entity = ExampleEntity.load(event.transaction.from.toHex())
18
+
19
+ // Entities only exist after they have been saved to the store;
20
+ // \`null\` checks allow to create entities on demand
21
+ if (!entity) {
22
+ entity = new ExampleEntity(event.transaction.from.toHex())
23
+
24
+ // Entity fields can be set using simple assignments
25
+ entity.count = BigInt.fromI32(0)
26
+ }
27
+
28
+ // BigInt and BigDecimal math are supported
29
+ entity.count = entity.count + BigInt.fromI32(1)
30
+
31
+ // Entity fields can be set based on event parameters
32
+ ${generateEventFieldAssignments(event)
33
+ .slice(0, 2)
34
+ .join('\n')}
35
+
36
+ // Entities can be written to the store with \`.save()\`
37
+ entity.save()
38
+
39
+ // Note: If a handler doesn't require existing field values, it is faster
40
+ // _not_ to load the entity from the store. Instead, create it fresh with
41
+ // \`new Entity(...)\`, set the fields that should be updated and save the
42
+ // entity back to the store. Fields that were not set or unset remain
43
+ // unchanged, allowing for partial updates to be applied.
44
+
45
+ // It is also possible to access smart contracts from mappings. For
46
+ // example, the contract that has emitted the event can be connected to
47
+ // with:
48
+ //
49
+ // let contract = Contract.bind(event.address)
50
+ //
51
+ // The following functions can then be called on this contract to access
52
+ // state variables and other data:
53
+ //
54
+ // ${
55
+ abi
56
+ .codeGenerator()
57
+ .callableFunctions()
58
+ .isEmpty()
59
+ ? 'None'
60
+ : abi
61
+ .codeGenerator()
62
+ .callableFunctions()
63
+ .map(fn => `- contract.${fn.get('name')}(...)`)
64
+ .join('\n// ')
65
+ }
66
+ }
67
+ `
68
+ : `
69
+ export function handle${event._alias}(event: ${event._alias}): void {}
70
+ `,
71
+ )
72
+ .join('\n')}`
73
+
74
+ module.exports = {
75
+ generatePlaceholderHandlers,
76
+ }
@@ -1,7 +1,6 @@
1
1
  const immutable = require('immutable')
2
2
  const ABI = require('./abi')
3
3
  const DataSourcesExtractor = require('../../command-helpers/data-sources')
4
- const { validateContractValues } = require('../../validation')
5
4
 
6
5
  module.exports = class EthereumSubgraph {
7
6
  constructor(options = {}) {
@@ -12,7 +11,6 @@ module.exports = class EthereumSubgraph {
12
11
 
13
12
  validateManifest() {
14
13
  return this.validateAbis()
15
- .concat(this.validateContractAddresses())
16
14
  .concat(this.validateEvents())
17
15
  .concat(this.validateCallFunctions())
18
16
  }
@@ -72,18 +70,6 @@ ${abiNames
72
70
  return nameErrors.concat(fileErrors)
73
71
  }
74
72
 
75
- validateContractAddresses() {
76
- const ethereumAddressPattern = /^(0x)?[0-9a-fA-F]{40}$/
77
-
78
- return validateContractValues(
79
- this.manifest,
80
- this.protocol,
81
- 'address',
82
- address => ethereumAddressPattern.test(address),
83
- "Must be 40 hexadecimal characters, with an optional '0x' prefix.",
84
- )
85
- }
86
-
87
73
  validateEvents() {
88
74
  const dataSourcesAndTemplates = DataSourcesExtractor.fromManifest(this.manifest, this.protocol)
89
75
 
@@ -4,6 +4,12 @@ const EthereumTemplateCodeGen = require('./ethereum/codegen/template')
4
4
  const EthereumABI = require('./ethereum/abi')
5
5
  const EthereumSubgraph = require('./ethereum/subgraph')
6
6
  const NearSubgraph = require('./near/subgraph')
7
+ const EthereumContract = require('./ethereum/contract')
8
+ const NearContract = require('./near/contract')
9
+ const EthereumManifestScaffold = require('./ethereum/scaffold/manifest')
10
+ const NearManifestScaffold = require('./near/scaffold/manifest')
11
+ const EthereumMappingScaffold = require('./ethereum/scaffold/mapping')
12
+ const NearMappingScaffold = require('./near/scaffold/mapping')
7
13
 
8
14
  module.exports = class Protocol {
9
15
  static fromDataSources(dataSourcesAndTemplates) {
@@ -15,7 +21,7 @@ module.exports = class Protocol {
15
21
  this.name = this.normalizeName(name)
16
22
  }
17
23
 
18
- availableProtocols() {
24
+ static availableProtocols() {
19
25
  return immutable.fromJS({
20
26
  // `ethereum/contract` is kept for backwards compatibility.
21
27
  // New networks (or protocol perhaps) shouldn't have the `/contract` anymore (unless a new case makes use of it).
@@ -24,15 +30,62 @@ module.exports = class Protocol {
24
30
  })
25
31
  }
26
32
 
33
+ static availableNetworks() {
34
+ return immutable.fromJS({
35
+ ethereum: [
36
+ 'mainnet',
37
+ 'kovan',
38
+ 'rinkeby',
39
+ 'ropsten',
40
+ 'goerli',
41
+ 'poa-core',
42
+ 'poa-sokol',
43
+ 'xdai',
44
+ 'matic',
45
+ 'mumbai',
46
+ 'fantom',
47
+ 'bsc',
48
+ 'chapel',
49
+ 'clover',
50
+ 'avalanche',
51
+ 'fuji',
52
+ 'celo',
53
+ 'celo-alfajores',
54
+ 'fuse',
55
+ 'mbase',
56
+ 'arbitrum-one',
57
+ 'arbitrum-rinkeby',
58
+ 'optimism',
59
+ 'optimism-kovan',
60
+ 'aurora',
61
+ 'aurora-testnet',
62
+ ],
63
+ near: [
64
+ 'near-mainnet',
65
+ 'near-testnet'
66
+ ],
67
+ })
68
+ }
69
+
27
70
  normalizeName(name) {
28
- return this.availableProtocols()
29
- .findKey(possibleNames => possibleNames.includes(name))
71
+ return Protocol.availableProtocols().findKey(possibleNames =>
72
+ possibleNames.includes(name),
73
+ )
74
+ }
75
+
76
+ displayName() {
77
+ switch (this.name) {
78
+ case 'ethereum':
79
+ return 'Ethereum'
80
+ case 'near':
81
+ return 'NEAR'
82
+ }
30
83
  }
31
84
 
32
85
  // Receives a data source kind, and checks if it's valid
33
86
  // for the given protocol instance (this).
34
87
  isValidKindName(kind) {
35
- return this.availableProtocols()
88
+ return Protocol.availableProtocols()
36
89
  .get(this.name, immutable.List())
37
90
  .includes(kind)
38
91
  }
@@ -40,7 +93,15 @@ module.exports = class Protocol {
40
93
  hasABIs() {
41
94
  switch (this.name) {
42
95
  case 'ethereum':
43
- case 'ethereum/contract':
96
+ return true
97
+ case 'near':
98
+ return false
99
+ }
100
+ }
101
+
102
+ hasEvents() {
103
+ switch (this.name) {
104
+ case 'ethereum':
44
105
  return true
45
106
  case 'near':
46
107
  return false
@@ -50,7 +111,6 @@ module.exports = class Protocol {
50
111
  getTypeGenerator(options) {
51
112
  switch (this.name) {
52
113
  case 'ethereum':
53
- case 'ethereum/contract':
54
114
  return new EthereumTypeGenerator(options)
55
115
  case 'near':
56
116
  return null
@@ -60,7 +120,6 @@ module.exports = class Protocol {
60
120
  getTemplateCodeGen(template) {
61
121
  switch (this.name) {
62
122
  case 'ethereum':
63
- case 'ethereum/contract':
64
123
  return new EthereumTemplateCodeGen(template)
65
124
  default:
66
125
  throw new Error(
@@ -72,7 +131,6 @@ module.exports = class Protocol {
72
131
  getABI() {
73
132
  switch (this.name) {
74
133
  case 'ethereum':
75
- case 'ethereum/contract':
76
134
  return EthereumABI
77
135
  case 'near':
78
136
  return null
@@ -84,14 +142,38 @@ module.exports = class Protocol {
84
142
 
85
143
  switch (this.name) {
86
144
  case 'ethereum':
87
- case 'ethereum/contract':
88
145
  return new EthereumSubgraph(optionsWithProtocol)
89
146
  case 'near':
90
147
  return new NearSubgraph(optionsWithProtocol)
91
148
  default:
92
- throw new Error(
93
- `Data sources with kind '${this.name}' are not supported yet`,
94
- )
149
+ throw new Error(`Data sources with kind '${this.name}' are not supported yet`)
150
+ }
151
+ }
152
+
153
+ getContract() {
154
+ switch (this.name) {
155
+ case 'ethereum':
156
+ return EthereumContract
157
+ case 'near':
158
+ return NearContract
159
+ }
160
+ }
161
+
162
+ getManifestScaffold() {
163
+ switch (this.name) {
164
+ case 'ethereum':
165
+ return EthereumManifestScaffold
166
+ case 'near':
167
+ return NearManifestScaffold
168
+ }
169
+ }
170
+
171
+ getMappingScaffold() {
172
+ switch (this.name) {
173
+ case 'ethereum':
174
+ return EthereumMappingScaffold
175
+ case 'near':
176
+ return NearMappingScaffold
95
177
  }
96
178
  }
97
179
  }
@@ -0,0 +1,46 @@
1
+ const MINIMUM_ACCOUNT_ID_LENGTH = 2
2
+ const MAXIMUM_ACCOUNT_ID_LENGTH = 64
3
+
4
+ const RULES_URL = 'https://docs.near.org/docs/concepts/account#account-id-rules'
5
+
6
+ module.exports = class NearContract {
7
+ static identifierName() {
8
+ return 'account'
9
+ }
10
+
11
+ constructor(account) {
12
+ this.account = account
13
+ }
14
+
15
+ _validateLength() {
16
+ return this.account.length >= MINIMUM_ACCOUNT_ID_LENGTH &&
17
+ this.account.length <= MAXIMUM_ACCOUNT_ID_LENGTH
18
+ }
19
+
20
+ _validateFormat() {
21
+ const pattern = /^(([a-z\d]+[\-_])*[a-z\d]+\.)*([a-z\d]+[\-_])*[a-z\d]+$/
22
+
23
+ return pattern.test(this.account)
24
+ }
25
+
26
+ validate() {
27
+ if (!this._validateLength(this.account)) {
28
+ return {
29
+ valid: false,
30
+ error: `Account must be between '${MINIMUM_ACCOUNT_ID_LENGTH}' and '${MAXIMUM_ACCOUNT_ID_LENGTH}' characters, see ${RULES_URL}`,
31
+ }
32
+ }
33
+
34
+ if (!this._validateFormat()) {
35
+ return {
36
+ valid: false,
37
+ error: `Account must conform to the rules on ${RULES_URL}`,
38
+ }
39
+ }
40
+
41
+ return {
42
+ valid: true,
43
+ error: null,
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,16 @@
1
+ const source = ({ contract }) => `
2
+ account: '${contract}'`
3
+
4
+ const mapping = () => `
5
+ apiVersion: 0.0.5
6
+ language: wasm/assemblyscript
7
+ entities:
8
+ - ExampleEntity
9
+ receiptHandlers:
10
+ - handler: handleReceipt
11
+ file: ./src/mapping.ts`
12
+
13
+ module.exports = {
14
+ source,
15
+ mapping,
16
+ }