Skip to content

Metadata API

The Metadata API provides comprehensive functionality for creating, managing, and serializing transaction metadata in the Cardano blockchain. It supports both CBOR and JSON formats, enabling you to attach structured data to transactions with type safety and validation.

  • CBOR Serialization: Native CBOR format support for Cardano metadata
  • JSON Conversion: Convert between JSON and CBOR metadata formats
  • Structured Data: Support for maps, lists, and nested data structures
  • Type Safety: Strong typing for different metadata value types
  • Long strings: Strings in metadata maps and lists are split into 64-byte chunks
  • Builder Pattern: Convenient builder pattern for metadata construction

The main interface for all metadata operations, providing methods for data manipulation and serialization.

Utility class for creating and converting metadata objects between different formats.

Interface for map-type metadata structures with key-value pairs.

Interface for list-type metadata structures containing ordered elements.

Key Methods:

  • MetadataBuilder.createMetadata() - Create new metadata instance
  • put() - Add key-value pairs to metadata
  • serialize() - Convert to CBOR bytes
  • toJson() - Convert to JSON format

Create simple metadata with key-value pairs:

// Create empty metadata
Metadata metadata = MetadataBuilder.createMetadata();
// Add simple key-value pairs
metadata.put(1L, "Hello Cardano");
metadata.put(2L, BigInteger.valueOf(100));
metadata.put(3L, "metadata".getBytes());
// Add boolean value (as integer)
metadata.put(4L, BigInteger.valueOf(1)); // true
metadata.put(5L, BigInteger.valueOf(0)); // false
System.out.println("Basic metadata created with 5 entries");

Create complex metadata with nested structures:

// Create metadata with nested maps
Metadata structuredMetadata = MetadataBuilder.createMetadata();
// Create nested map
MetadataMap nestedMap = MetadataBuilder.createMap();
nestedMap.put("name", "Cardano Transaction");
nestedMap.put("version", BigInteger.valueOf(1));
nestedMap.put("timestamp", BigInteger.valueOf(System.currentTimeMillis()));
// Create list of values
MetadataList valuesList = MetadataBuilder.createList();
valuesList.add("value1");
valuesList.add("value2");
valuesList.add(BigInteger.valueOf(42));
// Add to main metadata
structuredMetadata.put(100L, nestedMap);
structuredMetadata.put(200L, valuesList);
structuredMetadata.put(300L, "Simple string value");
System.out.println("Structured metadata created");

Convert metadata to different formats:

Metadata metadata = MetadataBuilder.createMetadata();
metadata.put(674L, "Simple message");
metadata.put(675L, BigInteger.valueOf(12345));
// Serialize to CBOR bytes
byte[] cborBytes = metadata.serialize();
System.out.println("CBOR size: " + cborBytes.length + " bytes");
// Convert to JSON string
String jsonString = MetadataBuilder.toJson(metadata);
System.out.println("JSON: " + jsonString);
// Convert to hex string for inspection
String hexString = HexUtil.encodeHexString(cborBytes);
System.out.println("CBOR Hex: " + hexString);

Convert JSON metadata to CBOR format:

// JSON metadata string
String jsonMetadata = """
{
"674": {
"msg": ["Hello", "Cardano", "World"]
},
"675": {
"field1": "value1",
"field2": 42
}
}
""";
// Convert JSON to Metadata
Metadata metadata = MetadataBuilder.metadataFromJson(jsonMetadata);
// Serialize to CBOR
byte[] cborBytes = metadata.serialize();
System.out.println("Converted JSON to CBOR: " + cborBytes.length + " bytes");

For CIP-20 compliant message metadata, use the dedicated MessageMetadata class from the CIP20 module instead of building the label-674 structure manually. See the CIP20 API page for details.

Create application-specific metadata structures:

public class ApplicationMetadata {
public static Metadata createTransactionMetadata(String appName, String version,
Map<String, Object> customData) {
Metadata metadata = MetadataBuilder.createMetadata();
// Application info (label 1000)
MetadataMap appInfo = MetadataBuilder.createMap();
appInfo.put("name", appName);
appInfo.put("version", version);
appInfo.put("timestamp", BigInteger.valueOf(System.currentTimeMillis()));
metadata.put(1000L, appInfo);
// Custom data (label 1001)
if (customData != null && !customData.isEmpty()) {
MetadataMap customMap = MetadataBuilder.createMap();
for (Map.Entry<String, Object> entry : customData.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof String) {
customMap.put(key, (String) value);
} else if (value instanceof Number) {
customMap.put(key, BigInteger.valueOf(((Number) value).longValue()));
} else if (value instanceof byte[]) {
customMap.put(key, (byte[]) value);
}
}
metadata.put(1001L, customMap);
}
return metadata;
}
}
// Usage
Map<String, Object> customData = new HashMap<>();
customData.put("transactionId", "tx_12345");
customData.put("amount", 1000000);
customData.put("description", "Payment for services");
Metadata appMetadata = ApplicationMetadata.createTransactionMetadata(
"MyCardanoApp", "1.0.0", customData
);

The Metadata API provides full support for standard metadata formats while allowing custom metadata structures for application-specific needs.