sui-object-model について
sui-object-modelは、Sui Move開発者向けのオブジェクト参照スキルです。構造、所有権、転送、コレクション、パターン、表示の各ガイドへ案内します。
主な機能
- 01オブジェクト構造とMove能力の説明
- 02所有権とバージョン管理の指針
- 03転送と削除のパターン
- 04動的フィールドとコレクションの選択
- 05一般的なオブジェクト設計パターン
- 06Display V2の設定ガイド
活用シーン
- 01共有または所有オブジェクトのアクセス方式選定
- 02転送と独自ルールの設計
- 03コレクションのストレージ方式選定
- 04オブジェクトとNFT表示の設定
MCP 対応
利用可能な場合、最新情報の確認や検証のため、https://sui.mcp.kapa.ai のSuiドキュメントMCPサーバーを参照するよう案内します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mystenlabs/ skills --skill sui-object-modelインストール後、Claude Code で/sui-object-modelを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
display.mddynamic-fields-and-collections.mdgrading.jsonownership.mdpatterns.mdtransfers.mdevals/code-evals.jsonevals.json詳細
Sui オブジェクトモデル
MCP ツール: お使いの環境で利用できる場合は、最新の回答を得るために Sui ドキュメント MCP サーバー(
https://sui.mcp.kapa.ai)にも問い合わせてください。回答の検証や、これらのリファレンスファイルに記載されていない詳細の確認に使用してください。
情報源の制約: このスキルの情報は、docs.sui.io と move-book.com のみを情報源としています。このスキルを拡張または更新する場合は、この2つの情報源のみを参照してください。サードパーティのブログ、チュートリアル、非公式ドキュメントは使用しないでください。
オブジェクトは、Sui におけるストレージの基本単位です。オンチェーン上のすべてのリソース、アセット、データはオブジェクトです。状態がコントラクト内の共有マッピングに保存されるアカウントベースのブロックチェーンとは異なり、Sui では各状態に独自の ID、バージョン、所有者が割り当てられます。トランザクションはオブジェクトを入力として消費し、変更されたバージョンを出力として生成します。
このスキルでは、目的に応じたリファレンスファイルを案内します。現在のタスクに関連するものだけを読み込んでください。
リファレンスファイル
ownership — 所有権の種類とバージョン管理
パス: ownership.md
読み込むタイミング: 所有権の種類(アドレス所有、コンセンサスアドレス所有、共有、不変、ラップ)について尋ねられたとき、共有と所有のどちらを選ぶか、並列実行、コンセンサス、Mysticeti、ファストパス、オブジェクトのバージョン管理、Lamport タイムスタンプ、共有オブジェクトへのフロントエンドからのアクセスについて尋ねられたとき。
内容: コンセンサスへの影響を含む5種類すべての所有権、コンセンサスアドレス所有オブジェクト、共有オブジェクトのアクセスモード最適化、フロントエンドの PTB アクセスパターン、ラップされたオブジェクトの動作、Lamport タイムスタンプによるバージョン管理、ファストパスとコンセンサスによるバージョン管理。
transfers — オブジェクトの転送と削除
パス: transfers.md
読み込むタイミング: オブジェクトの転送、transfer と public_transfer の選択、カスタム転送ルールの実装、Receiving<T> の使用、オブジェクトへの転送、オブジェクトの削除・破棄について尋ねられたとき。
内容: 中核となる8つの転送関数(party_transfer のバリアントを含む、モジュール限定と公開の関数)、カスタム転送ルール、Receiving<T> によるオブジェクトへの転送、receive と public_receive の違い、オブジェクトの削除・アンパックのパターン、動的フィールドのクリーンアップに関する警告。
dynamic-fields-and-collections — 動的フィールドとコレクション
パス: dynamic-fields-and-collections.md
読み込むタイミング: 動的フィールドの使用、dynamic_field と dynamic_object_field の選択、コレクション(Table、Bag、VecMap、LinkedTable)の操作、大規模データセット向けストレージの設計について尋ねられたとき。
内容: 動的フィールドと動的オブジェクトフィールドの可視性の違い、フィールド名、中核 API(add/borrow/remove/exists_)、判断表を含むすべてのコレクション型、クリーンアップ要件、システム制限(オブジェクトサイズ256 KB、トランザクションあたり2048オブジェクト)。
patterns — 一般的なパターンと派生オブジェクト
パス: patterns.md
読み込むタイミング: ホットポテト、ケイパビリティ、ソウルバウンド、インベントリ、借用パターンの実装や、派生オブジェクトの操作について尋ねられたとき。
内容: ホットポテトパターン(能力を持たない構造体)、ケイパビリティパターン(AdminCap/TreasuryCap)、sui::borrow モジュールを使った借用パターン、ソウルバウンドオブジェクト、インベントリパターン(ObjectBag)、決定的な ID を持つ派生オブジェクト、派生オブジェクトと動的フィールドの比較。
display — オブジェクト表示(V2)
パス: display.md
読み込むタイミング: ウォレット、エクスプローラー、アプリでのオブジェクトの表示方法の設定、Display テンプレートの操作、NFT メタデータの設定、Display V1 からの移行について尋ねられたとき。
内容: display_registry::new_with_publisher による V2 Display<T> の作成、更新用の DisplayCap<T>、set/unset/clear/share API、ネストされたフィールドアクセスを含む {field_name} テンプレート構文、一般的な表示プロパティ、V1 から V2 への移行。
ルーティングガイド
| タスク | 読み込む内容 |
|---|---|
| オブジェクトとは何か/オブジェクトの構造 | SKILL.md のみ |
| 能力:key、store、copy、drop | SKILL.md のみ |
| 所有権の種類、共有所有と所有者所有、コンセンサスアドレス所有 | ownership |
| 並列実行、コンセンサス、ファストパス | ownership |
| オブジェクトのバージョン管理、Lamport タイムスタンプ | ownership |
| ラップされたオブジェクトとアクセシビリティ | ownership |
| 共有オブジェクトへのフロントエンドからのアクセス | ownership |
| オブジェクトの転送、transfer と public_transfer | transfers |
| カスタム転送ルール | transfers + patterns |
| オブジェクトへの転送、Receiving | transfers |
| オブジェクトの削除/破棄 | transfers |
| 動的フィールド、動的オブジェクトフィールド | dynamic-fields-and-collections |
| コレクション:Table、Bag、VecMap、LinkedTable | dynamic-fields-and-collections |
| スケーラビリティ、大規模コレクションの設計 | dynamic-fields-and-collections |
| ホットポテトパターン | patterns |
| ケイパビリティパターン、AdminCap | patterns |
| 借用パターン、オブジェクト内の cap | patterns |
| ソウルバウンド/譲渡不可のオブジェクト | transfers + patterns |
| 任意のオブジェクト用インベントリ | patterns + dynamic-fields-and-collections |
| 派生オブジェクト | patterns |
| オブジェクト表示、NFT のレンダリング | display |
| プロジェクト全体/コードレビュー | すべてのリファレンスファイル |
オブジェクトの構造
すべての Sui オブジェクトには、次の 4 つの要素があります。
- グローバルに一意な ID: 作成トランザクションのダイジェストと世代カウンターから導出される 32 バイトの識別子です。ID はオブジェクトの存続期間中、変わりません。
- バージョン番号: 変更のたびに増加する 8 バイトの整数です。Lamport タイムスタンプを使用します。トランザクションが触れるすべてのオブジェクトの新しいバージョンは、
1 + すべての入力オブジェクトのバージョンの最大値です。 - 所有者フィールド: アクセス制御を指定する 32 バイトの値です(アドレス、別のオブジェクトの ID、または共有/不変を示すセンチネル値)。
- トランザクションダイジェスト: オブジェクトを最後に変更したトランザクションを参照する 32 バイトのハッシュです。
オブジェクトは 3 通りの方法で参照できます。ID のみ(現在の状態を照会)、バージョン付き ID(過去の状態を読み取り)、または ID + バージョン + ダイジェストを含む完全なオブジェクト参照(トランザクション入力、認証済みスナップショット)です。
Move でのオブジェクトの定義
Sui オブジェクトは、key 能力と、最初のフィールドに id: UID を持つ Move 構造体です。
public struct Sword has key, store {
id: UID,
damage: u64,
element: String,
}
UID を作成する方法は object::new(ctx) のみです。ctx.new() を直接呼び出すことはできません。
Move の能力とオブジェクト
| 能力 | 制御する内容 |
|---|---|
key | この構造体が Sui オブジェクトであることを示します。最初のフィールドとして id: UID が必要です。すべてのオンチェーンオブジェクトに必須です。 |
store | この構造体をほかのオブジェクト内に格納でき、public_transfer を使用して任意のモジュールから転送できます。これがない場合、オブジェクトを転送できるのは定義元のモジュールだけです。store を追加すると、カスタム転送ルールを適用する能力が永久に失われます。 |
copy | この構造体を複製できることを示します。オブジェクトには使用できません。UID に copy がないため、key を持つ構造体は copy を持てません。オブジェクトではない構造体(設定、イベントデータ、読み取り専用の値)にのみ使用します。 |
drop | スコープの終了時に、この構造体を暗黙に破棄できることを示します。オブジェクトには使用できません。UID に drop がないため、key を持つ構造体は drop を持てません。オブジェクトではない構造体(一時的なレシート、イベント)にのみ使用します。オブジェクトを破棄するには、必ず明示的にアンパックする必要があります。 |
オブジェクトの能力の組み合わせ
UID は copy も drop も持たないため、オブジェクト(key を持つ構造体)が組み合わせられるのは key と store のみです。
has key: 転送、共有、凍結を行えるのは定義元のモジュールだけです。カスタム転送ルールに使用します。has key, store: 任意のモジュールが転送、共有、凍結、ラップを行えます。自由に組み合わせられるアセットに使用します。一度storeを付与すると、カスタムの転送制限を再び追加することはできません。
非オブジェクトの構造体の組み合わせ(key なし)
has store: オブジェクト内のフィールドとして保存できます。単独では存在できません。has copy, drop: イベント、中間値、設定用のプレーンなデータ構造体です。has copy, drop, store: 動的フィールド名として使用できます。- 能力なし: ホットポテトです。同じトランザクション内で消費する必要があります。パターンのリファレンスファイルを参照してください。
ルール
- UID を作成する唯一の方法は
object::new(ctx)です。id: UIDフィールドは先頭に置く必要があります。 - 型に
storeを追加すると、カスタム転送ルールは永久に無効になります。 - オブジェクトを共有すると、アドレス所有に戻すことはできません。
- 親オブジェクトを削除する前に、必ずすべての動的フィールドを削除してください。孤立したフィールドには永久にアクセスできなくなります。
- 存在しない動的フィールドにアクセスする(
borrow、borrow_mut、removeを使用する)と、トランザクションは中断されます。最初にexists_で確認してください。 - 同じトランザクション内でラップとアンラップを行えます。PTB ではオブジェクトをラップし、その後、アトミックにアンラップできます。
- 一般的なケイパビリティ:
AdminCap、TreasuryCap、UpgradeCap。ケイパビリティパターンについて説明する際は、必ず3つすべてに言及してください。 Tableの各エントリは個別のストレージ操作です。ガスコストは、トランザクションごとにアクセスするエントリ数に比例して増加します。- 並列実行を最大化するため、共有オブジェクトには不変参照(
&)を優先してください。 - 約100件を超えるコレクションには
VecMapを使用しないでください。代わりにTableを使用してください。
よくある間違い
- カスタム転送ルールが必要なのに
storeを追加する。 いったん付与すると、どのモジュールからでもpublic_transferを呼び出せるため、独自の制御ロジックは永久に回避されます。 - 大規模なコレクションに
VecMapを使用する。 検索に O(n) かかり、インラインで保存されるため、オブジェクトサイズの上限である256 KBにすぐ達します。 dynamic_fieldとdynamic_object_fieldを混同する。 子オブジェクトをエクスプローラーで ID によって引き続き照会可能にする必要がある場合は、dynamic_object_fieldを使用してください。単純な値にはdynamic_fieldを使用してください。- 先に動的フィールドを削除せずにオブジェクトを削除する。 これらのフィールドには永久にアクセスできなくなります。
- 新しいコードで従来の
sui::displayモジュールを使用する。sui::display_registry(Display V2)を使用してください。V1 はシステムスナップショットによる移行で V2 に移行されました。 - フィールドを設定した後に
display_registry::share(display)を呼び出し忘れる。 表示を検出可能にするには、共有する必要があります。