diff --git a/mm2src/mm2_main/src/lp_ordermatch.rs b/mm2src/mm2_main/src/lp_ordermatch.rs index dba2139998..d7619074bf 100644 --- a/mm2src/mm2_main/src/lp_ordermatch.rs +++ b/mm2src/mm2_main/src/lp_ordermatch.rs @@ -86,7 +86,7 @@ use crate::lp_swap::taker_swap::FailAt; pub use best_orders::{best_orders_rpc, best_orders_rpc_v2}; pub use orderbook_depth::orderbook_depth_rpc; -pub use orderbook_rpc::{orderbook_rpc, orderbook_rpc_v2}; +pub use orderbook_rpc::{orderbook_rpc, orderbook_rpc_v2, AggregatedOrderbookEntryV2}; cfg_wasm32! { use mm2_db::indexed_db::{ConstructibleDb, DbLocked}; @@ -5645,7 +5645,7 @@ async fn subscribe_to_orderbook_topic( Ok(()) } -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct RpcOrderbookEntryV2 { coin: String, address: OrderbookAddress, @@ -5770,7 +5770,7 @@ fn choose_taker_confs_and_notas( } } -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(tag = "address_type", content = "address_data")] pub enum OrderbookAddress { Transparent(String), diff --git a/mm2src/mm2_main/src/lp_ordermatch/orderbook_rpc.rs b/mm2src/mm2_main/src/lp_ordermatch/orderbook_rpc.rs index d76af5dfba..67a88a822f 100644 --- a/mm2src/mm2_main/src/lp_ordermatch/orderbook_rpc.rs +++ b/mm2src/mm2_main/src/lp_ordermatch/orderbook_rpc.rs @@ -13,7 +13,7 @@ use serde_json::{self as json, Value as Json}; use super::{addr_format_from_protocol_info, is_my_order, mm2_internal_pubkey_hex, orderbook_address, subscribe_to_orderbook_topic, OrdermatchContext, RpcOrderbookEntryV2}; -#[derive(Debug, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct AggregatedOrderbookEntryV2 { #[serde(flatten)] entry: RpcOrderbookEntryV2, diff --git a/mm2src/mm2_main/src/lp_swap.rs b/mm2src/mm2_main/src/lp_swap.rs index fc8fcfc277..8a9fa82ca2 100644 --- a/mm2src/mm2_main/src/lp_swap.rs +++ b/mm2src/mm2_main/src/lp_swap.rs @@ -142,7 +142,7 @@ pub use taker_swap::{calc_max_taker_vol, check_balance_for_taker_swap, max_taker run_taker_swap, taker_swap_trade_preimage, RunTakerSwapInput, TakerSavedSwap, TakerSwap, TakerSwapData, TakerSwapPreparedParams, TakerTradePreimage, MAKER_PAYMENT_SPENT_BY_WATCHER_LOG, REFUND_TEST_FAILURE_LOG, WATCHER_MESSAGE_SENT_LOG}; -pub use trade_preimage::trade_preimage_rpc; +pub use trade_preimage::{trade_preimage_rpc, TradePreimageResponse}; pub const SWAP_PREFIX: TopicPrefix = "swap"; pub const SWAP_V2_PREFIX: TopicPrefix = "swapv2"; diff --git a/mm2src/mm2_main/src/lp_swap/trade_preimage.rs b/mm2src/mm2_main/src/lp_swap/trade_preimage.rs index cb31ed63e9..fc9c0508f7 100644 --- a/mm2src/mm2_main/src/lp_swap/trade_preimage.rs +++ b/mm2src/mm2_main/src/lp_swap/trade_preimage.rs @@ -18,6 +18,7 @@ construct_detailed!(DetailedRequiredBalance, required_balance); pub type TradePreimageRpcResult = Result>; +/// Calculate all fees for the swap and max volume (for maker) pub async fn trade_preimage_rpc( ctx: MmArc, req: TradePreimageRequest, diff --git a/mm2src/mm2_main/src/rpc/lp_commands/lr_swap.rs b/mm2src/mm2_main/src/rpc/lp_commands/lr_swap.rs new file mode 100644 index 0000000000..105463e399 --- /dev/null +++ b/mm2src/mm2_main/src/rpc/lp_commands/lr_swap.rs @@ -0,0 +1,29 @@ +//? RPC implementation for swaps with liquidity routing (LR) + +use mm2_err_handle::mm_error::{MmResult, MmError}; +use mm2_core::mm_ctx::MmArc; +use types::{LrFindBestSwapPathRequest, LrFindBestSwapPathResponse, LrFillOrderRequest, LrFillOrderResponse}; +use errors::LrSwapRpcError; + +pub mod errors; +pub mod types; + +/// Find best swap path with liquidity routing over evm tokens. +/// For the provided list of orderbook entries this RPC searches for the most price effective swap with LR +pub async fn lr_find_best_swap_path_rpc( + ctx: MmArc, + req: LrFindBestSwapPathRequest, +) -> MmResult { + MmError::err(LrSwapRpcError::SomeError) +} + +/// Run a swap with LR part +pub async fn lr_fill_order_rpc( + ctx: MmArc, + req: LrFillOrderRequest, +) -> MmResult { + MmError::err(LrSwapRpcError::SomeError) +} + +// TODO: Do we need to extend trade_preimage_rpc to include LR-part fee? +// In fact, lr_find_best_swap_path_rpc has same behaviour: returns trade fee \ No newline at end of file diff --git a/mm2src/mm2_main/src/rpc/lp_commands/lr_swap/errors.rs b/mm2src/mm2_main/src/rpc/lp_commands/lr_swap/errors.rs new file mode 100644 index 0000000000..57df715d6a --- /dev/null +++ b/mm2src/mm2_main/src/rpc/lp_commands/lr_swap/errors.rs @@ -0,0 +1,13 @@ +//? Errors for LR swaps rpc + +use common::{HttpStatusCode, StatusCode}; +use enum_derives::EnumFromStringify; +use ser_error_derive::SerializeErrorType; +use serde::Serialize; + +#[derive(Debug, Display, Serialize, SerializeErrorType)] +#[serde(tag = "error_type", content = "error_data")] +pub enum LrSwapRpcError { + #[display(fmt = "LR swap error")] + SomeError, +} \ No newline at end of file diff --git a/mm2src/mm2_main/src/rpc/lp_commands/lr_swap/types.rs b/mm2src/mm2_main/src/rpc/lp_commands/lr_swap/types.rs new file mode 100644 index 0000000000..4e9f3bd374 --- /dev/null +++ b/mm2src/mm2_main/src/rpc/lp_commands/lr_swap/types.rs @@ -0,0 +1,61 @@ +//? Types for LR swaps rpc +use mm2_number::MmNumber; +use mm2_number::BigDecimal; + +use crate::lp_ordermatch::AggregatedOrderbookEntryV2; +use crate::rpc::lp_commands::one_inch::types::ClassicSwapDetails; +use crate::lp_swap::TradePreimageResponse; +use mm2_rpc::data::legacy::{SellBuyRequest, SellBuyResponse}; +//use trading_api::one_inch_api::types::ClassicSwapData; +//use coins::TradeFee; + +/// Request to find best swap path with LR rpc. +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct LrFindBestSwapPathRequest { + /// Base (source) coin ticker + pub base: String, + /// Rel (target) coin ticker + pub rel: String, + /// Swap amount in base coins to sell (with fraction) + pub amount: MmNumber, + /// List of maker orders which is searched for best path with LR + pub orderbook_entries: Vec, + /// List of tokens allowed to route through with LR + pub route_tokens: Vec, +} + +/// Response for find best swap path with LR rpc +#[derive(Serialize)] +pub struct LrFindBestSwapPathResponse { + /// Swap tx data (from 1inch quote) + pub lr_swap_details: ClassicSwapDetails, + /// found best order which can be filled with LR swap + pub best_order: AggregatedOrderbookEntryV2, + /// base/rel price including the price of the LR swap part + pub total_price: BigDecimal, + /// Same retuned + pub trade_fee: TradePreimageResponse, +} + +/// Request to sell or buy with LR +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct LrFillOrderRequest { + /// Original sell or buy request (but only MatchBy::Orders could be used to fill the maker swap found in ) + #[serde(flatten)] + pub fill_req: SellBuyRequest, + + /// Tx data to create one inch swap (from 1inch quote) + /// TODO: make this a enum to allow other LR providers + pub lr_swap_details: ClassicSwapDetails, +} + +/// Request to sell or buy with LR +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct LrFillOrderResponse { + /// Original sell or buy response + #[serde(flatten)] + pub fill_response: SellBuyResponse, +} \ No newline at end of file diff --git a/mm2src/mm2_main/src/rpc/lp_commands/mod.rs b/mm2src/mm2_main/src/rpc/lp_commands/mod.rs index e61d5aead8..bcf4f5763c 100644 --- a/mm2src/mm2_main/src/rpc/lp_commands/mod.rs +++ b/mm2src/mm2_main/src/rpc/lp_commands/mod.rs @@ -4,3 +4,4 @@ pub(crate) mod one_inch; pub(crate) mod pubkey; pub(crate) mod tokens; pub(crate) mod trezor; +pub(crate) mod lr_swap; diff --git a/mm2src/mm2_main/src/rpc/lp_commands/one_inch/types.rs b/mm2src/mm2_main/src/rpc/lp_commands/one_inch/types.rs index 202eb0dcf2..e440a48075 100644 --- a/mm2src/mm2_main/src/rpc/lp_commands/one_inch/types.rs +++ b/mm2src/mm2_main/src/rpc/lp_commands/one_inch/types.rs @@ -125,17 +125,24 @@ pub struct ClassicSwapCreateRequest { pub use_permit2: Option, } -/// Response for both classic swap quote or create swap calls -#[derive(Serialize, Debug)] -pub struct ClassicSwapResponse { +/// Details to create classic swap calls +#[derive(Serialize, Deserialize, Debug)] +pub struct ClassicSwapDetails { /// Destination token amount, in coins (with fraction) pub dst_amount: DetailedAmount, /// Source (base) token info #[serde(skip_serializing_if = "Option::is_none")] pub src_token: Option, + /// Source (base) token name as it is defined in the coins file + pub kdf_src_token: Option, /// Destination (rel) token info #[serde(skip_serializing_if = "Option::is_none")] pub dst_token: Option, + /// Destination (rel) token name as it is defined in the coins file. + /// This is used to show route tokens in the GUI, like they are in the coin file. + /// However, route tokens can be missed in the coins file and therefore cannot be filled. + /// In this case GUI may use TokenInfo::Address or TokenInfo::Symbol + pub kdf_dst_token: Option, /// Used liquidity sources #[serde(skip_serializing_if = "Option::is_none")] pub protocols: Option>>>, @@ -146,7 +153,10 @@ pub struct ClassicSwapResponse { pub gas: Option, } -impl ClassicSwapResponse { +/// Response for both classic swap quote or create swap calls +pub type ClassicSwapResponse = ClassicSwapDetails; + +impl ClassicSwapDetails { pub(crate) fn from_api_classic_swap_data( data: one_inch_api::types::ClassicSwapData, decimals: u8, @@ -154,7 +164,9 @@ impl ClassicSwapResponse { Ok(Self { dst_amount: MmNumber::from(u256_to_big_decimal(U256::from_dec_str(&data.dst_amount)?, decimals)?).into(), src_token: data.src_token, + kdf_src_token: todo!(), dst_token: data.dst_token, + kdf_dst_token: todo!(), protocols: data.protocols, tx: data .tx @@ -165,7 +177,7 @@ impl ClassicSwapResponse { } } -#[derive(Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug)] pub struct TxFields { pub from: Address, pub to: Address, diff --git a/mm2src/mm2_number/src/mm_number_multi_repr.rs b/mm2src/mm2_number/src/mm_number_multi_repr.rs index 501a7626ba..973f1ffeb5 100644 --- a/mm2src/mm2_number/src/mm_number_multi_repr.rs +++ b/mm2src/mm2_number/src/mm_number_multi_repr.rs @@ -3,10 +3,10 @@ use crate::from_ratio_to_dec; use crate::mm_number::MmNumber; use bigdecimal::BigDecimal; use num_rational::BigRational; -use serde::Serialize; +use serde::{Deserialize, Serialize}; /// MmNumber representation in all available forms. -#[derive(Clone, Debug, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct MmNumberMultiRepr { pub decimal: BigDecimal, pub rational: BigRational, diff --git a/mm2src/mm2_rpc/src/data/legacy/orders.rs b/mm2src/mm2_rpc/src/data/legacy/orders.rs index 9890b1d709..d88e73a8cd 100644 --- a/mm2src/mm2_rpc/src/data/legacy/orders.rs +++ b/mm2src/mm2_rpc/src/data/legacy/orders.rs @@ -36,7 +36,7 @@ pub struct SellBuyRequest { pub save_in_history: bool, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Debug, Deserialize)] pub struct SellBuyResponse { #[serde(flatten)] pub request: TakerRequestForRpc,