@graphprotocol/graph-cli 0.30.2 → 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 +3 -0
- package/src/command-helpers/compiler.js +2 -1
- package/src/command-helpers/network.js +13 -1
- package/src/command-helpers/scaffold.js +2 -2
- package/src/commands/add.js +19 -11
- package/src/commands/deploy.js +24 -11
- package/src/commands/init.js +88 -9
- package/src/commands/test.js +82 -55
- 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",
|
|
@@ -59,6 +59,9 @@ const getEtherscanLikeAPIUrl = (network) => {
|
|
|
59
59
|
case "aurora": return `https://api.aurorascan.dev/api`
|
|
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
|
+
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`;
|
|
62
65
|
default: return `https://api-${network}.etherscan.io/api`
|
|
63
66
|
}
|
|
64
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
|
}
|
|
@@ -79,12 +79,12 @@ const writeScaffold = async (scaffold, directory, spinner) => {
|
|
|
79
79
|
await writeScaffoldDirectory(scaffold, directory, spinner)
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
const writeABI = async (abi, contractName
|
|
82
|
+
const writeABI = async (abi, contractName) => {
|
|
83
83
|
let data = prettier.format(JSON.stringify(abi.data), {
|
|
84
84
|
parser: 'json',
|
|
85
85
|
})
|
|
86
86
|
|
|
87
|
-
await fs.writeFile(
|
|
87
|
+
await fs.writeFile(`./abis/${contractName}.json`, data, { encoding: 'utf-8' })
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
const writeSchema = async (abi, protocol, schemaPath, entities) => {
|
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 })
|
|
@@ -95,7 +99,7 @@ module.exports = {
|
|
|
95
99
|
let { collisionEntities, onlyCollisions, abiData } = updateEventNamesOnCollision(ethabi, entities, contractName, mergeEntities)
|
|
96
100
|
ethabi.data = abiData
|
|
97
101
|
|
|
98
|
-
await writeABI(ethabi, contractName
|
|
102
|
+
await writeABI(ethabi, contractName)
|
|
99
103
|
await writeSchema(ethabi, protocol, result.getIn(['schema', 'file']), collisionEntities)
|
|
100
104
|
await writeMapping(ethabi, protocol, contractName, collisionEntities)
|
|
101
105
|
|
|
@@ -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/commands/test.js
CHANGED
|
@@ -13,12 +13,12 @@ const HELP = `
|
|
|
13
13
|
${chalk.bold('graph test')} ${chalk.dim('[options]')} ${chalk.bold('<datasource>')}
|
|
14
14
|
|
|
15
15
|
${chalk.dim('Options:')}
|
|
16
|
-
-c, --coverage Run the tests in coverage mode
|
|
16
|
+
-c, --coverage Run the tests in coverage mode
|
|
17
17
|
-d, --docker Run the tests in a docker container(Note: Please execute from the root folder of the subgraph)
|
|
18
18
|
-f --force Binary - overwrites folder + file when downloading. Docker - rebuilds the docker image
|
|
19
19
|
-h, --help Show usage information
|
|
20
20
|
-l, --logs Logs to the console information about the OS, CPU model and download url (debugging purposes)
|
|
21
|
-
-r, --recompile Force-recompile tests
|
|
21
|
+
-r, --recompile Force-recompile tests
|
|
22
22
|
-v, --version <tag> Choose the version of the rust binary that you want to be downloaded/used
|
|
23
23
|
`
|
|
24
24
|
|
|
@@ -43,16 +43,16 @@ module.exports = {
|
|
|
43
43
|
version,
|
|
44
44
|
} = toolbox.parameters.options
|
|
45
45
|
|
|
46
|
-
let opts =
|
|
46
|
+
let opts = {}
|
|
47
47
|
// Support both long and short option variants
|
|
48
|
-
opts.
|
|
49
|
-
opts.
|
|
50
|
-
opts.
|
|
51
|
-
opts.
|
|
52
|
-
opts.
|
|
53
|
-
opts.
|
|
54
|
-
opts.
|
|
55
|
-
|
|
48
|
+
opts.coverage = coverage || c
|
|
49
|
+
opts.docker = docker || d
|
|
50
|
+
opts.force = force || f
|
|
51
|
+
opts.help = help || h
|
|
52
|
+
opts.logs = logs || l
|
|
53
|
+
opts.recompile = recompile || r
|
|
54
|
+
opts.version = version || v
|
|
55
|
+
opts.testsFolder = './tests'
|
|
56
56
|
// Fix if a boolean flag (e.g -c, --coverage) has an argument
|
|
57
57
|
try {
|
|
58
58
|
fixParameters(toolbox.parameters, {
|
|
@@ -76,18 +76,49 @@ module.exports = {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
let datasource = toolbox.parameters.first || toolbox.parameters.array[0]
|
|
79
|
-
|
|
80
79
|
// Show help text if requested
|
|
81
|
-
if (opts.
|
|
80
|
+
if (opts.help) {
|
|
82
81
|
print.info(HELP)
|
|
83
82
|
return
|
|
84
83
|
}
|
|
85
84
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
// Check if matchstick.yaml config exists
|
|
86
|
+
if(filesystem.exists('matchstick.yaml')) {
|
|
87
|
+
try {
|
|
88
|
+
// Load the config
|
|
89
|
+
let config = await yaml.load(filesystem.read('matchstick.yaml', 'utf8'))
|
|
90
|
+
|
|
91
|
+
// Check if matchstick.yaml and testsFolder not null
|
|
92
|
+
if(config && config.testsFolder) {
|
|
93
|
+
// assign test folder from matchstick.yaml if present
|
|
94
|
+
opts.testsFolder = config.testsFolder
|
|
95
|
+
}
|
|
96
|
+
} catch (error) {
|
|
97
|
+
print.info('A problem occurred while reading matchstick.yaml. Please attend to the errors below:')
|
|
98
|
+
print.error(error.message)
|
|
99
|
+
process.exit(1)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
opts.cachePath = path.join(opts.testsFolder, '.latest.json')
|
|
104
|
+
setVersionFromCache(opts)
|
|
105
|
+
|
|
106
|
+
// Fetch the latest version tag if version is not specified with -v/--version or if the version is not cached
|
|
107
|
+
if (opts.force || (!opts.version && !opts.latestVersion)) {
|
|
108
|
+
print.info("Fetching latest version tag")
|
|
109
|
+
let result = await fetch('https://api.github.com/repos/LimeChain/matchstick/releases/latest')
|
|
110
|
+
let json = await result.json()
|
|
111
|
+
opts.latestVersion = json.tag_name
|
|
112
|
+
|
|
113
|
+
filesystem.file(opts.cachePath, {
|
|
114
|
+
content: {
|
|
115
|
+
version: json.tag_name,
|
|
116
|
+
timestamp: Date.now()
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
}
|
|
89
120
|
|
|
90
|
-
if(opts.
|
|
121
|
+
if(opts.docker) {
|
|
91
122
|
runDocker(datasource, opts)
|
|
92
123
|
} else {
|
|
93
124
|
runBinary(datasource, opts)
|
|
@@ -95,13 +126,25 @@ module.exports = {
|
|
|
95
126
|
}
|
|
96
127
|
}
|
|
97
128
|
|
|
129
|
+
async function setVersionFromCache(opts) {
|
|
130
|
+
if(filesystem.exists(opts.cachePath) == 'file') {
|
|
131
|
+
let cached = filesystem.read(opts.cachePath, 'json')
|
|
132
|
+
// Get the cache age in days
|
|
133
|
+
let cacheAge = (Date.now() - cached.timestamp) / (1000 * 60 * 60 * 24)
|
|
134
|
+
// If cache age is less than 1 day, use the cached version
|
|
135
|
+
if (cacheAge < 1) {
|
|
136
|
+
opts.latestVersion = cached.version
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
98
141
|
async function runBinary(datasource, opts) {
|
|
99
|
-
let coverageOpt = opts.
|
|
100
|
-
let forceOpt = opts.
|
|
101
|
-
let logsOpt = opts.
|
|
102
|
-
let versionOpt = opts.
|
|
103
|
-
let latestVersion = opts.
|
|
104
|
-
let recompileOpt = opts.
|
|
142
|
+
let coverageOpt = opts.coverage
|
|
143
|
+
let forceOpt = opts.force
|
|
144
|
+
let logsOpt = opts.logs
|
|
145
|
+
let versionOpt = opts.version
|
|
146
|
+
let latestVersion = opts.latestVersion
|
|
147
|
+
let recompileOpt = opts.recompile
|
|
105
148
|
|
|
106
149
|
const platform = await getPlatform(logsOpt)
|
|
107
150
|
|
|
@@ -126,10 +169,10 @@ async function getPlatform(logsOpt) {
|
|
|
126
169
|
const arch = os.arch()
|
|
127
170
|
const cpuCore = os.cpus()[0]
|
|
128
171
|
const isM1 = (arch === 'arm64' && /Apple (M1|processor)/.test(cpuCore.model))
|
|
129
|
-
const linuxInfo = type === 'Linux' ? await getLinuxInfo() :
|
|
130
|
-
const linuxDistro = linuxInfo.
|
|
131
|
-
const release = linuxInfo.
|
|
132
|
-
const majorVersion = parseInt(linuxInfo.
|
|
172
|
+
const linuxInfo = type === 'Linux' ? await getLinuxInfo() : {}
|
|
173
|
+
const linuxDistro = linuxInfo.name
|
|
174
|
+
const release = linuxInfo.version || os.release()
|
|
175
|
+
const majorVersion = parseInt(linuxInfo.version, 10) || semver.major(release)
|
|
133
176
|
|
|
134
177
|
if (logsOpt) {
|
|
135
178
|
print.info(`OS type: ${linuxDistro || type}\nOS arch: ${arch}\nOS release: ${release}\nOS major version: ${majorVersion}\nCPU model: ${cpuCore.model}`)
|
|
@@ -148,6 +191,8 @@ async function getPlatform(logsOpt) {
|
|
|
148
191
|
} else if (type === 'Linux') {
|
|
149
192
|
if (majorVersion === 18) {
|
|
150
193
|
return 'binary-linux-18'
|
|
194
|
+
} if (majorVersion === 22) {
|
|
195
|
+
return 'binary-linux-22'
|
|
151
196
|
} else {
|
|
152
197
|
return 'binary-linux-20'
|
|
153
198
|
}
|
|
@@ -163,13 +208,13 @@ async function getLinuxInfo() {
|
|
|
163
208
|
try {
|
|
164
209
|
let result = await system.run("cat /etc/*-release | grep -E '(^VERSION|^NAME)='", {trim: true})
|
|
165
210
|
let infoArray = result.replace(/['"]+/g, '').split('\n').map(p => p.split('='))
|
|
166
|
-
let
|
|
211
|
+
let linuxInfo = {}
|
|
167
212
|
|
|
168
213
|
infoArray.forEach((val) => {
|
|
169
|
-
|
|
214
|
+
linuxInfo[val[0].toLowerCase()] = val[1]
|
|
170
215
|
});
|
|
171
216
|
|
|
172
|
-
return
|
|
217
|
+
return linuxInfo
|
|
173
218
|
} catch (error) {
|
|
174
219
|
print.error(`Error fetching the Linux version:\n ${error}`)
|
|
175
220
|
process.exit(1)
|
|
@@ -177,39 +222,21 @@ async function getLinuxInfo() {
|
|
|
177
222
|
}
|
|
178
223
|
|
|
179
224
|
async function runDocker(datasource, opts) {
|
|
180
|
-
let coverageOpt = opts.
|
|
181
|
-
let forceOpt = opts.
|
|
182
|
-
let versionOpt = opts.
|
|
183
|
-
let latestVersion = opts.
|
|
184
|
-
let recompileOpt = opts.
|
|
225
|
+
let coverageOpt = opts.coverage
|
|
226
|
+
let forceOpt = opts.force
|
|
227
|
+
let versionOpt = opts.version
|
|
228
|
+
let latestVersion = opts.latestVersion
|
|
229
|
+
let recompileOpt = opts.recompile
|
|
185
230
|
|
|
186
231
|
// Remove binary-install-raw binaries, because docker has permission issues
|
|
187
232
|
// when building the docker images
|
|
188
|
-
await filesystem.remove(
|
|
233
|
+
await filesystem.remove('./node_modules/binary-install-raw/bin')
|
|
189
234
|
|
|
190
235
|
// Get current working directory
|
|
191
236
|
let current_folder = await filesystem.cwd()
|
|
192
237
|
|
|
193
238
|
// Declate dockerfilePath with default location
|
|
194
|
-
let dockerfilePath =
|
|
195
|
-
|
|
196
|
-
// Check if matchstick.yaml config exists
|
|
197
|
-
if(filesystem.exists('matchstick.yaml')) {
|
|
198
|
-
try {
|
|
199
|
-
// Load the config
|
|
200
|
-
let config = await yaml.load(filesystem.read('matchstick.yaml', 'utf8'))
|
|
201
|
-
|
|
202
|
-
// Check if matchstick.yaml is not empty
|
|
203
|
-
if(config != null) {
|
|
204
|
-
// If a custom tests folder is declared update dockerfilePath
|
|
205
|
-
dockerfilePath = path.join(config.testsFolder || 'tests', '.docker/Dockerfile')
|
|
206
|
-
}
|
|
207
|
-
} catch (error) {
|
|
208
|
-
print.info('A problem occurred while reading matchstick.yaml. Please attend to the errors below:')
|
|
209
|
-
print.error(error.message)
|
|
210
|
-
process.exit(1)
|
|
211
|
-
}
|
|
212
|
-
}
|
|
239
|
+
let dockerfilePath = path.join(opts.testsFolder || 'tests', '.docker/Dockerfile')
|
|
213
240
|
|
|
214
241
|
// Check if the Dockerfil already exists
|
|
215
242
|
let dockerfileExists = filesystem.exists(dockerfilePath)
|
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',
|