Object Display

A creator or a builder who owns a Publisher object can use the sui::display module to define display properties for their objects. To get a Publisher object check out the Publisher page.

Display<T> is an object that specifies a set of named templates for the type T (for example, for a type 0x2::capy::Capy the display would be Display<0x2::capy::Capy>). All objects of the type T will be processed in the Sui Full Node RPC through the matching Display definition and will have processed result attached when an object is queried.

Description

Sui Object Display is a template engine which allows for on-chain display configuration for type to be handled off-chain by the ecosystem. It has the ability to use an object's data for substitution into a template string.

There's no limitation to what fields can be set, all object properties can be accessed via the {property} syntax and inserted as a part of the template string (see examples for the illustration).

Example

For the following Hero module, the Display would vary based on the "name", "id" and "image_url" properties of the type "Hero". The template defined in the init function can be represented as:

{
    "name": "{name}",
    "link": "https://sui-heroes.io/hero/{id}",
    "image_url": "ipfs://{img_url}",
    "description": "A true Hero of the Sui ecosystem!",
    "project_url": "https://sui-heroes.io",
    "creator": "Unknown Sui Fan"
}
/// Example of an unlimited "Sui Hero" collection - anyone is free to
/// mint their Hero. Shows how to initialize the `Publisher` and how
/// to use it to get the `Display<Hero>` object - a way to describe a
/// type for the ecosystem.
module examples::my_hero {
    use std::string::String;

    // The creator bundle: these two packages often go together.
    use sui::package;
    use sui::display;

    /// The Hero - an outstanding collection of digital art.
    public struct Hero has key, store {
        id: UID,
        name: String,
        img_url: String,
    }

    /// One-Time-Witness for the module.
    public struct MY_HERO has drop {}

    /// In the module initializer we claim the `Publisher` object
    /// to then create a `Display`. The `Display` is initialized with
    /// a set of fields (but can be modified later) and published via
    /// the `update_version` call.
    ///
    /// Keys and values are set in the initializer but could also be
    /// set after publishing if a `Publisher` object was created.
    fun init(otw: MY_HERO, ctx: &mut TxContext) {
        let keys = vector[
            b"name".to_string(),
            b"link".to_string(),
            b"image_url".to_string(),
            b"description".to_string(),
            b"project_url".to_string(),
            b"creator".to_string(),
        ];

        let values = vector[
            // For `name` we can use the `Hero.name` property
            b"{name}".to_string(),
            // For `link` we can build a URL using an `id` property
            b"https://sui-heroes.io/hero/{id}".to_string(),
            // For `image_url` we use an IPFS template + `img_url` property.
            b"ipfs://{img_url}".to_string(),
            // Description is static for all `Hero` objects.
            b"A true Hero of the Sui ecosystem!".to_string(),
            // Project URL is usually static
            b"https://sui-heroes.io".to_string(),
            // Creator field can be any
            b"Unknown Sui Fan".to_string()
        ];

        // Claim the `Publisher` for the package!
        let publisher = package::claim(otw, ctx);

        // Get a new `Display` object for the `Hero` type.
        let mut display = display::new_with_fields<Hero>(
            &publisher, keys, values, ctx
        );

        // Commit first version of `Display` to apply changes.
        display.update_version();

        transfer::public_transfer(publisher, ctx.sender());
        transfer::public_transfer(display, ctx.sender());
    }

    /// Anyone can mint their `Hero`!
    public fun mint(name: String, img_url: String, ctx: &mut TxContext): Hero {
        let id = object::new(ctx);
        Hero { id, name, img_url }
    }
}

Methods description

Display is created via the display::new<T> call, which can be performed either in a custom function (or a module initializer) or as a part of a programmable transaction.

module sui::display {
    /// Get a new Display object for the `T`.
    /// Publisher must be the publisher of the T, `from_package`
    /// check is performed.
    public fun new<T>(pub: &Publisher): Display<T> { /* ... */ }
}

Once acquired, the Display can be modified:

module sui::display {
    /// Sets multiple fields at once
    public fun add_multiple(
        self: &mut Display,
        keys: vector<String>,
        values: vector<String
    ) { /* ... */ }

    /// Edit a single field
    public fun edit(self: &mut Display, key: String, value: String) { /* ... */ }

    /// Remove a key from Display
    public fun remove(self: &mut Display, key: String ) { /* ... */ }
}

To apply changes and set the Display for the T, one last call is required: update_version publishes version by emitting an event which Full Node listens to and uses to get a template for the type.

module sui::display {
    /// Update the version of Display and emit an event
    public fun update_version(self: &mut Display) { /* ... */ }
}

Learn more