iota_json_rpc_types/
iota_coin.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use iota_types::{
6    balance::Supply,
7    base_types::{ObjectDigest, ObjectID, ObjectRef, SequenceNumber, TransactionDigest},
8    coin::CoinMetadata,
9    error::IotaError,
10    messages_checkpoint::CheckpointSequenceNumber,
11    object::Object,
12};
13use schemars::JsonSchema;
14use serde::{Deserialize, Serialize};
15use serde_with::{DeserializeAs, DisplayFromStr, SerializeAs, serde_as};
16
17use crate::{
18    Page,
19    iota_primitives::{
20        Base58 as Base58Schema, ObjectID as ObjectIDSchema,
21        SequenceNumberString as SequenceNumberStringSchema,
22    },
23};
24
25pub type CoinPage = Page<Coin, ObjectID>;
26
27#[serde_as]
28#[derive(Clone, Serialize, Deserialize, JsonSchema)]
29#[schemars(rename = "Supply")]
30pub struct IotaSupply {
31    #[serde_as(as = "DisplayFromStr")]
32    #[schemars(with = "String")]
33    pub value: u64,
34}
35
36impl SerializeAs<Supply> for IotaSupply {
37    fn serialize_as<S>(source: &Supply, serializer: S) -> Result<S::Ok, S::Error>
38    where
39        S: serde::Serializer,
40    {
41        IotaSupply::from(source.clone()).serialize(serializer)
42    }
43}
44
45impl<'de> DeserializeAs<'de, Supply> for IotaSupply {
46    fn deserialize_as<D>(deserializer: D) -> Result<Supply, D::Error>
47    where
48        D: serde::Deserializer<'de>,
49    {
50        let schema = IotaSupply::deserialize(deserializer)?;
51        Ok(Supply::from(schema))
52    }
53}
54
55impl From<Supply> for IotaSupply {
56    fn from(supply: Supply) -> Self {
57        Self {
58            value: supply.value,
59        }
60    }
61}
62
63impl From<IotaSupply> for Supply {
64    fn from(schema: IotaSupply) -> Self {
65        Self {
66            value: schema.value,
67        }
68    }
69}
70
71#[serde_as]
72#[derive(Serialize, Deserialize, Debug, JsonSchema, PartialEq, Eq, Clone)]
73#[serde(rename_all = "camelCase")]
74pub struct Balance {
75    pub coin_type: String,
76    pub coin_object_count: usize,
77    #[schemars(with = "String")]
78    #[serde_as(as = "DisplayFromStr")]
79    pub total_balance: u128,
80}
81
82impl Balance {
83    pub fn zero(coin_type: String) -> Self {
84        Self {
85            coin_type,
86            coin_object_count: 0,
87            total_balance: 0,
88        }
89    }
90}
91
92#[serde_as]
93#[derive(Serialize, Deserialize, Debug, JsonSchema, PartialEq, Eq, Clone)]
94#[serde(rename_all = "camelCase")]
95pub struct Coin {
96    pub coin_type: String,
97    #[schemars(with = "ObjectIDSchema")]
98    pub coin_object_id: ObjectID,
99    #[serde_as(as = "SequenceNumberStringSchema")]
100    #[schemars(with = "SequenceNumberStringSchema")]
101    pub version: SequenceNumber,
102    #[schemars(with = "Base58Schema")]
103    pub digest: ObjectDigest,
104    #[schemars(with = "String")]
105    #[serde_as(as = "DisplayFromStr")]
106    pub balance: u64,
107    #[schemars(with = "Base58Schema")]
108    pub previous_transaction: TransactionDigest,
109}
110
111impl Coin {
112    pub fn object_ref(&self) -> ObjectRef {
113        ObjectRef::new(self.coin_object_id, self.version, self.digest)
114    }
115}
116
117#[serde_as]
118#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone, PartialEq, Eq)]
119#[serde(rename_all = "camelCase")]
120pub struct IotaCoinMetadata {
121    /// Number of decimal places the coin uses.
122    pub decimals: u8,
123    /// Name for the token
124    pub name: String,
125    /// Symbol for the token
126    pub symbol: String,
127    /// Description of the token
128    pub description: String,
129    /// URL for the token logo
130    pub icon_url: Option<String>,
131    /// Object id for the CoinMetadata object
132    #[schemars(with = "Option<ObjectIDSchema>")]
133    pub id: Option<ObjectID>,
134}
135
136impl TryFrom<Object> for IotaCoinMetadata {
137    type Error = IotaError;
138    fn try_from(object: Object) -> Result<Self, Self::Error> {
139        let metadata: CoinMetadata = object.try_into()?;
140        Ok(metadata.into())
141    }
142}
143
144impl From<CoinMetadata> for IotaCoinMetadata {
145    fn from(metadata: CoinMetadata) -> Self {
146        let CoinMetadata {
147            decimals,
148            name,
149            symbol,
150            description,
151            icon_url,
152            id,
153        } = metadata;
154        Self {
155            id: Some(*id.object_id()),
156            decimals,
157            name,
158            symbol,
159            description,
160            icon_url,
161        }
162    }
163}
164
165/// Provides a summary of the circulating IOTA supply.
166#[serde_as]
167#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
168#[serde(rename_all = "camelCase")]
169pub struct IotaCirculatingSupply {
170    /// Circulating supply in NANOS at the given timestamp.
171    pub value: u64,
172    /// Percentage of total supply that is currently circulating (range: 0.0 to
173    /// 1.0).
174    pub circulating_supply_percentage: f64,
175    /// Timestamp (UTC) when the circulating supply was calculated.
176    pub at_checkpoint: CheckpointSequenceNumber,
177}