Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 24 additions & 18 deletions packages/toolkit/src/repository/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,25 +421,31 @@ export class DappnodeRepository extends ApmRepository {
carReader: CarReader;
root: CID;
}> {
// 1. Download the CAR
const url = `${this.gatewayUrl}/ipfs/${hash}?format=car`;
const res = await fetch(url, {
headers: { Accept: "application/vnd.ipld.car" }
});
if (!res.ok) throw new Error(`Gateway error: ${res.status} ${res.statusText}`);

// 2. Parse into a CarReader
const bytes = new Uint8Array(await res.arrayBuffer());
const carReader = await CarReader.fromBytes(bytes);

// 3. Verify the root CID
const roots = await carReader.getRoots();
const root = roots[0];
if (roots.length !== 1 || root.toString() !== CID.parse(hash).toString()) {
throw new Error(`UNTRUSTED CONTENT: expected root ${hash}, got ${roots}`);
const url = `${this.gatewayUrl}/ipfs/${hash}?format=car&dag-scope=all&car-order=dfs&car-dups=n`;
let lastError: unknown;
for (let attempt = 0; attempt < 3; attempt++) {
try {
const res = await fetch(url, {
headers: { Accept: "application/vnd.ipld.car; version=1; order=dfs; dups=n" }
});
if (!res.ok) throw new Error(`Gateway error: ${res.status} ${res.statusText}`);

const bytes = new Uint8Array(await res.arrayBuffer());
const carReader = await CarReader.fromBytes(bytes);

const expected = CID.parse(hash.replace(/^\/ipfs\//, ""));
const rootBlock = await carReader.get(expected);
if (!rootBlock) throw new Error(`CAR missing requested root block ${expected}`);
const root = expected // use the CID I asked for as the root for exporter

return { carReader, root };
} catch (e) {
lastError = e;
// Wait a bit before retrying
if (attempt < 2) await new Promise(r => setTimeout(r, 500));
Copy link

Copilot AI Sep 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magic number 500 (milliseconds) should be defined as a named constant to improve readability and maintainability.

Copilot uses AI. Check for mistakes.
}
}

return { carReader, root };
throw lastError instanceof Error ? lastError : new Error(String(lastError));
}

/**
Expand Down
Loading