@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphprotocol/graph-cli",
3
- "version": "0.30.4",
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.1.1",
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.2.0",
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
  }
@@ -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')
@@ -22,18 +22,19 @@ ${chalk.bold('graph deploy')} [options] ${chalk.bold('<subgraph-name>')} ${chalk
22
22
 
23
23
  Options:
24
24
 
25
- --product <subgraph-studio|hosted-service>
25
+ --product <subgraph-studio|hosted-service>
26
26
  Selects the product to which to deploy
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
- --debug-fork ID of a remote subgraph whose store will be GraphQL queried
34
- -o, --output-dir <path> Output directory for build results (default: build/)
35
- --skip-migrations Skip subgraph migrations (default: false)
36
- -w, --watch Regenerate types when subgraph files change (default: false)
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,
@@ -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 yaml = require('yaml')
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
+ }
@@ -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',