From 77114e5f436ce4d08b6cc77f7da099fa04d0b012 Mon Sep 17 00:00:00 2001 From: dzmitry-lahoda Date: Wed, 10 Apr 2024 11:37:25 +0100 Subject: [PATCH] fixing tests --- contracts/cosmwasm/order/src/lib.rs | 6 ++++-- contracts/cosmwasm/order/src/types.rs | 4 ++-- mantis/node/src/bin/simulator.rs | 8 ++++---- mantis/node/src/mantis/solve.rs | 8 ++++---- mantis/node/src/solver/cows.rs | 14 +++++++------- mantis/node/src/solver/orderbook.rs | 6 +++--- mantis/node/src/solver/solution.rs | 4 ++-- mantis/node/src/solver/types.rs | 20 +++++++++++--------- mantis/node/tests/mantis.rs | 2 ++ 9 files changed, 39 insertions(+), 33 deletions(-) diff --git a/contracts/cosmwasm/order/src/lib.rs b/contracts/cosmwasm/order/src/lib.rs index 50836303..3afd87be 100644 --- a/contracts/cosmwasm/order/src/lib.rs +++ b/contracts/cosmwasm/order/src/lib.rs @@ -259,12 +259,14 @@ impl OrderContract<'_> { /// Provides solution for set of orders. /// All fully + /// Solver does not pay for solution evaluation upfront, but slashed if his solution violates constrains upon best solution picked. + /// So solver cheap to update his solution and prevent spam. #[msg(exec)] - pub fn solve(&self, mut ctx: ExecCtx, msg: SolutionSubMsg) -> StdResult { + pub fn solve(&self, mut ctx: ExecCtx, msg: SolutionSubMsg) -> StdResult { // read all orders as solver provided let mut all_orders = join_solution_with_orders(&self.orders, &msg, &ctx)?; let at_least_one = all_orders.first().expect("at least one"); - + // normalize pair let ab = DenomPair::new( at_least_one.given().denom.clone(), diff --git a/contracts/cosmwasm/order/src/types.rs b/contracts/cosmwasm/order/src/types.rs index 16b5c2fc..6df4f469 100644 --- a/contracts/cosmwasm/order/src/types.rs +++ b/contracts/cosmwasm/order/src/types.rs @@ -37,8 +37,8 @@ pub struct OrderItem { } impl OrderItem { - pub fn side(&self) -> OrderSide { - if self.msg.wants.denom == self.given.denom { + pub fn side(&self, pair: &DenomPair) -> OrderSide { + if self.given.denom == pair.a { OrderSide::A } else { OrderSide::B diff --git a/mantis/node/src/bin/simulator.rs b/mantis/node/src/bin/simulator.rs index 54b0b764..218dc4b2 100644 --- a/mantis/node/src/bin/simulator.rs +++ b/mantis/node/src/bin/simulator.rs @@ -1,11 +1,11 @@ use mantis_cw::OrderSide; -use mantis_node::solver::{orderbook::OrderList, solution::Solution, types::Order}; +use mantis_node::solver::{orderbook::OrderList, solution::Solution, types::SolverOrder}; use mantis_node::{prelude::*, solver::types::Price}; fn main() { // decide on basics - let order_a = Order::new_integer(100_000, 3, OrderSide::B, 1); - let order_b = Order::new_integer(3, 100_000, OrderSide::A, 2); + let order_a = SolverOrder::new_integer(100_000, 3, OrderSide::B, 1); + let order_b = SolverOrder::new_integer(3, 100_000, OrderSide::A, 2); assert!(order_a.is_acceptable_price(order_b.limit_price)); assert!(order_b.is_acceptable_price(order_a.limit_price)); @@ -35,7 +35,7 @@ fn main() { ); // randomize price around 2.0 (ratio of 2 price tokens in pair) - let orders = (1..100).map(|x| Order::random_f64(2., 0.1, (50, 150), x)); + let orders = (1..100).map(|x| SolverOrder::random_f64(2., 0.1, (50, 150), x)); let orders = OrderList { value: orders.collect(), }; diff --git a/mantis/node/src/mantis/solve.rs b/mantis/node/src/mantis/solve.rs index b737883c..836bb20f 100644 --- a/mantis/node/src/mantis/solve.rs +++ b/mantis/node/src/mantis/solve.rs @@ -113,10 +113,10 @@ pub fn find_cows(all_orders: &[OrderItem]) -> Vec { for (ab, orders) in all_orders.into_iter() { let orders = orders.collect::>(); let orders = orders.iter().map(|x| { - crate::solver::types::Order::new_integer( + crate::solver::types::SolverOrder::new_integer( x.given.amount.u128(), x.msg.wants.amount.u128(), - x.side(), + x.side(&ab), x.order_id, ) }); @@ -124,7 +124,8 @@ pub fn find_cows(all_orders: &[OrderItem]) -> Vec { value: orders.collect(), }; let optimal_price = orders.compute_optimal_price(1000); - println!("optimal_price: {:?}", optimal_price); + println!("mantis::solver::cows::optimal_price: {:?}", optimal_price); + println!("mantis::solver::cows::orders: {:?}", orders); let mut solution = Solution::new(orders.value.clone()); solution = solution.match_orders(optimal_price); let cows = solution @@ -141,7 +142,6 @@ pub fn find_cows(all_orders: &[OrderItem]) -> Vec { } }) .collect::>(); - println!("optimal price {:?}", optimal_price); let optimal_price = decimal_to_fraction(optimal_price.0); println!("cows: {:?}", cows); if !cows.is_empty() { diff --git a/mantis/node/src/solver/cows.rs b/mantis/node/src/solver/cows.rs index a8ff2c8b..04663b20 100644 --- a/mantis/node/src/solver/cows.rs +++ b/mantis/node/src/solver/cows.rs @@ -12,7 +12,7 @@ pub struct Solver { target_price: Price, buy_token: BuyToken, sell_token: SellToken, - order: Order, + order: SolverOrder, } impl Solver { @@ -29,7 +29,7 @@ impl Solver { target_price, buy_token, sell_token, - order: Order::new_decimal(dec!(0.0), Price(dec!(0.0)), OrderSide::A, solver_order_id), + order: SolverOrder::new_decimal(dec!(0.0), Price(dec!(0.0)), OrderSide::A, solver_order_id), } } @@ -37,7 +37,7 @@ impl Solver { self.target_price } - fn f_maximize(&self, order: &Order) -> Amount { + fn f_maximize(&self, order: &SolverOrder) -> Amount { let decimal = match order.order_type { OrderSide::A => { self.buy_token.0 - order.amount_filled @@ -67,7 +67,7 @@ impl Solver { let side = if is_buy { OrderSide::A } else { OrderSide::B }; - let orders: Vec> = (0..=num_orders) + let orders: Vec> = (0..=num_orders) .map(|i| { self.order_for( Amount::from_usize(i).expect("works") * original_token_amount @@ -98,7 +98,7 @@ impl Solver { max_solution.ok_or("No max solution found") } - fn match_ob_with_order(&self, order: &Order) -> Result, &'static str> { + fn match_ob_with_order(&self, order: &SolverOrder) -> Result, &'static str> { let mut orderbook = self.orders.clone(); orderbook.value.push(order.clone()); orderbook @@ -109,7 +109,7 @@ impl Solver { Ok(Solution::new(orderbook.value).match_orders(optimal_price)) } - fn order_for(&self, amount: Decimal, order_type: OrderSide, id: Id) -> Order { - Order::new_decimal(amount, self.limit_price(), order_type, id) + fn order_for(&self, amount: Decimal, order_type: OrderSide, id: Id) -> SolverOrder { + SolverOrder::new_decimal(amount, self.limit_price(), order_type, id) } } diff --git a/mantis/node/src/solver/orderbook.rs b/mantis/node/src/solver/orderbook.rs index 069151e2..a97fd187 100644 --- a/mantis/node/src/solver/orderbook.rs +++ b/mantis/node/src/solver/orderbook.rs @@ -6,7 +6,7 @@ use crate::solver::types::*; #[derive(Clone, Debug)] pub struct OrderList { - pub value: Vec>, + pub value: Vec>, } impl OrderList { @@ -15,7 +15,7 @@ impl OrderList { } fn apply_filter

(&self, expr: P) -> Self where - P: FnMut(&Order) -> bool, + P: FnMut(&SolverOrder) -> bool, { OrderList { value: self.value.iter().cloned().filter(expr).collect(), @@ -67,7 +67,7 @@ impl OrderList { self.apply_filter(|order| order.id == id) } - pub fn all(&self) -> &Vec> { + pub fn all(&self) -> &Vec> { &self.value } diff --git a/mantis/node/src/solver/solution.rs b/mantis/node/src/solver/solution.rs index 6c43d134..4c3541d1 100644 --- a/mantis/node/src/solver/solution.rs +++ b/mantis/node/src/solver/solution.rs @@ -12,7 +12,7 @@ pub struct Solution { impl Solution { /// ensures orders are sorted - pub fn new(mut orders: Vec>) -> Self { + pub fn new(mut orders: Vec>) -> Self { orders.sort_by(|a, b| { a.limit_price .partial_cmp(&b.limit_price) @@ -116,7 +116,7 @@ impl Solution { ) -> Self { Self::new( (0..num_orders) - .map(|_| Order::random_f64(mean, std, volume_range, next())) + .map(|_| SolverOrder::random_f64(mean, std, volume_range, next())) .collect(), ) } diff --git a/mantis/node/src/solver/types.rs b/mantis/node/src/solver/types.rs index 6a475874..6500853c 100644 --- a/mantis/node/src/solver/types.rs +++ b/mantis/node/src/solver/types.rs @@ -36,8 +36,10 @@ pub enum OrderBookStatus { Matched, } + +/// Order as handled by solver math #[derive(Debug, Clone)] -pub struct Order { +pub struct SolverOrder { pub amount_in: Amount, pub filled_price: Amount, pub order_type: OrderSide, @@ -48,7 +50,7 @@ pub struct Order { pub limit_price: Price, } -impl Order { +impl SolverOrder { pub fn print(&self) { println!( "[{}]-{}- Limit Price: {}, In: {}, Filled: {}, Filled price: {}, Out: {}", @@ -67,7 +69,7 @@ impl Order { order_type: OrderSide, id: Id, ) -> Self { - Order { + SolverOrder { amount_in, filled_price: dec!(0.0), order_type, @@ -79,17 +81,17 @@ impl Order { } } - pub fn new_integer(amount_in: u128, min_want: u128, order_type: OrderSide, id: Id) -> Self { + pub fn new_integer(amount_in: u128, min_want: u128, order_side: OrderSide, id: Id) -> Self { let amount_in: Amount = amount_in.try_into().expect("smaller"); let min_want: Amount = min_want.try_into().expect("smaller"); - let limit_price = match order_type { + let limit_price = match order_side { OrderSide::A => amount_in / min_want, OrderSide::B => min_want / amount_in, }; - Order { + SolverOrder { amount_in, filled_price: dec!(0.0), - order_type, + order_type: order_side, amount_out: dec!(0.0), amount_filled: dec!(0.0), status: OrderStatus::Pending, @@ -186,7 +188,7 @@ impl Order { } } -impl Order { +impl SolverOrder { pub fn random_f64(mean: f64, std: f64, volume_range: (u64, u64), id: Id) -> Self { let amount_in = rand::thread_rng().gen_range(volume_range.0..volume_range.1 + 1) as f64; let normal = rand_distr::Normal::new(mean, std).unwrap(); @@ -198,7 +200,7 @@ impl Order { OrderSide::B }; - Order::new_decimal( + SolverOrder::new_decimal( Decimal::from_f64_retain(amount_in).unwrap(), Price(Decimal::from_f64_retain(limit_price).unwrap()), order_type, diff --git a/mantis/node/tests/mantis.rs b/mantis/node/tests/mantis.rs index f2722e16..859454df 100644 --- a/mantis/node/tests/mantis.rs +++ b/mantis/node/tests/mantis.rs @@ -83,6 +83,8 @@ fn cows_two_perfect_math_orders () { // try solve let orders = query_all_orders(&deps, &env); + assert_eq!(orders.len() , 2); + let cows_per_pair = mantis_node::mantis::solve::find_cows(orders.as_slice()); assert_eq!(cows_per_pair.len() , 1); do_solve(cows_per_pair, &mut deps, &env, info.clone());