iota_types/
balance.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use 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}