@graphprotocol/graph-cli 0.30.4 → 0.31.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 +3 -3
- package/src/command-helpers/abi.js +2 -0
- package/src/command-helpers/compiler.js +2 -1
- package/src/command-helpers/network.js +13 -1
- package/src/commands/add.js +18 -10
- package/src/commands/deploy.js +24 -11
- package/src/commands/init.js +88 -9
- package/src/protocols/index.js +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphprotocol/graph-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"license": "(Apache-2.0 OR MIT)",
|
|
5
5
|
"description": "CLI for building for and deploying to The Graph",
|
|
6
6
|
"dependencies": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"binary-install-raw": "0.0.13",
|
|
9
9
|
"chalk": "3.0.0",
|
|
10
10
|
"chokidar": "3.5.1",
|
|
11
|
-
"debug": "4.
|
|
11
|
+
"debug": "4.3.1",
|
|
12
12
|
"docker-compose": "0.23.4",
|
|
13
13
|
"dockerode": "2.5.8",
|
|
14
14
|
"fs-extra": "9.0.0",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"graphql": "15.5.0",
|
|
18
18
|
"immutable": "3.8.2",
|
|
19
19
|
"ipfs-http-client": "34.0.0",
|
|
20
|
-
"jayson": "3.
|
|
20
|
+
"jayson": "3.6.6",
|
|
21
21
|
"js-yaml": "3.13.1",
|
|
22
22
|
"node-fetch": "2.6.0",
|
|
23
23
|
"pkginfo": "0.4.1",
|
|
@@ -60,6 +60,8 @@ const getEtherscanLikeAPIUrl = (network) => {
|
|
|
60
60
|
case "aurora-testnet": return `https://api-testnet.aurorascan.dev/api`
|
|
61
61
|
case "optimism-kovan": return `https://api-kovan-optimistic.etherscan.io/api`
|
|
62
62
|
case "optimism": return `https://api-optimistic.etherscan.io/api`
|
|
63
|
+
case "avalanche": return `https://api.snowtrace.io/api`;
|
|
64
|
+
case "fuji": return `https://api-testnet.snowtrace.io/api`;
|
|
63
65
|
default: return `https://api-${network}.etherscan.io/api`
|
|
64
66
|
}
|
|
65
67
|
}
|
|
@@ -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, 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
|
|
@@ -25,6 +25,7 @@ The IPFS URL must be of the following format: http(s)://host[:port]/[path]`)
|
|
|
25
25
|
host: url.hostname,
|
|
26
26
|
port: url.port,
|
|
27
27
|
'api-path': url.pathname.replace(/\/$/, '') + '/api/v0/',
|
|
28
|
+
headers,
|
|
28
29
|
})
|
|
29
30
|
: undefined
|
|
30
31
|
|
|
@@ -107,7 +107,19 @@ function hasChanges(identifierName, network, networkConfig, dataSource) {
|
|
|
107
107
|
return networkChanged || addressChanged || startBlockChanged
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
const updateNetworksFile = async (toolbox, network, dataSource, address, networksFile) => {
|
|
111
|
+
await toolbox.patching.update(networksFile, (config) => {
|
|
112
|
+
if(Object.keys(config).includes(network)) {
|
|
113
|
+
Object.assign(config[network], { [dataSource]: { address } })
|
|
114
|
+
} else {
|
|
115
|
+
Object.assign(config, { [network]: { [dataSource]: { address } }})
|
|
116
|
+
}
|
|
117
|
+
return config
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
110
121
|
module.exports = {
|
|
111
122
|
updateSubgraphNetwork,
|
|
112
|
-
initNetworksConfig
|
|
123
|
+
initNetworksConfig,
|
|
124
|
+
updateNetworksFile
|
|
113
125
|
}
|
package/src/commands/add.js
CHANGED
|
@@ -9,6 +9,7 @@ const { generateDataSource, writeABI, writeSchema, writeMapping } = require('../
|
|
|
9
9
|
const { loadAbiFromEtherscan, loadAbiFromBlockScout } = require('../command-helpers/abi')
|
|
10
10
|
const EthereumABI = require('../protocols/ethereum/abi')
|
|
11
11
|
const { fixParameters } = require('../command-helpers/gluegun')
|
|
12
|
+
const { updateNetworksFile } = require('../command-helpers/network')
|
|
12
13
|
|
|
13
14
|
const HELP = `
|
|
14
15
|
${chalk.bold('graph add')} <address> [<subgraph-manifest default: "./subgraph.yaml">]
|
|
@@ -18,6 +19,7 @@ ${chalk.dim('Options:')}
|
|
|
18
19
|
--abi <path> Path to the contract ABI (default: download from Etherscan)
|
|
19
20
|
--contract-name Name of the contract (default: Contract)
|
|
20
21
|
--merge-entities Whether to merge entities with the same name (default: false)
|
|
22
|
+
--network-file <path> Networks file (default: "./networks.json")
|
|
21
23
|
-h, --help Show usage information
|
|
22
24
|
`
|
|
23
25
|
|
|
@@ -33,20 +35,12 @@ module.exports = {
|
|
|
33
35
|
contractName,
|
|
34
36
|
h,
|
|
35
37
|
help,
|
|
36
|
-
mergeEntities
|
|
38
|
+
mergeEntities,
|
|
39
|
+
networkFile
|
|
37
40
|
} = toolbox.parameters.options
|
|
38
41
|
|
|
39
|
-
let address = toolbox.parameters.first
|
|
40
|
-
let manifestPath = toolbox.parameters.second || './subgraph.yaml'
|
|
41
42
|
contractName = contractName || 'Contract'
|
|
42
43
|
|
|
43
|
-
// Validate the address
|
|
44
|
-
if (!address) {
|
|
45
|
-
print.error('No contract address provided')
|
|
46
|
-
process.exitCode = 1
|
|
47
|
-
return
|
|
48
|
-
}
|
|
49
|
-
|
|
50
44
|
try {
|
|
51
45
|
fixParameters(toolbox.parameters, {
|
|
52
46
|
h,
|
|
@@ -59,12 +53,22 @@ module.exports = {
|
|
|
59
53
|
return
|
|
60
54
|
}
|
|
61
55
|
|
|
56
|
+
let address = toolbox.parameters.first || toolbox.parameters.array[0]
|
|
57
|
+
let manifestPath = toolbox.parameters.second || toolbox.parameters.array[1] || './subgraph.yaml'
|
|
58
|
+
|
|
62
59
|
// Show help text if requested
|
|
63
60
|
if (help || h) {
|
|
64
61
|
print.info(HELP)
|
|
65
62
|
return
|
|
66
63
|
}
|
|
67
64
|
|
|
65
|
+
// Validate the address
|
|
66
|
+
if (!address) {
|
|
67
|
+
print.error('No contract address provided')
|
|
68
|
+
process.exitCode = 1
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
68
72
|
const dataSourcesAndTemplates = await DataSourcesExtractor.fromFilePath(manifestPath)
|
|
69
73
|
let protocol = Protocol.fromDataSources(dataSourcesAndTemplates)
|
|
70
74
|
let manifest = await Subgraph.load(manifestPath, { protocol })
|
|
@@ -120,6 +124,10 @@ module.exports = {
|
|
|
120
124
|
|
|
121
125
|
await Subgraph.write(result, manifestPath)
|
|
122
126
|
|
|
127
|
+
// Update networks.json
|
|
128
|
+
const networksFile = networkFile || "./networks.json"
|
|
129
|
+
await updateNetworksFile(toolbox, network, contractName, address, networksFile)
|
|
130
|
+
|
|
123
131
|
// Detect Yarn and/or NPM
|
|
124
132
|
let yarn = await system.which('yarn')
|
|
125
133
|
let npm = await system.which('npm')
|
package/src/commands/deploy.js
CHANGED
|
@@ -22,18 +22,19 @@ ${chalk.bold('graph deploy')} [options] ${chalk.bold('<subgraph-name>')} ${chalk
|
|
|
22
22
|
|
|
23
23
|
Options:
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
--product <subgraph-studio|hosted-service>
|
|
26
26
|
Selects the product to which to deploy
|
|
27
|
-
|
|
28
|
-
-g,
|
|
29
|
-
|
|
30
|
-
-l
|
|
31
|
-
-h,
|
|
32
|
-
-i,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
--studio Shortcut for --product subgraph-studio
|
|
28
|
+
-g, --node <node> Graph node to which to deploy
|
|
29
|
+
--deploy-key <key> User deploy key
|
|
30
|
+
-l --version-label <label> Version label used for the deployment
|
|
31
|
+
-h, --help Show usage information
|
|
32
|
+
-i, --ipfs <node> Upload build results to an IPFS node (default: ${DEFAULT_IPFS_URL})
|
|
33
|
+
-hdr, --headers <map> Add custom headers that will be used by the IPFS HTTP client (default: {})
|
|
34
|
+
--debug-fork ID of a remote subgraph whose store will be GraphQL queried
|
|
35
|
+
-o, --output-dir <path> Output directory for build results (default: build/)
|
|
36
|
+
--skip-migrations Skip subgraph migrations (default: false)
|
|
37
|
+
-w, --watch Regenerate types when subgraph files change (default: false)
|
|
37
38
|
`
|
|
38
39
|
|
|
39
40
|
const processForm = async (
|
|
@@ -91,6 +92,8 @@ module.exports = {
|
|
|
91
92
|
i,
|
|
92
93
|
help,
|
|
93
94
|
ipfs,
|
|
95
|
+
headers,
|
|
96
|
+
hdr,
|
|
94
97
|
node,
|
|
95
98
|
o,
|
|
96
99
|
outputDir,
|
|
@@ -103,11 +106,20 @@ module.exports = {
|
|
|
103
106
|
// Support both long and short option variants
|
|
104
107
|
help = help || h
|
|
105
108
|
ipfs = ipfs || i || DEFAULT_IPFS_URL
|
|
109
|
+
headers = headers || hdr || "{}"
|
|
106
110
|
node = node || g
|
|
107
111
|
outputDir = outputDir || o
|
|
108
112
|
watch = watch || w
|
|
109
113
|
versionLabel = versionLabel || l
|
|
110
114
|
|
|
115
|
+
try {
|
|
116
|
+
headers = JSON.parse(headers)
|
|
117
|
+
} catch (e) {
|
|
118
|
+
print.error("Please make sure headers is a valid JSON value")
|
|
119
|
+
process.exitCode = 1
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
|
|
111
123
|
let subgraphName, manifest
|
|
112
124
|
try {
|
|
113
125
|
;[subgraphName, manifest] = fixParameters(toolbox.parameters, {
|
|
@@ -216,6 +228,7 @@ module.exports = {
|
|
|
216
228
|
|
|
217
229
|
let compiler = createCompiler(manifest, {
|
|
218
230
|
ipfs,
|
|
231
|
+
headers,
|
|
219
232
|
outputDir,
|
|
220
233
|
outputFormat: 'wasm',
|
|
221
234
|
skipMigrations,
|
package/src/commands/init.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
const chalk = require('chalk')
|
|
2
|
-
const fetch = require('node-fetch')
|
|
3
|
-
const immutable = require('immutable')
|
|
4
2
|
const os = require('os')
|
|
5
3
|
const path = require('path')
|
|
6
4
|
const toolbox = require('gluegun/toolbox')
|
|
7
|
-
const
|
|
5
|
+
const fs = require('fs')
|
|
6
|
+
const graphCli = require('../cli')
|
|
8
7
|
|
|
9
8
|
const {
|
|
10
9
|
getSubgraphBasename,
|
|
@@ -423,9 +422,9 @@ module.exports = {
|
|
|
423
422
|
contractName,
|
|
424
423
|
node,
|
|
425
424
|
studio,
|
|
426
|
-
product
|
|
425
|
+
product
|
|
427
426
|
},
|
|
428
|
-
{ commands },
|
|
427
|
+
{ commands, addContract: false },
|
|
429
428
|
)
|
|
430
429
|
}
|
|
431
430
|
|
|
@@ -484,9 +483,9 @@ module.exports = {
|
|
|
484
483
|
contractName: inputs.contractName,
|
|
485
484
|
node,
|
|
486
485
|
studio: inputs.studio,
|
|
487
|
-
product: inputs.product
|
|
486
|
+
product: inputs.product
|
|
488
487
|
},
|
|
489
|
-
{ commands },
|
|
488
|
+
{ commands, addContract: true },
|
|
490
489
|
)
|
|
491
490
|
}
|
|
492
491
|
},
|
|
@@ -720,9 +719,9 @@ const initSubgraphFromContract = async (
|
|
|
720
719
|
contractName,
|
|
721
720
|
node,
|
|
722
721
|
studio,
|
|
723
|
-
product
|
|
722
|
+
product
|
|
724
723
|
},
|
|
725
|
-
{ commands },
|
|
724
|
+
{ commands, addContract },
|
|
726
725
|
) => {
|
|
727
726
|
let { print } = toolbox
|
|
728
727
|
|
|
@@ -815,5 +814,85 @@ const initSubgraphFromContract = async (
|
|
|
815
814
|
return
|
|
816
815
|
}
|
|
817
816
|
|
|
817
|
+
while (addContract) {
|
|
818
|
+
addContract = await addAnotherContract(toolbox, { protocolInstance, directory })
|
|
819
|
+
}
|
|
820
|
+
|
|
818
821
|
printNextSteps(toolbox, { subgraphName, directory }, { commands })
|
|
819
822
|
}
|
|
823
|
+
|
|
824
|
+
const addAnotherContract = async (toolbox, { protocolInstance, directory }) => {
|
|
825
|
+
const addContractConfirmation = await toolbox.prompt.confirm('Add another contract?')
|
|
826
|
+
|
|
827
|
+
if (addContractConfirmation) {
|
|
828
|
+
let abiFromFile
|
|
829
|
+
let ProtocolContract = protocolInstance.getContract()
|
|
830
|
+
|
|
831
|
+
let questions = [
|
|
832
|
+
{
|
|
833
|
+
type: 'input',
|
|
834
|
+
name: 'contract',
|
|
835
|
+
message: () => `Contract ${ProtocolContract.identifierName()}`,
|
|
836
|
+
validate: async (value) => {
|
|
837
|
+
// Validate whether the contract is valid
|
|
838
|
+
const { valid, error } = validateContract(value, ProtocolContract)
|
|
839
|
+
return valid ? true : error
|
|
840
|
+
},
|
|
841
|
+
},
|
|
842
|
+
{
|
|
843
|
+
type: 'select',
|
|
844
|
+
name: 'localAbi',
|
|
845
|
+
message: 'Provide local ABI path?',
|
|
846
|
+
choices: ['yes', 'no'],
|
|
847
|
+
result: (value) => {
|
|
848
|
+
abiFromFile = value === 'yes' ? true : false
|
|
849
|
+
return abiFromFile
|
|
850
|
+
},
|
|
851
|
+
},
|
|
852
|
+
{
|
|
853
|
+
type: 'input',
|
|
854
|
+
name: 'abi',
|
|
855
|
+
message: 'ABI file (path)',
|
|
856
|
+
skip: () => abiFromFile === false
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
type: 'input',
|
|
860
|
+
name: 'contractName',
|
|
861
|
+
message: 'Contract Name',
|
|
862
|
+
initial: 'Contract',
|
|
863
|
+
validate: (value) => value && value.length > 0,
|
|
864
|
+
},
|
|
865
|
+
]
|
|
866
|
+
|
|
867
|
+
// Get the cwd before process.chdir in order to switch back in the end of command execution
|
|
868
|
+
const cwd = process.cwd();
|
|
869
|
+
|
|
870
|
+
try {
|
|
871
|
+
let { abi, contract, contractName } = await toolbox.prompt.ask(questions)
|
|
872
|
+
|
|
873
|
+
if (fs.existsSync(directory)) {
|
|
874
|
+
process.chdir(directory)
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
let commandLine = ['add', contract, '--contract-name', contractName]
|
|
878
|
+
|
|
879
|
+
if (abiFromFile) {
|
|
880
|
+
if (abi.includes(directory)) {
|
|
881
|
+
commandLine.push('--abi', path.normalize(abi.replace(directory, '')))
|
|
882
|
+
} else {
|
|
883
|
+
commandLine.push('--abi', abi)
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
await graphCli.run(commandLine)
|
|
888
|
+
} catch (e) {
|
|
889
|
+
toolbox.print.error(e)
|
|
890
|
+
process.exit(1)
|
|
891
|
+
}
|
|
892
|
+
finally {
|
|
893
|
+
process.chdir(cwd)
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
return addContractConfirmation
|
|
898
|
+
}
|
package/src/protocols/index.js
CHANGED
|
@@ -52,6 +52,7 @@ module.exports = class Protocol {
|
|
|
52
52
|
'matic',
|
|
53
53
|
'mumbai',
|
|
54
54
|
'fantom',
|
|
55
|
+
'fantom-testnet',
|
|
55
56
|
'bsc',
|
|
56
57
|
'chapel',
|
|
57
58
|
'clover',
|
|
@@ -60,6 +61,8 @@ module.exports = class Protocol {
|
|
|
60
61
|
'celo',
|
|
61
62
|
'celo-alfajores',
|
|
62
63
|
'fuse',
|
|
64
|
+
'moonbeam',
|
|
65
|
+
'moonriver',
|
|
63
66
|
'mbase',
|
|
64
67
|
'arbitrum-one',
|
|
65
68
|
'arbitrum-rinkeby',
|