Skip to content

Commit 37dffcb

Browse files
authored
Merge pull request #8 from y86993/master
Add Header to Subgraph API Call, Switch IPFS Gateway to Filebase, and Enhance Error Handling
2 parents 22c42e8 + f62e654 commit 37dffcb

File tree

5 files changed

+93
-69
lines changed

5 files changed

+93
-69
lines changed

.env.example

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ ENS_TOKEN_LIST_NAME=t2crtokens.eth
66

77
LATEST_TOKEN_LIST_URL=https://t2crtokens.eth.limo
88

9-
PROVIDER_URL=https://mainnet.infura.io/v3/<api-key>
10-
IPFS_GATEWAY=https://ipfs.kleros.io
9+
PROVIDER_URL=https://mainnet.infura.io/v3/<your-key>
10+
IPFS_GATEWAY=https://cdn.kleros.link
11+
FILEBASE_TOKEN=
1112
WALLET_KEY=
1213

1314
# Optional. If not provided, 300 seconds (5 minutes will be used).
1415
POLL_PERIOD_SECONDS=300
16+

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,23 @@
1717
"@secretlint/secretlint-rule-preset-recommend": "^2.1.0",
1818
"@secretlint/secretlint-rule-secp256k1-privatekey": "^2.1.0",
1919
"@types/jest": "^26.0.4",
20-
"@typescript-eslint/eslint-plugin": "^3.6.0",
21-
"@typescript-eslint/parser": "^3.6.0",
2220
"@types/level": "^6.0.2",
23-
"@types/lodash": "^4.14.157",
24-
"@types/node": "^14.0.23",
21+
"@types/lodash": "^4.17.4",
22+
"@types/node": "^20.12.12",
2523
"@types/node-fetch": "^2.5.7",
2624
"@types/sharp": "^0.28.0",
25+
"@typescript-eslint/eslint-plugin": "^3.6.0",
26+
"@typescript-eslint/parser": "^3.6.0",
2727
"eslint": "^7.4.0",
2828
"eslint-config-prettier": "^6.11.0",
2929
"eslint-plugin-prettier": "^3.1.4",
3030
"prettier": "^2.0.5",
3131
"secretlint": "^2.1.0",
32-
"typescript": "^3.9.6"
32+
"typescript": "^5.4.5"
3333
},
3434
"dependencies": {
3535
"@ensdomains/ens-contracts": "^0.0.22",
36+
"@filebase/client": "^0.0.5",
3637
"@uniswap/token-lists": "^1.0.0-beta.33",
3738
"ajv": "^6.12.3",
3839
"content-hash": "^2.5.2",

src/index.ts

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ const tryGet = async (key: string, db: Level<string, string>) => {
2828
}
2929
}
3030

