Skip to content

Commit

Permalink
feat: fungible metadata amount utils
Browse files Browse the repository at this point in the history
  • Loading branch information
chris13524 committed Dec 5, 2024
1 parent 6111c70 commit 8017600
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 19 deletions.
1 change: 1 addition & 0 deletions crates/yttrium/src/chain_abstraction/amount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use alloy::primitives::{
};

#[derive(Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi_macros::Record))]
pub struct Amount {
pub symbol: String, // USDC, USD
pub amount: U256, // e.g. 40000, 4
Expand Down
19 changes: 2 additions & 17 deletions crates/yttrium/src/chain_abstraction/api/fungible_price.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,8 @@ pub struct FungiblePriceItem {
pub icon_url: String,
pub price: f64,
#[serde(
deserialize_with = "deserialize_unit",
serialize_with = "serialize_unit"
deserialize_with = "crate::utils::deserialize_unit",
serialize_with = "crate::utils::serialize_unit"
)]
pub decimals: Unit,
}

fn deserialize_unit<'de, D>(deserializer: D) -> Result<Unit, D::Error>
where
D: serde::Deserializer<'de>,
{
Unit::new(u8::deserialize(deserializer)?)
.ok_or(serde::de::Error::custom("Unit must be less than 77"))
}

fn serialize_unit<S>(unit: &Unit, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u8(unit.get())
}
29 changes: 28 additions & 1 deletion crates/yttrium/src/chain_abstraction/api/route.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use {
super::Transaction,
alloy::primitives::{Address, U256},
crate::chain_abstraction::amount::Amount,
alloy::primitives::{utils::Unit, Address, U256},
relay_rpc::domain::ProjectId,
serde::{Deserialize, Serialize},
};
Expand Down Expand Up @@ -33,8 +34,34 @@ pub struct FundingMetadata {
pub chain_id: String,
pub token_contract: Address,
pub symbol: String,

// The amount that was sources (includes the bridging fee)
pub amount: U256,

// The amount taken by the bridge as a fee
pub bridging_fee: U256,

#[serde(
deserialize_with = "crate::utils::deserialize_unit",
serialize_with = "crate::utils::serialize_unit"
)]
#[serde(default = "default_unit")]
pub decimals: Unit,
}

// TODO remove default when Blockchain API is updated to provide this
fn default_unit() -> Unit {
Unit::new(6).unwrap()
}

impl FundingMetadata {
pub fn to_amount(&self) -> Amount {
Amount::new(self.symbol.clone(), self.amount, self.decimals)
}

pub fn to_bridging_fee_amount(&self) -> Amount {
Amount::new(self.symbol.clone(), self.bridging_fee, self.decimals)
}
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand Down
65 changes: 65 additions & 0 deletions crates/yttrium/src/chain_abstraction/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1374,6 +1374,71 @@ async fn happy_path_full_dependency_on_route_ui_fields() {
result.transactions[0].gas = U64::from(60000 /* 55437 */); // until Blockchain API estimates this
result.transactions[1].gas = U64::from(140000 /* 107394 */); // until Blockchain API estimates this

assert_eq!(result.metadata.funding_from.len(), 1);
assert_eq!(result.metadata.funding_from.first().unwrap().symbol, "USDC");
assert_eq!(
result.metadata.funding_from.first().unwrap().decimals,
Unit::new(6).unwrap()
);
assert_eq!(
result
.metadata
.funding_from
.first()
.unwrap()
.clone()
.to_amount()
.symbol,
"USDC"
);
assert!(result
.metadata
.funding_from
.first()
.unwrap()
.to_amount()
.formatted
.ends_with(" USDC"));
println!(
"{}",
result.metadata.funding_from.first().unwrap().to_amount().formatted
);
assert!(result
.metadata
.funding_from
.first()
.unwrap()
.to_amount()
.formatted
.starts_with("1.5"));
assert!(result
.metadata
.funding_from
.first()
.unwrap()
.to_bridging_fee_amount()
.formatted
.starts_with("0."));
assert!(
result.metadata.funding_from.first().unwrap().amount <= required_amount
);
assert!(result.metadata.funding_from.first().unwrap().amount > send_amount);
assert!(
result.metadata.funding_from.first().unwrap().bridging_fee > U256::ZERO
);
assert!(
result.metadata.funding_from.first().unwrap().bridging_fee
< send_amount / U256::from(2)
);
assert_eq!(
result.metadata.funding_from.first().unwrap().chain_id,
source.bridge_token(&sources).params.chain.eip155_chain_id()
);
assert_eq!(
&result.metadata.funding_from.first().unwrap().token_contract,
source.bridge_token(&sources).token.address()
);

let start = Instant::now();
let route_ui_fields = client
.get_route_ui_fields(
Expand Down
1 change: 1 addition & 0 deletions crates/yttrium/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub mod smart_accounts;
pub mod test_helpers;
pub mod transaction;
pub mod user_operation;
pub mod utils;

#[cfg(test)]
pub mod examples;
21 changes: 20 additions & 1 deletion crates/yttrium/src/uniffi_compat.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use alloy::primitives::{Address, Bytes, B256, U256, U64};
use crate::chain_abstraction::amount::Amount;
use crate::chain_abstraction::api::route::FundingMetadata;
use alloy::primitives::{utils::Unit, Address, Bytes, B256, U256, U64};

// TODO use https://mozilla.github.io/uniffi-rs/next/udl/remote_ext_types.html#remote-types when it's available

Expand Down Expand Up @@ -26,3 +28,20 @@ uniffi::custom_type!(B256, String, {
try_lift: |val| Ok(val.parse()?),
lower: |obj| obj.to_string(),
});

uniffi::custom_type!(Unit, u8, {
try_lift: |val| Ok(Unit::new(val).expect("Unit must be less than 77")),
lower: |obj| obj.get(),
});

#[cfg(feature = "uniffi")]
#[uniffi::export]
fn funding_metadata_to_amount(value: FundingMetadata) -> Amount {
value.to_amount()
}

#[cfg(feature = "uniffi")]
#[uniffi::export]
fn funding_metadata_to_bridging_fee_amount(value: FundingMetadata) -> Amount {
value.to_bridging_fee_amount()
}
17 changes: 17 additions & 0 deletions crates/yttrium/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use alloy::primitives::utils::Unit;
use serde::Deserialize;

pub fn deserialize_unit<'de, D>(deserializer: D) -> Result<Unit, D::Error>
where
D: serde::Deserializer<'de>,
{
Unit::new(u8::deserialize(deserializer)?)
.ok_or(serde::de::Error::custom("Unit must be less than 77"))
}

pub fn serialize_unit<S>(unit: &Unit, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u8(unit.get())
}

0 comments on commit 8017600

Please sign in to comment.