1use 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 pub decimals: u8,
123 pub name: String,
125 pub symbol: String,
127 pub description: String,
129 pub icon_url: Option<String>,
131 #[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#[serde_as]
167#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
168#[serde(rename_all = "camelCase")]
169pub struct IotaCirculatingSupply {
170 pub value: u64,
172 pub circulating_supply_percentage: f64,
175 pub at_checkpoint: CheckpointSequenceNumber,
177}