diff --git a/Cargo.lock b/Cargo.lock index 2ec96fc9d..048f68bee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6839,6 +6839,14 @@ dependencies = [ "frame-support", ] +[[package]] +name = "primitives-currency-swap-proxy" +version = "0.1.0" +dependencies = [ + "frame-support", + "primitives-currency-swap", +] + [[package]] name = "primitives-ethereum" version = "0.1.0" diff --git a/crates/primitives-currency-swap-proxy/Cargo.toml b/crates/primitives-currency-swap-proxy/Cargo.toml new file mode 100644 index 000000000..42f02b79d --- /dev/null +++ b/crates/primitives-currency-swap-proxy/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "primitives-currency-swap-proxy" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +primitives-currency-swap = { version = "0.1", path = "../primitives-currency-swap" } + +frame-support = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } + +[features] +default = ["std"] +std = ["frame-support/std", "primitives-currency-swap/std"] +try-runtime = ["frame-support/try-runtime", "primitives-currency-swap/try-runtime"] diff --git a/crates/primitives-currency-swap-proxy/src/lib.rs b/crates/primitives-currency-swap-proxy/src/lib.rs new file mode 100644 index 000000000..0b1373712 --- /dev/null +++ b/crates/primitives-currency-swap-proxy/src/lib.rs @@ -0,0 +1,75 @@ +//! Currency swap proxy related primitives. + +// Either generate code at stadard mode, or `no_std`, based on the `std` feature presence. +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::{ + sp_std::marker::PhantomData, + traits::{Currency, OnUnbalanced}, +}; +use primitives_currency_swap::CurrencySwap; + +/// A utility type alias for easy access to [`CurrencySwap::From`] of [`Config::CurrencySwap`]. +type CurrencyFromFor = <::CurrencySwap as CurrencySwap< + ::AccountIdFrom, + ::AccountIdTo, +>>::From; + +/// A utility type alias for easy access to [`CurrencySwap::To`] of [`Config::CurrencySwap`]. +type CurrencyToFor = <::CurrencySwap as CurrencySwap< + ::AccountIdFrom, + ::AccountIdTo, +>>::To; + +/// A utility type alias for easy access to [`Currency::NegativeImbalance`] of +/// [`CurrencySwap::From`] of [`Config::CurrencySwap`]. +type CurrencyFromNegativeImbalanceFor = + as Currency<::AccountIdFrom>>::NegativeImbalance; + +/// A utility type alias for easy access to [`Currency::NegativeImbalance`] of +/// [`CurrencySwap::To`] of [`Config::CurrencySwap`]. +type CurrencyToNegativeImbalanceFor = + as Currency<::AccountIdTo>>::NegativeImbalance; + +/// The general config for the currency swap proxy implementations. +pub trait Config { + /// The type used as an Account ID for the currency we proxy from. + type AccountIdFrom; + /// The type used as an Account ID for the currency we proxy to. + type AccountIdTo; + + /// The curreny swap implementation to use for proxying. + type CurrencySwap: CurrencySwap; +} + +/// An [`OnUnbalanced`] implementation that routes the imbalance through the currency swap and +/// passes the resulting imbalance to the `To`. +/// If swap fails, will try to pass the original imbalance to the `Fallback`. +pub struct SwapUnbalanced(PhantomData<(T, To, Fallback)>); + +impl OnUnbalanced> + for SwapUnbalanced +where + T: Config, + To: OnUnbalanced>, + Fallback: OnUnbalanced>, +{ + fn on_nonzero_unbalanced(amount: CurrencyFromNegativeImbalanceFor) { + let amount = match T::CurrencySwap::swap(amount) { + Ok(amount) => amount, + Err(primitives_currency_swap::Error { + cause: error, + incoming_imbalance, + }) => { + let error: frame_support::sp_runtime::DispatchError = error.into(); + frame_support::sp_tracing::error!( + message = "unable to route the funds through the swap", + ?error + ); + Fallback::on_unbalanceds(std::iter::once(incoming_imbalance)); + return; + } + }; + To::on_unbalanceds(std::iter::once(amount)) + } +}