Skip to content

Provenance Attributes

Provenance attributes provide a flexible way to encode additional information about digital content and its creation process and store them in the NFT’s metadata. Think of them as extensible tags that can capture any aspect of how content came to be - from the tools used to create it to the inspirations that shaped it.

This provides a way to encode information describing the provenance claim by the originator in a standardized way.

These NFT attributes are optional but highly encouraged.

NFT Metadata Structure

Provenance attributes live within the NFT’s metadata in a standardized location. Here’s the structure:

interface NFTMetadata {
royal: {
provenance: {
// The Blake3 hash of the content
contentHash: string;
// Optional title
title?: string;
// URLs where the content can be found
fileLocations: Array<{
url: string;
}>;
// Array of provenance attributes
attributes: ProvenanceAttribute[];
};
};
}

This structure ensures that provenance information, including all attributes, remains consistently accessible within the NFT metadata. The royal.provenance namespace keeps this data distinct from other metadata the NFT might contain.

Core Concept

Every provenance attribute follows a simple, consistent structure:

interface ProvenanceAttribute {
// The type of attribute (e.g., "display", "contributor", "ai")
type: string;
// Structured data relevant to this type of attribute
data: any;
}

This intentionally minimal structure allows for:

  • Easy addition of new attribute types as needs evolve
  • Flexible data structures within each type
  • Simple validation and processing
  • Clear separation of concerns

Standard Attribute Types

While you can create custom attribute types, the protocol recognizes several standard types that serve common use cases:

Display Attribute

Provides consistent presentation information for clients rendering the content.

{
type: "display",
data: {
// Required: Main title for display
title: string,
// Optional: Longer description
description?: string,
// Optional: Related URL
url?: string,
// Optional: Image URL for display
image_url?: string
}
}

Example usage:

{
"type": "display",
"data": {
"title": "Sunset over Mountains",
"description": "Digital painting created using Procreate",
"image_url": "https://example.com/preview.jpg"
}
}

Contributor Attribute

Documents individual contributions to the content. This captures human input separate from tool usage.

{
type: "contributor",
data: {
// Required: Royal ID of the contributor
account_id: string,
// Required: Short description of contribution
title: string,
// Optional: Detailed description
description?: string,
// Optional: Related URLs
urls?: Array<{
url: string,
name?: string
}>
}
}

Example usage:

{
"type": "contributor",
"data": {
"account_id": "1234",
"title": "Character Design",
"description": "Created the initial character concepts and final artwork",
"urls": [
{
"url": "https://portfolio.example.com/concept-art",
"name": "Concept Sketches"
}
]
}
}

AI Service Attribute

Records the use of AI tools in content creation, providing transparency about AI involvement.

{
type: "ai",
data: {
service: {
// Required: Royal ID of the AI service
account_id: string,
// Required: Name of the service
name: string,
// Required: Service URL
url: string
},
// Optional: Additional service-specific metadata
metadata: Record<string, any>
}
}

Example usage:

{
"type": "ai",
"data": {
"service": {
"account_id": "5678",
"name": "Midjourney",
"url": "https://midjourney.com"
},
"metadata": {
"prompt": "A serene mountain landscape at sunset",
"model_version": "5.0",
"guidance_scale": 7.5
}
}
}

Inspiration Attribute

Links to other content that inspired this creation, creating a web of creative influences.

{
type: "inspiration",
data: {
// Required: Reference to inspiring content
inspired_by: string,
// Optional: Brief description
title?: string,
// Optional: Detailed explanation
description?: string
}
}

Example usage:

{
"type": "inspiration",
"data": {
"inspired_by": "claim_789",
"title": "Inspired by Classical Architecture",
"description": "The geometric patterns draw heavily from Roman temple designs"
}
}

Best Practices

  1. Use Multiple Attributes: Don’t hesitate to use multiple attributes, even of the same type, to fully document the creation process.

  2. Be Specific: Include detailed information in attribute data - this creates a richer provenance record.

  3. Maintain Consistency: When using standard attribute types, follow their defined structures to ensure compatibility.

  4. Consider the Timeline: Attributes should reflect the state at creation time - they become part of the immutable record.

Extending the System

The attribute system is designed for extension. To create a new attribute type:

  1. Choose a descriptive, lowercase type name
  2. Define a clear data structure
  3. Document the structure and intended usage
  4. Consider providing example implementations

While you can create custom attribute types for specific needs, consider if one of the standard types might serve your purpose first.

Implementation Notes

When implementing provenance attribute support:

// Example validation helper
function validateAttribute(attribute: ProvenanceAttribute): boolean {
// Basic structure check
if (!attribute.type || !attribute.data) {
return false;
}
// Type-specific validation
switch (attribute.type) {
case "display":
return !!attribute.data.title; // Title is required
case "contributor":
return !!attribute.data.account_id && !!attribute.data.title;
// ... other type validations
}
return true; // Unknown types pass basic validation
}

Remember:

  • Validate attributes before registration
  • Store the complete attribute data
  • Handle unknown attribute types gracefully
  • Consider how to present attributes to users