@graphprotocol/graph-cli 0.36.1 → 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 +1 -1
- package/src/command-helpers/compiler.js +1 -1
- package/src/commands/build.js +7 -3
- package/src/commands/codegen.js +5 -0
- package/src/commands/init.js +12 -3
- package/src/compiler/index.js +128 -73
- package/src/debug.js +15 -0
- package/src/protocols/index.js +140 -128
- package/src/protocols/substreams/manifest.graphql +45 -0
- package/src/protocols/substreams/scaffold/manifest.js +13 -0
- package/src/protocols/substreams/subgraph.js +17 -0
- package/src/scaffold/index.js +7 -2
- package/src/subgraph.js +14 -3
package/package.json
CHANGED
|
@@ -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
|
package/src/commands/build.js
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
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
|
package/src/commands/codegen.js
CHANGED
|
@@ -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 !== ''
|
package/src/commands/init.js
CHANGED
|
@@ -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
|
-
|
|
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()
|
|
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 => {
|
package/src/compiler/index.js
CHANGED
|
@@ -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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
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
|
package/src/protocols/index.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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',
|
|
78
|
-
'juno-1',
|
|
79
|
-
'uni-3'
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
|
165
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,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
|
+
}
|
package/src/scaffold/index.js
CHANGED
|
@@ -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:
|
|
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
|
|