31+
interface IPFSResponse {
32+
hash: string
33+
}
34+
3135
async function main() {
3236
const db = new Level('./db')
3337
console.info()
@@ -62,57 +66,75 @@ async function main() {
6266
console.info(` got cache: ipfs://${cachedMultihash}`)
6367
continue
6468
} else {
65-
const imageBuffer = await (
66-
await fetch(`${process.env.IPFS_GATEWAY}${token.logoURI}`)
67-
).buffer()
69+
const imageUrl = `${process.env.IPFS_GATEWAY}${token.logoURI}`
70+
console.info(`Fetching image from URL: ${imageUrl}`)
71+
const imageBuffer = await (await fetch(imageUrl)).buffer()
72+
73+
try {
74+
const imageSharp = sharp(imageBuffer)
75+
const metadata = await imageSharp.metadata()
76+
77+
console.info(`Image metadata:`, metadata)
78+
79+
if (!metadata.format) {
80+
throw new Error('Unsupported image format')
81+
}
82+
83+
const resizedImageBuffer = await imageSharp.resize(64, 64).png().toBuffer()
6884

69-
const imageSharp = await sharp(imageBuffer).resize(64, 64).png()
70-
const resizedImageBuffer = await imageSharp.toBuffer()
85+
console.info(` Pinning shrunk image to ${process.env.IPFS_GATEWAY}`)
86+
let ipfsResponse: IPFSResponse[] | null = null
7187

72-
console.info(` Pinning shrunk image to ${process.env.IPFS_GATEWAY}`)
73-
let ipfsResponse
88+
for (let attempt = 1; attempt <= 10; attempt++) {
89+
try {
90+
ipfsResponse = await ipfsPublish(
91+
`${token.symbol}.png`,
92+
resizedImageBuffer,
93+
)
94+
console.info(` Done.`)
95+
break
96+
} catch (err) {
97+
console.warn(
98+
` Failed to upload ${token.symbol} to gateway IPFS.`,
99+
err,
100+
)
101+
if (attempt === 5) {
102+
console.error(
103+
` Could not upload ${token.symbol} image to gateway IPFS after 5 attempts.`,
104+
)
105+
} else {
106+
console.warn(` Retrying ${attempt + 1} of ${5}`)
107+
}
108+
}
109+
}
74110

75-
for (let attempt = 1; attempt <= 10; attempt++)
76-
try {
77-
ipfsResponse = await ipfsPublish(
78-
`${token.symbol}.png`,
79-
resizedImageBuffer,
111+
if (!ipfsResponse) {
112+
console.error()
113+
throw new Error(
114+
`Failed to upload ${token.symbol} image to ipfs gateway. Halting`,
80115
)
81-
console.info(` Done.`)
82-
break
83-
} catch (err) {
84-
console.warn(
85-
` Failed to upload ${token.symbol} to gateway IPFS.`,
86-
err,
116+
}
117+
118+
const multihash = ipfsResponse[0].hash
119+
120+
if (ipfsResponse) {
121+
// Was successfully pinned to IPFS, no point in resubmitting.
122+
console.log(` Caching ${multihash}`)
123+
await db.put(
124+
cacheName(token.logoURI as string, token.symbol),
125+
multihash,
87126
)
88-
if (attempt === 5)
89-
console.error(
90-
` Could not upload ${token.symbol} image to gateway IPFS after 5 attempts.`,
91-
)
92-
else console.warn(` Retrying ${attempt + 1} of ${5}`)
93127
}
94128

95-
if (!ipfsResponse) {
96-
console.error()
97-
throw new Error(
98-
`Failed to upload ${token.symbol} image to ipfs gateway. Halting`,
99-
)
100-
}
101-
const multihash = ipfsResponse[0].hash
102-
103-
if (ipfsResponse) {
104-
// Was successfully pinned to IPFS, no point in resubmitting.
105-
console.log(` Caching ${multihash}`)
106-
await db.put(
107-
cacheName(token.logoURI as string, token.symbol),
108-
multihash,
109-
)
129+
tokensWithLogo.push({
130+
...token,
131+
logoURI: `ipfs://${multihash}`,
132+
})
133+
} catch (err) {
134+
console.error(`Failed to process image for token ${token.symbol}:`, err)
135+
console.error(`Token details:`, token)
136+
throw err // stop execution on error
110137
}
111-
112-
tokensWithLogo.push({
113-
...token,
114-
logoURI: `ipfs://${multihash}`,
115-
})
116138
}
117139
}
118140

@@ -127,4 +149,7 @@ async function main() {
127149
)
128150
}
129151

130-
main()
152+
main().catch((err) => {
153+
console.error('Unhandled error:', err)
154+
process.exit(1) // Added to ensure the script exits with an error code
155+
})

src/utils/get-tokens.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ const fetchTokensBatch = async (id: string): Promise<Item[]> => {
3939
{
4040
method: 'POST',
4141
body: JSON.stringify(subgraphQuery),
42+
headers: {
43+
'Content-Type': 'application/json',
44+
},
4245
},
4346
)
4447

src/utils/ipfs-publish.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,24 @@
1-
import fetch from 'node-fetch'
1+
import { File, FilebaseClient } from '@filebase/client';
2+
3+
const filebase = new FilebaseClient({
4+
token: process.env.FILEBASE_TOKEN ?? ""
5+
});
26

37
/**
4-
* Send file to IPFS network via the Kleros IPFS node
8+
* Send file to IPFS network via Filebase
59
* @param {string} fileName - The name that will be used to store the file. This is useful to preserve extension type.
610
* @param {ArrayBuffer} data - The raw data from the file to upload.
711
* @returns {object} ipfs response. Should include the hash and path of the stored item.
812
*/
913
async function ipfsPublish(
1014
fileName: string,
1115
data: ArrayBuffer | Buffer,
12-
): Promise<Record<string, string>[]> {
13-
data = await Buffer.from(data)
16+
): Promise<{ hash: string; path: string }[]> { // Return an array of objects with a hash property
17+
const buffer = Buffer.from(data);
1418

15-
return (
16-
await (
17-
await fetch(`${process.env.IPFS_GATEWAY}/add`, {
18-
method: 'POST',
19-
body: JSON.stringify({
20-
fileName,
21-
buffer: data,
22-
}),
23-
headers: {
24-
'content-type': 'application/json',
25-
},
26-
})
27-
).json()
28-
).data
19+
const cid = await filebase.storeDirectory([new File([buffer], fileName)]);
20+
21+
return [{ hash: cid, path: `${cid}/${fileName}` }]; // Return an array
2922
}
3023

3124
export default ipfsPublish

0 commit comments

Comments
 (0)