-
Notifications
You must be signed in to change notification settings - Fork 228
Update IPFS endpoints #2055
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Update IPFS endpoints #2055
Changes from 6 commits
bc83ee9
98703c3
f9b5238
719bd67
9e00a1a
dc97cb5
a1fd202
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@graphprotocol/graph-cli': patch | ||
--- | ||
|
||
updated IPFS endpoints, added deprecation notice when using old ones |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is wrong. The |
||
if (!response.ok) { | ||
throw new Error(`failed to fetch from IPFS: ${response.statusText}`); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The IPFS URL should just be https://ipfs.thegraph.com For GET requests (read a file), you'd append For POST requests (adding a file) you'd append |
||
|
||
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}`, | ||
}; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This (and all other package.json's below) should use
--ipfs https://ipfs.thegraph.com