DEVELOPER DOCS
Uploading NFTs

Uploading NFTs To Bundlr

When you use Bundlr to store NFT data on Arweave, you’re guaranteed your NFT will be both permanent and immutable. Here’s how you do it.

NFT Assets

There are generally three parts to an NFT:

  1. Smart contract
  2. NFT metadata
  3. NFT assets

The smart contract can be on any chain, the metadata and assets are stored on an external storage provider. The smart contract stores a pointer to the NFT metadata, and then the NFT metadata contains links to the NFT assets.

In the example above for the Bundlr Developer Quests NFT (opens in a new tab), there is a name and description that are shown on platforms like Opensea when the NFT is viewed. The image parameter points to a static image of the NFT. The animation_url parameter is optional and points to a video, song, or HTML animation file.

Steps To Creating An NFT

  1. Upload your assets to Bundlr
  2. Embed the URLs to the assets in NFT metadata
  3. Use the URL to the NFT metadata to mint your NFT. This guide does not cover the smart contract setup, if you’re unsure of how to do this, Thirdweb (opens in a new tab) has free, audited contracts available for use.

Uploading Assets

After installing the Bundlr SDK, use the following to upload your assets. Make sure to set the Content-Type value to match the content type of your asset.

import Bundlr from "@bundlr-network/client";
import * as fs from "fs";
import dotenv from "dotenv";
dotenv.config();
 
const privateKey = process.env.PRIVATE_KEY;
// One of https://docs.bundlr.network/overview/supported-tokens
const currency = "matic";
 
// Devnet (uploads are kept for 60 days)
const bundlr = new Bundlr("http://devnet.bundlr.network", currency, privateKey, {
	providerUrl: "https://rpc-mumbai.maticvigil.com", // MATIC Devnet, change if using a different currency
});
 
// Node 2 (uploads are permanent and immutable)
// const bundlr = new Bundlr("http://devnet.bundlr.network", currency, privateKey);
 
const fileToUpload = "./myNFT.png";
const tags = [{ name: "Content-Type", value: "image/png" }];
 
// Get size of file
const { size } = await fs.promises.stat(fileToUpload);
// Get cost to upload "size" bytes
const price = await bundlr.getPrice(size);
console.log(
	`Uploading ${size} bytes costs ${bundlr.utils.fromAtomic(price)} ${currency}`,
);
// Fund the node
await bundlr.fund(price);
 
// Upload metadata
try {
	const response = await bundlr.uploadFile(fileToUpload, tags);
	console.log(`File uploaded ==> https://arweave.net/${response.id}`);
} catch (e) {
	console.log("Error uploading file ", e);
}

Creating Metadata

Embed the URLs generated from the above script into your NFT metadata. The following example is from the Bundlr Quests NFT.

{
	"name": "Bundlr Quests",
	"description": "Bundlr Quest 2: OnlyBundlr",
	"image": "https://arweave.net/737m0bA1kW4BlIJOg_kOGUpHAAI-3Ec9bdo8S_xTFKI",
	"animation_url": "https://arweave.net/peRdpP3pjyFQ6m4Hca5fZY5zgz7RSlE86j-_5BEwnW0",
	"background_color": "FEF4EE"
}

Uploading Metadata

Finally, upload your NFT metadata to Bundlr and use the URL generated to mint the NFT.

import Bundlr from "@bundlr-network/client";
import * as fs from "fs";
import dotenv from "dotenv";
dotenv.config();
 
const privateKey = process.env.PRIVATE_KEY;
// One of https://docs.bundlr.network/overview/supported-tokens
const currency = "matic";
 
// Devnet (uploads are kept for 60 days)
const bundlr = new Bundlr("http://devnet.bundlr.network", currency, privateKey, {
	providerUrl: "https://rpc-mumbai.maticvigil.com", // MATIC Devnet, change if using a different currency
});
 
// Node 2 (uploads are permanent and immutable)
// const bundlr = new Bundlr("http://devnet.bundlr.network", currency, privateKey);
 
const fileToUpload = "./metadata.json";
const tags = [{ name: "Content-Type", value: "application/json" }];
 
// Get size of file
const { size } = await fs.promises.stat(fileToUpload);
// Get cost to upload "size" bytes
const price = await bundlr.getPrice(size);
console.log(
	`Uploading ${size} bytes costs ${bundlr.utils.fromAtomic(price)} ${currency}`,
);
// Fund the node
await bundlr.fund(price);
 
// Upload metadata
try {
	const response = await bundlr.uploadFile(fileToUpload, tags);
	console.log(`File uploaded ==> https://arweave.net/${response.id}`);
} catch (e) {
	console.log("Error uploading file ", e);
}