CIP-67 — Asset name labels
CIP67 (Cardano Improvement Proposal 67) defines a standard for asset name labels on the Cardano blockchain. The Cardano Client Library provides utilities for creating, validating, and working with CIP67-compliant asset names. The utilities keep the rules around padding, CRC8 checksum, and label ranges in one place so you can focus on assembling asset names without re-implementing the bit-twiddling logic.
Key Features
Section titled “Key Features”- Label Encoding: Convert decimal labels to CIP67 asset name prefixes
- Label Decoding: Extract labels from CIP67 asset names
- Validation: Verify CIP67 compliance and checksum validation
- CRC8 Checksum: Built-in CRC8 checksum calculation and verification
- Standard Compliance: Full CIP67 specification support
Dependencies
Section titled “Dependencies”- Group ID: com.bloxbean.cardano
- Artifact ID: cardano-client-cip67
- Dependencies: crypto
Usage Examples
Section titled “Usage Examples”Converting Labels to Asset Name Prefixes
Section titled “Converting Labels to Asset Name Prefixes”Generate the 4-byte prefix for a given label; you can append your own suffix bytes afterwards.
// Convert a decimal label to CIP67 asset name prefixint label = 222; // Label range: [0, 65535]byte[] prefixBytes = CIP67AssetNameUtil.labelToPrefix(label);
// Convert to hex string for displayString prefixHex = HexUtil.encodeHexString(prefixBytes);System.out.println("Label " + label + " -> Prefix: " + prefixHex);// Output: Label 222 -> Prefix: 000de140Extracting Labels from Asset Names
Section titled “Extracting Labels from Asset Names”Recover the numeric label from the prefix to inspect or validate existing assets.
// Extract label from CIP67 asset name prefixbyte[] prefixBytes = HexUtil.decodeHexString("000de140");int extractedLabel = CIP67AssetNameUtil.prefixToLabel(prefixBytes);
System.out.println("Prefix 000de140 -> Label: " + extractedLabel);// Output: Prefix 000de140 -> Label: 222Validating CIP67 Asset Names
Section titled “Validating CIP67 Asset Names”isValidAssetName checks the padding and the checksum. It doesn’t check every padding bit (see known issues), so treat it as a sanity check rather than proof of a well-formed name.
// Validate asset name from bytesbyte[] assetNameBytes = HexUtil.decodeHexString("000de140");boolean isValidBytes = CIP67AssetNameUtil.isValidAssetName(assetNameBytes);
System.out.println("Asset name valid (bytes): " + isValidBytes);// Output: Asset name valid (bytes): true
// Validate asset name from integerint assetNameInt = 0x000de140;boolean isValidInt = CIP67AssetNameUtil.isValidAssetName(assetNameInt);
System.out.println("Asset name valid (int): " + isValidInt);// Output: Asset name valid (int): trueWorking with Asset Names in Transactions
Section titled “Working with Asset Names in Transactions”Combine the CIP67 prefix with your human-readable suffix to form the final asset name used in minting.
// Create asset name with CIP67 labelint label = 222; // NFT labelbyte[] labelPrefix = CIP67AssetNameUtil.labelToPrefix(label);
// Create full asset name by combining prefix with unique suffixbyte[] uniqueSuffix = "MyNFT".getBytes(StandardCharsets.UTF_8);byte[] fullAssetName = new byte[labelPrefix.length + uniqueSuffix.length];System.arraycopy(labelPrefix, 0, fullAssetName, 0, labelPrefix.length);System.arraycopy(uniqueSuffix, 0, fullAssetName, labelPrefix.length, uniqueSuffix.length);
// Create asset with CIP67-compliant nameAsset nftAsset = Asset.builder() .name("0x" + HexUtil.encodeHexString(fullAssetName)) // without 0x, the text is read as UTF-8 .value(BigInteger.ONE) .build();Batch Processing of Asset Names
Section titled “Batch Processing of Asset Names”Run validations over multiple asset names and extract labels where valid.
// Process multiple asset namesList<String> assetNameHexes = Arrays.asList( "000de140", // Valid CIP67 asset name "000de141", // Invalid padding "100de140", // Invalid checksum "000de130" // Invalid checksum);
for (String assetNameHex : assetNameHexes) { byte[] assetNameBytes = HexUtil.decodeHexString(assetNameHex); boolean isValid = CIP67AssetNameUtil.isValidAssetName(assetNameBytes);
if (isValid) { int label = CIP67AssetNameUtil.prefixToLabel(assetNameBytes); System.out.println(assetNameHex + " -> Valid, Label: " + label); } else { System.out.println(assetNameHex + " -> Invalid"); }}Common Label Examples
Section titled “Common Label Examples”Predefined labels are handy for common asset categories; encode them once and reuse.
// Common CIP67 labelsMap<Integer, String> commonLabels = new HashMap<>();commonLabels.put(222, "NFT Standard");commonLabels.put(333, "Fungible Token Standard");commonLabels.put(444, "Rich Fungible Token Standard");
for (Map.Entry<Integer, String> entry : commonLabels.entrySet()) { int label = entry.getKey(); String description = entry.getValue();
byte[] prefix = CIP67AssetNameUtil.labelToPrefix(label); String prefixHex = HexUtil.encodeHexString(prefix);
System.out.println("Label " + label + " (" + description + ") -> " + prefixHex);}API Reference
Section titled “API Reference”CIP67AssetNameUtil Class
Section titled “CIP67AssetNameUtil Class”Utility class for CIP67 asset name operations.
Static Methods
Section titled “Static Methods”labelToPrefix(int label)
Section titled “labelToPrefix(int label)”Converts a decimal label to CIP67 asset name prefix.
public static byte[] labelToPrefix(int label)Parameters:
label- Decimal label in range [0, 65535]
Returns: 4-byte prefix array
prefixToLabel(byte[] labelBytes)
Section titled “prefixToLabel(byte[] labelBytes)”Extracts the label from CIP67 asset name prefix.
public static int prefixToLabel(byte[] labelBytes)Parameters:
labelBytes- 4-byte prefix array
Returns: Decimal label
isValidAssetName(int assetName)
Section titled “isValidAssetName(int assetName)”Validates a CIP67 asset name from integer value.
public static boolean isValidAssetName(int assetName)Parameters:
assetName- Asset name as integer
Returns: true if valid CIP67 asset name
isValidAssetName(byte[] assetName)
Section titled “isValidAssetName(byte[] assetName)”Validates a CIP67 asset name from byte array.
public static boolean isValidAssetName(byte[] assetName)Parameters:
assetName- Asset name as byte array
Returns: true if valid CIP67 asset name
CIP67 Specification Details
Section titled “CIP67 Specification Details”Asset Name Structure
Section titled “Asset Name Structure”A CIP-67 prefix is 4 bytes, [0000 | 16-bit label | 8-bit CRC8 checksum | 0000], followed by the rest of the asset name.
Label Constraints
Section titled “Label Constraints”- Range: 0 to 65535
- Encoding: Big-endian format
- Checksum: CRC8 validation required
Validation Rules
Section titled “Validation Rules”- Padding Check: The first and last 4 bits must be 0000
- Checksum Verification: The CRC8 checksum must match the label
Common Label Registry
Section titled “Common Label Registry”| Label | Description | Prefix (Hex) |
|---|---|---|
| 100 | CIP-68 reference token | 000643b0 |
| 222 | CIP-68 NFT | 000de140 |
| 333 | CIP-68 fungible token | 0014df10 |
| 444 | CIP-68 rich fungible token | 001bc280 |
Best Practices
Section titled “Best Practices”- Use Standard Labels: Use established labels (222, 333, 444) for common asset types
- Validate Asset Names: Always validate asset names before using them
- Handle Errors: Check validation results before processing asset names
- Preserve Checksums: Don’t modify asset name prefixes without recalculating checksums
- Document Custom Labels: Document any custom labels used in your application
Integration with Other Standards
Section titled “Integration with Other Standards”With CIP68 (Datum Metadata)
Section titled “With CIP68 (Datum Metadata)”// Create CIP68-compliant asset nameint label = 222; // NFT label for CIP68byte[] labelPrefix = CIP67AssetNameUtil.labelToPrefix(label);
// Combine with asset-specific data, in hex with a 0x prefixString assetName = "0x" + HexUtil.encodeHexString(labelPrefix) + HexUtil.encodeHexString("MyUniqueNFT".getBytes(StandardCharsets.UTF_8));For more information about CIP67, refer to the official CIP67 specification.