1use move_core_types::{
6 account_address::AccountAddress,
7 ident_str,
8 identifier::IdentStr,
9 language_storage::{StructTag, TypeTag},
10};
11use serde::{Deserialize, Serialize};
12
13use crate::{IOTA_FRAMEWORK_ADDRESS, MoveTypeTagTrait, base_types::EpochId, id::UID};
14
15pub const CONFIG_MODULE_NAME: &IdentStr = ident_str!("config");
16pub const CONFIG_STRUCT_NAME: &IdentStr = ident_str!("Config");
17pub const SETTING_STRUCT_NAME: &IdentStr = ident_str!("Setting");
18pub const SETTING_DATA_STRUCT_NAME: &IdentStr = ident_str!("SettingData");
19pub const RESOLVED_IOTA_CONFIG: (&AccountAddress, &IdentStr, &IdentStr) = (
20 &IOTA_FRAMEWORK_ADDRESS,
21 CONFIG_MODULE_NAME,
22 CONFIG_STRUCT_NAME,
23);
24
25#[derive(Debug, Serialize, Deserialize)]
27pub struct Config {
28 pub id: UID,
29}
30
31#[derive(Debug, Serialize, Deserialize)]
33pub struct Setting<V> {
34 pub data: Option<SettingData<V>>,
35}
36
37#[derive(Debug, Serialize, Deserialize)]
39pub struct SettingData<V> {
40 pub newer_value_epoch: u64,
41 pub newer_value: Option<V>,
42 pub older_value_opt: Option<V>,
43}
44
45impl Config {
46 pub fn type_() -> StructTag {
47 StructTag {
48 address: IOTA_FRAMEWORK_ADDRESS,
49 module: CONFIG_MODULE_NAME.to_owned(),
50 name: CONFIG_STRUCT_NAME.to_owned(),
51 type_params: vec![],
52 }
53 }
54}
55
56pub fn setting_type(value_tag: TypeTag) -> StructTag {
57 StructTag {
58 address: IOTA_FRAMEWORK_ADDRESS,
59 module: CONFIG_MODULE_NAME.to_owned(),
60 name: SETTING_STRUCT_NAME.to_owned(),
61 type_params: vec![value_tag],
62 }
63}
64
65impl MoveTypeTagTrait for Config {
66 fn get_type_tag() -> TypeTag {
67 TypeTag::Struct(Box::new(Config::type_()))
68 }
69}
70
71impl<V: MoveTypeTagTrait> MoveTypeTagTrait for Setting<V> {
72 fn get_type_tag() -> TypeTag {
73 TypeTag::Struct(Box::new(setting_type(V::get_type_tag())))
74 }
75}
76
77pub fn is_setting(tag: &StructTag) -> bool {
78 let StructTag {
79 address,
80 module,
81 name,
82 type_params,
83 } = tag;
84 *address == IOTA_FRAMEWORK_ADDRESS
85 && module.as_ident_str() == CONFIG_MODULE_NAME
86 && name.as_ident_str() == SETTING_STRUCT_NAME
87 && type_params.len() == 1
88}
89
90impl<V> Setting<V> {
91 pub fn read_value(&self, cur_epoch: Option<EpochId>) -> Option<&V> {
95 self.data.as_ref()?.read_value(cur_epoch)
96 }
97}
98
99impl<V> SettingData<V> {
100 pub fn read_value(&self, cur_epoch: Option<EpochId>) -> Option<&V> {
105 let use_newer_value = match cur_epoch {
106 Some(cur_epoch) => cur_epoch > self.newer_value_epoch,
107 None => true,
108 };
109 if use_newer_value {
110 self.newer_value.as_ref()
111 } else {
112 self.older_value_opt.as_ref()
113 }
114 }
115}