diff --git a/mm2src/mm2_main/src/lp_swap/maker_swap.rs b/mm2src/mm2_main/src/lp_swap/maker_swap.rs index fe0b50bd64..a1a84dd170 100644 --- a/mm2src/mm2_main/src/lp_swap/maker_swap.rs +++ b/mm2src/mm2_main/src/lp_swap/maker_swap.rs @@ -2125,7 +2125,6 @@ pub async fn run_maker_swap(swap: RunMakerSwapInput, ctx: MmArc) { ) } - #[cfg(target_arch = "wasm32")] if event.is_error() { error!("[swap uuid={uuid_str}] {event:?}"); } diff --git a/mm2src/mm2_main/src/lp_swap/taker_restart.rs b/mm2src/mm2_main/src/lp_swap/taker_restart.rs index 431d1a7c32..9c03e32524 100644 --- a/mm2src/mm2_main/src/lp_swap/taker_restart.rs +++ b/mm2src/mm2_main/src/lp_swap/taker_restart.rs @@ -15,7 +15,7 @@ use super::swap_watcher::{default_watcher_maker_payment_spend_factor, default_wa #[cfg(not(any(test, feature = "run-docker-tests")))] use common::now_sec; -pub async fn get_command_based_on_watcher_activity( +pub async fn get_command_based_on_maker_or_watcher_activity( ctx: &MmArc, swap: &TakerSwap, mut saved: TakerSavedSwap, @@ -136,6 +136,7 @@ pub async fn check_maker_payment_spend_and_add_event( timestamp: now_ms(), event, }; + swap.apply_event(to_save.event.clone()); saved.events.push(to_save); let new_swap = SavedSwap::Taker(saved); try_s!(new_swap.save_to_db(ctx).await); @@ -208,6 +209,7 @@ pub async fn add_taker_payment_spent_event( timestamp: now_ms(), event, }; + swap.apply_event(to_save.event.clone()); saved.events.push(to_save); Ok(()) } @@ -255,6 +257,7 @@ pub async fn add_taker_payment_refunded_by_watcher_event( timestamp: now_ms(), event, }; + swap.apply_event(to_save.event.clone()); saved.events.push(to_save); let new_swap = SavedSwap::Taker(saved); diff --git a/mm2src/mm2_main/src/lp_swap/taker_swap.rs b/mm2src/mm2_main/src/lp_swap/taker_swap.rs index 0e4d178b4d..2ef1d455f8 100644 --- a/mm2src/mm2_main/src/lp_swap/taker_swap.rs +++ b/mm2src/mm2_main/src/lp_swap/taker_swap.rs @@ -13,7 +13,7 @@ use super::{broadcast_my_swap_status, broadcast_swap_message, broadcast_swap_msg use crate::mm2::lp_network::subscribe_to_topic; use crate::mm2::lp_ordermatch::TakerOrderBuilder; use crate::mm2::lp_swap::swap_v2_common::mark_swap_as_finished; -use crate::mm2::lp_swap::taker_restart::get_command_based_on_watcher_activity; +use crate::mm2::lp_swap::taker_restart::get_command_based_on_maker_or_watcher_activity; use crate::mm2::lp_swap::{broadcast_p2p_tx_msg, broadcast_swap_msg_every_delayed, tx_helper_topic, wait_for_maker_payment_conf_duration, TakerSwapWatcherData, MAX_STARTED_AT_DIFF}; use coins::lp_price::fetch_swap_coins_price; @@ -471,7 +471,6 @@ pub async fn run_taker_swap(swap: RunTakerSwapInput, ctx: MmArc) { ) } - #[cfg(target_arch = "wasm32")] if event.is_error() { error!("[swap uuid={uuid}] {event:?}"); } @@ -784,7 +783,7 @@ impl TakerSwap { #[inline] fn wait_refund_until(&self) -> u64 { self.r().data.taker_payment_lock + 3700 } - fn apply_event(&self, event: TakerSwapEvent) { + pub(crate) fn apply_event(&self, event: TakerSwapEvent) { match event { TakerSwapEvent::Started(data) => { self.w().data = data; @@ -2039,7 +2038,8 @@ impl TakerSwap { && maker_coin.is_supported_by_watchers() && saved.watcher_message_sent() { - command = get_command_based_on_watcher_activity(&ctx, &swap, saved, command).await?; + // discover events occurred while taker was offline, due to maker or watcher activity + command = get_command_based_on_maker_or_watcher_activity(&ctx, &swap, saved, command).await?; } drop_mutability!(command); diff --git a/mm2src/mm2_main/tests/docker_tests/swap_watcher_tests.rs b/mm2src/mm2_main/tests/docker_tests/swap_watcher_tests.rs index 22019abdb1..e3a84a749d 100644 --- a/mm2src/mm2_main/tests/docker_tests/swap_watcher_tests.rs +++ b/mm2src/mm2_main/tests/docker_tests/swap_watcher_tests.rs @@ -666,6 +666,55 @@ fn test_taker_completes_swap_after_restart() { block_on(mm_bob.stop()).unwrap(); } +// Verifies https://github.com/KomodoPlatform/komodo-defi-framework/issues/2111 +#[test] +fn test_taker_completes_swap_after_taker_payment_spent_while_offline() { + let coins = json!([mycoin_conf(1000), mycoin1_conf(1000)]); + let mut mm_bob = run_maker_node(&coins, &[], &[]); + let (mut mm_alice, mut alice_conf) = run_taker_node(&coins, &[], &[&mm_bob.ip.to_string()]); + + let uuids = block_on(start_swaps( + &mut mm_bob, + &mut mm_alice, + &[("MYCOIN1", "MYCOIN")], + 25., + 25., + 2., + )); + + // stop taker after taker payment sent + block_on(mm_alice.wait_for_log(120., |log| log.contains("Taker payment tx"))).unwrap(); + alice_conf.conf["dbdir"] = mm_alice.folder.join("DB").to_str().unwrap().into(); + block_on(mm_alice.stop()).unwrap(); + + // wait for taker payment spent by maker + block_on(mm_bob.wait_for_log(120., |log| log.contains("Taker payment spend tx"))).unwrap(); + // and restart taker + let mut mm_alice = block_on(MarketMakerIt::start_with_envs( + alice_conf.conf, + alice_conf.rpc_password.clone(), + None, + &[], + )) + .unwrap(); + + let (_alice_dump_log, _alice_dump_dashboard) = mm_alice.mm_dump(); + log!("Alice log path: {}", mm_alice.log_path.display()); + enable_coin(&mm_alice, "MYCOIN"); + enable_coin(&mm_alice, "MYCOIN1"); + + block_on(wait_for_swaps_finish_and_check_status( + &mut mm_bob, + &mut mm_alice, + &uuids, + 2., + 25., + )); + + block_on(mm_alice.stop()).unwrap(); + block_on(mm_bob.stop()).unwrap(); +} + #[test] fn test_watcher_spends_maker_payment_utxo_utxo() { let alice_privkey = hex::encode(random_secp256k1_secret());