Skip to content

Commit

Permalink
Use gateway endpoint to fetch files
Browse files Browse the repository at this point in the history
  • Loading branch information
dappnodedev committed Sep 4, 2024
1 parent a1e80b2 commit 44cf883
Show file tree
Hide file tree
Showing 4 changed files with 906 additions and 70 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,8 @@
"tsx": "^4.17.0",
"typescript": "^5.5.4"
},
"packageManager": "[email protected]"
"packageManager": "[email protected]",
"resolutions": {
"protons-runtime": "5.5.0"
}
}
1 change: 1 addition & 0 deletions packages/toolkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
},
"dependencies": {
"@dappnode/types": "workspace:^0.1.0",
"@helia/verified-fetch": "1.4.3",
"@ipld/car": "^5.3.2",
"esm": "^3.2.25",
"ethers": "^6.10.0",
Expand Down
45 changes: 19 additions & 26 deletions packages/toolkit/src/repository/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { getReleaseSignatureStatus, serializeIpfsDirectory } from "./releaseSign
import { isEnsDomain } from "../isEnsDomain.js";
import { dappnodeRegistry } from "./params.js";
import { ethers } from "ethers";
import { createVerifiedFetch } from "@helia/verified-fetch";

const source = "ipfs" as const;

Expand All @@ -42,6 +43,7 @@ const source = "ipfs" as const;
export class DappnodeRepository extends ApmRepository {
protected ipfs: KuboRPCClient;
protected timeout: number;
protected ipfsGatewayUrl: string;

/**
* Constructs an instance of DappnodeRepository
Expand All @@ -51,6 +53,7 @@ export class DappnodeRepository extends ApmRepository {
constructor(ipfsUrl: string, ethersProvider: ethers.AbstractProvider, timeout?: number) {
super(ethersProvider);
this.timeout = timeout || 30 * 1000;
this.ipfsGatewayUrl = ipfsUrl;
this.ipfs = create({ url: ipfsUrl, timeout: this.timeout });
}

Expand Down Expand Up @@ -231,9 +234,9 @@ export class DappnodeRepository extends ApmRepository {
}

// Process matched entries. If multiple files are allowed, and more than one file matches, we parse all of them.
const { maxSize: maxLength, format } = fileConfig;
const { format } = fileConfig;
const contents = await Promise.all(
matchingEntries.map((entry) => this.writeFileToMemory(entry.cid.toString(), maxLength))
matchingEntries.map((entry) => this.getVerifiedContentFromGateway(entry.cid.toString()))
);

// If multiple files are allowed, we return an array of parsed assets.
Expand All @@ -246,34 +249,22 @@ export class DappnodeRepository extends ApmRepository {
* This function is intended for small files.
*
* @param hash - The content identifier (CID) of the file to download.
* @param maxLength - The maximum length of the file in bytes. If the downloaded file exceeds this length, an error is thrown.
* @returns The downloaded file content as a UTF8 string.
* @throws Error when the maximum size is exceeded.
* @see catString
* @see catCarReaderToMemory
*/
public async writeFileToMemory(hash: string, maxLength?: number): Promise<string> {
const chunks = [];
const { carReader, root } = await this.getAndVerifyContentFromGateway(hash);
const content = await this.unpackCarReader(carReader, root);
for await (const chunk of content) chunks.push(chunk);

// Concatenate the chunks into a single Uint8Array
let totalLength = 0;
chunks.forEach((chunk) => (totalLength += chunk.length));
const buffer = new Uint8Array(totalLength);
let offset = 0;
chunks.forEach((chunk) => {
buffer.set(chunk, offset);
offset += chunk.length;
private async getVerifiedContentFromGateway(hash: string): Promise<string> {
// TODO: Add max leght?
const cid = CID.parse(this.sanitizeIpfsPath(hash));

const customGatewayFetch = await createVerifiedFetch({
gateways: [this.ipfsGatewayUrl]
});

if (maxLength && buffer.length >= maxLength) throw Error(`Maximum size ${maxLength} bytes exceeded`);
const response = await customGatewayFetch(cid);

// Convert the Uint8Array to a string
// TODO: This assumes the data is UTF-8 encoded. If it's not, you will need a more complex conversion. Research which encoding is used by IPFS.
const decoder = new TextDecoder("utf-8");
return decoder.decode(buffer);
// Log the full response body (assuming it's text-based)
const content = await response.text();

return content;
}

/**
Expand Down Expand Up @@ -379,7 +370,9 @@ export class DappnodeRepository extends ApmRepository {

public async list(hash: string): Promise<IPFSEntry[]> {
const files: IPFSEntry[] = [];
const dagGet = await this.ipfs.dag.get(CID.parse(this.sanitizeIpfsPath(hash)), { timeout: this.timeout });
const cid = CID.parse(this.sanitizeIpfsPath(hash));

const dagGet = await this.ipfs.dag.get(cid, { timeout: this.timeout });
if (dagGet.value.Links)
for (const link of dagGet.value.Links)
files.push({
Expand Down
Loading

0 comments on commit 44cf883

Please sign in to comment.