创建存储结构(结构体)
⚠️ Update Notice:
Please read Substrate to Polkadot SDK page first.
创建类似分组存储项的结构体是跟踪它们的有序方法。
以这种方式分组时,引用它们比单独保留各个 StorageValue 项更容易。
这可以使测试和创世配置更容易。
本指南向您展示如何创建一个 StorageValue 存储项,该项保存一个结构体并在 on_initialize 中使用。
此结构体执行以下操作:
- 跟踪初始金额 (
issuance) - 跟踪接收该金额的帐户 (
minter) - 跟踪可以燃烧一定金额的帐户 (
burner) - 在
on_initialize中(部分)使用
开始之前
确保您有一个可用于构建结构体的模块。 如果您没有正在使用的模块,请使用 模板模块。
-
创建一个结构体
将结构体命名为
MetaData并声明其不同的类型:#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default)] pub struct MetaData<AccountId, Balance> { issuance: Balance, minter: AccountId, burner: AccountId, } -
将结构体声明为存储项
使用
StorageValue将结构体声明为存储中的新单个项:#[pallet::storage] #[pallet::getter(fn meta_data)] pub(super) type MetaDataStore<T: Config> = StorageValue<_, MetaData<T::AccountId, T::Balance>, ValueQuery>; -
配置
GenesisConfig使用
#[pallet::genesis_config]属性从您的MetaData结构体初始化值。// 将 `admin` 声明为 `T::AccountId` 类型。 #[pallet::genesis_config] pub struct GenesisConfig<T: Config> { pub admin: T::AccountId, } // 为其提供默认值。 #[cfg(feature = "std")] impl<T: Config> Default for GenesisConfig<T> { fn default() -> Self { Self { admin: Default::default(), } } }此
admin变量必须与node/chainspec.rs文件内fn testnet_genesis中使用的变量相对应。 -
配置
GenesisBuild使用
#[pallet::genesis_build]属性初始化结构体的值,使用admin初始化T::AccountId类型的值:#[pallet::genesis_build] impl<T: Config> GenesisBuild<T> for GenesisConfig<T> { fn build(&self) { MetaDataStore::<T>::put(MetaData { issuance: Zero::zero(), minter: self.admin.clone(), burner: self.admin.clone(), }); } } -
在
on_initialize()中使用结构体为在启动链时初始化的
MetaData的issuance字段分配一个金额:fn on_initialize(_n: T::BlockNumber) -> Weight { // 为 StorageValue 结构体创建一个别名。 let mut meta = MetaDataStore::<T>::get(); // 向 `issuance` 字段添加一个值。 let value: T::Balance = 50u8.into(); meta.issuance = meta.issuance.saturating_add(value); // 将金额添加到存储中的 `minter` 帐户。 Accounts::<T>::mutate(&meta.minter, |bal| { *bal = bal.saturating_add(value); }); }
on_initialize 函数确保在启动链时将指定项的值写入存储。
示例
reward-coin示例模块
