From 57677b8001a7d90bf20626777ea25508533b0abd Mon Sep 17 00:00:00 2001 From: FroVolod Date: Sun, 28 Jan 2024 19:06:17 +0200 Subject: [PATCH] refactored --- src/commands/tokens/send_ft/amount_ft.rs | 127 +++++++++++++---------- src/types/ft_properties.rs | 46 +++++++- 2 files changed, 114 insertions(+), 59 deletions(-) diff --git a/src/commands/tokens/send_ft/amount_ft.rs b/src/commands/tokens/send_ft/amount_ft.rs index bb30b4ed5..3bcc8bf44 100644 --- a/src/commands/tokens/send_ft/amount_ft.rs +++ b/src/commands/tokens/send_ft/amount_ft.rs @@ -43,37 +43,45 @@ impl AmountFtContext { previous_context.ft_contract_account_id ) })?; - let crate::types::ft_properties::FtMetadata { decimals, symbol } = - crate::types::ft_properties::params_ft_metadata( - previous_context.ft_contract_account_id.clone(), - &network_config, - near_primitives::types::Finality::Final.into(), - )?; + let ft_metadata = crate::types::ft_properties::params_ft_metadata( + previous_context.ft_contract_account_id.clone(), + &network_config, + near_primitives::types::Finality::Final.into(), + )?; let mut amount_ft = scope.amount_ft.clone(); - if amount_ft.symbol.to_uppercase() != symbol.to_uppercase() { + if amount_ft.symbol().to_uppercase() != ft_metadata.symbol.to_uppercase() { return color_eyre::eyre::Result::Err(color_eyre::eyre::eyre!( "Invalid currency symbol" )); - } else if decimals < amount_ft.decimals.into() { + } else if ft_metadata.decimals < amount_ft.decimals().into() { return color_eyre::eyre::Result::Err(color_eyre::eyre::eyre!( - "Error: Invalid decimal places. Your FT amount exceeds {decimals} decimal places." + "Error: Invalid decimal places. Your FT amount exceeds {} decimal places.", + ft_metadata.decimals )); } else { - let actual_decimals = u32::try_from(decimals) + let actual_decimals = u32::try_from(ft_metadata.decimals) .wrap_err("Error converting u64 to u32")? - .checked_sub(amount_ft.decimals.into()) + .checked_sub(amount_ft.decimals().into()) .wrap_err("FT Balance: underflow or overflow happens")?; - amount_ft.amount = amount_ft - .amount - .checked_mul( - 10u128 - .checked_pow(actual_decimals) - .wrap_err("FT Balance: overflow happens")?, - ) - .wrap_err("FT Balance: overflow happens")?; - amount_ft.decimals = decimals.try_into().wrap_err("Error converting u64 to u8")?; - amount_ft.symbol = symbol; + amount_ft.set_amount( + amount_ft + .amount() + .checked_mul( + 10u128 + .checked_pow(actual_decimals) + .wrap_err("FT Balance: overflow happens")?, + ) + .wrap_err("FT Balance: overflow happens")?, + ); + amount_ft.set_decimals( + ft_metadata + .decimals + .try_into() + .wrap_err("Error converting u64 to u8")?, + ); + amount_ft.set_symbol(ft_metadata.symbol.clone()); + amount_ft.normalize(&ft_metadata)?; } Ok(Self { @@ -101,27 +109,28 @@ impl AmountFt { ) })?; - let crate::types::ft_properties::FtMetadata { decimals, symbol } = - crate::types::ft_properties::params_ft_metadata( - context.ft_contract_account_id.clone(), - &network_config, - near_primitives::types::Finality::Final.into(), - )?; + let ft_metadata = crate::types::ft_properties::params_ft_metadata( + context.ft_contract_account_id.clone(), + &network_config, + near_primitives::types::Finality::Final.into(), + )?; eprintln!(); - let sym = symbol.clone(); + let sym = ft_metadata.symbol.clone(); match CustomType::::new(&format!( - "Enter an amount FT to transfer (example: 10{symbol} or 0.5{symbol}):" + "Enter an amount FT to transfer (example: 10{symbol} or 0.5{symbol}):", + symbol = ft_metadata.symbol )) .with_validator(move |ft: &crate::types::ft_properties::FungibleToken| { - if ft.symbol.to_uppercase() != sym.to_uppercase() { + if ft.symbol().to_uppercase() != sym.to_uppercase() { Ok(inquire::validator::Validation::Invalid( inquire::validator::ErrorMessage::Custom("Invalid currency symbol".into()), )) - } else if decimals < ft.decimals.into() { + } else if ft_metadata.decimals < ft.decimals().into() { Ok(inquire::validator::Validation::Invalid( inquire::validator::ErrorMessage::Custom(format!( - "Invalid decimal places. Your FT amount exceeds {decimals} decimal places." + "Invalid decimal places. Your FT amount exceeds {} decimal places.", + ft_metadata.decimals )), )) } else { @@ -130,45 +139,51 @@ impl AmountFt { }) .with_formatter(&|ft| { let one_ft: u128 = 10u128 - .checked_pow(ft.decimals.into()) + .checked_pow(ft.decimals().into()) .expect("FT Balance: overflow happens"); - if ft.amount == 0 { - format!("0 {}", symbol) - } else if ft.amount % one_ft == 0 { - format!("{} {}", ft.amount / one_ft, symbol) + if ft.amount() == 0 { + format!("0 {}", ft_metadata.symbol) + } else if ft.amount() % one_ft == 0 { + format!("{} {}", ft.amount() / one_ft, ft_metadata.symbol) } else { format!( "{}.{} {}", - ft.amount / one_ft, + ft.amount() / one_ft, format!( "{:0>decimals$}", - (ft.amount % one_ft), - decimals = ft.decimals.into() + (ft.amount() % one_ft), + decimals = ft.decimals().into() ) .trim_end_matches('0'), - symbol + ft_metadata.symbol ) } }) .prompt() { Ok(mut fungible_token) => { - let actual_decimals = u32::try_from(decimals) + let actual_decimals = u32::try_from(ft_metadata.decimals) .wrap_err("Error converting u64 to u32")? - .checked_sub(fungible_token.decimals.into()) + .checked_sub(fungible_token.decimals().into()) .wrap_err("FT Balance: underflow or overflow happens")?; - fungible_token.amount = fungible_token - .amount - .checked_mul( - 10u128 - .checked_pow(actual_decimals) - .wrap_err("FT Balance: overflow happens")?, - ) - .wrap_err("FungibleToken: overflow happens")?; - fungible_token.decimals = - decimals.try_into().wrap_err("Error converting u64 to u8")?; - fungible_token.symbol = symbol; - Ok(Some(fungible_token)) + fungible_token.set_amount( + fungible_token + .amount() + .checked_mul( + 10u128 + .checked_pow(actual_decimals) + .wrap_err("FT Balance: overflow happens")?, + ) + .wrap_err("FungibleToken: overflow happens")?, + ); + fungible_token.set_decimals( + ft_metadata + .decimals + .try_into() + .wrap_err("Error converting u64 to u8")?, + ); + fungible_token.set_symbol(ft_metadata.symbol.clone()); + Ok(Some(fungible_token.normalize(&ft_metadata)?)) } Err(err) => Err(color_eyre::Report::msg(err)), } @@ -270,7 +285,7 @@ impl DepositContext { method_name: "ft_transfer".to_string(), args: serde_json::to_vec(&json!({ "receiver_id": receiver_account_id.to_string(), - "amount": amount_ft.amount.to_string() + "amount": amount_ft.amount().to_string() }))?, gas: previous_context.gas.as_gas(), deposit: deposit.as_yoctonear(), diff --git a/src/types/ft_properties.rs b/src/types/ft_properties.rs index a2960a7aa..41d2c5d74 100644 --- a/src/types/ft_properties.rs +++ b/src/types/ft_properties.rs @@ -5,9 +5,9 @@ use crate::common::JsonRpcClientExt; #[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd)] pub struct FungibleToken { - pub amount: u128, - pub decimals: u8, - pub symbol: String, + amount: u128, + decimals: u8, + symbol: String, } impl FungibleToken { @@ -18,6 +18,46 @@ impl FungibleToken { symbol, } } + + pub fn normalize(&self, ft_metadata: &FtMetadata) -> color_eyre::eyre::Result { + if ft_metadata.decimals != u64::from(self.decimals) { + color_eyre::eyre::Result::Err(color_eyre::eyre::eyre!( + "Invalid decimal places. Your FT amount exceeds {} decimal places.", + ft_metadata.decimals + )) + } else if ft_metadata.symbol != self.symbol { + color_eyre::eyre::Result::Err(color_eyre::eyre::eyre!("Invalid currency symbol")) + } else { + Ok(self.clone()) + } + } + + pub fn amount(&self) -> u128 { + self.amount + } + + pub fn decimals(&self) -> u8 { + self.decimals + } + + pub fn symbol(&self) -> String { + self.symbol.to_owned() + } + + pub fn set_amount(&mut self, new_amount: u128) -> Self { + self.amount = new_amount; + self.clone() + } + + pub fn set_decimals(&mut self, new_decimals: u8) -> Self { + self.decimals = new_decimals; + self.clone() + } + + pub fn set_symbol(&mut self, new_symbol: String) -> Self { + self.symbol = new_symbol; + self.clone() + } } impl std::fmt::Display for FungibleToken {