diff --git a/.changeset/moody-cars-rule.md b/.changeset/moody-cars-rule.md new file mode 100644 index 000000000..c72d481a1 --- /dev/null +++ b/.changeset/moody-cars-rule.md @@ -0,0 +1,5 @@ +--- +'@graphprotocol/graph-cli': patch +--- + +updated IPFS endpoints, added deprecation notice when using old ones diff --git a/examples/aggregations/package.json b/examples/aggregations/package.json index d45881028..5fc500912 100644 --- a/examples/aggregations/package.json +++ b/examples/aggregations/package.json @@ -12,7 +12,7 @@ "codegen": "graph codegen", "create": "graph create example --node https://api.studio.thegraph.com/deploy/", "create-local": "graph create example --node http://127.0.0.1:8020", - "deploy": "graph deploy example --ipfs https://api.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", + "deploy": "graph deploy example --ipfs https://ipfs.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", "deploy-local": "graph deploy example --ipfs http://127.0.0.1:5001 --node http://127.0.0.1:8020", "test": "graph test" }, diff --git a/examples/arweave-blocks-transactions/package.json b/examples/arweave-blocks-transactions/package.json index bf76c9b6a..bfb2d2067 100644 --- a/examples/arweave-blocks-transactions/package.json +++ b/examples/arweave-blocks-transactions/package.json @@ -14,7 +14,7 @@ "codegen": "graph codegen", "create": "graph create arweave-example --node https://api.studio.thegraph.com/deploy/", "create-local": "graph create arweave-example --node http://localhost:8020", - "deploy": "graph deploy arweave-example --ipfs https://api.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", + "deploy": "graph deploy arweave-example --ipfs https://ipfs.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", "deploy-local": "graph deploy arweave-example -l v0.1.0 --ipfs http://localhost:5001 --node http://localhost:8020", "remove-local": "graph remove arweave-example --node http://localhost:8020" }, diff --git a/examples/cosmos-block-filtering/package.json b/examples/cosmos-block-filtering/package.json index dd8b7d839..26b810d4d 100644 --- a/examples/cosmos-block-filtering/package.json +++ b/examples/cosmos-block-filtering/package.json @@ -13,7 +13,7 @@ "codegen": "graph codegen", "create": "graph create cosmos-block-filtering --node https://api.studio.thegraph.com/deploy/", "create-local": "graph create cosmos-block-filtering --node http://127.0.0.1:8020", - "deploy": "graph deploy cosmos-block-filtering --ipfs https://api.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", + "deploy": "graph deploy cosmos-block-filtering --ipfs https://ipfs.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", "deploy-local": "graph deploy cosmos-block-filtering -l v0.1.0 --ipfs http://127.0.0.1:5001 --node http://127.0.0.1:8020", "prepare:cosmoshub": "mustache config/cosmoshub.json subgraph.template.yaml > subgraph.yaml", "prepare:osmosis": "mustache config/osmosis.json subgraph.template.yaml > subgraph.yaml", diff --git a/examples/cosmos-osmosis-token-swaps/package.json b/examples/cosmos-osmosis-token-swaps/package.json index e28e0827d..10a38cbcf 100644 --- a/examples/cosmos-osmosis-token-swaps/package.json +++ b/examples/cosmos-osmosis-token-swaps/package.json @@ -13,7 +13,7 @@ "codegen": "graph codegen", "create": "graph create osmosis-token-swaps --node https://api.studio.thegraph.com/deploy/", "create-local": "graph create osmosis-token-swaps --node http://0.0.0.0:8020", - "deploy": "graph deploy osmosis-token-swaps --ipfs https://api.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", + "deploy": "graph deploy osmosis-token-swaps --ipfs https://ipfs.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", "deploy-local": "graph deploy osmosis-token-swaps -l v0.1.0 --ipfs http://0.0.0.0:5001 --node http://0.0.0.0:8020", "remove-local": "graph remove osmosis-token-swaps --node http://0.0.0.0:8020" }, diff --git a/examples/cosmos-validator-delegations/package.json b/examples/cosmos-validator-delegations/package.json index 572e875e4..d25c6530d 100644 --- a/examples/cosmos-validator-delegations/package.json +++ b/examples/cosmos-validator-delegations/package.json @@ -13,7 +13,7 @@ "codegen": "graph codegen", "create": "graph create cosmos-validator-delegations --node https://api.studio.thegraph.com/deploy/", "create-local": "graph create cosmos-validator-delegations --node http://127.0.0.1:8020", - "deploy": "graph deploy cosmos-validator-delegations --ipfs https://api.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", + "deploy": "graph deploy cosmos-validator-delegations --ipfs https://ipfs.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", "deploy-local": "graph deploy cosmos-validator-delegations -l v0.1.0 --ipfs http://127.0.0.1:5001 --node http://127.0.0.1:8020", "prepare:cosmoshub": "mustache config/cosmoshub.json subgraph.template.yaml > subgraph.yaml", "prepare:osmosis": "mustache config/osmosis.json subgraph.template.yaml > subgraph.yaml", diff --git a/examples/cosmos-validator-rewards/package.json b/examples/cosmos-validator-rewards/package.json index 45c49d870..a7a1f599e 100644 --- a/examples/cosmos-validator-rewards/package.json +++ b/examples/cosmos-validator-rewards/package.json @@ -13,7 +13,7 @@ "codegen": "graph codegen", "create": "graph create cosmos-validator-rewards --node https://api.studio.thegraph.com/deploy/", "create-local": "graph create cosmos-validator-rewards --node http://127.0.0.1:8020", - "deploy": "graph deploy cosmos-validator-rewards --ipfs https://api.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", + "deploy": "graph deploy cosmos-validator-rewards --ipfs https://ipfs.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", "deploy-local": "graph deploy cosmos-validator-rewards -l v0.1.0 --ipfs http://127.0.0.1:5001 --node http://127.0.0.1:8020", "prepare:cosmoshub": "mustache config/cosmoshub.json subgraph.template.yaml > subgraph.yaml", "prepare:osmosis": "mustache config/osmosis.json subgraph.template.yaml > subgraph.yaml", diff --git a/examples/ethereum-gravatar/package.json b/examples/ethereum-gravatar/package.json index bda33a86d..95185946f 100644 --- a/examples/ethereum-gravatar/package.json +++ b/examples/ethereum-gravatar/package.json @@ -14,7 +14,7 @@ "codegen": "graph codegen", "create": "graph create example --node https://api.studio.thegraph.com/deploy/", "create-local": "graph create example --node http://127.0.0.1:8020", - "deploy": "graph deploy example --ipfs https://api.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", + "deploy": "graph deploy example --ipfs https://ipfs.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", "deploy-local": "graph deploy example --ipfs http://127.0.0.1:5001 --node http://127.0.0.1:8020" }, "devDependencies": { diff --git a/examples/near-blocks/package.json b/examples/near-blocks/package.json index 83bee499c..42e445112 100644 --- a/examples/near-blocks/package.json +++ b/examples/near-blocks/package.json @@ -13,7 +13,7 @@ "codegen": "graph codegen", "create": "graph create example --node https://api.studio.thegraph.com/deploy/", "create-local": "graph create example --node http://127.0.0.1:8020", - "deploy": "graph deploy example --ipfs https://api.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", + "deploy": "graph deploy example --ipfs https://ipfs.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", "deploy-local": "graph deploy example --ipfs http://localhost:5001 --node http://127.0.0.1:8020" }, "devDependencies": { diff --git a/examples/near-receipts/package.json b/examples/near-receipts/package.json index 4a4d6b75f..e8af67f5b 100644 --- a/examples/near-receipts/package.json +++ b/examples/near-receipts/package.json @@ -13,7 +13,7 @@ "codegen": "graph codegen", "create": "graph create example --node https://api.studio.thegraph.com/deploy/", "create-local": "graph create example --node http://127.0.0.1:8020", - "deploy": "graph deploy example --ipfs https://api.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", + "deploy": "graph deploy example --ipfs https://ipfs.thegraph.com/ipfs/ --node https://api.studio.thegraph.com/deploy/", "deploy-local": "graph deploy example --ipfs http://localhost:5001 --node http://127.0.0.1:8020" }, "devDependencies": { diff --git a/packages/cli/src/command-helpers/compiler.test.ts b/packages/cli/src/command-helpers/compiler.test.ts index 533ed0549..7570a4aad 100644 --- a/packages/cli/src/command-helpers/compiler.test.ts +++ b/packages/cli/src/command-helpers/compiler.test.ts @@ -1,42 +1,70 @@ import { describe, expect, it } from 'vitest'; -import { appendApiVersionForGraph } from './compiler.js'; +import { getGraphIpfsUrl } from './ipfs.js'; -describe('appendApiVersionForGraph', { concurrent: true }, () => { - it('append /api/v0 to Prod URL with trailing slash', () => { - expect(appendApiVersionForGraph('https://api.thegraph.com/ipfs/')).toBe( - 'https://api.thegraph.com/ipfs/api/v0', - ); +const DEFAULT_IPFS_URL = 'https://ipfs.thegraph.com/ipfs/api/v0'; + +describe('getGraphIpfsUrl', { concurrent: true }, () => { + it('returns default URL when input is undefined', () => { + expect(getGraphIpfsUrl(undefined)).toEqual({ + ipfsUrl: DEFAULT_IPFS_URL, + }); + }); + + it('returns default URL when input is empty string', () => { + expect(getGraphIpfsUrl('')).toEqual({ + ipfsUrl: DEFAULT_IPFS_URL, + }); + }); + + it('returns input URL when valid and not deprecated', () => { + const validUrl = 'https://ipfs.network.example.com'; + expect(getGraphIpfsUrl(validUrl)).toEqual({ + ipfsUrl: validUrl, + }); + }); + + it('trim trailing slash from valid url', () => { + const validUrl = 'https://ipfs.network.example.com/ipfs/'; + expect(getGraphIpfsUrl(validUrl)).toEqual({ + ipfsUrl: 'https://ipfs.network.example.com/ipfs', + }); }); - it('append /api/v0 to Prod URL without trailing slash', () => { - expect(appendApiVersionForGraph('https://api.thegraph.com/ipfs')).toBe( - 'https://api.thegraph.com/ipfs/api/v0', - ); + it('returns default URL with warning for deprecated api.thegraph.com URL', () => { + const result = getGraphIpfsUrl('https://api.thegraph.com/ipfs/api/v0'); + expect(result.ipfsUrl).toEqual(DEFAULT_IPFS_URL); + expect(result.warning).toContain('deprecated'); }); - it('append /api/v0 to Staging URL without trailing slash', () => { - expect(appendApiVersionForGraph('https://staging.api.thegraph.com/ipfs')).toBe( - 'https://staging.api.thegraph.com/ipfs/api/v0', - ); + it('returns default URL with warning for deprecated ipfs.testnet.thegraph.com URL', () => { + const result = getGraphIpfsUrl('https://ipfs.testnet.thegraph.com/abc'); + expect(result.ipfsUrl).toEqual(DEFAULT_IPFS_URL); + expect(result.warning).toContain('deprecated'); }); - it('do nothing if Prod URL has /api/v0', () => { - expect(appendApiVersionForGraph('https://api.thegraph.com/ipfs/api/v0')).toBe( - 'https://api.thegraph.com/ipfs/api/v0', - ); + it('returns default URL with warning for deprecated ipfs.network.thegraph.com URL', () => { + const result = getGraphIpfsUrl('https://ipfs.network.thegraph.com/xyz'); + expect(result.ipfsUrl).toEqual(DEFAULT_IPFS_URL); + expect(result.warning).toContain('deprecated'); }); - it('do nothing if Prod URL has no /ipfs', () => { - expect(appendApiVersionForGraph('https://api.thegraph.com')).toBe('https://api.thegraph.com'); + it('returns default URL with warning for invalid URL', () => { + const result = getGraphIpfsUrl('not-a-valid-url'); + expect(result.ipfsUrl).toEqual(DEFAULT_IPFS_URL); + expect(result.warning).toContain('Invalid IPFS URL'); }); - it('do nothing for non-graph endpoint', () => { - expect(appendApiVersionForGraph('https://ipfs.saihaj.dev/')).toBe('https://ipfs.saihaj.dev/'); + it('preserves non-deprecated graph endpoints', () => { + const url = 'https://ipfs.thegraph.com/ipfs'; + expect(getGraphIpfsUrl(url)).toEqual({ + ipfsUrl: DEFAULT_IPFS_URL, + }); }); - it('do nothing for non-graph endpoint ending with /ipfs', () => { - expect(appendApiVersionForGraph('https://ipfs.saihaj.dev/ipfs/')).toBe( - 'https://ipfs.saihaj.dev/ipfs/', - ); + it('preserves third-party IPFS endpoints', () => { + const url = 'https://ipfs.example.com/api'; + expect(getGraphIpfsUrl(url)).toEqual({ + ipfsUrl: url, + }); }); }); diff --git a/packages/cli/src/command-helpers/compiler.ts b/packages/cli/src/command-helpers/compiler.ts index cd684068f..46d4f0f3d 100644 --- a/packages/cli/src/command-helpers/compiler.ts +++ b/packages/cli/src/command-helpers/compiler.ts @@ -4,6 +4,7 @@ import Compiler from '../compiler/index.js'; import { GRAPH_CLI_SHARED_HEADERS } from '../constants.js'; import Protocol from '../protocols/index.js'; import { createIpfsClient } from '../utils.js'; +import { getGraphIpfsUrl } from './ipfs.js'; interface CreateCompilerOptions { ipfs: string | URL | undefined; @@ -16,22 +17,6 @@ interface CreateCompilerOptions { protocol: Protocol; } -/** - * Appends /api/v0 to the end of a The Graph IPFS URL - */ -export function appendApiVersionForGraph(inputString: string) { - // Check if the input string is a valid The Graph IPFS URL - const pattern = /^(https?:\/\/)?([\w-]+\.)+thegraph\.com\/ipfs\/?$/; - if (pattern.test(inputString)) { - // account for trailing slash - if (inputString.endsWith('/')) { - return inputString.slice(0, -1) + '/api/v0'; - } - return inputString + '/api/v0'; - } - return inputString; -} - // Helper function to construct a subgraph compiler export function createCompiler( manifest: string, @@ -57,7 +42,7 @@ The IPFS URL must be of the following format: http(s)://host[:port]/[path]`); // Connect to the IPFS node (if a node address was provided) const ipfsClient = ipfs ? createIpfsClient({ - url: appendApiVersionForGraph(ipfs.toString()), + url: getGraphIpfsUrl(ipfs.toString()).ipfsUrl, headers: { ...headers, ...GRAPH_CLI_SHARED_HEADERS, diff --git a/packages/cli/src/command-helpers/file-resolver.ts b/packages/cli/src/command-helpers/file-resolver.ts index 9a6b273f0..9d8d5fdff 100644 --- a/packages/cli/src/command-helpers/file-resolver.ts +++ b/packages/cli/src/command-helpers/file-resolver.ts @@ -1,7 +1,7 @@ import os from 'node:os'; import path from 'node:path'; import fs from 'fs-extra'; -import { DEFAULT_IPFS_URL } from './ipfs.js'; +import { getGraphIpfsUrl } from './ipfs.js'; export interface FileSource { path: string; @@ -39,7 +39,7 @@ export async function resolveFile( try { // If it's an IPFS hash (Qm...) if (source.startsWith('Qm')) { - const response = await fetch(`${DEFAULT_IPFS_URL}/cat?arg=${source}`); + const response = await fetch(`${getGraphIpfsUrl().ipfsUrl}/cat?arg=${source}`); if (!response.ok) { throw new Error(`failed to fetch from IPFS: ${response.statusText}`); } diff --git a/packages/cli/src/command-helpers/ipfs.ts b/packages/cli/src/command-helpers/ipfs.ts index 6e3886285..e384ed182 100644 --- a/packages/cli/src/command-helpers/ipfs.ts +++ b/packages/cli/src/command-helpers/ipfs.ts @@ -1,3 +1,47 @@ -const DEFAULT_IPFS_URL = 'https://api.thegraph.com/ipfs/api/v0' as const; +const DEFAULT_IPFS_URL = 'https://ipfs.thegraph.com/ipfs/api/v0' as const; -export { DEFAULT_IPFS_URL }; +/** + * Validates supplied IPFS URL and provides warnings for deprecated/invalid URLs + * @param ipfsUrl - The IPFS URL to validate, can be undefined + * @returns An object with the validated URL and optional warning message + */ +export function getGraphIpfsUrl(ipfsUrl?: string): { ipfsUrl: string; warning?: string } { + if (!ipfsUrl) { + return { ipfsUrl: DEFAULT_IPFS_URL }; + } + + // trim trailing slash + ipfsUrl = ipfsUrl.replace(/\/+$/, ''); + + try { + new URL(ipfsUrl); + + const deprecatedPatterns = [ + /^https?:\/\/ipfs\.testnet\.thegraph\.com.*/, + /^https?:\/\/ipfs\.network\.thegraph\.com.*/, + /^https?:\/\/api\.thegraph\.com\/ipfs.*/, + ]; + + const isDeprecated = deprecatedPatterns.some(pattern => pattern.test(ipfsUrl)); + if (isDeprecated) { + return { + ipfsUrl: DEFAULT_IPFS_URL, + warning: `IPFS URL ${ipfsUrl} is deprecated. Using default URL instead: ${DEFAULT_IPFS_URL}`, + }; + } + + // if default URL - make sure it ends with /api/v0 + if (DEFAULT_IPFS_URL.startsWith(ipfsUrl)) { + return { + ipfsUrl: DEFAULT_IPFS_URL, + }; + } + + return { ipfsUrl }; + } catch (e) { + return { + ipfsUrl: DEFAULT_IPFS_URL, + warning: `Invalid IPFS URL: ${ipfsUrl}. Using default URL instead: ${DEFAULT_IPFS_URL}`, + }; + } +} diff --git a/packages/cli/src/commands/build.ts b/packages/cli/src/commands/build.ts index 9d0f22497..cb27ad3d1 100644 --- a/packages/cli/src/commands/build.ts +++ b/packages/cli/src/commands/build.ts @@ -2,6 +2,7 @@ import { filesystem } from 'gluegun'; import { Args, Command, Flags } from '@oclif/core'; import { createCompiler } from '../command-helpers/compiler.js'; import * as DataSourcesExtractor from '../command-helpers/data-sources.js'; +import { getGraphIpfsUrl } from '../command-helpers/ipfs.js'; import { updateSubgraphNetwork } from '../command-helpers/network.js'; import debug from '../debug.js'; import Protocol from '../protocols/index.js'; @@ -86,9 +87,13 @@ export default class BuildCommand extends Command { const identifierName = protocol.getContract()!.identifierName(); await updateSubgraphNetwork(manifest, network, networkFile, identifierName); } + const { ipfsUrl, warning } = getGraphIpfsUrl(ipfs); + if (warning) { + this.warn(warning); + } const compiler = createCompiler(manifest, { - ipfs, + ipfs: ipfsUrl, outputDir, outputFormat, skipMigrations, diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 75bbbe5d6..f8c6d0909 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -1,7 +1,7 @@ import path from 'node:path'; import { Args, Command, Flags } from '@oclif/core'; import * as DataSourcesExtractor from '../command-helpers/data-sources.js'; -import { DEFAULT_IPFS_URL } from '../command-helpers/ipfs.js'; +import { getGraphIpfsUrl } from '../command-helpers/ipfs.js'; import { assertGraphTsVersion, assertManifestApiVersion } from '../command-helpers/version.js'; import debug from '../debug.js'; import Protocol from '../protocols/index.js'; @@ -42,7 +42,7 @@ export default class CodegenCommand extends Command { ipfs: Flags.string({ summary: 'IPFS node to use for fetching subgraph data.', char: 'i', - default: DEFAULT_IPFS_URL, + default: getGraphIpfsUrl().ipfsUrl, }), 'uncrashable-config': Flags.file({ summary: 'Directory for uncrashable config.', @@ -89,6 +89,11 @@ export default class CodegenCommand extends Command { this.error(e, { exit: 1 }); } + const { ipfsUrl, warning } = getGraphIpfsUrl(ipfs); + if (warning) { + this.warn(warning); + } + const generator = new TypeGenerator({ subgraphManifest: manifest, outputDir, @@ -97,7 +102,7 @@ export default class CodegenCommand extends Command { uncrashable, subgraphSources, uncrashableConfig: uncrashableConfig || 'uncrashable-config.yaml', - ipfsUrl: ipfs, + ipfsUrl, }); // Watch working directory for file updates or additions, trigger diff --git a/packages/cli/src/commands/deploy.ts b/packages/cli/src/commands/deploy.ts index 599c80073..5f6a65dde 100644 --- a/packages/cli/src/commands/deploy.ts +++ b/packages/cli/src/commands/deploy.ts @@ -3,9 +3,9 @@ import { URL } from 'node:url'; import { print, prompt } from 'gluegun'; import { Args, Command, Flags } from '@oclif/core'; import { identifyDeployKey } from '../command-helpers/auth.js'; -import { appendApiVersionForGraph, createCompiler } from '../command-helpers/compiler.js'; +import { createCompiler } from '../command-helpers/compiler.js'; import * as DataSourcesExtractor from '../command-helpers/data-sources.js'; -import { DEFAULT_IPFS_URL } from '../command-helpers/ipfs.js'; +import { getGraphIpfsUrl } from '../command-helpers/ipfs.js'; import { createJsonRpcClient } from '../command-helpers/jsonrpc.js'; import { updateSubgraphNetwork } from '../command-helpers/network.js'; import { chooseNodeUrl } from '../command-helpers/node.js'; @@ -60,7 +60,7 @@ export default class DeployCommand extends Command { ipfs: Flags.string({ summary: 'Upload build results to an IPFS node.', char: 'i', - default: DEFAULT_IPFS_URL, + default: getGraphIpfsUrl().ipfsUrl, }), 'ipfs-hash': Flags.string({ summary: 'IPFS hash of the subgraph manifest to deploy.', @@ -228,9 +228,12 @@ export default class DeployCommand extends Command { // we are provided the IPFS hash, so we deploy directly if (ipfsHash) { - // Connect to the IPFS node (if a node address was provided) + const { ipfsUrl, warning } = getGraphIpfsUrl(ipfs); + if (warning) { + this.warn(warning); + } const ipfsClient = createIpfsClient({ - url: appendApiVersionForGraph(ipfs.toString()), + url: ipfsUrl, headers: { ...headers, ...GRAPH_CLI_SHARED_HEADERS, @@ -277,8 +280,12 @@ export default class DeployCommand extends Command { await updateSubgraphNetwork(manifest, network, networkFile, identifierName); } + const { ipfsUrl, warning } = getGraphIpfsUrl(ipfs); + if (warning) { + this.warn(warning); + } const compiler = createCompiler(manifest, { - ipfs, + ipfs: ipfsUrl, headers, outputDir, outputFormat: 'wasm', diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 8a5e23ab0..80507b9d6 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -4,10 +4,9 @@ import path from 'node:path'; import { filesystem, print, prompt, system } from 'gluegun'; import { Args, Command, Flags } from '@oclif/core'; import { Network } from '@pinax/graph-networks-registry'; -import { appendApiVersionForGraph } from '../command-helpers/compiler.js'; import { ContractService } from '../command-helpers/contracts.js'; import { resolveFile } from '../command-helpers/file-resolver.js'; -import { DEFAULT_IPFS_URL } from '../command-helpers/ipfs.js'; +import { getGraphIpfsUrl } from '../command-helpers/ipfs.js'; import { initNetworksConfig } from '../command-helpers/network.js'; import { chooseNodeUrl } from '../command-helpers/node.js'; import { PromptManager } from '../command-helpers/prompt-manager.js'; @@ -122,7 +121,7 @@ export default class InitCommand extends Command { ipfs: Flags.string({ summary: 'IPFS node to use for fetching subgraph data.', char: 'i', - default: DEFAULT_IPFS_URL, + default: getGraphIpfsUrl().ipfsUrl, }), }; @@ -200,6 +199,11 @@ export default class InitCommand extends Command { deploy: yarn ? 'yarn deploy' : 'npm run deploy', }; + const { ipfsUrl, warning } = getGraphIpfsUrl(ipfs); + if (warning) { + this.warn(warning); + } + // If all parameters are provided from the command-line, // go straight to creating the subgraph from the example if (fromExample && subgraphName && directory) { @@ -299,7 +303,7 @@ export default class InitCommand extends Command { spkgPath, skipInstall, skipGit, - ipfsUrl: ipfs, + ipfsUrl, }, { commands, addContract: false }, ); @@ -340,11 +344,15 @@ export default class InitCommand extends Command { contractName, startBlock, spkgPath, - ipfsUrl: ipfs, + ipfsUrl, }); if (!answers) { this.exit(1); } + const { ipfsUrl: suppliedIpfsUrl, warning } = getGraphIpfsUrl(answers.ipfs); + if (warning) { + this.warn(warning); + } await initSubgraphFromContract.bind(this)( { @@ -361,7 +369,7 @@ export default class InitCommand extends Command { spkgPath: answers.spkgPath, skipInstall, skipGit, - ipfsUrl: answers.ipfs, + ipfsUrl: suppliedIpfsUrl, }, { commands, addContract: true }, ); @@ -1258,7 +1266,7 @@ async function initSubgraphFromContract( if (isComposedSubgraph) { try { const ipfsClient = createIpfsClient({ - url: appendApiVersionForGraph(ipfsUrl), + url: ipfsUrl, headers: { ...GRAPH_CLI_SHARED_HEADERS, }, diff --git a/packages/cli/src/commands/publish.ts b/packages/cli/src/commands/publish.ts index aadc7b6ea..0d595dc0c 100644 --- a/packages/cli/src/commands/publish.ts +++ b/packages/cli/src/commands/publish.ts @@ -5,7 +5,7 @@ import { Args, Command, Flags, ux } from '@oclif/core'; import { URL, URLSearchParams } from '@whatwg-node/fetch'; import { createCompiler } from '../command-helpers/compiler.js'; import * as DataSourcesExtractor from '../command-helpers/data-sources.js'; -import { DEFAULT_IPFS_URL } from '../command-helpers/ipfs.js'; +import { getGraphIpfsUrl } from '../command-helpers/ipfs.js'; import Protocol from '../protocols/index.js'; export default class PublishCommand extends Command { @@ -34,7 +34,7 @@ export default class PublishCommand extends Command { ipfs: Flags.string({ summary: 'Upload build results to an IPFS node.', char: 'i', - default: DEFAULT_IPFS_URL, + default: getGraphIpfsUrl().ipfsUrl, }), 'ipfs-hash': Flags.string({ summary: 'IPFS hash of the subgraph manifest to deploy.', @@ -128,6 +128,11 @@ export default class PublishCommand extends Command { ); } + const { ipfsUrl, warning } = getGraphIpfsUrl(ipfs); + if (warning) { + this.warn(warning); + } + if (ipfsHash) { await this.publishWithBrowser({ ipfsHash, @@ -148,7 +153,7 @@ export default class PublishCommand extends Command { } const compiler = createCompiler(manifest, { - ipfs, + ipfs: ipfsUrl, outputDir: 'build/', outputFormat: 'wasm', skipMigrations: false, diff --git a/packages/cli/src/type-generator.ts b/packages/cli/src/type-generator.ts index b38d5c35b..715125aec 100644 --- a/packages/cli/src/type-generator.ts +++ b/packages/cli/src/type-generator.ts @@ -8,8 +8,8 @@ import prettier from 'prettier'; import uncrashable from '@float-capital/float-subgraph-uncrashable/src/Index.bs.js'; import DataSourceTemplateCodeGenerator from './codegen/template.js'; import { GENERATED_FILE_NOTE, ModuleImports } from './codegen/typescript.js'; -import { appendApiVersionForGraph } from './command-helpers/compiler.js'; import { displayPath } from './command-helpers/fs.js'; +import { getGraphIpfsUrl } from './command-helpers/ipfs.js'; import { Spinner, step, withSpinner } from './command-helpers/spinner.js'; import { GRAPH_CLI_SHARED_HEADERS } from './constants.js'; import debug from './debug.js'; @@ -112,7 +112,7 @@ export default class TypeGenerator { if (this.options.subgraphSources.length > 0) { const ipfsClient = createIpfsClient({ - url: appendApiVersionForGraph(this.options.ipfsUrl.toString()), + url: getGraphIpfsUrl(this.options.ipfsUrl.toString()).ipfsUrl, headers: { ...GRAPH_CLI_SHARED_HEADERS, }, diff --git a/website/src/components/dropzone.tsx b/website/src/components/dropzone.tsx index 3f2cb16ed..87ec1b3c5 100644 --- a/website/src/components/dropzone.tsx +++ b/website/src/components/dropzone.tsx @@ -114,7 +114,7 @@ export function SubgraphImageDropZone(props: React.InputHTMLAttributes