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