@graphprotocol/graph-cli 0.36.0 → 0.37.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphprotocol/graph-cli",
3
- "version": "0.36.0",
3
+ "version": "0.37.0",
4
4
  "license": "(Apache-2.0 OR MIT)",
5
5
  "description": "CLI for building for and deploying to The Graph",
6
6
  "dependencies": {
@@ -6,7 +6,7 @@ const Compiler = require('../compiler')
6
6
  // Helper function to construct a subgraph compiler
7
7
  const createCompiler = (
8
8
  manifest,
9
- { ipfs, headers, outputDir, outputFormat, skipMigrations, blockIpfsMethods, protocol }
9
+ { ipfs, headers, outputDir, outputFormat, skipMigrations, blockIpfsMethods, protocol },
10
10
  ) => {
11
11
  // Parse the IPFS URL
12
12
  let url
@@ -6,6 +6,8 @@ const { updateSubgraphNetwork } = require('../command-helpers/network')
6
6
  const DataSourcesExtractor = require('../command-helpers/data-sources')
7
7
  const Protocol = require('../protocols')
8
8
 
9
+ let buildDebug = require('../debug')('graph-cli:build')
10
+
9
11
  const HELP = `
10
12
  ${chalk.bold('graph build')} [options] ${chalk.bold('[<subgraph-manifest>]')}
11
13
 
@@ -41,7 +43,7 @@ module.exports = {
41
43
  w,
42
44
  watch,
43
45
  network,
44
- networkFile
46
+ networkFile,
45
47
  } = toolbox.parameters.options
46
48
 
47
49
  // Support both short and long option variants
@@ -76,7 +78,7 @@ module.exports = {
76
78
  networkFile =
77
79
  networkFile !== undefined && networkFile !== ''
78
80
  ? networkFile
79
- : filesystem.resolve("networks.json")
81
+ : filesystem.resolve('networks.json')
80
82
 
81
83
  // Show help text if requested
82
84
  if (help) {
@@ -95,7 +97,9 @@ module.exports = {
95
97
  return
96
98
  }
97
99
 
98
- if (network && filesystem.exists(networkFile) !== "file") {
100
+ buildDebug('Detected protocol "%s" (%o)', protocol.name, protocol)
101
+
102
+ if (network && filesystem.exists(networkFile) !== 'file') {
99
103
  print.error(`Network file '${networkFile}' does not exists or is not a file!`)
100
104
  process.exitCode = 1
101
105
  return
@@ -21,6 +21,8 @@ Options:
21
21
  -uc, --uncrashable-config <path> Directory for uncrashable config (default: ./uncrashable-config.yaml)
22
22
  `
23
23
 
24
+ let codegenDebug = require('../debug')('graph-cli:codegen')
25
+
24
26
  module.exports = {
25
27
  description: 'Generates AssemblyScript types for a subgraph',
26
28
  run: async toolbox => {
@@ -54,6 +56,7 @@ module.exports = {
54
56
  ;[manifest] = fixParameters(toolbox.parameters, {
55
57
  h,
56
58
  help,
59
+ skipMigrations,
57
60
  w,
58
61
  watch,
59
62
  u,
@@ -65,6 +68,8 @@ module.exports = {
65
68
  return
66
69
  }
67
70
 
71
+ codegenDebug('Initialized codegen manifest: %o', manifest)
72
+
68
73
  // Fall back to default values for options / parameters
69
74
  outputDir =
70
75
  outputDir !== undefined && outputDir !== ''
@@ -26,6 +26,8 @@ const availableNetworks = Protocol.availableNetworks()
26
26
 
27
27
  const DEFAULT_EXAMPLE_SUBGRAPH = 'ethereum/gravatar'
28
28
 
29
+ let initDebug = require('../debug')('graph-cli:init')
30
+
29
31
  const HELP = `
30
32
  ${chalk.bold('graph init')} [options] [subgraph-name] [directory]
31
33
 
@@ -170,10 +172,17 @@ const processInitForm = async (
170
172
  type: 'select',
171
173
  name: 'network',
172
174
  message: () => `${protocolInstance.displayName()} network`,
173
- choices: () =>
174
- availableNetworks
175
+ choices: () => {
176
+ initDebug(
177
+ 'Generating list of available networks for protocol "%s" (%M)',
178
+ protocol,
179
+ availableNetworks.get(protocol),
180
+ )
181
+ return availableNetworks
175
182
  .get(protocol) // Get networks related to the chosen protocol.
176
- .toArray(), // Needed because of gluegun. It can't even receive a JS iterable.
183
+ .toArray() // Needed because of gluegun. It can't even receive a JS iterable.
184
+ },
185
+
177
186
  skip: fromExample !== undefined,
178
187
  initial: network || 'mainnet',
179
188
  result: value => {
@@ -11,6 +11,9 @@ const Subgraph = require('../subgraph')
11
11
  const Watcher = require('../watcher')
12
12
  const { applyMigrations } = require('../migrations')
13
13
  const asc = require('./asc')
14
+ const SubstreamsSubgraph = require('../protocols/substreams/subgraph')
15
+
16
+ let compilerDebug = require('../debug')('graph-cli:compiler')
14
17
 
15
18
  class Compiler {
16
19
  constructor(options) {
@@ -20,36 +23,38 @@ class Compiler {
20
23
  this.blockIpfsMethods = options.blockIpfsMethods
21
24
  this.libsDirs = []
22
25
 
23
- for (
24
- let dir = path.resolve(this.sourceDir);
25
- // Terminate after the root dir or when we have found node_modules
26
- dir !== undefined;
27
- // Continue with the parent directory, terminate after the root dir
28
- dir = path.dirname(dir) === dir ? undefined : path.dirname(dir)
29
- ) {
30
- if (fs.existsSync(path.join(dir, 'node_modules'))) {
31
- this.libsDirs.push(path.join(dir, 'node_modules'))
26
+ if (options.protocol.name !== 'substreams') {
27
+ for (
28
+ let dir = path.resolve(this.sourceDir);
29
+ // Terminate after the root dir or when we have found node_modules
30
+ dir !== undefined;
31
+ // Continue with the parent directory, terminate after the root dir
32
+ dir = path.dirname(dir) === dir ? undefined : path.dirname(dir)
33
+ ) {
34
+ if (fs.existsSync(path.join(dir, 'node_modules'))) {
35
+ this.libsDirs.push(path.join(dir, 'node_modules'))
36
+ }
32
37
  }
33
- }
34
38
 
35
- if (this.libsDirs.length === 0) {
36
- throw Error(
37
- `could not locate \`node_modules\` in parent directories of subgraph manifest`,
38
- )
39
- }
39
+ if (this.libsDirs.length === 0) {
40
+ throw Error(
41
+ `could not locate \`node_modules\` in parent directories of subgraph manifest`,
42
+ )
43
+ }
40
44
 
41
- const globalsFile = path.join('@graphprotocol', 'graph-ts', 'global', 'global.ts')
42
- const globalsLib = this.libsDirs.find(item => {
43
- return fs.existsSync(path.join(item, globalsFile))
44
- })
45
+ const globalsFile = path.join('@graphprotocol', 'graph-ts', 'global', 'global.ts')
46
+ const globalsLib = this.libsDirs.find(item => {
47
+ return fs.existsSync(path.join(item, globalsFile))
48
+ })
45
49
 
46
- if (!globalsLib) {
47
- throw Error(
48
- 'Could not locate `@graphprotocol/graph-ts` package in parent directories of subgraph manifest.',
49
- )
50
- }
50
+ if (!globalsLib) {
51
+ throw Error(
52
+ 'Could not locate `@graphprotocol/graph-ts` package in parent directories of subgraph manifest.',
53
+ )
54
+ }
51
55
 
52
- this.globalsFile = path.join(globalsLib, globalsFile)
56
+ this.globalsFile = path.join(globalsLib, globalsFile)
57
+ }
53
58
 
54
59
  this.protocol = this.options.protocol
55
60
  this.ABI = this.protocol.getABI()
@@ -83,7 +88,10 @@ class Compiler {
83
88
  }
84
89
  let subgraph = await this.loadSubgraph()
85
90
  let compiledSubgraph = await this.compileSubgraph(subgraph)
86
- let localSubgraph = await this.writeSubgraphToOutputDirectory(compiledSubgraph)
91
+ let localSubgraph = await this.writeSubgraphToOutputDirectory(
92
+ this.options.protocol,
93
+ compiledSubgraph,
94
+ )
87
95
 
88
96
  if (this.ipfs !== undefined) {
89
97
  let ipfsHash = await this.uploadSubgraphToIPFS(localSubgraph)
@@ -214,6 +222,7 @@ class Compiler {
214
222
  dataSources.map(dataSource =>
215
223
  dataSource.updateIn(['mapping', 'file'], mappingPath =>
216
224
  this._compileDataSourceMapping(
225
+ this.protocol,
217
226
  dataSource,
218
227
  mappingPath,
219
228
  compiledFiles,
@@ -243,7 +252,11 @@ class Compiler {
243
252
  )
244
253
  }
245
254
 
246
- _compileDataSourceMapping(dataSource, mappingPath, compiledFiles, spinner) {
255
+ _compileDataSourceMapping(protocol, dataSource, mappingPath, compiledFiles, spinner) {
256
+ if (protocol.name == 'substreams') {
257
+ return
258
+ }
259
+
247
260
  try {
248
261
  let dataSourceName = dataSource.getIn(['name'])
249
262
 
@@ -378,7 +391,7 @@ class Compiler {
378
391
  _validateMappingContent(filePath) {
379
392
  const data = fs.readFileSync(filePath)
380
393
  if (
381
- this.blockIpfsMethods &&
394
+ this.blockIpfsMethods &&
382
395
  (data.includes('ipfs.cat') || data.includes('ipfs.map'))
383
396
  ) {
384
397
  throw Error(`
@@ -389,7 +402,7 @@ class Compiler {
389
402
  }
390
403
  }
391
404
 
392
- async writeSubgraphToOutputDirectory(subgraph) {
405
+ async writeSubgraphToOutputDirectory(protocol, subgraph) {
393
406
  const displayDir = `${this.displayPath(this.options.outputDir)}${
394
407
  toolbox.filesystem.separator
395
408
  }`
@@ -437,6 +450,30 @@ class Compiler {
437
450
  )
438
451
  }
439
452
 
453
+ if (protocol.name == 'substreams') {
454
+ updatedDataSource = updatedDataSource
455
+ // Write data source ABIs to the output directory
456
+ .updateIn(['source', 'package'], substreamsPackage =>
457
+ substreamsPackage.update('file', packageFile => {
458
+ packageFile = path.resolve(this.sourceDir, packageFile)
459
+ let packageContent = fs.readFileSync(packageFile)
460
+
461
+ return path.relative(
462
+ this.options.outputDir,
463
+ this._writeSubgraphFile(
464
+ packageFile,
465
+ packageContent,
466
+ this.sourceDir,
467
+ this.subgraphDir(this.options.outputDir, dataSource),
468
+ spinner,
469
+ ),
470
+ )
471
+ }),
472
+ )
473
+
474
+ return updatedDataSource
475
+ }
476
+
440
477
  // The mapping file is already being written to the output
441
478
  // directory by the AssemblyScript compiler
442
479
  return updatedDataSource.updateIn(['mapping', 'file'], mappingFile =>
@@ -445,7 +482,7 @@ class Compiler {
445
482
  path.resolve(this.sourceDir, mappingFile),
446
483
  ),
447
484
  )
448
- })
485
+ }),
449
486
  )
450
487
 
451
488
  // Copy template files and update their paths
@@ -453,40 +490,40 @@ class Compiler {
453
490
  templates === undefined
454
491
  ? templates
455
492
  : templates.map(template => {
456
- let updatedTemplate = template
457
-
458
- if (this.protocol.hasABIs()) {
459
- updatedTemplate = updatedTemplate
460
- // Write template ABIs to the output directory
461
- .updateIn(['mapping', 'abis'], abis =>
462
- abis.map(abi =>
463
- abi.update('file', abiFile => {
464
- abiFile = path.resolve(this.sourceDir, abiFile)
465
- let abiData = this.ABI.load(abi.get('name'), abiFile)
466
- return path.relative(
467
- this.options.outputDir,
468
- this._writeSubgraphFile(
469
- abiFile,
470
- JSON.stringify(abiData.data.toJS(), null, 2),
471
- this.sourceDir,
472
- this.subgraphDir(this.options.outputDir, template),
473
- spinner,
474
- ),
475
- )
476
- }),
477
- ),
478
- )
479
- }
480
-
481
- // The mapping file is already being written to the output
482
- // directory by the AssemblyScript compiler
483
- return updatedTemplate.updateIn(['mapping', 'file'], mappingFile =>
484
- path.relative(
485
- this.options.outputDir,
486
- path.resolve(this.sourceDir, mappingFile),
487
- ),
488
- )
489
- })
493
+ let updatedTemplate = template
494
+
495
+ if (this.protocol.hasABIs()) {
496
+ updatedTemplate = updatedTemplate
497
+ // Write template ABIs to the output directory
498
+ .updateIn(['mapping', 'abis'], abis =>
499
+ abis.map(abi =>
500
+ abi.update('file', abiFile => {
501
+ abiFile = path.resolve(this.sourceDir, abiFile)
502
+ let abiData = this.ABI.load(abi.get('name'), abiFile)
503
+ return path.relative(
504
+ this.options.outputDir,
505
+ this._writeSubgraphFile(
506
+ abiFile,
507
+ JSON.stringify(abiData.data.toJS(), null, 2),
508
+ this.sourceDir,
509
+ this.subgraphDir(this.options.outputDir, template),
510
+ spinner,
511
+ ),
512
+ )
513
+ }),
514
+ ),
515
+ )
516
+ }
517
+
518
+ // The mapping file is already being written to the output
519
+ // directory by the AssemblyScript compiler
520
+ return updatedTemplate.updateIn(['mapping', 'file'], mappingFile =>
521
+ path.relative(
522
+ this.options.outputDir,
523
+ path.resolve(this.sourceDir, mappingFile),
524
+ ),
525
+ )
526
+ }),
490
527
  )
491
528
 
492
529
  // Write the subgraph manifest itself
@@ -537,15 +574,28 @@ class Compiler {
537
574
  }
538
575
 
539
576
  // Upload all mappings
540
- for (let [i, dataSource] of subgraph.get('dataSources').entries()) {
541
- updates.push({
542
- keyPath: ['dataSources', i, 'mapping', 'file'],
543
- value: await this._uploadFileToIPFS(
544
- dataSource.getIn(['mapping', 'file']),
545
- uploadedFiles,
546
- spinner,
547
- ),
548
- })
577
+ if (this.protocol.name !== 'substreams') {
578
+ for (let [i, dataSource] of subgraph.get('dataSources').entries()) {
579
+ updates.push({
580
+ keyPath: ['dataSources', i, 'mapping', 'file'],
581
+ value: await this._uploadFileToIPFS(
582
+ dataSource.getIn(['mapping', 'file']),
583
+ uploadedFiles,
584
+ spinner,
585
+ ),
586
+ })
587
+ }
588
+ } else {
589
+ for (let [i, dataSource] of subgraph.get('dataSources').entries()) {
590
+ updates.push({
591
+ keyPath: ['dataSources', i, 'source', 'package', 'file'],
592
+ value: await this._uploadFileToIPFS(
593
+ dataSource.getIn(['source', 'package', 'file']),
594
+ uploadedFiles,
595
+ spinner,
596
+ ),
597
+ })
598
+ }
549
599
  }
550
600
 
551
601
  for (let [i, template] of subgraph.get('templates', immutable.List()).entries()) {
@@ -584,6 +634,11 @@ class Compiler {
584
634
  }
585
635
 
586
636
  async _uploadFileToIPFS(maybeRelativeFile, uploadedFiles, spinner) {
637
+ compilerDebug(
638
+ 'Resolving IPFS file "%s" from output dir "%s"',
639
+ maybeRelativeFile,
640
+ this.options.outputDir,
641
+ )
587
642
  let absoluteFile = path.resolve(this.options.outputDir, maybeRelativeFile)
588
643
  step(spinner, 'Add file to IPFS', this.displayPath(absoluteFile))
589
644
 
package/src/debug.js ADDED
@@ -0,0 +1,15 @@
1
+ const debugFactory = require('debug')
2
+
3
+ debugFactory.formatters.L = immutableList => {
4
+ return JSON.stringify(immutableList)
5
+ }
6
+
7
+ debugFactory.formatters.M = immutableMap => {
8
+ if (immutableMap.toMap != null) {
9
+ return JSON.stringify(immutableMap.toMap())
10
+ }
11
+
12
+ return immutableMap
13
+ }
14
+
15
+ module.exports = debugFactory
@@ -6,17 +6,23 @@ const EthereumABI = require('./ethereum/abi')
6
6
  const EthereumSubgraph = require('./ethereum/subgraph')
7
7
  const NearSubgraph = require('./near/subgraph')
8
8
  const CosmosSubgraph = require('./cosmos/subgraph')
9
+ const SubstreamsSubgraph = require('./substreams/subgraph')
9
10
  const EthereumContract = require('./ethereum/contract')
10
11
  const NearContract = require('./near/contract')
12
+ const ArweaveManifestScaffold = require('./arweave/scaffold/manifest')
11
13
  const EthereumManifestScaffold = require('./ethereum/scaffold/manifest')
12
14
  const NearManifestScaffold = require('./near/scaffold/manifest')
13
15
  const CosmosManifestScaffold = require('./cosmos/scaffold/manifest')
16
+ const SubstreamsManifestScaffold = require('./substreams/scaffold/manifest')
14
17
  const ArweaveMappingScaffold = require('./arweave/scaffold/mapping')
15
18
  const EthereumMappingScaffold = require('./ethereum/scaffold/mapping')
16
19
  const NearMappingScaffold = require('./near/scaffold/mapping')
17
20
  const CosmosMappingScaffold = require('./cosmos/scaffold/mapping')
21
+ const { ThrowStatement } = require('assemblyscript')
18
22
 
19
- module.exports = class Protocol {
23
+ let protocolDebug = require('../debug')('graph-cli:protocol')
24
+
25
+ class Protocol {
20
26
  static fromDataSources(dataSourcesAndTemplates) {
21
27
  const firstDataSourceKind = dataSourcesAndTemplates[0].kind
22
28
  return new Protocol(firstDataSourceKind)
@@ -24,6 +30,27 @@ module.exports = class Protocol {
24
30
 
25
31
  constructor(name) {
26
32
  this.name = Protocol.normalizeName(name)
33
+
34
+ switch (this.name) {
35
+ case 'arweave':
36
+ this.config = arweaveProtocol
37
+ break
38
+ case 'cosmos':
39
+ this.config = cosmosProtocol
40
+ break
41
+ case 'ethereum':
42
+ this.config = ethereumProtocol
43
+ break
44
+ case 'near':
45
+ this.config = nearProtocol
46
+ break
47
+ case 'substreams':
48
+ this.config = substreamsProtocol
49
+ break
50
+ default:
51
+ // Do not throw when undefined, a better error message is printed after the constructor
52
+ // when validating the Subgraph itself
53
+ }
27
54
  }
28
55
 
29
56
  static availableProtocols() {
@@ -33,12 +60,13 @@ module.exports = class Protocol {
33
60
  arweave: ['arweave'],
34
61
  ethereum: ['ethereum', 'ethereum/contract'],
35
62
  near: ['near'],
36
- cosmos: ['cosmos']
63
+ cosmos: ['cosmos'],
64
+ substreams: ['substreams'],
37
65
  })
38
66
  }
39
67
 
40
68
  static availableNetworks() {
41
- return immutable.fromJS({
69
+ let networks = immutable.fromJS({
42
70
  arweave: ['arweave-mainnet'],
43
71
  ethereum: [
44
72
  'mainnet',
@@ -74,30 +102,30 @@ module.exports = class Protocol {
74
102
  'cosmoshub-4',
75
103
  'theta-testnet-001', // CosmosHub testnet
76
104
  'osmosis-1',
77
- 'osmo-test-4', // Osmosis testnet
78
- 'juno-1',
79
- 'uni-3' // Juno testnet
105
+ 'osmo-test-4', // Osmosis testnet
106
+ 'juno-1',
107
+ 'uni-3', // Juno testnet
80
108
  ],
81
109
  })
110
+
111
+ let allNetworks = []
112
+ networks.forEach(value => {
113
+ allNetworks.push(...value)
114
+ })
115
+
116
+ networks = networks.set('substreams', immutable.fromJS(allNetworks))
117
+
118
+ return networks
82
119
  }
83
120
 
84
121
  static normalizeName(name) {
85
- return Protocol.availableProtocols().findKey(possibleNames =>
86
- possibleNames.includes(name),
87
- )
122
+ return Protocol.availableProtocols().findKey(possibleNames => {
123
+ return possibleNames.includes(name)
124
+ })
88
125
  }
89
126
 
90
127
  displayName() {
91
- switch (this.name) {
92
- case 'arweave':
93
- return 'Arweave'
94
- case 'ethereum':
95
- return 'Ethereum'
96
- case 'near':
97
- return 'NEAR'
98
- case 'cosmos':
99
- return 'Cosmos'
100
- }
128
+ return this.config.displayName
101
129
  }
102
130
 
103
131
  // Receives a data source kind, and checks if it's valid
@@ -109,68 +137,34 @@ module.exports = class Protocol {
109
137
  }
110
138
 
111
139
  hasABIs() {
112
- switch (this.name) {
113
- case 'arweave':
114
- return false
115
- case 'ethereum':
116
- return true
117
- case 'near':
118
- return false
119
- case 'cosmos':
120
- return false
121
- }
140
+ return this.config.abi != null
122
141
  }
123
142
 
124
143
  hasContract() {
125
- switch (this.name) {
126
- case 'arweave':
127
- return false
128
- case 'ethereum':
129
- return true
130
- case 'near':
131
- return true
132
- case 'cosmos':
133
- return false
134
- }
144
+ return this.config.contract != null
135
145
  }
136
146
 
137
147
  hasEvents() {
138
- switch (this.name) {
139
- case 'arweave':
140
- return false
141
- case 'ethereum':
142
- return true
143
- case 'near':
144
- return false
145
- case 'cosmos':
146
- return false
147
- }
148
+ // A problem with hasEvents usage in the codebase is that it's almost every where
149
+ // where used, the ABI data is actually use after the conditional, so it seems
150
+ // both concept are related. So internally, we map to this condition.
151
+ return this.hasABIs()
148
152
  }
149
153
 
150
154
  hasTemplates() {
151
- switch (this.name) {
152
- case 'arweave':
153
- return false
154
- case 'ethereum':
155
- return true
156
- case 'near':
157
- return false
158
- case 'cosmos':
159
- return false
160
- }
155
+ return this.config.getTemplateCodeGen != null
156
+ }
157
+
158
+ hasDataSourceMappingFile() {
159
+ return this.config.getMappingScaffold != null
161
160
  }
162
161
 
163
162
  getTypeGenerator(options) {
164
- switch (this.name) {
165
- case 'arweave':
166
- return null
167
- case 'ethereum':
168
- return new EthereumTypeGenerator(options)
169
- case 'near':
170
- return null
171
- case 'cosmos':
172
- return null
163
+ if (this.config == null || this.config.getTypeGenerator == null) {
164
+ return null
173
165
  }
166
+
167
+ return this.config.getTypeGenerator(options)
174
168
  }
175
169
 
176
170
  getTemplateCodeGen(template) {
@@ -180,80 +174,98 @@ module.exports = class Protocol {
180
174
  )
181
175
  }
182
176
 
183
- switch (this.name) {
184
- case 'ethereum':
185
- return new EthereumTemplateCodeGen(template)
186
- default:
187
- throw new Error(`Template data sources with kind '${this.name}' is unknown`)
188
- }
177
+ return this.config.getTemplateCodeGen(template)
189
178
  }
190
179
 
191
180
  getABI() {
192
- switch (this.name) {
193
- case 'arweave':
194
- return null
195
- case 'ethereum':
196
- return EthereumABI
197
- case 'near':
198
- return null
199
- case 'cosmos':
200
- return null
201
- }
181
+ return this.config.abi
202
182
  }
203
183
 
204
184
  getSubgraph(options = {}) {
205
- const optionsWithProtocol = { ...options, protocol: this }
206
-
207
- switch (this.name) {
208
- case 'arweave':
209
- return new ArweaveSubgraph(optionsWithProtocol)
210
- case 'ethereum':
211
- return new EthereumSubgraph(optionsWithProtocol)
212
- case 'near':
213
- return new NearSubgraph(optionsWithProtocol)
214
- case 'cosmos':
215
- return new CosmosSubgraph(optionsWithProtocol)
216
- default:
217
- throw new Error(`Data sources with kind '${this.name}' are not supported yet`)
218
- }
185
+ return this.config.getSubgraph({ ...options, protocol: this })
219
186
  }
220
187
 
221
188
  getContract() {
222
- switch (this.name) {
223
- case 'arweave':
224
- return null
225
- case 'ethereum':
226
- return EthereumContract
227
- case 'near':
228
- return NearContract
229
- case 'cosmos':
230
- return null
231
- }
189
+ return this.config.contract
232
190
  }
233
191
 
234
192
  getManifestScaffold() {
235
- switch (this.name) {
236
- case 'arweave':
237
- return ArweaveMappingScaffold
238
- case 'ethereum':
239
- return EthereumManifestScaffold
240
- case 'near':
241
- return NearManifestScaffold
242
- case 'cosmos':
243
- return CosmosManifestScaffold
244
- }
193
+ return this.config.manifestScaffold
245
194
  }
246
195
 
247
196
  getMappingScaffold() {
248
- switch (this.name) {
249
- case 'arweave':
250
- return ArweaveMappingScaffold
251
- case 'ethereum':
252
- return EthereumMappingScaffold
253
- case 'near':
254
- return NearMappingScaffold
255
- case 'cosmos':
256
- return CosmosMappingScaffold
257
- }
197
+ return this.config.mappingScaffold
258
198
  }
259
199
  }
200
+
201
+ const arweaveProtocol = {
202
+ displayName: 'Arweave',
203
+ abi: undefined,
204
+ contract: undefined,
205
+ getTemplateCodeGen: undefined,
206
+ getTypeGenerator: undefined,
207
+ getSubgraph(options) {
208
+ return new ArweaveSubgraph(options)
209
+ },
210
+ manifestScaffold: ArweaveManifestScaffold,
211
+ mappingScaffold: ArweaveMappingScaffold,
212
+ }
213
+
214
+ const cosmosProtocol = {
215
+ displayName: 'Cosmos',
216
+ abi: undefined,
217
+ contract: undefined,
218
+ getTemplateCodeGen: undefined,
219
+ getTypeGenerator: undefined,
220
+ getSubgraph(options) {
221
+ return new CosmosSubgraph(options)
222
+ },
223
+ manifestScaffold: CosmosManifestScaffold,
224
+ mappingScaffold: CosmosMappingScaffold,
225
+ }
226
+
227
+ const ethereumProtocol = {
228
+ displayName: 'Ethereum',
229
+ abi: EthereumABI,
230
+ contract: EthereumContract,
231
+ getTemplateCodeGen(template) {
232
+ return new EthereumTemplateCodeGen(template)
233
+ },
234
+ getTypeGenerator(options) {
235
+ return new EthereumTypeGenerator(options)
236
+ },
237
+ getSubgraph(options) {
238
+ return new EthereumSubgraph(options)
239
+ },
240
+ manifestScaffold: EthereumManifestScaffold,
241
+ mappingScaffold: EthereumMappingScaffold,
242
+ }
243
+
244
+ const nearProtocol = {
245
+ displayName: 'NEAR',
246
+ abi: undefined,
247
+ contract: NearContract,
248
+ getTypeGenerator: undefined,
249
+ getTemplateCodeGen: undefined,
250
+ getSubgraph(options) {
251
+ return new NearSubgraph(options)
252
+ },
253
+ manifestScaffold: NearManifestScaffold,
254
+ mappingScaffold: NearMappingScaffold,
255
+ }
256
+
257
+ const substreamsProtocol = {
258
+ displayName: 'Substreams',
259
+ abi: undefined,
260
+ contract: undefined,
261
+ getTypeGenerator: undefined,
262
+ getTemplateCodeGen: undefined,
263
+ getSubgraph(options) {
264
+ return new SubstreamsSubgraph(options)
265
+ },
266
+ manifestScaffold: SubstreamsManifestScaffold,
267
+ mappingScaffold: undefined,
268
+ }
269
+
270
+ protocolDebug('Available networks %M', Protocol.availableNetworks())
271
+ module.exports = Protocol
@@ -0,0 +1,45 @@
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
+ }
20
+
21
+ type Schema {
22
+ file: File!
23
+ }
24
+
25
+ type DataSource {
26
+ kind: String!
27
+ name: String!
28
+ network: String
29
+ source: SubstreamsSource!
30
+ mapping: SubstreamMapping!
31
+ }
32
+
33
+ type SubstreamsSource {
34
+ package: SubstreamsPackage!
35
+ }
36
+
37
+ type SubstreamsPackage {
38
+ moduleName: String!
39
+ file: String!
40
+ }
41
+
42
+ type SubstreamMapping {
43
+ apiVersion: String!
44
+ kind: String!
45
+ }
@@ -0,0 +1,13 @@
1
+ const source = () => `
2
+ package:
3
+ moduleName: graph_out
4
+ file: substreams-eth-block-meta-v0.1.0.spkg`
5
+
6
+ const mapping = () => `
7
+ apiVersion: 0.0.5
8
+ kind: substreams/graph-entities`
9
+
10
+ module.exports = {
11
+ source,
12
+ mapping,
13
+ }
@@ -0,0 +1,17 @@
1
+ const immutable = require('immutable')
2
+
3
+ module.exports = class SubstreamsSubgraph {
4
+ constructor(options = {}) {
5
+ this.manifest = options.manifest
6
+ this.resolveFile = options.resolveFile
7
+ this.protocol = options.protocol
8
+ }
9
+
10
+ validateManifest() {
11
+ return immutable.List()
12
+ }
13
+
14
+ handlerTypes() {
15
+ return immutable.List([])
16
+ }
17
+ }
@@ -99,10 +99,15 @@ dataSources:
99
99
  )
100
100
  }
101
101
 
102
+ generateMappings() {
103
+ return this.protocol.getMappingScaffold()
104
+ ? { [`${strings.kebabCase(this.contractName)}.ts`]: this.generateMapping() }
105
+ : undefined
106
+ }
107
+
102
108
  generateMapping() {
103
109
  const hasEvents = this.protocol.hasEvents()
104
110
  const events = hasEvents ? abiEvents(this.abi).toJS() : []
105
-
106
111
  const protocolMapping = this.protocol.getMappingScaffold()
107
112
 
108
113
  return prettier.format(
@@ -141,7 +146,7 @@ dataSources:
141
146
  'subgraph.yaml': this.generateManifest(),
142
147
  'schema.graphql': this.generateSchema(),
143
148
  'tsconfig.json': this.generateTsConfig(),
144
- src: { [`${strings.kebabCase(this.contractName)}.ts`]: this.generateMapping() },
149
+ src: this.generateMappings(),
145
150
  abis: this.generateABIs(),
146
151
  tests: this.generateTests(),
147
152
  }
package/src/subgraph.js CHANGED
@@ -6,6 +6,8 @@ let { strOptions } = require('yaml/types')
6
6
  let graphql = require('graphql/language')
7
7
  let validation = require('./validation')
8
8
 
9
+ let subgraphDebug = require('./debug')('graph-cli:subgraph')
10
+
9
11
  const throwCombinedError = (filename, errors) => {
10
12
  throw new Error(
11
13
  errors.reduce(
@@ -39,6 +41,7 @@ const buildCombinedWarning = (filename, warnings) =>
39
41
 
40
42
  module.exports = class Subgraph {
41
43
  static async validate(data, protocol, { resolveFile }) {
44
+ subgraphDebug(`Validating Subgraph with protocol "%s"`, protocol)
42
45
  if (protocol.name == null) {
43
46
  return immutable.fromJS([
44
47
  {
@@ -134,11 +137,19 @@ Please update it to tell users more about your subgraph.`,
134
137
  .filter(dataSource => protocol.isValidKindName(dataSource.get('kind')))
135
138
  .reduce((errors, dataSource, dataSourceIndex) => {
136
139
  let path = ['dataSources', dataSourceIndex, 'mapping']
137
-
138
140
  let mapping = dataSource.get('mapping')
139
-
140
141
  const handlerTypes = protocolSubgraph.handlerTypes()
141
142
 
143
+ subgraphDebug(
144
+ 'Validating dataSource "%s" handlers with %d handlers types defined for protocol',
145
+ dataSource.get('name'),
146
+ handlerTypes.size,
147
+ )
148
+
149
+ if (handlerTypes.size == 0) {
150
+ return errors
151
+ }
152
+
142
153
  const areAllHandlersEmpty = handlerTypes
143
154
  .map(handlerType => mapping.get(handlerType, immutable.List()))
144
155
  .every(handlers => handlers.isEmpty())
@@ -159,7 +170,7 @@ At least one such handler must be defined.`,
159
170
  }
160
171
 
161
172
  static validateContractValues(manifest, protocol) {
162
- if (!protocol.hasContract()){
173
+ if (!protocol.hasContract()) {
163
174
  return immutable.List()
164
175
  }
165
176
 
@@ -14,7 +14,7 @@ const { step, withSpinner } = require('./command-helpers/spinner')
14
14
  const { applyMigrations } = require('./migrations')
15
15
  const { GENERATED_FILE_NOTE } = require('./codegen/typescript')
16
16
  const { displayPath } = require('./command-helpers/fs')
17
- const uncrashable = require('../node_modules/@float-capital/float-subgraph-uncrashable/src/Index.bs.js')
17
+ const uncrashable = require('@float-capital/float-subgraph-uncrashable/src/Index.bs.js')
18
18
 
19
19
  module.exports = class TypeGenerator {
20
20
  constructor(options) {