1use std::fmt;
2
3use cosmrs::proto::cosmos::bank::v1beta1::{
4 DenomUnit as ProtoDenomUnit, Metadata, MsgSend, Params as ProtoParams,
5 SendEnabled as ProtoSendEnabled,
6};
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9
10use crate::chain::coin::Denom;
11use crate::chain::msg::Msg;
12use crate::{
13 chain::{coin::Coin, error::ChainError, request::PaginationResponse},
14 modules::auth::model::Address,
15};
16
17use super::error::BankError;
18
19#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
20pub struct BalanceResponse {
21 pub balance: Coin,
22}
23
24#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
25pub struct BalancesResponse {
26 pub balances: Vec<Coin>,
27
28 pub next: Option<PaginationResponse>,
29}
30
31#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
32pub struct DenomMetadataResponse {
33 pub meta: Option<DenomMetadata>,
34}
35
36#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
37pub struct DenomsMetadataResponse {
38 pub metas: Vec<DenomMetadata>,
39
40 pub next: Option<PaginationResponse>,
41}
42
43#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
44pub struct DenomMetadata {
45 pub description: String,
46
47 pub denom_units: Vec<DenomUnit>,
48
49 pub base: String,
51
52 pub display: String,
54
55 pub name: String,
59
60 pub symbol: String,
65 pub uri: String,
66 pub uri_hash: String,
67}
68
69impl TryFrom<Metadata> for DenomMetadata {
70 type Error = ChainError;
71
72 fn try_from(meta: Metadata) -> Result<Self, Self::Error> {
73 Ok(Self {
74 description: meta.description,
75 denom_units: meta
76 .denom_units
77 .into_iter()
78 .map(TryInto::try_into)
79 .collect::<Result<Vec<_>, _>>()?,
80 base: meta.base,
81 display: meta.display,
82 name: meta.name,
83 symbol: meta.symbol,
84 uri: meta.uri,
85 uri_hash: meta.uri_hash,
86 })
87 }
88}
89
90impl From<DenomMetadata> for Metadata {
91 fn from(meta: DenomMetadata) -> Self {
92 Self {
93 description: meta.description,
94 denom_units: meta.denom_units.into_iter().map(Into::into).collect(),
95 base: meta.base,
96 display: meta.display,
97 name: meta.name,
98 symbol: meta.symbol,
99 uri: meta.uri,
100 uri_hash: meta.uri_hash,
101 }
102 }
103}
104
105#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq)]
106pub struct DenomUnit {
107 pub denom: Denom,
109
110 pub exponent: u32,
114
115 pub aliases: Vec<String>,
117}
118
119impl TryFrom<ProtoDenomUnit> for DenomUnit {
120 type Error = ChainError;
121
122 fn try_from(du: ProtoDenomUnit) -> Result<Self, Self::Error> {
123 Ok(Self {
124 denom: du.denom.parse()?,
125 exponent: du.exponent,
126 aliases: du.aliases,
127 })
128 }
129}
130
131impl From<DenomUnit> for ProtoDenomUnit {
132 fn from(du: DenomUnit) -> Self {
133 Self {
134 denom: du.denom.into(),
135 exponent: du.exponent,
136 aliases: du.aliases,
137 }
138 }
139}
140
141#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq, Hash)]
142pub struct ParamsResponse {
143 pub params: Option<Params>,
144}
145
146#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq, Hash)]
147pub struct Params {
148 pub send_enabled: Vec<SendEnabled>,
149 pub default_send_enabled: bool,
150}
151
152impl TryFrom<ProtoParams> for Params {
153 type Error = ChainError;
154
155 fn try_from(p: ProtoParams) -> Result<Self, Self::Error> {
156 Ok(Self {
157 send_enabled: p
158 .send_enabled
159 .into_iter()
160 .map(TryInto::try_into)
161 .collect::<Result<Vec<_>, _>>()?,
162 default_send_enabled: p.default_send_enabled,
163 })
164 }
165}
166
167impl From<Params> for ProtoParams {
168 fn from(p: Params) -> Self {
169 Self {
170 send_enabled: p.send_enabled.into_iter().map(Into::into).collect(),
171 default_send_enabled: p.default_send_enabled,
172 }
173 }
174}
175
176#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, PartialEq, Hash)]
178pub struct SendEnabled {
179 pub denom: Denom,
180 pub enabled: bool,
181}
182
183impl TryFrom<ProtoSendEnabled> for SendEnabled {
184 type Error = ChainError;
185
186 fn try_from(se: ProtoSendEnabled) -> Result<Self, Self::Error> {
187 Ok(Self {
188 denom: se.denom.parse()?,
189 enabled: se.enabled,
190 })
191 }
192}
193
194impl From<SendEnabled> for ProtoSendEnabled {
195 fn from(se: SendEnabled) -> Self {
196 Self {
197 denom: se.denom.into(),
198 enabled: se.enabled,
199 }
200 }
201}
202
203#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
204pub struct SendRequest {
205 pub from: Address,
206 pub to: Address,
207 pub amounts: Vec<Coin>,
208}
209
210pub type SendRequestProto = SendRequest;
211
212impl fmt::Display for SendRequest {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 write!(f, "{} sends ", self.from)?;
215
216 for a in &self.amounts {
217 write!(f, "{a} ")?;
218 }
219
220 write!(f, "-> {}", self.to)
221 }
222}
223
224impl Msg for SendRequestProto {
225 type Proto = MsgSend;
226 type Err = BankError;
227}
228
229impl TryFrom<MsgSend> for SendRequest {
230 type Error = BankError;
231
232 fn try_from(msg: MsgSend) -> Result<Self, Self::Error> {
233 Ok(Self {
234 from: msg.from_address.parse()?,
235 to: msg.to_address.parse()?,
236 amounts: msg
237 .amount
238 .into_iter()
239 .map(TryFrom::try_from)
240 .collect::<Result<Vec<_>, _>>()?,
241 })
242 }
243}
244
245impl TryFrom<SendRequest> for MsgSend {
246 type Error = BankError;
247
248 fn try_from(req: SendRequest) -> Result<Self, Self::Error> {
249 if req.amounts.is_empty() {
250 return Err(BankError::EmptyAmount);
251 }
252
253 for amount in &req.amounts {
254 if amount.amount == 0 {
255 return Err(BankError::EmptyAmount);
256 }
257 }
258
259 Ok(Self {
260 from_address: req.from.into(),
261 to_address: req.to.into(),
262 amount: req.amounts.into_iter().map(Into::into).collect(),
263 })
264 }
265}
266
267