a manifold extension to port fully onchain an existing collection minted with offchain content
clgsms/scripts/fetch-metadata.js
JavaScript · 50 lines · 2 KBRAWDOWNLOAD
#!/usr/bin/env node
/**
* Build per-token metadata fragments from the original Arweave metadata.
*
* node scripts/fetch-metadata.js [outDir=meta] [from=1] [to=100]
*
* For each token it downloads the original JSON, drops the image fields (they
* are replaced onchain by the AVIF data URI), and writes the inner JSON
* fragment — no surrounding braces — to <outDir>/<id>.json. Those are the exact
* bytes storeArtwork expects as `metadata`, so each token keeps precisely the
* name, description and attributes it was minted with.
*
* Plain node, no chain access. Re-run it freely; review the fragments before
* uploading (scripts/store.js compares them byte for byte).
*/
import { mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
const BASE =
process.env.ARWEAVE_BASE ??
"https://arweave.net/2ydrm9ZHH7qxYrybOI4XeY9elm2JjpwSVXjcBhaZL6k";
const STRIP = ["image", "image_url", "image_details", "animation_url"];
const [outDir = process.env.META_DIR ?? "meta", from = "1", to = "100"] =
process.argv.slice(2);
mkdirSync(outDir, { recursive: true });
let total = 0;
for (let id = Number(from); id <= Number(to); id++) {
const res = await fetch(`${BASE}/${id}`);
if (!res.ok) throw new Error(`#${id}: HTTP ${res.status} from ${BASE}/${id}`);
const json = await res.json();
const dropped = STRIP.filter((k) => k in json);
for (const k of dropped) delete json[k];
const fragment = JSON.stringify(json).slice(1, -1); // drop the surrounding { }
const path = join(outDir, `${id}.json`);
writeFileSync(path, fragment);
total += fragment.length;
console.log(
`#${id}: ${fragment.length} B -> ${path}` +
(dropped.length > 0 ? ` (dropped ${dropped.join(", ")})` : " (no image field found!)"),
);
}
console.log(
`\n${total} bytes of metadata total. Review the fragments, then store them with\n` +
` npx hardhat run scripts/store.js --network <net>`,
);