diff --git a/mm2src/lp_ordermatch.rs b/mm2src/lp_ordermatch.rs index 31a6f3a865..0fd8ac36dc 100644 --- a/mm2src/lp_ordermatch.rs +++ b/mm2src/lp_ordermatch.rs @@ -812,8 +812,8 @@ impl BalanceTradeFeeUpdatedHandler for BalanceUpdateOrdermatchHandler { spawn(async move { maker_order_cancelled_p2p_notify(ctx, &order).await }); None } else if new_volume < order.available_amount() { - let update_msg = - new_protocol::MakerOrderUpdated::new(order.uuid).with_new_max_volume(new_volume.to_ratio()); + let mut update_msg = new_protocol::MakerOrderUpdated::new(order.uuid); + update_msg.with_new_max_volume(new_volume.to_ratio()); let base = order.base.to_owned(); let rel = order.rel.to_owned(); let ctx = self.ctx.clone(); @@ -2714,8 +2714,8 @@ async fn process_taker_connect(ctx: MmArc, sender_pubkey: H256Json, connect_msg: // If volume is less order will be cancelled a bit later if my_order.available_amount() >= my_order.min_base_vol { - let updated_msg = new_protocol::MakerOrderUpdated::new(my_order.uuid) - .with_new_max_volume(my_order.available_amount().into()); + let mut updated_msg = new_protocol::MakerOrderUpdated::new(my_order.uuid); + updated_msg.with_new_max_volume(my_order.available_amount().into()); maker_order_updated_p2p_notify(ctx.clone(), &my_order.base, &my_order.rel, updated_msg).await; } save_my_maker_order(&ctx, &my_order); @@ -3428,13 +3428,13 @@ pub async fn update_maker_order(ctx: MmArc, req: Json) -> Result { try_s!(validate_price(new_price.clone())); - update_msg = update_msg.with_new_price(new_price.clone().into()); + update_msg.with_new_price(new_price.clone().into()); new_price }, None => original_price, @@ -3452,13 +3452,13 @@ pub async fn update_maker_order(ctx: MmArc, req: Json) -> Result Result Result HistoricalOrder { HistoricalOrder { - max_base_vol: if new_order.new_max_volume.is_some() { + max_base_vol: if new_order.new_max_volume().is_some() { Some(old_order.max_base_vol.clone()) } else { None }, - min_base_vol: if new_order.new_min_volume.is_some() { + min_base_vol: if new_order.new_min_volume().is_some() { Some(old_order.min_base_vol.clone()) } else { None }, - price: if new_order.new_price.is_some() { + price: if new_order.new_price().is_some() { Some(old_order.price.clone()) } else { None }, updated_at: old_order.updated_at, - conf_settings: if new_order.conf_settings == old_order.conf_settings { - None + conf_settings: if let Some(settings) = new_order.new_conf_settings() { + if Some(settings) == old_order.conf_settings { + None + } else { + old_order.conf_settings + } } else { - old_order.conf_settings + None }, } } diff --git a/mm2src/lp_ordermatch/new_protocol.rs b/mm2src/lp_ordermatch/new_protocol.rs index abd68c067c..49d4199fd7 100644 --- a/mm2src/lp_ordermatch/new_protocol.rs +++ b/mm2src/lp_ordermatch/new_protocol.rs @@ -137,20 +137,37 @@ pub struct MakerOrderCancelled { pub pair_trie_root: H64, } -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct MakerOrderUpdated { +#[derive(Clone, Debug, Eq, Deserialize, PartialEq, Serialize)] +pub struct MakerOrderUpdatedV1 { uuid: CompactUuid, pub new_price: Option, pub new_max_volume: Option, pub new_min_volume: Option, - pub conf_settings: Option, timestamp: u64, pair_trie_root: H64, } +#[derive(Clone, Debug, Eq, Deserialize, PartialEq, Serialize)] +pub struct MakerOrderUpdatedV2 { + uuid: CompactUuid, + pub new_price: Option, + pub new_max_volume: Option, + pub new_min_volume: Option, + timestamp: u64, + pair_trie_root: H64, + pub conf_settings: Option, +} + +#[derive(Clone, Debug, Eq, Deserialize, PartialEq, Serialize)] +#[serde(untagged)] +pub enum MakerOrderUpdated { + V1(MakerOrderUpdatedV1), + V2(MakerOrderUpdatedV2), +} + impl MakerOrderUpdated { pub fn new(uuid: Uuid) -> Self { - MakerOrderUpdated { + MakerOrderUpdated::V2(MakerOrderUpdatedV2 { uuid: uuid.into(), new_price: None, new_max_volume: None, @@ -158,38 +175,73 @@ impl MakerOrderUpdated { conf_settings: None, timestamp: now_ms() / 1000, pair_trie_root: H64::default(), - } + }) } - pub fn with_new_price(mut self, new_price: BigRational) -> Self { - self.new_price = Some(new_price); - self + pub fn with_new_price(&mut self, new_price: BigRational) { + match self { + MakerOrderUpdated::V1(v1) => v1.new_price = Some(new_price), + MakerOrderUpdated::V2(v2) => v2.new_price = Some(new_price), + } } - pub fn with_new_max_volume(mut self, new_max_volume: BigRational) -> Self { - self.new_max_volume = Some(new_max_volume); - self + pub fn with_new_max_volume(&mut self, new_max_volume: BigRational) { + match self { + MakerOrderUpdated::V1(v1) => v1.new_max_volume = Some(new_max_volume), + MakerOrderUpdated::V2(v2) => v2.new_max_volume = Some(new_max_volume), + } } - pub fn with_new_min_volume(mut self, new_min_volume: BigRational) -> Self { - self.new_min_volume = Some(new_min_volume); - self + pub fn with_new_min_volume(&mut self, new_min_volume: BigRational) { + match self { + MakerOrderUpdated::V1(v1) => v1.new_min_volume = Some(new_min_volume), + MakerOrderUpdated::V2(v2) => v2.new_min_volume = Some(new_min_volume), + } } - pub fn with_new_conf_settings(mut self, conf_settings: OrderConfirmationsSettings) -> Self { - self.conf_settings = Some(conf_settings); - self + pub fn with_new_conf_settings(&mut self, conf_settings: OrderConfirmationsSettings) { + match self { + MakerOrderUpdated::V1(_) => {}, + MakerOrderUpdated::V2(v2) => { + v2.conf_settings = Some(conf_settings); + }, + } } - pub fn new_price(&self) -> Option { self.new_price.as_ref().map(|num| num.clone().into()) } + pub fn new_price(&self) -> Option { + match self { + MakerOrderUpdated::V1(v1) => v1.new_price.as_ref().map(|num| num.clone().into()), + MakerOrderUpdated::V2(v2) => v2.new_price.as_ref().map(|num| num.clone().into()), + } + } - pub fn new_max_volume(&self) -> Option { self.new_max_volume.as_ref().map(|num| num.clone().into()) } + pub fn new_max_volume(&self) -> Option { + match self { + MakerOrderUpdated::V1(v1) => v1.new_max_volume.as_ref().map(|num| num.clone().into()), + MakerOrderUpdated::V2(v2) => v2.new_max_volume.as_ref().map(|num| num.clone().into()), + } + } - pub fn new_min_volume(&self) -> Option { self.new_min_volume.as_ref().map(|num| num.clone().into()) } + pub fn new_min_volume(&self) -> Option { + match self { + MakerOrderUpdated::V1(v1) => v1.new_min_volume.as_ref().map(|num| num.clone().into()), + MakerOrderUpdated::V2(v2) => v2.new_min_volume.as_ref().map(|num| num.clone().into()), + } + } - pub fn new_conf_settings(&self) -> Option { self.conf_settings } + pub fn new_conf_settings(&self) -> Option { + match self { + MakerOrderUpdated::V1(_) => None, + MakerOrderUpdated::V2(v2) => v2.conf_settings, + } + } - pub fn uuid(&self) -> Uuid { self.uuid.into() } + pub fn uuid(&self) -> Uuid { + match self { + MakerOrderUpdated::V1(v1) => v1.uuid.into(), + MakerOrderUpdated::V2(v2) => v2.uuid.into(), + } + } } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -226,3 +278,89 @@ pub struct MakerConnected { pub taker_order_uuid: CompactUuid, pub maker_order_uuid: CompactUuid, } + +#[cfg(test)] +mod new_protocol_tests { + use common::new_uuid; + + use super::*; + + #[test] + fn check_maker_order_updated_serde() { + let uuid = CompactUuid::from(new_uuid()); + let timestamp = now_ms() / 1000; + let conf_settings = Some(OrderConfirmationsSettings { + base_confs: 5, + base_nota: true, + rel_confs: 5, + rel_nota: true, + }); + // old format should be deserialized to MakerOrderUpdated::V1 + let v1 = MakerOrderUpdatedV1 { + uuid, + new_price: Some(BigRational::from_integer(2.into())), + new_max_volume: Some(BigRational::from_integer(3.into())), + new_min_volume: Some(BigRational::from_integer(1.into())), + timestamp, + pair_trie_root: H64::default(), + }; + + let expected = MakerOrderUpdated::V1(MakerOrderUpdatedV1 { + uuid, + new_price: Some(BigRational::from_integer(2.into())), + new_max_volume: Some(BigRational::from_integer(3.into())), + new_min_volume: Some(BigRational::from_integer(1.into())), + timestamp, + pair_trie_root: H64::default(), + }); + + let serialized = rmp_serde::to_vec(&v1).unwrap(); + + let deserialized: MakerOrderUpdated = rmp_serde::from_read_ref(serialized.as_slice()).unwrap(); + + assert_eq!(deserialized, expected); + + // new format should be deserialized to old + let v2 = MakerOrderUpdated::V2(MakerOrderUpdatedV2 { + uuid, + new_price: Some(BigRational::from_integer(2.into())), + new_max_volume: Some(BigRational::from_integer(3.into())), + new_min_volume: Some(BigRational::from_integer(1.into())), + timestamp, + pair_trie_root: H64::default(), + conf_settings, + }); + + let expected = MakerOrderUpdatedV1 { + uuid, + new_price: Some(BigRational::from_integer(2.into())), + new_max_volume: Some(BigRational::from_integer(3.into())), + new_min_volume: Some(BigRational::from_integer(1.into())), + timestamp, + pair_trie_root: H64::default(), + }; + + let serialized = rmp_serde::to_vec(&v2).unwrap(); + + let deserialized: MakerOrderUpdatedV1 = rmp_serde::from_read_ref(serialized.as_slice()).unwrap(); + + assert_eq!(deserialized, expected); + + // new format should be deserialized to new + let v2 = MakerOrderUpdated::V2(MakerOrderUpdatedV2 { + uuid, + new_price: Some(BigRational::from_integer(2.into())), + new_max_volume: Some(BigRational::from_integer(3.into())), + new_min_volume: Some(BigRational::from_integer(1.into())), + timestamp, + pair_trie_root: H64::default(), + conf_settings, + }); + + let serialized = rmp_serde::to_vec(&v2).unwrap(); + + let deserialized: MakerOrderUpdated = rmp_serde::from_read_ref(serialized.as_slice()).unwrap(); + + assert_eq!(deserialized, v2); + } +}