【Astar】WASMコントラクト(MappingとStructについて)
下のようなMapping構造を作りたいと思います。
各NFTのキャラクターの状態(空腹度など)を保持するイメージです。
結論としては、次のようになります。
これをどう実現していくのかを見ていきます。
1 どのようにして構造体を持ってくるのか
まずは任意のファイルにこのような構造体を設定します。
「types.rs」のような範囲用的な名前であれば、いろいろな構造体が作りやすいです。
次に、同じ階層に、「lib.rs」を作り、「pub mod ファイル名」で外から取れるようにします。
最後に、使用するファイルで「use」を用いて、使用することを宣言します。
これで、他のファイルで作ったstructを使用することができるようになります。
2 Structに必要な機能を実装していく
① Encode・Decodeの実装
次のようなエラーが出てきました。
「Status」に「StorableHint」が実装されていないことが原因のようです。
では「StorableHint」を見てみましょう。
Storable型の「Type」とStorageKey型の「PreferredKey」が実装されるようです。
では、「Storable」を見てみましょう。
「encode」「decode」関数が使われていますが、その過程で、「scale::Encode」「scale::Decode」が使われていることがわかります。
つまり、少なくともこれらを実装していないと、エラーが出てしまいます。
そのため、構造体に、「scale::Encode」と「scale::Decode」を実装させてみます。
下のように、「Status」構造体に「Encode」と「Decode」が加わりました。
② Typenfoの実装
すると、今度はエラーが変わり、「rmrk_common::types::Status」で 「Typenfo」が実装されていないとなりました。
そのため、下のように、「scale_info::TypeInfo」を実装しました。
しかし、先ほどと異なり、「cfg_attr」がついています。
これは、「条件付き属性マクロ」と言われるもので、第一引数がtrueの時、第二引数が適用されます。
では、なぜ「条件付き属性マクロ」にしているのでしょうか?
それは、TypeInfoトレイトを実装するために必要な「type_info」メソッドが「std」ライブラリに含まれる「TypeId」型を使用する必要があるからです。
つまり、「std」ライブラリがなければ使用できないため、「条件付き属性マクロ」としています。
ちなみに、type_infoメソッドを使うのは「SCALE」形式に変換するためです。
「SCALE」形式に変換するには、構造体の型情報が必要になります。
「type_info」メソッドを利用することで、下のような型情報を結果として得ることができます。
このように、「TypeInfo」が加わりました。
③ StorageLayoutの実装
実装すると、新しいエラーになりました。
次は、「StorageLayout」が実装されていないと言っています。
このように、「ink::storage::traits::StorageLayout」を追加してみました。
なお、「StorageLayout」にも「条件付き属性マクロ」が設定されているのは「Layout」という型を必要としているためです。
これで、エラーは消えました。
このように、StorageLayoutが追加されました。
ちなみに、「StorageLayout」はデータ構造がストレージ上でどのように配置されるかを自動的に計算してくれます。
例えば、このように「layout」メソッドを使ってみましょう。
Personという構造体のストレージ上のレイアウトを確認できます。
下のように、構造体のストレージ上でのレイアウトを取ってきてくれました。
④ 「Debug」「Clone」「PartialEq」の実装
せっかくなので、他にもよく使う、「Debug」「Clone」「PartialEq」を見てみましょう。
最終的に、下のようになりました。
まずは、「Debug」トレイトについてです。
このトレイトが実装されることで、「フォーマット可能な文字列」で使うことができます。
例えば、下の例で考えます。
Debugトレイトを実装することで、下のように{:?}の部分を置き換えることができます。
これにより、デバッグがしやすくなります。
次に、「Clone」トレイトです。
これがあることで、cloneメソッドを使うことができます。
cloneメソッドを使うことで、元の構造体とは独立した新しい値を取得することができます。
最後は「PartialEq」トレイトです。
==演算子を実装するため、比較を行うことができます。