Skip to content

Commit 098b433

Browse files
DenisCarriere0237hYaroShkvorets
committed
update NETWORK_SUBGRAPH_MAINNET & add api-key to CLI (#1760)
* update NETWORK_SUBGRAPH_MAINNET & add `api-key` to CLI * Fail publish if missing API key with Subgraph ID * get version from network subgraph --------- Co-authored-by: Etienne Donneger <[email protected]> Co-authored-by: YaroShkvorets <[email protected]>
1 parent 6f2cb45 commit 098b433

File tree

5 files changed

+79
-36
lines changed

5 files changed

+79
-36
lines changed

.changeset/breezy-eels-sniff.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphprotocol/graph-cli': minor
3+
---
4+
5+
Update deprecated endpoints and support API key for updating published subgraphs

packages/cli/src/commands/publish.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ export default class PublishCommand extends Command {
4646
required: false,
4747
default: 'https://cli.thegraph.com/publish',
4848
}),
49+
'api-key': Flags.string({
50+
summary: 'The API key to use for the Subgraph queries.',
51+
required: false,
52+
}),
4953
};
5054

5155
/**
@@ -56,11 +60,13 @@ export default class PublishCommand extends Command {
5660
webapp,
5761
subgraphId,
5862
protocolNetwork,
63+
apiKey,
5964
}: {
6065
ipfsHash: string;
6166
webapp: string;
6267
subgraphId: string | undefined;
6368
protocolNetwork: string | undefined;
69+
apiKey: string | undefined;
6470
}) {
6571
const answer = await ux.prompt(
6672
`Press ${chalk.green(
@@ -84,6 +90,9 @@ export default class PublishCommand extends Command {
8490
if (protocolNetwork) {
8591
searchParams.set('network', protocolNetwork);
8692
}
93+
if (apiKey) {
94+
searchParams.set('apiKey', apiKey);
95+
}
8796

8897
url.search = searchParams.toString();
8998

@@ -105,11 +114,25 @@ export default class PublishCommand extends Command {
105114
ipfs,
106115
'subgraph-id': subgraphId,
107116
'protocol-network': protocolNetwork,
117+
'api-key': apiKey,
108118
},
109119
} = await this.parse(PublishCommand);
110120

121+
if (subgraphId && !apiKey) {
122+
ux.error(
123+
'API key is required to publish to an existing subgraph (`--api-key`).\nSee https://thegraph.com/docs/en/deploying/subgraph-studio-faqs/#2-how-do-i-create-an-api-key',
124+
{ exit: 1 },
125+
);
126+
}
127+
111128
if (ipfsHash) {
112-
await this.publishWithBrowser({ ipfsHash, webapp: webUiUrl, subgraphId, protocolNetwork });
129+
await this.publishWithBrowser({
130+
ipfsHash,
131+
webapp: webUiUrl,
132+
subgraphId,
133+
protocolNetwork,
134+
apiKey,
135+
});
113136
return;
114137
}
115138

@@ -146,6 +169,7 @@ export default class PublishCommand extends Command {
146169
webapp: webUiUrl,
147170
subgraphId,
148171
protocolNetwork,
172+
apiKey,
149173
});
150174
return;
151175
}

website/src/lib/graphql.ts

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,13 @@
1-
import { print } from 'graphql';
2-
import { TypedDocumentNode } from '@graphql-typed-document-node/core';
3-
41
export const NETWORK_SUBGRAPH_MAINNET =
5-
'https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-arbitrum';
2+
'https://gateway.thegraph.com/api/{api-key}/subgraphs/id/DZz4kDTdmzWLWsV373w2bSmoar3umKKH9y82SUKr5qmp';
63
export const NETWORK_SUBGRAPH_SEPOLIA =
7-
'https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-arbitrum-sepolia';
4+
'https://gateway.thegraph.com/api/{api-key}/subgraphs/id/3xQHhMudr1oh69ut36G2mbzpYmYxwqCeU6wwqyCDCnqV';
85

9-
export async function networkSubgraphExecute<Result = unknown, Variables = unknown>(
10-
query: TypedDocumentNode<Result, Variables>,
11-
variables: Variables,
12-
{
13-
endpoint,
14-
}: {
15-
endpoint: string;
16-
},
17-
): Promise<Result> {
18-
const response = await fetch(endpoint, {
6+
export async function networkSubgraphExecute(query: string, endpoint: string, apiKey: string) {
7+
const response = await fetch(endpoint.replace('{api-key}', apiKey), {
198
method: 'POST',
209
body: JSON.stringify({
21-
query: print(query),
22-
variables,
10+
query,
2311
}),
2412
});
2513
return (await response.json()).data;

website/src/routes/publish.lazy.tsx

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { useState } from 'react';
22
import { ConnectKitButton, useModal } from 'connectkit';
3-
import { graphql } from 'gql.tada';
43
import { useForm } from 'react-hook-form';
54
import semver from 'semver';
65
import { Address } from 'viem';
@@ -129,9 +128,9 @@ const Manifest = z.object({
129128
repository: z.string().describe('An optional link to where the subgraph lives.').optional(),
130129
});
131130

132-
const GetSubgraphInfo = graphql(/* GraphQL */ `
133-
query GetSubgraphInfo($subgraphId: ID!) {
134-
subgraph(id: $subgraphId) {
131+
const GetSubgraphInfo = (subgraphId: string) => `
132+
{
133+
subgraph(id: "${subgraphId}") {
135134
id
136135
owner {
137136
id
@@ -155,7 +154,7 @@ const GetSubgraphInfo = graphql(/* GraphQL */ `
155154
}
156155
}
157156
}
158-
`);
157+
`;
159158

160159
function getEtherscanUrl({ chainId, hash }: { chainId: number; hash: string }) {
161160
switch (chainId) {
@@ -172,10 +171,12 @@ function DeploySubgraph({
172171
deploymentId,
173172
subgraphId,
174173
network,
174+
apiKey,
175175
}: {
176176
deploymentId: string;
177177
subgraphId: string | undefined;
178178
network: (typeof CHAINS)[number] | undefined;
179+
apiKey: string | undefined;
179180
}) {
180181
const { writeContractAsync, isPending, error: contractError } = useWriteContract({});
181182
const { setOpen } = useModal();
@@ -214,20 +215,32 @@ function DeploySubgraph({
214215
const chain = form.watch('chain');
215216

216217
const { data: subgraphInfo } = useQuery({
217-
queryKey: ['subgraph-info', subgraphId, chain, chainId],
218+
queryKey: ['subgraph-info', subgraphId, chain, chainId, apiKey],
218219
queryFn: async () => {
219-
if (!subgraphId) return;
220+
if (!subgraphId) {
221+
toast({
222+
description: 'Subgraph ID is missing. Please add it to the URL params and try again.',
223+
variant: 'destructive',
224+
});
225+
return;
226+
}
227+
if (!apiKey) {
228+
toast({
229+
description:
230+
'apiKey is missing in URL params. Please add it to the URL params and try again.',
231+
variant: 'destructive',
232+
});
233+
return;
234+
}
220235

221236
const subgraphEndpoint = chain ? getChainInfo(chain)?.subgraph : null;
222237

223238
if (!subgraphEndpoint) return;
224239

225240
const data = await networkSubgraphExecute(
226-
GetSubgraphInfo,
227-
{ subgraphId },
228-
{
229-
endpoint: subgraphEndpoint,
230-
},
241+
GetSubgraphInfo(subgraphId),
242+
subgraphEndpoint,
243+
apiKey,
231244
);
232245

233246
const metadata = data.subgraph?.metadata;
@@ -251,6 +264,11 @@ function DeploySubgraph({
251264
if (metadata.displayName) {
252265
form.setValue('displayName', metadata.displayName);
253266
}
267+
268+
if (data.subgraph.versions?.length > 0) {
269+
const version = data.subgraph.versions[data.subgraph.versions.length - 1];
270+
form.setValue('versionLabel', version.metadata?.label ?? '');
271+
}
254272
}
255273

256274
return data;
@@ -264,7 +282,7 @@ function DeploySubgraph({
264282
const version = form.watch('versionLabel');
265283

266284
const versionInfo = subgraphInfo.subgraph?.versions.find(
267-
({ metadata }) => metadata?.label === version,
285+
({ metadata }: { metadata: { label: string } }) => metadata?.label === version,
268286
);
269287

270288
if (!versionInfo) return false;
@@ -280,7 +298,9 @@ function DeploySubgraph({
280298

281299
const version = form.watch('versionLabel');
282300

283-
return !subgraphInfo.subgraph?.versions.some(({ metadata }) => metadata?.label === version);
301+
return !subgraphInfo.subgraph?.versions.some(
302+
({ metadata }: { metadata: { label: string } }) => metadata?.label === version,
303+
);
284304
}
285305

286306
function isOwner() {
@@ -375,7 +395,7 @@ function DeploySubgraph({
375395
if (e?.name === 'ContractFunctionExecutionError') {
376396
if (e.cause.name === 'ContractFunctionRevertedError') {
377397
toast({
378-
description: e.cause.reason,
398+
description: e.cause.message,
379399
variant: 'destructive',
380400
});
381401
return;
@@ -565,7 +585,7 @@ function DeploySubgraph({
565585
}
566586

567587
function Page() {
568-
const { id, subgraphId, network } = Route.useSearch();
588+
const { id, subgraphId, network, apiKey } = Route.useSearch();
569589

570590
const protocolNetwork = network
571591
? // @ts-expect-error we want to compare if it is a string or not
@@ -581,7 +601,12 @@ function Page() {
581601
<ConnectKitButton />
582602
</nav>
583603
{id ? (
584-
<DeploySubgraph deploymentId={id} subgraphId={subgraphId} network={protocolNetwork} />
604+
<DeploySubgraph
605+
deploymentId={id}
606+
subgraphId={subgraphId}
607+
network={protocolNetwork}
608+
apiKey={apiKey}
609+
/>
585610
) : (
586611
<div className="flex justify-center items-center min-h-screen -mt-16">
587612
Unable to find the Deployment ID. Go back to CLI

website/src/routes/publish.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const Route = createFileRoute('/publish')({
66
subgraphId: z.string().optional(),
77
// Transforming string to enum here doesn't actually work
88
network: z.string().optional(),
9-
id: z.string(),
9+
id: z.string().optional(),
10+
apiKey: z.string().optional(),
1011
}),
1112
});

0 commit comments

Comments
 (0)