IPFS Content IDs
In addition to using Irys transaction IDs, you can also use IPFS Content IDs (CIDs) when addressing data on Irys.
Irys does not currently verify that CIDs match their uploaded data. This will be added in a future release.
Content IDs vs transaction IDs
IPFS and Irys take a different approach to identifying data, IPFS uses Content Identifiers (CIDs) and Irys uses transaction IDs.
- IPFS Content Identifiers (CIDs) are generated by hashing the content being uploaded. The same data uploaded twice will generate the same CID.
- Irys transaction IDs are generated by hashing the content + metadata being uploaded. All uploads have a unique transaction ID.
Uploading with a CID
To upload data to Irys using a CID, embed it as the value of the IPFS-CID
tag when uploading data.
This code example generates a CID using the ipfs-only-hash
package which uses the SHA-256 algorithm by default. IPFS
also allows CIDs to be generated using SHA3 and Blake2, all of which are supported when uploading to Irys.
import IPFS from "ipfs-only-hash";
const generateCID = async (content) => {
return await IPFS.of(content);
};
const uploadToIrysWithCID = async () => {
// See: https://docs.irys.xyz/irys-sdk#connecting-to-irys
const irys = await getIrys();
const dataToUpload = "Irys + IPFS Content ID";
const contentID = await generateCID(dataToUpload);
console.log(`ContentID=${contentID}`);
const tags = [
{ name: "Content-Type", value: "text/html" },
{ name: "IPFS-CID", value: contentID },
];
const receipt = await irys.upload(dataToUpload, { tags: tags });
// You can download using either the Irys transaction ID or IPFS Content ID
console.log(`Transaction ID URL https://gateway.irys.xyz/${receipt.id}`);
console.log(`Content ID URL https://gateway.irys.xyz/ipfs/${contentID}`);
};
Downloading with a CID
To download data tagged with a CID, request it from the Irys gateway using a URL in the format https://gateway.irys.xyz/ipfs/:contentID
.
If the same CID is assigned to more than one transaction, the Irys gateway will always return the one with the earliest timestamp.
const fetchData = async (ipfsCID) => {
const url = `https://gateway.irys.xyz/ipfs/${ipfsCID}`;
console.log(`URL: ${url}`);
const response = await fetch(url);
const data = await response.text();
console.log(`DATA: ${data}`);
};
Migrating data from IPFS to Irys
You can migrate data from IPFS to Irys by first downloading the data from an IPFS gateway and then uploading it to Irys. Users can choose to tag the uploads with the original IPFS CID and continue to retrieve data using the CID, or switch to using Irys transaction IDs.
This code example shows how to:
- Download data from an IPFS gateway
- Determine the data's content type (for example:
image/png
) - Re-upload the data to Irys while tagging it with the existing content type
Prior to uploading, users must fund an Irys node. Most users will choose to up-front fund where they pre-fund an Irys node with sufficient tokens to cover all data being migrated. Users can also choose to lazy-fund the uploads where you fund each separate upload.
import fetch from "node-fetch";
import { fileTypeFromBuffer } from "file-type";
import Irys from "@irys/sdk";
const uploadToIrysWithCID = async (dataToUpload, contentType, contentID) => {
// See: https://docs.irys.xyz/irys-sdk#connecting-to-irys
const irys = await getIrys();
const tags = [
{ name: "Content-Type", value: contentType },
{ name: "IPFS-CID", value: contentID },
];
const receipt = await irys.upload(dataToUpload, { tags: tags });
console.log(`Direct URL: https://gateway.irys.xyz/${receipt.id}`);
console.log(`Content ID URL: https://gateway.irys.xyz/ipfs/${contentID}`);
};
const downloadAndDetermineContentType = async (ipfsCID) => {
try {
const ipfsURL = `https://ipfs.io/ipfs/${ipfsCID}`;
const response = await fetch(ipfsURL);
const arrayBuffer = await response.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
const contentType = await fileTypeFromBuffer(buffer);
if (contentType) {
console.log(`Content Type: ${contentType.mime}`);
await uploadToIrysWithCID(buffer, contentType.mime, ipfsCID);
} else {
console.error("Unable to determine content type");
}
} catch (error) {
console.error("Error:", error);
}
};
const ipfsCID = "QmUgL4YbnW9vMWZXLdAFzgxJwxpxJapZRLpjoT2ubU5WmF";
downloadAndDetermineContentType(ipfsCID);