cosm_tome_wasm_deploy_fork/modules/bank/
model.rs

1use std::fmt;
2
3use cosmrs::proto::traits::MessageExt;
4use cosmrs::proto::{
5    cosmos::bank::v1beta1::{
6        DenomUnit as ProtoDenomUnit, Metadata, MsgSend, Params as ProtoParams,
7        SendEnabled as ProtoSendEnabled,
8    },
9    Any,
10};
11use schemars::JsonSchema;
12use serde::{Deserialize, Serialize};
13
14use crate::chain::coin::Denom;
15use crate::{
16    chain::{
17        coin::Coin, error::ChainError, request::PaginationResponse, response::ChainTxResponse,
18    },
19    modules::auth::model::Address,
20};
21
22use super::error::BankError;
23
24#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
25pub struct BalanceResponse {
26    pub balance: Coin,
27}
28
29#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
30pub struct BalancesResponse {
31    pub balances: Vec<Coin>,
32
33    pub next: Option<PaginationResponse>,
34}
35
36#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
37pub struct DenomMetadataResponse {
38    pub meta: Option<DenomMetadata>,
39}
40
41#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
42pub struct DenomsMetadataResponse {
43    pub metas: Vec<DenomMetadata>,
44
45    pub next: Option<PaginationResponse>,
46}
47
48#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
49pub struct DenomMetadata {
50    pub description: String,
51
52    pub denom_units: Vec<DenomUnit>,
53
54    /// base represents the base denom (should be the DenomUnit with exponent = 0).
55    pub base: String,
56
57    /// display indicates the suggested denom string that should be displayed in clients.
58    pub display: String,
59
60    /// name defines the name of the token (eg: Cosmos Atom)
61    ///
62    /// Since: cosmos-sdk 0.43
63    pub name: String,
64
65    /// symbol is the token symbol usually shown on exchanges (eg: ATOM).
66    /// This can be the same as the display.
67    ///
68    /// Since: cosmos-sdk 0.43
69    pub symbol: String,
70}
71
72impl TryFrom<Metadata> for DenomMetadata {
73    type Error = ChainError;
74
75    fn try_from(meta: Metadata) -> Result<Self, Self::Error> {
76        Ok(Self {
77            description: meta.description,
78            denom_units: meta
79                .denom_units
80                .into_iter()
81                .map(TryInto::try_into)
82                .collect::<Result<Vec<_>, _>>()?,
83            base: meta.base,
84            display: meta.display,
85            name: meta.name,
86            symbol: meta.symbol,
87        })
88    }
89}
90
91impl From<DenomMetadata> for Metadata {
92    fn from(meta: DenomMetadata) -> Self {
93        Self {
94            description: meta.description,
95            denom_units: meta.denom_units.into_iter().map(Into::into).collect(),
96            base: meta.base,
97            display: meta.display,
98            name: meta.name,
99            symbol: meta.symbol,
100        }
101    }
102}
103
104#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
105pub struct DenomUnit {
106    /// denom represents the string name of the given denom unit (e.g uatom).
107    pub denom: Denom,
108
109    /// exponent represents the power of 10 exponent that one must raise the base_denom to in order to equal the given DenomUnit's denom.
110    /// 1 denom = 1^exponent base_denom
111    /// (e.g. with a base_denom of uatom, one can create a DenomUnit of 'atom' with exponent = 6, thus: 1 atom = 10^6 uatom).
112    pub exponent: u32,
113
114    /// aliases is a list of string aliases for the given denom
115    pub aliases: Vec<String>,
116}
117
118impl TryFrom<ProtoDenomUnit> for DenomUnit {
119    type Error = ChainError;
120
121    fn try_from(du: ProtoDenomUnit) -> Result<Self, Self::Error> {
122        Ok(Self {
123            denom: du.denom.parse()?,
124            exponent: du.exponent,
125            aliases: du.aliases,
126        })
127    }
128}
129
130impl From<DenomUnit> for ProtoDenomUnit {
131    fn from(du: DenomUnit) -> Self {
132        Self {
133            denom: du.denom.into(),
134            exponent: du.exponent,
135            aliases: du.aliases,
136        }
137    }
138}
139
140#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq, Hash)]
141pub struct ParamsResponse {
142    pub params: Option<Params>,
143}
144
145#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq, Hash)]
146pub struct Params {
147    pub send_enabled: Vec<SendEnabled>,
148    pub default_send_enabled: bool,
149}
150
151impl TryFrom<ProtoParams> for Params {
152    type Error = ChainError;
153
154    fn try_from(p: ProtoParams) -> Result<Self, Self::Error> {
155        Ok(Self {
156            send_enabled: p
157                .send_enabled
158                .into_iter()
159                .map(TryInto::try_into)
160                .collect::<Result<Vec<_>, _>>()?,
161            default_send_enabled: p.default_send_enabled,
162        })
163    }
164}
165
166impl From<Params> for ProtoParams {
167    fn from(p: Params) -> Self {
168        Self {
169            send_enabled: p.send_enabled.into_iter().map(Into::into).collect(),
170            default_send_enabled: p.default_send_enabled,
171        }
172    }
173}
174
175/// SendEnabled maps coin denom to a send_enabled status (whether a denom is sendable).
176#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq, Hash)]
177pub struct SendEnabled {
178    pub denom: Denom,
179    pub enabled: bool,
180}
181
182impl TryFrom<ProtoSendEnabled> for SendEnabled {
183    type Error = ChainError;
184
185    fn try_from(se: ProtoSendEnabled) -> Result<Self, Self::Error> {
186        Ok(Self {
187            denom: se.denom.parse()?,
188            enabled: se.enabled,
189        })
190    }
191}
192
193impl From<SendEnabled> for ProtoSendEnabled {
194    fn from(se: SendEnabled) -> Self {
195        Self {
196            denom: se.denom.into(),
197            enabled: se.enabled,
198        }
199    }
200}
201
202#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
203pub struct SendRequest {
204    pub from: Address,
205    pub to: Address,
206    pub amounts: Vec<Coin>,
207}
208
209pub type SendRequestProto = SendRequest;
210
211impl fmt::Display for SendRequest {
212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213        write!(f, "{} sends ", self.from)?;
214
215        for a in &self.amounts {
216            write!(f, "{a} ")?;
217        }
218
219        write!(f, "-> {}", self.to)
220    }
221}
222
223impl TryFrom<SendRequest> for Any {
224    type Error = BankError;
225
226    fn try_from(req: SendRequest) -> Result<Self, Self::Error> {
227        let proto: MsgSend = req.try_into()?;
228        Ok(proto.to_any().map_err(ChainError::prost_proto_encoding)?)
229    }
230}
231
232impl TryFrom<Any> for SendRequest {
233    type Error = BankError;
234
235    fn try_from(any: Any) -> Result<Self, Self::Error> {
236        MsgSend::from_any(&any)
237            .map_err(ChainError::prost_proto_decoding)?
238            .try_into()
239    }
240}
241
242impl TryFrom<MsgSend> for SendRequest {
243    type Error = BankError;
244
245    fn try_from(msg: MsgSend) -> Result<Self, Self::Error> {
246        Ok(Self {
247            from: msg.from_address.parse()?,
248            to: msg.to_address.parse()?,
249            amounts: msg
250                .amount
251                .into_iter()
252                .map(TryFrom::try_from)
253                .collect::<Result<Vec<_>, _>>()?,
254        })
255    }
256}
257
258impl TryFrom<SendRequest> for MsgSend {
259    type Error = BankError;
260
261    fn try_from(req: SendRequest) -> Result<Self, Self::Error> {
262        if req.amounts.is_empty() {
263            return Err(BankError::EmptyAmount);
264        }
265
266        for amount in &req.amounts {
267            if amount.amount == 0 {
268                return Err(BankError::EmptyAmount);
269            }
270        }
271
272        Ok(Self {
273            from_address: req.from.into(),
274            to_address: req.to.into(),
275            amount: req.amounts.into_iter().map(Into::into).collect(),
276        })
277    }
278}
279
280#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
281pub struct SendResponse {
282    pub res: ChainTxResponse,
283}