Hosting NFT metadata on BTFS

Upload your NFT image and metadata JSON to BTFS — TRON's decentralized file network — and use the resulting URIs as your tokenURI.

📘

Prerequisites

BitTorrent File System (BTFS) is a decentralized file-sharing protocol built on the TRON network and the BitTorrent ecosystem. NFT metadata — JSON files describing each token's name, image, and attributes — is stored off-chain and referenced by URI from the contract's tokenURI function. BTFS provides one option for hosting that metadata in a way that does not depend on a single web host staying online.

This guide walks you through uploading both an image and a metadata JSON to BTFS, getting the URIs you can plug into your TRC-721 contract.

Where to host metadata: BTFS vs alternatives

OptionCostPersistenceDecentralization
BTFSPay in BTT per MB per monthAs long as BTT is paidDecentralized over BTFS network
IPFS + pinning service (e.g., Pinata)Subscription or pay-per-pinAs long as pinnedDecentralized over IPFS network
ArweaveOne-time payment for permanent storagePermanentDecentralized
Self-hosted CDNHosting feeAs long as you maintain the hostCentralized

BTFS is a natural choice within the TRON ecosystem.

Step 1 — Install and initialize BTFS

For installation steps, follow the BTFS installation instructions.

When btfs init initializes the local node, the command generates a TRON wallet account associated with the node. Check the TRON address corresponding to the wallet through btfs id.

BTFS init output showing the node's TRON address

Step 2 — Fund your BTFS node with BTT

Uploading files to BTFS uses BTT as the payment token. The current storage price is approximately 0.0037 BTT per MB per month (verify with the BTFS documentation for the latest rate). Files are split into 30 redundancy copies of which any 10 reconstruct the original — for the uploader this means the effective price is roughly 3 × 0.0037 BTT per MB per month.

First, deposit BTT into the node's TRON account, then transfer that BTT to the BTFS network's accounting system.

Set a wallet password

Set a password for the node wallet:

btfs wallet password <YOUR_PASSWORD>

Deposit BTT to the BTFS accounting system

The following command transfers BTT from the local BTFS node account to the BTFS network's accounting system. The minimum transfer amount is 10 BTT, and the unit is μBTT (1 BTT = 1,000,000 μBTT):

btfs wallet deposit -p <YOUR_PASSWORD> 10000000

Step 3 — Upload the image

Step 3.1 — Add the image to your local node

Prepare an image file (this guide uses coral.jpeg). Add it to the local BTFS node using reed-Solomon chunking:

btfs add --chunker=reed-solomon coral.jpeg
BTFS add output showing the resulting hash

The output includes a hash like QmUK9nwtLEiHBJ48HAZHNmSQ53U6ADbRhATxs2tomadwKw — copy this hash for the next step.

Step 3.2 — Upload to the BTFS network

Upload the file by hash:

btfs storage upload QmUK9nwtLEiHBJ48HAZHNmSQ53U6ADbRhATxs2tomadwKw

When the btfs daemon window shows File storage successful, the upload has succeeded.

BTFS daemon log showing File storage successful

Step 3.3 — Verify the file is downloadable

Open the BTFS gateway URL in your browser:

https://gateway.btfs.io/btfs/QmUK9nwtLEiHBJ48HAZHNmSQ53U6ADbRhATxs2tomadwKw

If the image displays, the upload is complete and downloadable.

Step 4 — Construct the metadata JSON

Create a JSON file (this guide uses coral.json) following the TRC-721 metadata schema. Set the image field to the BTFS URL of the image you just uploaded:

{
  "name": "Coral #1",
  "description": "A unique TRC-721 collectible.",
  "image": "https://gateway.btfs.io/btfs/QmUK9nwtLEiHBJ48HAZHNmSQ53U6ADbRhATxs2tomadwKw",
  "attributes": [
    { "trait_type": "Color", "value": "Pink" },
    { "trait_type": "Rarity", "value": "Rare" }
  ]
}

Step 5 — Upload the metadata JSON

Upload the JSON to BTFS the same way as the image — btfs add then btfs storage upload — to get a hash for the metadata file:

BTFS upload of the metadata JSON file

Open the metadata URI in the browser to confirm:

https://gateway.btfs.io/btfs/QmWq4cp588QD8tzrSxvPs2bGikDdKyA35BT3iysBcP1jFD

The browser should render the JSON content.

Step 6 — Use the URI as tokenURI when minting

Use the metadata URL from Step 5 as the tokenURI argument when calling mintWithTokenURI on your deployed TRC-721 contract. See Issuing a TRC-721 token for the full minting flow.


Related resources