Expand description
Exports the sui_pkg_sdk! macro for generating Rust types from Move
source code and implementing relevant af_move_type traits.
Automates the conversion of Sui Move types to Rust. The goal is to extract as much information as possible at compile time about the Move types of a Sui package, generating equivalent Rust types that:
- are BCS-compatible with their on-chain counterparts, so that their contents can be deserialized from BCS bytes returned by RPCs
- embed type information based on their location (path) in a Move package + type parameters, so that a corresponding type tag can be easily constructed with just the missing information
- use the embedded type information when deserializing a
MoveInstanceto verify the type of incoming data, to avoid mistakenly deserializing a different type that has the same BCS bytes
See also:
af_move_typeaf_move_type_derivefor how the type tag information for a struct is derived from its declaration
§Move types to Rust types
This macro allows callers to almost copy and paste Move struct declarations and get equivalent Rust types. Some additional steps may be necessary however:
- If
phantomkeywords are present, they must be substituted by!phantom - Struct fields should be Rust types. That means they must be in scope. Special Move types like
address,vector<T>andu256are automatically converted to equivalent Rust types.
The only requirement for a struct field type is that it has the same BCS representation as
the Move type for that field. You may use that to your advantage. For instance, if a
u256 is supposed to be interpreted as a fixed point number, you may define a custom
FixedP(U256) type that (de)serializes to/from u256 bytes but behaves like a fixed point
number.
Additionally, you may add any outter attributes, e.g. docs, to structs and their fields.
All MoveStructs created by this macro will have a pretty Display
using tabled as a backend.
§Examples
use af_sui_pkg_sdk::sui_pkg_sdk;
sui_pkg_sdk!(package {
module clearing_house {
/// Used to dynamically load market objects as needed.
/// Used to dynamically load traders' position objects as needed.
struct ClearingHouse<!phantom T> has key {
id: UID,
// ...
}
/// Stores all deposits from traders for collateral T.
/// Stores the funds reserved for covering bad debt from untimely
/// liquidations.
///
/// The Clearing House keeps track of who owns each share of the vault.
struct Vault<!phantom T> has key, store {
id: UID,
collateral_balance: Balance<T>,
insurance_fund_balance: Balance<T>,
scaling_factor: u64
}
}
module keys {
/// Key type for accessing trader position in clearing house.
struct Position has copy, drop, store {
account_id: u64,
}
}
});Rust types clearing_house::{ClearingHouse, Vault} and keys::Position will be generated from
the macro call above.
Now suppose we have received a type tag and BCS contents of a Move object from an RPC call. We
can try deserializing it into a MoveInstance of one of these generated types
use af_move_type::{MoveInstance, otw::Otw};
let type_tag: TypeTag;
let base64_bcs: String;
let instance = MoveInstance::<Vault<Otw>>::from_raw_type(
type_tag,
&af_sui_types::decode_base64_default(base64_bcs)?
)?;
println!("Coin type {}", instance.type_.t);A few things are happening here:
from_raw_typeis checking first thattype_tagmatches the declaration of the struct, i.e., it is of the form_::clearing_house::Vault<_::_::_>. Anything else will fail immediately- then, it tries to deserialize
clearing_house::Vaultfrom the BCS bytes
Finally, notice that we’re accessing a type_ field in the Move instance. That’s because a
VaultTypeTag was automatically generated:
pub struct VaultTypeTag<T: MoveType> {
pub address: Address,
pub t: <T as MoveType>::TypeTag,
}Notice this contains information about the Vault’s type tag that couldn’t be derived at
compile time, namely, the address of the Move package defining the struct and the concrete type
of the generic type parameter.
One advantage of this type tag over carrying around the generic StructTag is that we can
access the type of the OTW directly, while to do so with the latter we’d have to check if
StructTag::type_params is not empty every time.
Re-exports§
pub use af_sui_types;pub use tabled;pub use af_move_type;pub use derive_new;pub use serde;
Macros§
- sui_
pkg_ sdk - Generate
MoveStructimplementations from Move source code.
Structs§
- Address
- Unique identifier for an Account on the Sui blockchain.
- MoveVec
- Table
- The structure provides an interface for building a table for types that implements
Tabled. - U256
Enums§
- TypeTag
- Type of a move value
Traits§
- HasKey
- Move
Struct - Trait marking a Move struct type. Has a specific way to construct a
StructTag. - Move
Type - Trait marking a Move data type. Has a specific way to construct a
TypeTag. - Tabled
- Tabled a trait responsible for providing a header fields and a row fields.
Functions§
Derive Macros§
- Move
Struct - Derives
af_move_typetrait implementations for a type representing a Move struct. - Tabled