@graphprotocol/graph-cli 0.54.0 → 0.55.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/CHANGELOG.md +13 -0
- package/dist/command-helpers/abi.js +5 -1
- package/dist/command-helpers/node.d.ts +7 -0
- package/dist/command-helpers/node.js +34 -1
- package/dist/command-helpers/studio.d.ts +1 -1
- package/dist/command-helpers/studio.js +1 -0
- package/dist/commands/deploy.d.ts +1 -0
- package/dist/commands/deploy.js +100 -1
- package/dist/protocols/index.js +1 -0
- package/oclif.manifest.json +8 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @graphprotocol/graph-cli
|
|
2
2
|
|
|
3
|
+
## 0.55.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1419](https://github.com/graphprotocol/graph-tooling/pull/1419)
|
|
8
|
+
[`e88ff02`](https://github.com/graphprotocol/graph-tooling/commit/e88ff02cd236f6c556afd99cecb00b6cffd738ed)
|
|
9
|
+
Thanks [@saihaj](https://github.com/saihaj)! - Introduce `--from-hosted-service` flag which will
|
|
10
|
+
make it easier to deploy subgraphs from hosted service to Studio.
|
|
11
|
+
|
|
12
|
+
- [#1418](https://github.com/graphprotocol/graph-tooling/pull/1418)
|
|
13
|
+
[`38c16be`](https://github.com/graphprotocol/graph-tooling/commit/38c16be4ed865bec12a4db63b219dba058f06e72)
|
|
14
|
+
Thanks [@uF4No](https://github.com/uF4No)! - feat: adds zksync era testnet
|
|
15
|
+
|
|
3
16
|
## 0.54.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
|
@@ -150,6 +150,8 @@ const getEtherscanLikeAPIUrl = (network) => {
|
|
|
150
150
|
return `https://api-testnet.ftmscan.com/api`;
|
|
151
151
|
case 'zksync-era':
|
|
152
152
|
return `https://block-explorer-api.mainnet.zksync.io/api`;
|
|
153
|
+
case 'zksync-era-testnet':
|
|
154
|
+
return `https://block-explorer-api.testnets.zksync.dev/api`;
|
|
153
155
|
case 'polygon-zkevm-testnet':
|
|
154
156
|
return `https://testnet-zkevm.polygonscan.com/api`;
|
|
155
157
|
case 'polygon-zkevm':
|
|
@@ -225,7 +227,9 @@ const getPublicRPCEndpoint = (network) => {
|
|
|
225
227
|
case 'rinkeby':
|
|
226
228
|
return 'https://rpc.ankr.com/eth_rinkeby';
|
|
227
229
|
case 'zksync-era':
|
|
228
|
-
return 'https://
|
|
230
|
+
return 'https://mainnet.era.zksync.io';
|
|
231
|
+
case 'zksync-era-testnet':
|
|
232
|
+
return 'https://testnet.era.zksync.dev';
|
|
229
233
|
case 'sepolia':
|
|
230
234
|
return 'https://rpc.ankr.com/eth_sepolia';
|
|
231
235
|
default:
|
|
@@ -11,3 +11,10 @@ export declare function chooseNodeUrl({ product, studio, node, allowSimpleName,
|
|
|
11
11
|
node: string | undefined;
|
|
12
12
|
allowSimpleName: boolean | undefined;
|
|
13
13
|
};
|
|
14
|
+
export declare function getHostedServiceSubgraphId({ subgraphName, }: {
|
|
15
|
+
subgraphName: string;
|
|
16
|
+
}): Promise<{
|
|
17
|
+
subgraph: string;
|
|
18
|
+
synced: boolean;
|
|
19
|
+
health: 'healthy' | 'unhealthy' | 'failed';
|
|
20
|
+
}>;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.chooseNodeUrl = exports.normalizeNodeUrl = exports.validateNodeUrl = void 0;
|
|
3
|
+
exports.getHostedServiceSubgraphId = exports.chooseNodeUrl = exports.normalizeNodeUrl = exports.validateNodeUrl = void 0;
|
|
4
4
|
const url_1 = require("url");
|
|
5
5
|
const gluegun_1 = require("gluegun");
|
|
6
6
|
const SUBGRAPH_STUDIO_URL = 'https://api.studio.thegraph.com/deploy/';
|
|
7
7
|
const HOSTED_SERVICE_URL = 'https://api.thegraph.com/deploy/';
|
|
8
|
+
const HOSTED_SERVICE_INDEX_NODE_URL = 'https://api.thegraph.com/index-node/graphql';
|
|
8
9
|
const validateNodeUrl = (node) => new url_1.URL(node);
|
|
9
10
|
exports.validateNodeUrl = validateNodeUrl;
|
|
10
11
|
const normalizeNodeUrl = (node) => new url_1.URL(node).toString();
|
|
@@ -38,3 +39,35 @@ function chooseNodeUrl({ product, studio, node, allowSimpleName, }) {
|
|
|
38
39
|
return { node, allowSimpleName };
|
|
39
40
|
}
|
|
40
41
|
exports.chooseNodeUrl = chooseNodeUrl;
|
|
42
|
+
async function getHostedServiceSubgraphId({ subgraphName, }) {
|
|
43
|
+
const response = await fetch(HOSTED_SERVICE_INDEX_NODE_URL, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
body: JSON.stringify({
|
|
46
|
+
query: /* GraphQL */ `
|
|
47
|
+
query GraphCli_getSubgraphId($subgraphName: String!) {
|
|
48
|
+
indexingStatusForCurrentVersion(subgraphName: $subgraphName) {
|
|
49
|
+
subgraph
|
|
50
|
+
synced
|
|
51
|
+
health
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
`,
|
|
55
|
+
variables: {
|
|
56
|
+
subgraphName,
|
|
57
|
+
},
|
|
58
|
+
}),
|
|
59
|
+
headers: {
|
|
60
|
+
'content-type': 'application/json',
|
|
61
|
+
'User-Agent': '@graphprotocol/graph-cli',
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
const { data, errors } = await response.json();
|
|
65
|
+
if (errors) {
|
|
66
|
+
throw new Error(errors[0].message);
|
|
67
|
+
}
|
|
68
|
+
if (!data.indexingStatusForCurrentVersion) {
|
|
69
|
+
throw new Error(`Subgraph "${subgraphName}" not found on the hosted service`);
|
|
70
|
+
}
|
|
71
|
+
return data.indexingStatusForCurrentVersion;
|
|
72
|
+
}
|
|
73
|
+
exports.getHostedServiceSubgraphId = getHostedServiceSubgraphId;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const allowedStudioNetworks: readonly ["mainnet", "rinkeby", "goerli", "gnosis", "chapel", "optimism-goerli", "clover", "fantom", "matic", "fantom-testnet", "arbitrum-goerli", "fuji", "celo-alfajores", "mumbai", "aurora-testnet", "near-testnet", "optimism", "optimism-goerli", "theta-testnet-001", "osmo-test-4", "base-testnet", "base", "celo", "arbitrum-one", "avalanche", "zksync-era", "sepolia", "polygon-zkevm-testnet", "polygon-zkevm"];
|
|
1
|
+
export declare const allowedStudioNetworks: readonly ["mainnet", "rinkeby", "goerli", "gnosis", "chapel", "optimism-goerli", "clover", "fantom", "matic", "fantom-testnet", "arbitrum-goerli", "fuji", "celo-alfajores", "mumbai", "aurora-testnet", "near-testnet", "optimism", "optimism-goerli", "theta-testnet-001", "osmo-test-4", "base-testnet", "base", "celo", "arbitrum-one", "avalanche", "zksync-era", "zksync-era-testnet", "sepolia", "polygon-zkevm-testnet", "polygon-zkevm"];
|
|
2
2
|
export declare const validateStudioNetwork: ({ studio, product, network, }: {
|
|
3
3
|
studio?: string | boolean | undefined;
|
|
4
4
|
product?: string | undefined;
|
|
@@ -22,6 +22,7 @@ export default class DeployCommand extends Command {
|
|
|
22
22
|
watch: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
23
23
|
network: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
24
24
|
'network-file': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
25
|
+
'from-hosted-service': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
25
26
|
};
|
|
26
27
|
run(): Promise<void>;
|
|
27
28
|
}
|
package/dist/commands/deploy.js
CHANGED
|
@@ -50,7 +50,103 @@ const headersFlag = core_1.Flags.custom({
|
|
|
50
50
|
const productOptions = ['subgraph-studio', 'hosted-service'];
|
|
51
51
|
class DeployCommand extends core_1.Command {
|
|
52
52
|
async run() {
|
|
53
|
-
const { args: { 'subgraph-name': subgraphNameArg, 'subgraph-manifest': manifest }, flags: { product: productFlag, studio, 'deploy-key': deployKeyFlag, 'access-token': accessToken, 'version-label': versionLabelFlag, ipfs, headers, node: nodeFlag, 'output-dir': outputDir, 'skip-migrations': skipMigrations, watch, 'debug-fork': debugFork, network, 'network-file': networkFile, 'ipfs-hash': ipfsHash, }, } = await this.parse(DeployCommand);
|
|
53
|
+
const { args: { 'subgraph-name': subgraphNameArg, 'subgraph-manifest': manifest }, flags: { product: productFlag, studio, 'deploy-key': deployKeyFlag, 'access-token': accessToken, 'version-label': versionLabelFlag, ipfs, headers, node: nodeFlag, 'output-dir': outputDir, 'skip-migrations': skipMigrations, watch, 'debug-fork': debugFork, network, 'network-file': networkFile, 'ipfs-hash': ipfsHash, 'from-hosted-service': hostedServiceSubgraphName, }, } = await this.parse(DeployCommand);
|
|
54
|
+
if (hostedServiceSubgraphName) {
|
|
55
|
+
const { health, subgraph: subgraphIpfsHash } = await (0, node_1.getHostedServiceSubgraphId)({
|
|
56
|
+
subgraphName: hostedServiceSubgraphName,
|
|
57
|
+
});
|
|
58
|
+
const safeToDeployFailedSubgraph = health === 'failed'
|
|
59
|
+
? await core_1.ux.confirm('This subgraph has failed indexing on hosted service. Do you wish to continue the deploy?')
|
|
60
|
+
: true;
|
|
61
|
+
if (!safeToDeployFailedSubgraph)
|
|
62
|
+
return;
|
|
63
|
+
const safeToDeployUnhealthySubgraph = health === 'unhealthy'
|
|
64
|
+
? await core_1.ux.confirm('This subgraph is not healthy on hosted service. Do you wish to continue the deploy?')
|
|
65
|
+
: true;
|
|
66
|
+
if (!safeToDeployUnhealthySubgraph)
|
|
67
|
+
return;
|
|
68
|
+
const { node } = (0, node_1.chooseNodeUrl)({ studio: true, product: undefined });
|
|
69
|
+
// shouldn't happen, but we need to satisfy the compiler
|
|
70
|
+
if (!node) {
|
|
71
|
+
this.error('No node URL available');
|
|
72
|
+
}
|
|
73
|
+
const requestUrl = new url_1.URL(node);
|
|
74
|
+
const client = (0, jsonrpc_1.createJsonRpcClient)(requestUrl);
|
|
75
|
+
// Exit with an error code if the client couldn't be created
|
|
76
|
+
if (!client) {
|
|
77
|
+
this.error('Failed to create RPC client');
|
|
78
|
+
}
|
|
79
|
+
// Use the deploy key, if one is set
|
|
80
|
+
let deployKey = deployKeyFlag;
|
|
81
|
+
if (!deployKey && accessToken) {
|
|
82
|
+
deployKey = accessToken; // backwards compatibility
|
|
83
|
+
}
|
|
84
|
+
deployKey = await (0, auth_1.identifyDeployKey)(node, deployKey);
|
|
85
|
+
if (!deployKey) {
|
|
86
|
+
this.error('No deploy key available');
|
|
87
|
+
}
|
|
88
|
+
// @ts-expect-error options property seems to exist
|
|
89
|
+
client.options.headers = { Authorization: 'Bearer ' + deployKey };
|
|
90
|
+
const subgraphName = await core_1.ux.prompt('What is the name of the subgraph you want to deploy?', {
|
|
91
|
+
required: true,
|
|
92
|
+
});
|
|
93
|
+
// Ask for label if not on hosted service
|
|
94
|
+
const versionLabel = versionLabelFlag ||
|
|
95
|
+
(await core_1.ux.prompt('Which version label to use? (e.g. "v0.0.1")', {
|
|
96
|
+
required: true,
|
|
97
|
+
}));
|
|
98
|
+
const spinner = gluegun_1.print.spin(`Deploying to Graph node ${requestUrl}`);
|
|
99
|
+
client.request('subgraph_deploy', {
|
|
100
|
+
name: subgraphName,
|
|
101
|
+
ipfs_hash: subgraphIpfsHash,
|
|
102
|
+
version_label: versionLabel,
|
|
103
|
+
debug_fork: debugFork,
|
|
104
|
+
}, async (
|
|
105
|
+
// @ts-expect-error TODO: why are the arguments not typed?
|
|
106
|
+
requestError,
|
|
107
|
+
// @ts-expect-error TODO: why are the arguments not typed?
|
|
108
|
+
jsonRpcError,
|
|
109
|
+
// @ts-expect-error TODO: why are the arguments not typed?
|
|
110
|
+
res) => {
|
|
111
|
+
if (jsonRpcError) {
|
|
112
|
+
let errorMessage = `Failed to deploy to Graph node ${requestUrl}: ${jsonRpcError.message}`;
|
|
113
|
+
// Provide helpful advice when the subgraph has not been created yet
|
|
114
|
+
if (jsonRpcError.message.match(/subgraph name not found/)) {
|
|
115
|
+
errorMessage += `
|
|
116
|
+
Make sure to create the subgraph first by running the following command:
|
|
117
|
+
$ graph create --node ${node} ${subgraphName}`;
|
|
118
|
+
}
|
|
119
|
+
if (jsonRpcError.message.match(/auth failure/)) {
|
|
120
|
+
errorMessage += '\nYou may need to authenticate first.';
|
|
121
|
+
}
|
|
122
|
+
spinner.fail(errorMessage);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
else if (requestError) {
|
|
126
|
+
spinner.fail(`HTTP error deploying the subgraph ${requestError.code}`);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
spinner.stop();
|
|
131
|
+
const base = requestUrl.protocol + '//' + requestUrl.hostname;
|
|
132
|
+
let playground = res.playground;
|
|
133
|
+
let queries = res.queries;
|
|
134
|
+
// Add a base URL if graph-node did not return the full URL
|
|
135
|
+
if (playground.charAt(0) === ':') {
|
|
136
|
+
playground = base + playground;
|
|
137
|
+
}
|
|
138
|
+
if (queries.charAt(0) === ':') {
|
|
139
|
+
queries = base + queries;
|
|
140
|
+
}
|
|
141
|
+
gluegun_1.print.success(`Deployed to ${playground}`);
|
|
142
|
+
gluegun_1.print.info('\nSubgraph endpoints:');
|
|
143
|
+
gluegun_1.print.info(`Queries (HTTP): ${queries}`);
|
|
144
|
+
gluegun_1.print.info(``);
|
|
145
|
+
process.exit(0);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
54
150
|
const subgraphName = subgraphNameArg ||
|
|
55
151
|
(await core_1.ux.prompt('What is the subgraph name?', {
|
|
56
152
|
required: true,
|
|
@@ -329,5 +425,8 @@ DeployCommand.flags = {
|
|
|
329
425
|
summary: 'Networks config file path.',
|
|
330
426
|
default: 'networks.json',
|
|
331
427
|
}),
|
|
428
|
+
'from-hosted-service': core_1.Flags.string({
|
|
429
|
+
summary: 'Hosted service Subgraph Name to deploy to studio.',
|
|
430
|
+
}),
|
|
332
431
|
};
|
|
333
432
|
exports.default = DeployCommand;
|
package/dist/protocols/index.js
CHANGED
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.55.0",
|
|
3
3
|
"commands": {
|
|
4
4
|
"add": {
|
|
5
5
|
"id": "add",
|
|
@@ -451,6 +451,12 @@
|
|
|
451
451
|
"summary": "Networks config file path.",
|
|
452
452
|
"multiple": false,
|
|
453
453
|
"default": "networks.json"
|
|
454
|
+
},
|
|
455
|
+
"from-hosted-service": {
|
|
456
|
+
"name": "from-hosted-service",
|
|
457
|
+
"type": "option",
|
|
458
|
+
"summary": "Hosted service Subgraph Name to deploy to studio.",
|
|
459
|
+
"multiple": false
|
|
454
460
|
}
|
|
455
461
|
},
|
|
456
462
|
"args": {
|
|
@@ -628,6 +634,7 @@
|
|
|
628
634
|
"base-testnet",
|
|
629
635
|
"base",
|
|
630
636
|
"zksync-era",
|
|
637
|
+
"zksync-era-testnet",
|
|
631
638
|
"sepolia",
|
|
632
639
|
"polygon-zkevm-testnet",
|
|
633
640
|
"polygon-zkevm",
|