CIP-25 — NFT metadata
CIP25 (Cardano Improvement Proposal 25) defines a standard for NFT metadata on the Cardano blockchain. The Cardano Client Library provides builders for the CIP25 metadata map and NFT/file helpers. You assemble NFT entries, group them under a policy with NFTMetadata, and serialize to CBOR for use as transaction metadata.
Key Features
Section titled “Key Features”- Standard Compliance: CIP25 metadata map (label 721)
- NFT Builder:
NFTfor asset fields and attributes - File Support:
NFTFilefor rich file entries - Policy Map:
NFTMetadatafor policy -> asset metadata layout
Dependencies
Section titled “Dependencies”- Group ID: com.bloxbean.cardano
- Artifact ID: cardano-client-cip25
- Dependencies: metadata
Usage Examples
Section titled “Usage Examples”Creating NFT Metadata
Section titled “Creating NFT Metadata”Create the NFT entry with images, descriptions, and files, then insert it under your policy id.
// Create CIP25 NFT entryNFT nft = NFT.create() .assetName("MyAwesomeNFT") .name("MyAwesomeNFT") .image("https://example.com/image.png") .description("A sample CIP25 NFT") .addFile(NFTFile.create() .mediaType("image/png") .name("image.png") .src("https://example.com/image.png")) .property("color", "blue") .property("rarity", "legendary");
// Wrap under policy id and label 721NFTMetadata nftMetadata = NFTMetadata.create() .addNFT(policyId, nft);
byte[] cborBytes = nftMetadata.serialize();Minting NFT with CIP25 Metadata
Section titled “Minting NFT with CIP25 Metadata”Pass the CBOR metadata into your transaction so wallets and indexers can read it later.
Attach the CBOR metadata when building your transaction.
// mintingScript is your NativeScript policy, and policyId its getPolicyId()Asset nftAsset = new Asset("MyAwesomeNFT", BigInteger.ONE);
Tx tx = new Tx() .mintAssets(mintingScript, List.of(nftAsset), senderAddress) .attachMetadata(nftMetadata) .from(senderAddress);For a complete example, see Minting an NFT.
Working with Files
Section titled “Working with Files”Use NFTFile to attach one or more files (e.g., media, thumbnails) to the NFT entry.
NFTFile file = NFTFile.create() .mediaType("image/png") .name("thumbnail.png") .src("https://example.com/thumbnail.png");
NFT nft = NFT.create() .assetName("MultiFile") .name("Multi-file NFT") .description("NFT with multiple files") .addFile(file);Custom Attributes
Section titled “Custom Attributes”Store additional fields on the NFT or file objects via the shared NFTProperties helpers.
NFT and NFTFile inherit from NFTProperties, so you can add arbitrary fields.
nft.property("power", "100");nft.property("tags", List.of("gaming", "collectible"));API Reference
Section titled “API Reference”NFTMetadata
Section titled “NFTMetadata”// Create new instancepublic static NFTMetadata create()
// Create from CBOR bytespublic static NFTMetadata create(byte[] cborBytes)
public NFTMetadata addNFT(String policyId, NFT nft)public NFT getNFT(String policyId, String assetName)public NFTMetadata removeNFT(String policyId, String assetName)public NFTMetadata version(int version) // default 1public byte[] serialize()public static NFT create()public NFT assetName(String assetName)public String getAssetName()
public NFT name(String name)public String getName()
public NFT image(String imageUri) // a URI over 64 bytes is split into chunkspublic List<String> getImages()
public NFT mediaType(String mediaType)public String getMediaType()
public NFT description(String description) // supports multiplepublic List<String> getDescriptions()
public NFT addFile(NFTFile nftFile)public List<NFTFile> getFiles()
// Additional propertiespublic NFT property(String name, String value)public NFT property(String name, Map<String, Object> values)public NFT property(String name, List<String> values)NFTFile
Section titled “NFTFile”public static NFTFile create()public NFTFile name(String name)public String getName()
public NFTFile mediaType(String mediaType)public String getMediaType()
public NFTFile src(String uri) // call multiple times to add morepublic List<String> getSrcs()
// Additional propertiespublic NFTFile property(String name, String value)public NFTFile property(String name, Map<String, Object> values)public NFTFile property(String name, List<String> values)CIP25 Specification Details
Section titled “CIP25 Specification Details”- Metadata Label: 721
- Structure:
{ "721": { "<policy_id>": { "<asset_name>": { ... } } } } - Files: support
mediaType,name, and one-or-manysrcvalues
Best Practices
Section titled “Best Practices”- Use HTTPS or IPFS links for images/files.
- Keep metadata concise to reduce transaction size.
- Set one
imageper NFT: CIP-25 reads animagearray as the chunks of one URI, so a second call would corrupt it. UseaddFilefor more files. - Set
assetNameon theNFTbefore adding it toNFTMetadata. - Validate URLs and lengths in your application code (no built-in validators are present).
Integration Examples
Section titled “Integration Examples”Combine CIP25 metadata with other metadata using CBORMetadata.merge(...) if needed.
CBORMetadata combined = (CBORMetadata) new CBORMetadata().merge(nftMetadata);combined.put(BigInteger.valueOf(100), "extra-field");For more information about CIP25, refer to the official CIP25 specification.