1use move_core_types::{
6 annotated_value::{MoveFieldLayout, MoveStructLayout, MoveTypeLayout},
7 ident_str,
8 identifier::IdentStr,
9 language_storage::{StructTag, TypeTag},
10};
11use schemars::JsonSchema;
12use serde::{Deserialize, Serialize};
13use serde_with::serde_as;
14
15use crate::{
16 IOTA_FRAMEWORK_ADDRESS,
17 error::{ExecutionError, ExecutionErrorKind},
18 iota_serde::{BigInt, Readable},
19};
20pub const BALANCE_MODULE_NAME: &IdentStr = ident_str!("balance");
21pub const BALANCE_STRUCT_NAME: &IdentStr = ident_str!("Balance");
22pub const BALANCE_CREATE_REWARDS_FUNCTION_NAME: &IdentStr = ident_str!("create_staking_rewards");
23pub const BALANCE_DESTROY_REBATES_FUNCTION_NAME: &IdentStr = ident_str!("destroy_storage_rebates");
24
25#[serde_as]
26#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, JsonSchema)]
27pub struct Supply {
28 #[schemars(with = "BigInt<u64>")]
29 #[serde_as(as = "Readable<BigInt<u64>, _>")]
30 pub value: u64,
31}
32
33#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema, Eq, PartialEq)]
34pub struct Balance {
35 value: u64,
36}
37
38impl Balance {
39 pub fn new(value: u64) -> Self {
40 Self { value }
41 }
42
43 pub fn type_(type_param: TypeTag) -> StructTag {
44 StructTag {
45 address: IOTA_FRAMEWORK_ADDRESS,
46 module: BALANCE_MODULE_NAME.to_owned(),
47 name: BALANCE_STRUCT_NAME.to_owned(),
48 type_params: vec![type_param],
49 }
50 }
51
52 pub fn type_tag(inner_type_param: TypeTag) -> TypeTag {
53 TypeTag::Struct(Box::new(Self::type_(inner_type_param)))
54 }
55
56 pub fn is_balance(s: &StructTag) -> bool {
57 s.address == IOTA_FRAMEWORK_ADDRESS
58 && s.module.as_ident_str() == BALANCE_MODULE_NAME
59 && s.name.as_ident_str() == BALANCE_STRUCT_NAME
60 }
61
62 pub fn withdraw(&mut self, amount: u64) -> Result<(), ExecutionError> {
63 fp_ensure!(
64 self.value >= amount,
65 ExecutionError::new_with_source(
66 ExecutionErrorKind::InsufficientCoinBalance,
67 format!("balance: {} required: {}", self.value, amount)
68 )
69 );
70 self.value -= amount;
71 Ok(())
72 }
73
74 pub fn deposit_for_safe_mode(&mut self, amount: u64) {
75 self.value += amount;
76 }
77
78 pub fn value(&self) -> u64 {
79 self.value
80 }
81
82 pub fn to_bcs_bytes(&self) -> Vec<u8> {
83 bcs::to_bytes(&self).unwrap()
84 }
85
86 pub fn layout(type_param: TypeTag) -> MoveStructLayout {
87 MoveStructLayout {
88 type_: Self::type_(type_param),
89 fields: vec![MoveFieldLayout::new(
90 ident_str!("value").to_owned(),
91 MoveTypeLayout::U64,
92 )],
93 }
94 }
95}