Sui上のオブジェクトは、その構造と動作が明示的であり、理解しやすい方法で表示できます。しかし、クライアントのためにより豊富なメタデータをサポートするために、Sui フレームワークで定義されているDisplay
オブジェクトを使用して、効率的にオブジェクトを「記述する」標準的な方法があります。
歴史的に、オブジェクトをユーザーインターフェースで表示できるように、標準的な構造に合意しようとする様々な試みがありました。一つのアプローチは、オブジェクト構造体内に特定のフィールドを定義し、それらが存在する場合にUIで使用するというものでした。このアプローチは柔軟性に欠け、開発者は全てのオブジェクトで同じフィールドを定義する必要があり、時にはそのフィールドがオブジェクトにとって意味をなさないこともありました。
/// 表示のためのオブジェクト構造を標準化する試み。
public struct CounterWithDisplay has key {
id: UID,
/// このフィールドが存在する場合、UIで`name`として表示されます。
name: String,
/// このフィールドが存在する場合、UIで`description`として表示されます。
description: String,
// ...
image: String,
/// オブジェクトの実際のフィールド。
counter: u64,
// ...
}
フィールドに静的データが含まれている場合、それは全てのオブジェクトで重複することになります。また、Moveにはインターフェースがないため、オブジェクトのタイプを「手動で」チェックしないと特定のフィールドがあるかどうかを知ることができず、クライアントのフェッチがより複雑になります。
これらの問題に対処するため、Suiはオブジェクトを表示するための標準的な方法を導入しています。オブジェクト構造体にフィールドを定義する代わりに、表示メタデータは別のオブジェクトに格納され、タイプに関連付けられます。これにより、表示メタデータが重複せず、拡張や維持が容易になります。
Sui Displayのもう一つの重要な機能は、テンプレートを定義し、そのテンプレート内でオブジェクトのフィールドを使用できることです。これにより、より柔軟な表示が可能になるだけでなく、開発者が全てのオブジェクトで同じ名前と型の同じフィールドを定義する必要がなくなります。
Sui Fullnodeによってオブジェクトディスプレイがネイティブにサポートされており、オブジェクトタイプにDisplayが関連付けられている場合、クライアントは任意のオブジェクトの表示メタデータをフェッチできます。
module book::arena {
use std::string::String;
use sui::package;
use sui::display;
/// `Publisher`オブジェクトを要求するための一回限りの証人。
public struct ARENA has drop {}
/// 表示されるオブジェクトの例。
public struct Hero has key {
id: UID,
class: String,
level: u64,
}
/// モジュールイニシャライザーで`Publisher`オブジェクトを作成し、
/// その後`Hero`タイプのDisplayを作成します。
fun init(otw: ARENA, ctx: &mut TxContext) {
let publisher = package::claim(otw, ctx);
let mut display = display::new<Hero>(&publisher, ctx);
display.add(
b"name".to_string(),
b"{class} (lvl. {level})".to_string()
);
display.add(
b"description".to_string(),
b"One of the greatest heroes of all time. Join us!".to_string()
);
display.add(
b"link".to_string(),
b"<https://example.com/hero/{id}>".to_string()
);
display.add(
b"image_url".to_string(),
b"<https://example.com/hero/{class}.jpg>".to_string()
);
// 新しいデータでディスプレイを更新します。
// 変更を適用するために呼び出す必要があります。
display.update_version();
transfer::public_transfer(publisher, ctx.sender());
transfer::public_transfer(display, ctx.sender());
}
}
オブジェクトはアカウントによって所有され、真の所有権の対象となる可能性がありますが、Displayはオブジェクトの作成者によって所有されることができます。これにより、作成者は表示メタデータを更新し、全てのオブジェクトを更新する必要なく、変更をグローバルに適用できます。作成者はDisplayを別のアカウントに転送したり、メタデータを管理するためのカスタム機能を持つアプリケーションをオブジェクトの周りに構築したりすることもできます。
最も広くサポートされているフィールドは以下の通りです:
name
- オブジェクトの名前。ユーザーがオブジェクトを表示する際に表示されます。description
- オブジェクトの説明。ユーザーがオブジェクトを表示する際に表示されます。link
- アプリケーションで使用するオブジェクトへのリンク。image_url
- オブジェクトの画像のURLまたはブロブ。thumbnail_url
- ウォレット、エクスプローラー、その他の製品でプレビューとして使用する小さな画像へのURL。project_url
- オブジェクトまたは作成者に関連するウェブサイトへのリンク。creator
- オブジェクトの作成者を示す文字列。最新のサポートされているフィールドのリストについては、Sui Documentationを参照してください。
標準的なフィールドのセットがありますが、Displayオブジェクトはそれらを強制しません。開発者は必要なフィールドを自由に定義でき、クライアントはそれらを適切に使用できます。一部のアプリケーションでは追加のフィールドが必要で、他のフィールドを省略する場合があり、Displayはそれらをサポートするのに十分な柔軟性があります。
Display
オブジェクトはsui::display
モジュールで定義されています。これはファントムタイプをパラメータとして取るジェネリック構造体です。ファントムタイプはDisplay
オブジェクトを記述するタイプと関連付けるために使用されます。Display
オブジェクトのfields
はキーバリューペアのVecMap
で、キーはフィールド名、値はフィールド値です。version
フィールドは表示メタデータのバージョン管理に使用され、update_display
呼び出し時に更新されます。
ファイル: sui-framework/sources/display.move
struct Display<phantom T: key> has key, store {
id: UID,
/// 表示用のフィールドを含みます。現在サポートされている
/// フィールドは: name, link, image, descriptionです。
fields: VecMap<String, String>,
/// Publisherによって手動でのみ更新できるバージョン。
version: u16
}