Display Sui对象显示标准

Sui 对象显示标准是一个模板引擎,允许对类型的链下表示(显示)进行链上管理。使用它,您可以将对象的数据替换为模板字符串。该标准不限制您可以设置的字段。您可以使用 {property}语法访问所有对象属性,然后将它们作为模板字符串的一部分插入。

使用Publisher您拥有的对象来设置sui::display类型。有关Publisher对象的更多信息,请参阅Sui Move 示例中的发布者主题。

在 Sui Move 中,Display表示一个为类型指定一组命名模板的对象T。例如,对于某种类型,0x2::capy::Capy显示语法为: Display<0x2::capy::Capy>。

TSui Full节点通过匹配定义来处理该类型的所有对象,并在使用查询中的设置Display查询对象时返回处理结果。{ showDisplay: true }

显示属性

建议的基本属性集包括:

  • name- 对象的名称。当用户查看对象时,会显示该名称。
  • description- 对象的描述。当用户查看对象时,会显示描述。
  • link- 指向要在应用程序中使用的对象的链接。
  • image_url- 包含对象图像的 URL 或 blob。
  • thumbnail_url-较小图像的 URL,可在钱包、浏览器和其他产品中用作预览。
  • project_url- 指向与对象或创建者相关的网站的链接。
  • creator- 指示对象创建者的字符串。

Sui Hero 模块示例

以下代码示例演示了Display示例Hero模块如何根据类型的name、id和属性而变化。以下表示该函数定义的模板:image_urlHeroinit

{
"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 can
/// 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 sui::tx_context::{sender, TxContext};
    use std::string::{utf8, String};
    use sui::transfer::transfer;
    use sui::object::{Self, UID};

    // 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,
        image_url: String,
    }

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

    /// In the module initializer one claims 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[
            utf8(b"name"),
            utf8(b"link"),
            utf8(b"image_url"),
            utf8(b"description"),
            utf8(b"project_url"),
            utf8(b"creator"),
        ];

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

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

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

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

        transfer(publisher, sender(ctx));
        transfer(display, sender(ctx));
    }

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

使用对象显示

该调用在自定义函数或模块初始值设定项中display::new创建一个,或者作为可编程事务的一部分。Display以下代码示例演示了如何创建Display:

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> { /* ... */ }
}

创建后Display,您可以对其进行修改。以下代码示例演示了如何修改Display:

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 ) { /* ... */ }
}

接下来,update_version调用应用更改并通过发出事件Display来设置 。T完整节点接收事件并使用事件中的数据来检索该类型的模板。

以下代码示例演示了如何使用该update_version调用:

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

Sui实用对象

在 Sui 中,实用程序对象启用功能授权。几乎所有模块都具有只有具有所需功能才能访问的功能。通用模块允许每个应用程序具有一种功能,例如市场。某些功能标记链上共享对象的所有权,或从另一个帐户访问共享数据。对于功能,提供有意义的对象描述以促进用户界面实现非常重要。这有助于避免当对象相似时意外传输错误的对象。它还为用户看到的项目提供用户友好的描述。

以下示例演示了如何创建 capy 功能:

module capy::utility {
/// A capability which grants Capy Manager permission to add
/// new genes and manage the Capy Market
    struct CapyManagerCap has key, store {
        id: UID 
    }
}

具有数据重复的典型对象

游戏内物品的常见情况是有大量相似的对象按某些标准分组。优化它们的大小以及铸造和更新它们的成本非常重要。通常,游戏对每个组或项目标准使用单个源图像或 URL。将源图像存储在每个对象内并不是最佳选择。在某些情况下,当游戏允许或购买游戏内物品时,用户会铸造游戏内物品。为此,必须提前创建并存储一些 IPFS/Arweave 元数据。这需要额外的逻辑,这些逻辑通常与物品的游戏内属性无关。

以下示例演示了如何创建 Capy:

module capy::capy_items {
/// A wearable Capy item. For some items there can be an
/// unlimited supply. And items with the same name are identical.
   public struct CapyItem has key, store {
        id: UID,
        name: String
    }
}

具有动态表示的独特对象# Sui Capys 使用动态图像生成。当卡比出生时,其属性决定了卡比的外观,例如颜色或图案。当用户将物品放在 Capy 上时,Capy 的外观会发生变化。当用户将多个物品放在 Capy 上时,物品组合就有机会获得奖励。

为了实现这一点,Capys 游戏 API 服务会刷新图像以响应用户发起的更改。Capy 的 URL 是一个带有capy.id. 但存储完整的 URL——以及 Capy 对象中的其他字段(由于其人口的多样性)——也会导致用户支付过多的存储费用并增加汽油费。

下面的例子演示了如何实现动态图像生成:

module capy::capy {
/// A Capy - very diverse object with different combination
/// of genes. Created dynamically + for images a dynamic SVG
/// generation is used.
   public struct Capy has key, store {
        id: UID,
        genes: vector<u8>
    }
}

具有独特静态内容的对象# 这是最简单的场景——一个对象代表一切本身。将元数据标准应用于此类对象非常容易,特别是当该对象永远保持不可变时。但是,如果元数据标准不断发展,并且某些生态系统项目为某些属性添加了新功能,则该对象始终保持其原始形式,并且可能需要向后兼容的更改。

module sui::devnet_nft {
/// A Collectible with a static data. URL, name, description are
/// set only once on a mint event
   public struct DevNetNFT has key, store {
        id: UID,
        name: String,
        description: String,
        url: Url,
    }
}