使用动态字段管理合约状态
动态字段的另一个有用应用是管理合约状态。你可能会倾向于为每个状态结构体使用多个共享对象。 例如,我们可以为笔记本电脑商店的配置设置如下:
public struct PriceConfigs has key {
id: UID,
price_range: vector<u64>,
}
public struct StoreHours has key {
id: UID,
open_hours: vector<vector<u8>>,
}
public struct SpecConfigs has key {
id: UID,
specs_range: vector<u64>,
}
fun init(ctx: &mut TxContext) {
let price_configs = PriceConfigs {
id: object::new(ctx),
price_range: vector[1000, 5000],
};
let store_hours = StoreHours {
id: object::new(ctx),
open_hours: vector[vector[9, 12], vector[1, 5]],
};
let spec_configs = SpecConfigs {
id: object::new(ctx),
specs_range: vector[1000, 10000],
};
transfer::share_object(price_configs);
transfer::share_object(store_hours);
transfer::share_object(spec_configs);
}
创建共享对象并不是一项繁重的工作。每个对象都是共享的,因此用户在购买笔记本电脑时可以访问和/或修改这些对象。例如:
public fun purchase_laptop(price_configs: &PriceConfigs, store_hours: &SotreHours,
spec_configs: &SpecConfigs, laptop: String, price: u64, ctx: &mut TxContext) {
}
如你所见,这个函数的签名太长且难以阅读。此外,代表用户提交交易的 Web 界面需要跟踪所有这些共享对象的地址。想象一下, 如果我们有 5 个甚至 10 个共享对象会发生什么!这也显得过于复杂,因为这些不同的结构体从未分离并独立存在,因此它们实际上并不需要成为对象。
更简洁的方法是创建一个单一的状态配置对象,并在那里添加动态字段:
public struct StateConfigs has key {
id: UID,
}
const PRICE_CONFIGS: vector<u8> = b"PRICE_CONFIGS";
public struct PriceConfigs has store {
price_range: vector<u64>,
}
const STORE_HOURS: vector<u8> = b"STORE_HOURS";
public struct StoreHours has store {
open_hours: vector<vector<u8>>,
}
const SPEC_CONFIGS: vector<u8> = b"SPEC_CONFIGS";
public struct SpecConfigs has store {
specs_range: vector<u64>,
}
fun init(ctx: &mut TxContext) {
let state_configs = StateConfigs {
id: object::new(ctx),
};
dynamic_fields::add(&mut state_configs.id, PRICE_CONFIGS, PriceConfigs {
id: object::new(ctx),
price_range: vector[1000, 5000],
});
dynamic_fields::add(&mut state_configs.id, STORE_HOURS, StoreHours {
id: object::new(ctx),
open_hours: vector[vector[9, 12], vector[1, 5]],
});
dynamic_fields::add(&mut state_configs.id, SPEC_CONFIGS, SpecConfigs {
id: object::new(ctx),
specs_range: vector[1000, 10000],
});
transfer::share(state_configs);
}
用户交易只需要跟踪并传递一个对象的地址:
public fun purchase_laptop(state_configs: &StateConfigs, laptop: String, price: u64, ctx: &mut TxContext) {
}
正如你所见,这样简洁得多!