Skip to main content

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