@graphprotocol/graph-cli 0.24.0 → 0.25.2
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/examples/basic-event-handlers/package.json +1 -1
- package/examples/basic-event-handlers/yarn.lock +4 -4
- package/examples/example-subgraph/package.json +1 -1
- package/examples/example-subgraph/yarn.lock +4 -4
- package/package.json +2 -2
- package/src/codegen/schema.js +9 -2
- package/src/codegen/types/defaults.js +34 -0
- package/src/codegen/types/index.js +8 -1
- package/src/command-helpers/scaffold.js +66 -0
- package/src/command-helpers/version.js +1 -1
- package/src/command-helpers/version.test.js +1 -1
- package/src/commands/init.js +129 -92
- package/src/commands/test.js +210 -27
- package/src/protocols/ethereum/contract.js +22 -0
- package/src/protocols/ethereum/scaffold/manifest.js +32 -0
- package/src/protocols/ethereum/scaffold/mapping.js +76 -0
- package/src/protocols/ethereum/subgraph.js +0 -14
- package/src/protocols/index.js +94 -12
- package/src/protocols/near/contract.js +46 -0
- package/src/protocols/near/scaffold/manifest.js +16 -0
- package/src/protocols/near/scaffold/mapping.js +39 -0
- package/src/protocols/near/subgraph.js +1 -23
- package/src/{scaffold.test.js → scaffold/ethereum.test.js} +27 -19
- package/src/scaffold/index.js +149 -0
- package/src/scaffold/mapping.js +49 -0
- package/src/scaffold/near.test.js +89 -0
- package/src/scaffold/schema.js +62 -0
- package/src/subgraph.js +8 -0
- package/src/validation/contract.js +56 -0
- package/src/validation/index.js +2 -1
- package/src/validation/manifest.js +0 -29
- package/tests/cli/init/{abis → ethereum/abis}/Marketplace.json +0 -0
- package/tests/cli/init/{abis → ethereum/abis}/OverloadedElements.json +0 -0
- package/tests/cli/init/{abis → ethereum/abis}/SoloMargin.json +0 -0
- package/tests/cli/init/{from-contract-with-abi-and-structs.stderr → ethereum/from-contract-with-abi-and-structs.stderr} +1 -1
- package/tests/cli/init/{from-contract-with-abi-and-structs.stdout → ethereum/from-contract-with-abi-and-structs.stdout} +0 -0
- package/tests/cli/init/{from-contract-with-abi.stderr → ethereum/from-contract-with-abi.stderr} +1 -1
- package/tests/cli/init/{from-contract-with-abi.stdout → ethereum/from-contract-with-abi.stdout} +0 -0
- package/tests/cli/init/{from-contract-with-overloaded-elements.stderr → ethereum/from-contract-with-overloaded-elements.stderr} +1 -1
- package/tests/cli/init/{from-contract-with-overloaded-elements.stdout → ethereum/from-contract-with-overloaded-elements.stdout} +0 -0
- package/tests/cli/init/{from-contract.stderr → ethereum/from-contract.stderr} +1 -1
- package/tests/cli/init/{from-contract.stdout → ethereum/from-contract.stdout} +0 -0
- package/tests/cli/init/{from-example.stderr → ethereum/from-example.stderr} +0 -0
- package/tests/cli/init/{from-example.stdout → ethereum/from-example.stdout} +0 -0
- package/tests/cli/init/near/from-contract.stderr +12 -0
- package/tests/cli/init/near/from-contract.stdout +12 -0
- package/tests/cli/init.test.js +143 -112
- package/tests/cli/util.js +56 -41
- package/tests/cli/validation/near-is-valid/subgraph.yaml +1 -0
- package/src/scaffold.js +0 -364
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"deploy-test": "../../bin/graph deploy test/basic-event-handlers --version-label v0.0.1 --ipfs http://localhost:15001 --node http://127.0.0.1:18020"
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@graphprotocol/graph-ts": "0.24.
|
|
12
|
+
"@graphprotocol/graph-ts": "0.24.1",
|
|
13
13
|
"apollo-fetch": "^0.7.0"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
# yarn lockfile v1
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
"@graphprotocol/graph-ts@0.24.
|
|
6
|
-
version "0.24.
|
|
7
|
-
resolved "https://registry.yarnpkg.com/@graphprotocol/graph-ts/-/graph-ts-0.24.
|
|
8
|
-
integrity sha512-
|
|
5
|
+
"@graphprotocol/graph-ts@0.24.1":
|
|
6
|
+
version "0.24.1"
|
|
7
|
+
resolved "https://registry.yarnpkg.com/@graphprotocol/graph-ts/-/graph-ts-0.24.1.tgz#50961b52b5383f9c5cf5e6e23fa039f24e729ddf"
|
|
8
|
+
integrity sha512-2vU4m5ZPQIqMlMce/z5vmOtGHRlRmcRhMfemS3NIwxCSxSBGVnX2zb7QBTzzdQKGwsAZdbz6V0okkOtvohELfQ==
|
|
9
9
|
dependencies:
|
|
10
10
|
assemblyscript "0.19.10"
|
|
11
11
|
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
# yarn lockfile v1
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
"@graphprotocol/graph-ts@0.24.
|
|
6
|
-
version "0.24.
|
|
7
|
-
resolved "https://registry.yarnpkg.com/@graphprotocol/graph-ts/-/graph-ts-0.24.
|
|
8
|
-
integrity sha512-
|
|
5
|
+
"@graphprotocol/graph-ts@0.24.1":
|
|
6
|
+
version "0.24.1"
|
|
7
|
+
resolved "https://registry.yarnpkg.com/@graphprotocol/graph-ts/-/graph-ts-0.24.1.tgz#50961b52b5383f9c5cf5e6e23fa039f24e729ddf"
|
|
8
|
+
integrity sha512-2vU4m5ZPQIqMlMce/z5vmOtGHRlRmcRhMfemS3NIwxCSxSBGVnX2zb7QBTzzdQKGwsAZdbz6V0okkOtvohELfQ==
|
|
9
9
|
dependencies:
|
|
10
10
|
assemblyscript "0.19.10"
|
|
11
11
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphprotocol/graph-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.2",
|
|
4
4
|
"description": "CLI for building for and deploying to The Graph",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"assemblyscript": "0.19.10",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"dockerode": "^2.5.8",
|
|
13
13
|
"fs-extra": "^9.0.0",
|
|
14
14
|
"glob": "^7.1.2",
|
|
15
|
-
"gluegun": "
|
|
15
|
+
"gluegun": "https://github.com/edgeandnode/gluegun#v4.3.1-pin-colors-dep",
|
|
16
16
|
"graphql": "^15.5.0",
|
|
17
17
|
"immutable": "^3.8.2",
|
|
18
18
|
"ipfs-http-client": "^34.0.0",
|
package/src/codegen/schema.js
CHANGED
|
@@ -80,17 +80,24 @@ module.exports = class SchemaCodeGenerator {
|
|
|
80
80
|
.map(field => {
|
|
81
81
|
const name = field.getIn(['name', 'value'])
|
|
82
82
|
const type = this._typeFromGraphQl(field.get('type'))
|
|
83
|
+
|
|
83
84
|
const isNullable = type instanceof tsCodegen.NullableType
|
|
85
|
+
const isPrimitive = type.isPrimitive && type.isPrimitive()
|
|
84
86
|
|
|
85
87
|
const directives = field.get('directives')
|
|
86
88
|
const isDerivedFrom = directives.some(directive => directive.getIn(['name', 'value']) === 'derivedFrom')
|
|
87
89
|
|
|
88
|
-
return { name, type, isNullable, isDerivedFrom }
|
|
90
|
+
return { name, type, isNullable, isPrimitive, isDerivedFrom }
|
|
89
91
|
})
|
|
90
92
|
// We only call the setter with the default value in the constructor for fields that are:
|
|
93
|
+
// - Not primitive (such as Int/i32)
|
|
91
94
|
// - Not nullable, so that AS doesn't break when subgraph developers try to access them before a `set`
|
|
92
95
|
// - Not tagged as `derivedFrom`, because they only exist in query time
|
|
93
|
-
.filter(({
|
|
96
|
+
.filter(({
|
|
97
|
+
isNullable,
|
|
98
|
+
isPrimitive,
|
|
99
|
+
isDerivedFrom,
|
|
100
|
+
}) => !(isNullable || isPrimitive || isDerivedFrom))
|
|
94
101
|
.map(({ name, type, isNullable }) => {
|
|
95
102
|
const fieldTypeString = isNullable ? type.inner.toString() : type.toString()
|
|
96
103
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const immutable = require('immutable')
|
|
2
|
+
|
|
3
|
+
// TODO: kill me
|
|
4
|
+
const EMPTY_ARRAY = 'new Array(0)'
|
|
5
|
+
|
|
6
|
+
const ASC_DEFAULTS = [
|
|
7
|
+
// Scalar values
|
|
8
|
+
|
|
9
|
+
['Address', 'Address.zero()'],
|
|
10
|
+
['Bytes', 'Bytes.empty()'],
|
|
11
|
+
['boolean', 'false'],
|
|
12
|
+
['i32', '0'],
|
|
13
|
+
['string', '""'],
|
|
14
|
+
['BigInt', 'BigInt.zero()'],
|
|
15
|
+
['BigDecimal', 'BigDecimal.zero()'],
|
|
16
|
+
|
|
17
|
+
// Arrays
|
|
18
|
+
|
|
19
|
+
['Array<Address>', EMPTY_ARRAY],
|
|
20
|
+
['Array<Bytes>', EMPTY_ARRAY],
|
|
21
|
+
['Array<boolean>', EMPTY_ARRAY],
|
|
22
|
+
['Array<i32>', EMPTY_ARRAY],
|
|
23
|
+
['Array<string>', EMPTY_ARRAY],
|
|
24
|
+
['Array<BigInt>', EMPTY_ARRAY],
|
|
25
|
+
['Array<BigDecimal>', EMPTY_ARRAY],
|
|
26
|
+
['Array<string | null>', EMPTY_ARRAY],
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
module.exports = immutable.fromJS({
|
|
30
|
+
AssemblyScript: ASC_DEFAULTS,
|
|
31
|
+
})
|
|
32
|
+
// TODO: use me:
|
|
33
|
+
// [/Array<.*>/, 'new Array(0)'],
|
|
34
|
+
// [/Array\<.*\>/, 'new Array(0)'],
|
|
@@ -89,8 +89,12 @@ const findInitializationForType = (fromTypeSystem, toTypeSystem, ascType) => {
|
|
|
89
89
|
|
|
90
90
|
// High-level type system API
|
|
91
91
|
|
|
92
|
+
const ascTypeForProtocol = (protocol, protocolType) =>
|
|
93
|
+
findConversionFromType(protocol, 'AssemblyScript', protocolType).getIn(['to', 'type'])
|
|
94
|
+
|
|
95
|
+
// TODO: this can be removed/replaced by the function above
|
|
92
96
|
const ascTypeForEthereum = ethereumType =>
|
|
93
|
-
|
|
97
|
+
ascTypeForProtocol('ethereum', ethereumType)
|
|
94
98
|
|
|
95
99
|
const ethereumTypeForAsc = ascType =>
|
|
96
100
|
findConversionFromType('AssemblyScript', 'ethereum', ascType).getIn(['to', 'type'])
|
|
@@ -120,6 +124,9 @@ const initializedValueFromAsc = ascType =>
|
|
|
120
124
|
findInitializationForType('AssemblyScript', 'Value', ascType)
|
|
121
125
|
|
|
122
126
|
module.exports = {
|
|
127
|
+
// protocol <-> AssemblyScript
|
|
128
|
+
ascTypeForProtocol,
|
|
129
|
+
|
|
123
130
|
// ethereum <-> AssemblyScript
|
|
124
131
|
ascTypeForEthereum,
|
|
125
132
|
ethereumTypeForAsc,
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const fs = require('fs-extra')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
|
|
4
|
+
const { step } = require('./spinner')
|
|
5
|
+
const Scaffold = require('../scaffold')
|
|
6
|
+
|
|
7
|
+
const generateScaffold = async (
|
|
8
|
+
{
|
|
9
|
+
protocolInstance,
|
|
10
|
+
abi,
|
|
11
|
+
contract,
|
|
12
|
+
network,
|
|
13
|
+
subgraphName,
|
|
14
|
+
indexEvents,
|
|
15
|
+
contractName = 'Contract',
|
|
16
|
+
node,
|
|
17
|
+
},
|
|
18
|
+
spinner,
|
|
19
|
+
) => {
|
|
20
|
+
step(spinner, 'Generate subgraph')
|
|
21
|
+
|
|
22
|
+
const scaffold = new Scaffold({
|
|
23
|
+
protocol: protocolInstance,
|
|
24
|
+
abi,
|
|
25
|
+
indexEvents,
|
|
26
|
+
contract,
|
|
27
|
+
network,
|
|
28
|
+
contractName,
|
|
29
|
+
subgraphName,
|
|
30
|
+
node,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
return scaffold.generate()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const writeScaffoldDirectory = async (scaffold, directory, spinner) => {
|
|
37
|
+
// Create directory itself
|
|
38
|
+
await fs.mkdirs(directory)
|
|
39
|
+
|
|
40
|
+
let promises = Object.keys(scaffold).map(async basename => {
|
|
41
|
+
let content = scaffold[basename]
|
|
42
|
+
let filename = path.join(directory, basename)
|
|
43
|
+
|
|
44
|
+
// Write file or recurse into subdirectory
|
|
45
|
+
if (typeof content === 'string') {
|
|
46
|
+
await fs.writeFile(filename, content, { encoding: 'utf-8' })
|
|
47
|
+
} else if (content == null) {
|
|
48
|
+
return // continue loop
|
|
49
|
+
} else {
|
|
50
|
+
writeScaffoldDirectory(content, path.join(directory, basename), spinner)
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
await Promise.all(promises)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const writeScaffold = async (scaffold, directory, spinner) => {
|
|
58
|
+
step(spinner, `Write subgraph to directory`)
|
|
59
|
+
await writeScaffoldDirectory(scaffold, directory, spinner)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = {
|
|
63
|
+
...module.exports,
|
|
64
|
+
generateScaffold,
|
|
65
|
+
writeScaffold,
|
|
66
|
+
}
|
|
@@ -57,7 +57,7 @@ const assertGraphTsVersion = async (sourceDir, minimumGraphTsVersion) => {
|
|
|
57
57
|
if (graphTsVersion && semver.lt(semver.coerce(graphTsVersion), minimumGraphTsVersion)) {
|
|
58
58
|
throw new Error(
|
|
59
59
|
`To use this version of the graph-cli you must upgrade the graph-ts dependency to a version greater than or equal to ${minimumGraphTsVersion}
|
|
60
|
-
Also, you'll probably need to take a look at our AssemblyScript migration guide because of language breaking changes: https://
|
|
60
|
+
Also, you'll probably need to take a look at our AssemblyScript migration guide because of language breaking changes: https://thegraph.com/docs/developer/assemblyscript-migration-guide`
|
|
61
61
|
)
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -197,7 +197,7 @@ describe('Version Command Helpers', () => {
|
|
|
197
197
|
.rejects
|
|
198
198
|
.toThrow(new Error(
|
|
199
199
|
`To use this version of the graph-cli you must upgrade the graph-ts dependency to a version greater than or equal to ${minimumGraphTsVersion}
|
|
200
|
-
Also, you'll probably need to take a look at our AssemblyScript migration guide because of language breaking changes: https://
|
|
200
|
+
Also, you'll probably need to take a look at our AssemblyScript migration guide because of language breaking changes: https://thegraph.com/docs/developer/assemblyscript-migration-guide`
|
|
201
201
|
))
|
|
202
202
|
})
|
|
203
203
|
test('When the installed graph-ts version is a supported one', async () => {
|
package/src/commands/init.js
CHANGED
|
@@ -14,98 +14,107 @@ const { validateStudioNetwork } = require('../command-helpers/studio')
|
|
|
14
14
|
const { withSpinner, step } = require('../command-helpers/spinner')
|
|
15
15
|
const { fixParameters } = require('../command-helpers/gluegun')
|
|
16
16
|
const { chooseNodeUrl } = require('../command-helpers/node')
|
|
17
|
-
const {
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
'rinkeby',
|
|
25
|
-
'ropsten',
|
|
26
|
-
'goerli',
|
|
27
|
-
'poa-core',
|
|
28
|
-
'poa-sokol',
|
|
29
|
-
'xdai',
|
|
30
|
-
'matic',
|
|
31
|
-
'mumbai',
|
|
32
|
-
'fantom',
|
|
33
|
-
'bsc',
|
|
34
|
-
'chapel',
|
|
35
|
-
'clover',
|
|
36
|
-
'avalanche',
|
|
37
|
-
'fuji',
|
|
38
|
-
'celo',
|
|
39
|
-
'celo-alfajores',
|
|
40
|
-
'fuse',
|
|
41
|
-
'mbase',
|
|
42
|
-
'arbitrum-one',
|
|
43
|
-
'arbitrum-rinkeby',
|
|
44
|
-
'optimism',
|
|
45
|
-
'optimism-kovan'
|
|
46
|
-
]
|
|
17
|
+
const { generateScaffold, writeScaffold } = require('../command-helpers/scaffold')
|
|
18
|
+
const { abiEvents } = require('../scaffold/schema')
|
|
19
|
+
const { validateContract } = require('../validation')
|
|
20
|
+
const Protocol = require('../protocols')
|
|
21
|
+
|
|
22
|
+
const protocolChoices = Array.from(Protocol.availableProtocols().keys())
|
|
23
|
+
const availableNetworks = Protocol.availableNetworks()
|
|
47
24
|
|
|
48
25
|
const HELP = `
|
|
49
26
|
${chalk.bold('graph init')} [options] [subgraph-name] [directory]
|
|
50
27
|
|
|
51
28
|
${chalk.dim('Options:')}
|
|
52
29
|
|
|
30
|
+
--protocol <${protocolChoices.join('|')}>
|
|
53
31
|
--product <subgraph-studio|hosted-service>
|
|
54
|
-
|
|
55
|
-
--studio
|
|
56
|
-
-g, --node <node>
|
|
57
|
-
--allow-simple-name
|
|
58
|
-
-h, --help
|
|
32
|
+
Selects the product for which to initialize
|
|
33
|
+
--studio Shortcut for --product subgraph-studio
|
|
34
|
+
-g, --node <node> Graph node for which to initialize
|
|
35
|
+
--allow-simple-name Use a subgraph name without a prefix (default: false)
|
|
36
|
+
-h, --help Show usage information
|
|
59
37
|
|
|
60
38
|
${chalk.dim('Choose mode with one of:')}
|
|
61
39
|
|
|
62
|
-
--from-contract <
|
|
63
|
-
--from-example
|
|
40
|
+
--from-contract <contract> Creates a scaffold based on an existing contract
|
|
41
|
+
--from-example Creates a scaffold based on an example subgraph
|
|
64
42
|
|
|
65
43
|
${chalk.dim('Options for --from-contract:')}
|
|
66
44
|
|
|
67
|
-
--
|
|
68
|
-
--
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
45
|
+
--contract-name Name of the contract (default: Contract)
|
|
46
|
+
--index-events Index contract events as entities
|
|
47
|
+
|
|
48
|
+
${chalk.dim.underline('Ethereum:')}
|
|
49
|
+
|
|
50
|
+
--abi <path> Path to the contract ABI (default: download from Etherscan)
|
|
51
|
+
--network <${availableNetworks.get('ethereum').join('|')}>
|
|
52
|
+
Selects the network the contract is deployed to
|
|
53
|
+
|
|
54
|
+
${chalk.dim.underline('NEAR:')}
|
|
55
|
+
|
|
56
|
+
--network <${availableNetworks.get('near').join('|')}>
|
|
57
|
+
Selects the network the contract is deployed to
|
|
72
58
|
`
|
|
73
59
|
|
|
74
60
|
const processInitForm = async (
|
|
75
61
|
toolbox,
|
|
76
62
|
{
|
|
63
|
+
protocol,
|
|
77
64
|
product,
|
|
78
65
|
studio,
|
|
79
66
|
node,
|
|
80
67
|
abi,
|
|
81
68
|
allowSimpleName,
|
|
82
69
|
directory,
|
|
83
|
-
|
|
70
|
+
contract,
|
|
84
71
|
fromExample,
|
|
85
72
|
network,
|
|
86
73
|
subgraphName,
|
|
87
74
|
contractName
|
|
88
75
|
},
|
|
89
76
|
) => {
|
|
90
|
-
let addressPattern = /^(0x)?[0-9a-fA-F]{40}$/
|
|
91
|
-
|
|
92
77
|
let abiFromEtherscan = undefined
|
|
93
78
|
let abiFromFile = undefined
|
|
79
|
+
let protocolInstance
|
|
80
|
+
let ProtocolContract
|
|
81
|
+
let ABI
|
|
94
82
|
|
|
95
83
|
let questions = [
|
|
84
|
+
{
|
|
85
|
+
type: 'select',
|
|
86
|
+
name: 'protocol',
|
|
87
|
+
message: 'Protocol',
|
|
88
|
+
choices: protocolChoices,
|
|
89
|
+
skip: protocolChoices.includes(protocol),
|
|
90
|
+
result: value => {
|
|
91
|
+
protocol = protocol || value
|
|
92
|
+
protocolInstance = new Protocol(protocol)
|
|
93
|
+
return protocol
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
96
|
{
|
|
97
97
|
type: 'select',
|
|
98
98
|
name: 'product',
|
|
99
99
|
message: 'Product for which to initialize',
|
|
100
100
|
choices: ['subgraph-studio', 'hosted-service'],
|
|
101
|
-
skip:
|
|
101
|
+
skip: () =>
|
|
102
|
+
protocol === 'near' ||
|
|
102
103
|
product === 'subgraph-studio' ||
|
|
103
104
|
product === 'hosted-service' ||
|
|
104
105
|
studio !== undefined || node !== undefined,
|
|
105
106
|
result: value => {
|
|
107
|
+
// For now we only support NEAR subgraphs in the Hosted Service
|
|
108
|
+
if (protocol === 'near') {
|
|
109
|
+
// Can be overwritten because the question will be skipped (product === undefined)
|
|
110
|
+
product = 'hosted-service'
|
|
111
|
+
return product
|
|
112
|
+
}
|
|
113
|
+
|
|
106
114
|
if (value == 'subgraph-studio') {
|
|
107
115
|
allowSimpleName = true
|
|
108
116
|
}
|
|
117
|
+
|
|
109
118
|
product = value
|
|
110
119
|
return value
|
|
111
120
|
},
|
|
@@ -146,8 +155,11 @@ const processInitForm = async (
|
|
|
146
155
|
{
|
|
147
156
|
type: 'select',
|
|
148
157
|
name: 'network',
|
|
149
|
-
message:
|
|
150
|
-
choices:
|
|
158
|
+
message: () => `${protocolInstance.displayName()} network`,
|
|
159
|
+
choices: () =>
|
|
160
|
+
availableNetworks
|
|
161
|
+
.get(protocol) // Get networks related to the chosen protocol.
|
|
162
|
+
.toArray(), // Needed because of gluegun. It can't even receive a JS iterable.
|
|
151
163
|
skip: fromExample !== undefined,
|
|
152
164
|
initial: network || 'mainnet',
|
|
153
165
|
result: value => {
|
|
@@ -157,35 +169,39 @@ const processInitForm = async (
|
|
|
157
169
|
},
|
|
158
170
|
{
|
|
159
171
|
type: 'input',
|
|
160
|
-
name: '
|
|
161
|
-
message:
|
|
172
|
+
name: 'contract',
|
|
173
|
+
message: () => {
|
|
174
|
+
ProtocolContract = protocolInstance.getContract()
|
|
175
|
+
return `Contract ${ProtocolContract.identifierName()}`
|
|
176
|
+
},
|
|
162
177
|
skip: fromExample !== undefined,
|
|
163
|
-
initial:
|
|
178
|
+
initial: contract,
|
|
164
179
|
validate: async value => {
|
|
165
180
|
if (fromExample !== undefined) {
|
|
166
181
|
return true
|
|
167
182
|
}
|
|
168
183
|
|
|
169
|
-
// Validate whether the
|
|
170
|
-
|
|
171
|
-
return `Contract address "${value}" is invalid.
|
|
172
|
-
Must be 40 hexadecimal characters, with an optional '0x' prefix.`
|
|
173
|
-
}
|
|
184
|
+
// Validate whether the contract is valid
|
|
185
|
+
const { valid, error } = validateContract(value, ProtocolContract)
|
|
174
186
|
|
|
175
|
-
return
|
|
187
|
+
return valid
|
|
188
|
+
? true
|
|
189
|
+
: error
|
|
176
190
|
},
|
|
177
191
|
result: async value => {
|
|
178
192
|
if (fromExample !== undefined) {
|
|
179
193
|
return value
|
|
180
194
|
}
|
|
181
195
|
|
|
196
|
+
ABI = protocolInstance.getABI()
|
|
197
|
+
|
|
182
198
|
// Try loading the ABI from Etherscan, if none was provided
|
|
183
|
-
if (!abi) {
|
|
199
|
+
if (protocolInstance.hasABIs() && !abi) {
|
|
184
200
|
try {
|
|
185
201
|
if (network === 'poa-core') {
|
|
186
|
-
abiFromBlockScout = await loadAbiFromBlockScout(network, value)
|
|
202
|
+
abiFromBlockScout = await loadAbiFromBlockScout(ABI, network, value)
|
|
187
203
|
} else {
|
|
188
|
-
abiFromEtherscan = await loadAbiFromEtherscan(network, value)
|
|
204
|
+
abiFromEtherscan = await loadAbiFromEtherscan(ABI, network, value)
|
|
189
205
|
}
|
|
190
206
|
} catch (e) {}
|
|
191
207
|
}
|
|
@@ -197,14 +213,17 @@ const processInitForm = async (
|
|
|
197
213
|
name: 'abi',
|
|
198
214
|
message: 'ABI file (path)',
|
|
199
215
|
initial: abi,
|
|
200
|
-
skip: () =>
|
|
216
|
+
skip: () =>
|
|
217
|
+
!protocolInstance.hasABIs() ||
|
|
218
|
+
fromExample !== undefined ||
|
|
219
|
+
abiFromEtherscan !== undefined,
|
|
201
220
|
validate: async value => {
|
|
202
|
-
if (fromExample || abiFromEtherscan) {
|
|
221
|
+
if (fromExample || abiFromEtherscan || !protocolInstance.hasABIs()) {
|
|
203
222
|
return true
|
|
204
223
|
}
|
|
205
224
|
|
|
206
225
|
try {
|
|
207
|
-
abiFromFile = await loadAbiFromFile(value)
|
|
226
|
+
abiFromFile = await loadAbiFromFile(ABI, value)
|
|
208
227
|
return true
|
|
209
228
|
} catch (e) {
|
|
210
229
|
return e.message
|
|
@@ -227,13 +246,13 @@ const processInitForm = async (
|
|
|
227
246
|
|
|
228
247
|
try {
|
|
229
248
|
let answers = await toolbox.prompt.ask(questions)
|
|
230
|
-
return { ...answers, abi: abiFromEtherscan || abiFromFile }
|
|
249
|
+
return { ...answers, abi: abiFromEtherscan || abiFromFile, protocolInstance }
|
|
231
250
|
} catch (e) {
|
|
232
251
|
return undefined
|
|
233
252
|
}
|
|
234
253
|
}
|
|
235
254
|
|
|
236
|
-
const loadAbiFromBlockScout = async (network, address) =>
|
|
255
|
+
const loadAbiFromBlockScout = async (ABI, network, address) =>
|
|
237
256
|
await withSpinner(
|
|
238
257
|
`Fetching ABI from BlockScout`,
|
|
239
258
|
`Failed to fetch ABI from BlockScout`,
|
|
@@ -260,6 +279,7 @@ const loadAbiFromBlockScout = async (network, address) =>
|
|
|
260
279
|
const getEtherscanLikeAPIUrl = (network) => {
|
|
261
280
|
switch(network){
|
|
262
281
|
case "mainnet": return `https://api.etherscan.io/api`;
|
|
282
|
+
case "arbitrum-one": return `https://api.arbiscan.io/api`;
|
|
263
283
|
case "bsc": return `https://api.bscscan.com/api`;
|
|
264
284
|
case "matic": return `https://api.polygonscan.com/api`;
|
|
265
285
|
case "mumbai": return `https://api-testnet.polygonscan.com/api`;
|
|
@@ -267,7 +287,7 @@ const getEtherscanLikeAPIUrl = (network) => {
|
|
|
267
287
|
}
|
|
268
288
|
}
|
|
269
289
|
|
|
270
|
-
const loadAbiFromEtherscan = async (network, address) =>
|
|
290
|
+
const loadAbiFromEtherscan = async (ABI, network, address) =>
|
|
271
291
|
await withSpinner(
|
|
272
292
|
`Fetching ABI from Etherscan`,
|
|
273
293
|
`Failed to fetch ABI from Etherscan`,
|
|
@@ -290,7 +310,7 @@ const loadAbiFromEtherscan = async (network, address) =>
|
|
|
290
310
|
},
|
|
291
311
|
)
|
|
292
312
|
|
|
293
|
-
const loadAbiFromFile = async filename => {
|
|
313
|
+
const loadAbiFromFile = async (ABI, filename) => {
|
|
294
314
|
let exists = await toolbox.filesystem.exists(filename)
|
|
295
315
|
|
|
296
316
|
if (!exists) {
|
|
@@ -315,6 +335,7 @@ module.exports = {
|
|
|
315
335
|
|
|
316
336
|
// Read CLI parameters
|
|
317
337
|
let {
|
|
338
|
+
protocol,
|
|
318
339
|
product,
|
|
319
340
|
studio,
|
|
320
341
|
node,
|
|
@@ -400,35 +421,47 @@ module.exports = {
|
|
|
400
421
|
|
|
401
422
|
// If all parameters are provided from the command-line,
|
|
402
423
|
// go straight to creating the subgraph from an existing contract
|
|
403
|
-
if (fromContract && subgraphName && directory && network && node) {
|
|
404
|
-
if (
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
424
|
+
if (fromContract && protocol && subgraphName && directory && network && node) {
|
|
425
|
+
if (!protocolChoices.includes(protocol)) {
|
|
426
|
+
print.error(`Protocol '${protocol}' is not supported, choose from these options: ${protocolChoices.join(', ')}`)
|
|
427
|
+
process.exitCode = 1
|
|
428
|
+
return
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const protocolInstance = new Protocol(protocol)
|
|
432
|
+
|
|
433
|
+
if (protocolInstance.hasABIs()) {
|
|
434
|
+
const ABI = protocolInstance.getABI()
|
|
435
|
+
if (abi) {
|
|
436
|
+
try {
|
|
437
|
+
abi = await loadAbiFromFile(ABI, abi)
|
|
438
|
+
} catch (e) {
|
|
439
|
+
print.error(`Failed to load ABI: ${e.message}`)
|
|
440
|
+
process.exitCode = 1
|
|
441
|
+
return
|
|
442
|
+
}
|
|
443
|
+
} else {
|
|
444
|
+
try {
|
|
445
|
+
if (network === 'poa-core') {
|
|
446
|
+
abi = await loadAbiFromBlockScout(ABI, network, fromContract)
|
|
447
|
+
} else {
|
|
448
|
+
abi = await loadAbiFromEtherscan(ABI, network, fromContract)
|
|
449
|
+
}
|
|
450
|
+
} catch (e) {
|
|
451
|
+
process.exitCode = 1
|
|
452
|
+
return
|
|
418
453
|
}
|
|
419
|
-
} catch (e) {
|
|
420
|
-
process.exitCode = 1
|
|
421
|
-
return
|
|
422
454
|
}
|
|
423
455
|
}
|
|
424
456
|
|
|
425
457
|
return await initSubgraphFromContract(
|
|
426
458
|
toolbox,
|
|
427
459
|
{
|
|
460
|
+
protocolInstance,
|
|
428
461
|
abi,
|
|
429
462
|
allowSimpleName,
|
|
430
463
|
directory,
|
|
431
|
-
|
|
464
|
+
contract: fromContract,
|
|
432
465
|
indexEvents,
|
|
433
466
|
network,
|
|
434
467
|
subgraphName,
|
|
@@ -443,13 +476,14 @@ module.exports = {
|
|
|
443
476
|
|
|
444
477
|
// Otherwise, take the user through the interactive form
|
|
445
478
|
let inputs = await processInitForm(toolbox, {
|
|
479
|
+
protocol,
|
|
446
480
|
product,
|
|
447
481
|
studio,
|
|
448
482
|
node,
|
|
449
483
|
abi,
|
|
450
484
|
allowSimpleName,
|
|
451
485
|
directory,
|
|
452
|
-
|
|
486
|
+
contract: fromContract,
|
|
453
487
|
fromExample,
|
|
454
488
|
network,
|
|
455
489
|
subgraphName,
|
|
@@ -484,12 +518,13 @@ module.exports = {
|
|
|
484
518
|
await initSubgraphFromContract(
|
|
485
519
|
toolbox,
|
|
486
520
|
{
|
|
521
|
+
protocolInstance: inputs.protocolInstance,
|
|
487
522
|
allowSimpleName,
|
|
488
523
|
subgraphName: inputs.subgraphName,
|
|
489
524
|
directory: inputs.directory,
|
|
490
525
|
abi: inputs.abi,
|
|
491
526
|
network: inputs.network,
|
|
492
|
-
|
|
527
|
+
contract: inputs.contract,
|
|
493
528
|
indexEvents,
|
|
494
529
|
contractName: inputs.contractName,
|
|
495
530
|
node,
|
|
@@ -713,12 +748,13 @@ const initSubgraphFromExample = async (
|
|
|
713
748
|
const initSubgraphFromContract = async (
|
|
714
749
|
toolbox,
|
|
715
750
|
{
|
|
751
|
+
protocolInstance,
|
|
716
752
|
allowSimpleName,
|
|
717
753
|
subgraphName,
|
|
718
754
|
directory,
|
|
719
755
|
abi,
|
|
720
756
|
network,
|
|
721
|
-
|
|
757
|
+
contract,
|
|
722
758
|
indexEvents,
|
|
723
759
|
contractName,
|
|
724
760
|
node,
|
|
@@ -742,7 +778,7 @@ const initSubgraphFromContract = async (
|
|
|
742
778
|
return
|
|
743
779
|
}
|
|
744
780
|
|
|
745
|
-
if (abiEvents(abi).length === 0) {
|
|
781
|
+
if (protocolInstance.hasABIs() && abiEvents(abi).length === 0) {
|
|
746
782
|
// Fail if the ABI does not contain any events
|
|
747
783
|
print.error(`ABI does not contain any events`)
|
|
748
784
|
process.exitCode = 1
|
|
@@ -760,7 +796,7 @@ const initSubgraphFromContract = async (
|
|
|
760
796
|
return
|
|
761
797
|
}
|
|
762
798
|
|
|
763
|
-
// Scaffold subgraph
|
|
799
|
+
// Scaffold subgraph
|
|
764
800
|
let scaffold = await withSpinner(
|
|
765
801
|
`Create subgraph scaffold`,
|
|
766
802
|
`Failed to create subgraph scaffold`,
|
|
@@ -768,10 +804,11 @@ const initSubgraphFromContract = async (
|
|
|
768
804
|
async spinner => {
|
|
769
805
|
let scaffold = await generateScaffold(
|
|
770
806
|
{
|
|
807
|
+
protocolInstance,
|
|
771
808
|
subgraphName,
|
|
772
809
|
abi,
|
|
773
810
|
network,
|
|
774
|
-
|
|
811
|
+
contract,
|
|
775
812
|
indexEvents,
|
|
776
813
|
contractName,
|
|
777
814
|
node,
|