diff --git a/state-chain/custom-rpc/src/lib.rs b/state-chain/custom-rpc/src/lib.rs index dcbd730ebb..fc74c26089 100644 --- a/state-chain/custom-rpc/src/lib.rs +++ b/state-chain/custom-rpc/src/lib.rs @@ -36,7 +36,7 @@ use pallet_cf_pools::{ use pallet_cf_swapping::SwapLegInfo; use sc_client_api::{BlockchainEvents, HeaderBackend}; use serde::{Deserialize, Serialize}; -use sp_api::{ApiError, CallApiAt}; +use sp_api::{ApiError, ApiExt, CallApiAt}; use sp_core::U256; use sp_runtime::{ traits::{Block as BlockT, Header as HeaderT, UniqueSaturatedInto}, @@ -55,10 +55,10 @@ use state_chain_runtime::{ AuctionState, BoostPoolDepth, BoostPoolDetails, BrokerInfo, ChainAccounts, CustomRuntimeApi, DispatchErrorWithMessage, ElectoralRuntimeApi, FailingWitnessValidators, LiquidityProviderBoostPoolInfo, LiquidityProviderInfo, RuntimeApiPenalty, - TaintedTransactionEvents, ValidatorInfo, + SimulatedSwapInformationV2, TaintedTransactionEvents, ValidatorInfo, }, safe_mode::RuntimeSafeMode, - Hash, NetworkFee, SolanaInstance, + Block, Hash, NetworkFee, SolanaInstance, }; use std::{ collections::{BTreeMap, HashMap}, @@ -422,6 +422,29 @@ pub struct RpcSwapOutputV2 { pub egress_fee: RpcFee, pub broker_commission: RpcFee, } +fn into_rpc_swap_output( + simulated_swap_info_v2: SimulatedSwapInformationV2, + from_asset: Asset, + to_asset: Asset, +) -> RpcSwapOutputV2 { + RpcSwapOutputV2 { + intermediary: simulated_swap_info_v2.intermediary.map(Into::into), + output: simulated_swap_info_v2.output.into(), + network_fee: RpcFee { + asset: cf_primitives::STABLE_ASSET, + amount: simulated_swap_info_v2.network_fee.into(), + }, + ingress_fee: RpcFee { + asset: from_asset, + amount: simulated_swap_info_v2.ingress_fee.into(), + }, + egress_fee: RpcFee { asset: to_asset, amount: simulated_swap_info_v2.egress_fee.into() }, + broker_commission: RpcFee { + asset: cf_primitives::STABLE_ASSET, + amount: simulated_swap_info_v2.broker_fee.into(), + }, + } +} #[derive(Serialize, Deserialize, Clone)] pub enum SwapRateV2AdditionalOrder { @@ -1388,71 +1411,66 @@ where additional_orders: Option>, at: Option, ) -> RpcResult { + let amount = amount + .try_into() + .map_err(|_| "Swap input amount too large.") + .and_then(|amount: u128| { + if amount == 0 { + Err("Swap input amount cannot be zero.") + } else { + Ok(amount) + } + }) + .map_err(|s| ErrorObject::owned(ErrorCode::InvalidParams.code(), s, None::<()>))?; + let additional_orders = additional_orders.map(|additional_orders| { + additional_orders + .into_iter() + .map(|additional_order| match additional_order { + SwapRateV2AdditionalOrder::LimitOrder { + base_asset, + quote_asset, + side, + tick, + sell_amount, + } => + state_chain_runtime::runtime_apis::SimulateSwapAdditionalOrder::LimitOrder { + base_asset, + quote_asset, + side, + tick, + sell_amount: sell_amount.unique_saturated_into(), + }, + }) + .collect() + }); self.with_runtime_api(at, |api, hash| { - Ok::<_, CfApiError>( - api.cf_pool_simulate_swap( + if api.api_version::>(hash).unwrap().unwrap() < 2 { + let old_result = api.cf_pool_simulate_swap_before_version_2( hash, from_asset, to_asset, - amount - .try_into() - .map_err(|_| "Swap input amount too large.") - .and_then(|amount: u128| { - if amount == 0 { - Err("Swap input amount cannot be zero.") - } else { - Ok(amount) - } - }) - .map_err(|s| { - ErrorObject::owned(ErrorCode::InvalidParams.code(), s, None::<()>) - })?, - broker_commission, - dca_parameters, - additional_orders.map(|additional_orders| { - additional_orders - .into_iter() - .map(|additional_order| { - match additional_order { - SwapRateV2AdditionalOrder::LimitOrder { - base_asset, - quote_asset, - side, - tick, - sell_amount, - } => state_chain_runtime::runtime_apis::SimulateSwapAdditionalOrder::LimitOrder { - base_asset, - quote_asset, - side, - tick, - sell_amount: sell_amount.unique_saturated_into(), - } - } - }) - .collect() - }), - )? - .map(|simulated_swap_info_v2| RpcSwapOutputV2 { - intermediary: simulated_swap_info_v2.intermediary.map(Into::into), - output: simulated_swap_info_v2.output.into(), - network_fee: RpcFee { - asset: cf_primitives::STABLE_ASSET, - amount: simulated_swap_info_v2.network_fee.into(), - }, - ingress_fee: RpcFee { - asset: from_asset, - amount: simulated_swap_info_v2.ingress_fee.into(), - }, - egress_fee: RpcFee { - asset: to_asset, - amount: simulated_swap_info_v2.egress_fee.into(), - }, - broker_commission: RpcFee { - asset: cf_primitives::STABLE_ASSET, - amount: simulated_swap_info_v2.broker_fee.into(), - }, - })?, - ) + amount, + additional_orders, + )?; + Ok(old_result.map(|old_version| { + into_rpc_swap_output(old_version.into(), from_asset, to_asset) + })?) + } else { + Ok::<_, CfApiError>( + api.cf_pool_simulate_swap( + hash, + from_asset, + to_asset, + amount, + broker_commission, + dca_parameters, + additional_orders, + )? + .map(|simulated_swap_info_v2| { + into_rpc_swap_output(simulated_swap_info_v2, from_asset, to_asset) + })?, + ) + } }) } diff --git a/state-chain/runtime/src/lib.rs b/state-chain/runtime/src/lib.rs index f81fcfe4d7..1a8246d3a9 100644 --- a/state-chain/runtime/src/lib.rs +++ b/state-chain/runtime/src/lib.rs @@ -28,7 +28,7 @@ use crate::{ runtime_decl_for_custom_runtime_api::CustomRuntimeApi, AuctionState, BoostPoolDepth, BoostPoolDetails, BrokerInfo, DispatchErrorWithMessage, FailingWitnessValidators, LiquidityProviderBoostPoolInfo, LiquidityProviderInfo, RuntimeApiPenalty, - SimulateSwapAdditionalOrder, SimulatedSwapInformation, TaintedTransactionEvents, + SimulateSwapAdditionalOrder, SimulatedSwapInformationV2, TaintedTransactionEvents, ValidatorInfo, }, }; @@ -1534,7 +1534,7 @@ impl_runtime_apis! { broker_commission: BasisPoints, dca_parameters: Option, additional_orders: Option>, - ) -> Result { + ) -> Result { if let Some(additional_orders) = additional_orders { for (index, additional_order) in additional_orders.into_iter().enumerate() { match additional_order { @@ -1657,7 +1657,7 @@ impl_runtime_apis! { let (output, egress_fee) = remove_fees(IngressOrEgress::Egress, to, output); - Ok(SimulatedSwapInformation { + Ok(SimulatedSwapInformationV2 { intermediary, output, network_fee, diff --git a/state-chain/runtime/src/runtime_apis.rs b/state-chain/runtime/src/runtime_apis.rs index 12585f7f45..a5ed6332ae 100644 --- a/state-chain/runtime/src/runtime_apis.rs +++ b/state-chain/runtime/src/runtime_apis.rs @@ -146,6 +146,28 @@ pub struct SimulatedSwapInformation { pub network_fee: AssetAmount, pub ingress_fee: AssetAmount, pub egress_fee: AssetAmount, +} + +impl From for SimulatedSwapInformationV2 { + fn from(value: SimulatedSwapInformation) -> Self { + SimulatedSwapInformationV2 { + intermediary: value.intermediary, + output: value.output, + network_fee: value.network_fee, + ingress_fee: value.ingress_fee, + egress_fee: value.egress_fee, + broker_fee: Default::default(), + } + } +} +/// Struct that represents the estimated output of a Swap. +#[derive(Encode, Decode, TypeInfo)] +pub struct SimulatedSwapInformationV2 { + pub intermediary: Option, + pub output: AssetAmount, + pub network_fee: AssetAmount, + pub ingress_fee: AssetAmount, + pub egress_fee: AssetAmount, pub broker_fee: AssetAmount, } @@ -282,7 +304,7 @@ decl_runtime_apis!( broker_commission: BasisPoints, dca_parameters: Option, additional_limit_orders: Option>, - ) -> Result; + ) -> Result; fn cf_pool_info( base_asset: Asset, quote_asset: Asset,