From 8c1e5899a02d716072da82dc968bdba375db9855 Mon Sep 17 00:00:00 2001 From: FroVolod Date: Sat, 1 Mar 2025 13:32:13 +0200 Subject: [PATCH] refactored FtTransfer --- src/commands/tokens/send_ft/mod.rs | 17 ++----- src/types/ft_properties.rs | 74 +++++++++++++++++++++++------- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/src/commands/tokens/send_ft/mod.rs b/src/commands/tokens/send_ft/mod.rs index 78b5bfea..5d7e6158 100644 --- a/src/commands/tokens/send_ft/mod.rs +++ b/src/commands/tokens/send_ft/mod.rs @@ -80,18 +80,11 @@ pub fn get_prepopulated_transaction( deposit: &crate::types::near_token::NearToken, gas: &crate::common::NearGas, ) -> color_eyre::eyre::Result { - let args_ft_transfer = serde_json::to_vec(&json!({ - "receiver_id": receiver_account_id, - "amount": amount_ft.amount().to_string(), - "memo": memo.as_ref().and_then(|s| { - let trimmed = s.trim(); - if trimmed.is_empty() { - None - } else { - Some(trimmed.to_string()) - } - }) - }))?; + let args_ft_transfer = serde_json::to_vec(&crate::types::ft_properties::FtTransfer { + receiver_id: receiver_account_id.clone(), + amount: amount_ft.amount(), + memo: memo.clone(), + })?; let action_ft_transfer = near_primitives::transaction::Action::FunctionCall(Box::new( near_primitives::transaction::FunctionCallAction { diff --git a/src/types/ft_properties.rs b/src/types/ft_properties.rs index bd3a37b3..800d6202 100644 --- a/src/types/ft_properties.rs +++ b/src/types/ft_properties.rs @@ -1,5 +1,6 @@ use color_eyre::eyre::{Context, ContextCompat}; use serde::de::{Deserialize, Deserializer}; +use serde::ser::{Serialize, Serializer}; use crate::common::CallResultExt; use crate::common::JsonRpcClientExt; @@ -219,6 +220,32 @@ pub fn params_ft_metadata( Ok(ft_metadata) } +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct FtTransfer { + pub receiver_id: near_primitives::types::AccountId, + #[serde(deserialize_with = "parse_u128_string", serialize_with = "to_string")] + pub amount: u128, + #[serde(skip_serializing_if = "Option::is_none")] + pub memo: Option, +} + +fn parse_u128_string<'de, D>(deserializer: D) -> color_eyre::eyre::Result +where + D: Deserializer<'de>, +{ + String::deserialize(deserializer)? + .parse::() + .map_err(serde::de::Error::custom) +} + +fn to_string(value: &T, serializer: S) -> Result +where + S: Serializer, +{ + let s = value.to_string(); + String::serialize(&s, serializer) +} + #[cfg(test)] mod tests { use super::*; @@ -270,21 +297,34 @@ mod tests { assert_eq!(ft_transfer_amount.to_string(), "all".to_string()); assert_eq!(ft_transfer_amount, FungibleTokenTransferAmount::MaxAmount); } -} - -#[derive(Debug, Clone, serde::Deserialize)] -pub struct FtTransfer { - pub receiver_id: String, - #[serde(deserialize_with = "parse_u128_string")] - pub amount: u128, - pub memo: Option, -} - -fn parse_u128_string<'de, D>(deserializer: D) -> color_eyre::eyre::Result -where - D: Deserializer<'de>, -{ - String::deserialize(deserializer)? - .parse::() - .map_err(serde::de::Error::custom) + #[test] + fn ft_transfer_with_memo_to_vec_u8() { + let ft_transfer = serde_json::to_vec(&crate::types::ft_properties::FtTransfer { + receiver_id: "fro_volod.testnet".parse().unwrap(), + amount: FungibleToken::from_str("0.123456 USDC").unwrap().amount(), + memo: Some("Memo".to_string()), + }) + .unwrap(); + assert_eq!( + serde_json::from_slice::(&ft_transfer) + .unwrap() + .to_string(), + "{\"amount\":\"123456\",\"memo\":\"Memo\",\"receiver_id\":\"fro_volod.testnet\"}" + ); + } + #[test] + fn ft_transfer_without_memo_to_vec_u8() { + let ft_transfer = serde_json::to_vec(&crate::types::ft_properties::FtTransfer { + receiver_id: "fro_volod.testnet".parse().unwrap(), + amount: FungibleToken::from_str("0.123456 USDC").unwrap().amount(), + memo: None, + }) + .unwrap(); + assert_eq!( + serde_json::from_slice::(&ft_transfer) + .unwrap() + .to_string(), + "{\"amount\":\"123456\",\"receiver_id\":\"fro_volod.testnet\"}" + ); + } }