diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py
index e48c508..650010e 100644
--- a/basicswap/basicswap.py
+++ b/basicswap/basicswap.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2019-2024 tecnovert
-# Copyright (c) 2024 The Basicswap developers
+# Copyright (c) 2024-2025 The Basicswap developers
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
@@ -10327,7 +10327,14 @@ class BasicSwap(BaseApp):
             elif coin == Coins.NAV:
                 rv["immature"] = walletinfo["immature_balance"]
             elif coin == Coins.LTC:
-                rv["mweb_address"] = self.getCachedStealthAddressForCoin(Coins.LTC_MWEB)
+                try:
+                    rv["mweb_address"] = self.getCachedStealthAddressForCoin(
+                        Coins.LTC_MWEB
+                    )
+                except Exception as e:
+                    self.log.warning(
+                        f"getCachedStealthAddressForCoin for {ci.coin_name()} failed with: {e}"
+                    )
                 rv["mweb_balance"] = walletinfo["mweb_balance"]
                 rv["mweb_pending"] = (
                     walletinfo["mweb_unconfirmed"] + walletinfo["mweb_immature"]
diff --git a/basicswap/interface/base.py b/basicswap/interface/base.py
index ec821c2..be31631 100644
--- a/basicswap/interface/base.py
+++ b/basicswap/interface/base.py
@@ -2,6 +2,7 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2024 tecnovert
+# Copyright (c) 2025 The Basicswap developers
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
@@ -53,6 +54,10 @@ class CoinInterface:
         self._mx_wallet = threading.Lock()
         self._altruistic = True
 
+    def interface_type(self) -> int:
+        # coin_type() returns the base coin type, interface_type() returns the coin+balance type.
+        return self.coin_type()
+
     def setDefaults(self):
         self._unknown_wallet_seed = True
         self._restore_height = None
diff --git a/basicswap/interface/btc.py b/basicswap/interface/btc.py
index 7f37245..4b8bc8b 100644
--- a/basicswap/interface/btc.py
+++ b/basicswap/interface/btc.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2020-2024 tecnovert
-# Copyright (c) 2024 The Basicswap developers
+# Copyright (c) 2024-2025 The Basicswap developers
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
@@ -1397,6 +1397,7 @@ class BTCInterface(Secp256k1Interface):
         cb_swap_value: int,
         b_fee: int,
         restore_height: int,
+        spend_actual_balance: bool = False,
         lock_tx_vout=None,
     ) -> bytes:
         self._log.info(
diff --git a/basicswap/interface/dcr/dcr.py b/basicswap/interface/dcr/dcr.py
index 6a8d436..614a73d 100644
--- a/basicswap/interface/dcr/dcr.py
+++ b/basicswap/interface/dcr/dcr.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2024 tecnovert
-# Copyright (c) 2024 The Basicswap developers
+# Copyright (c) 2024-2025 The Basicswap developers
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
@@ -1726,6 +1726,7 @@ class DCRInterface(Secp256k1Interface):
         cb_swap_value: int,
         b_fee: int,
         restore_height: int,
+        spend_actual_balance: bool = False,
         lock_tx_vout=None,
     ) -> bytes:
         self._log.info("spendBLockTx %s:\n", chain_b_lock_txid.hex())
diff --git a/basicswap/interface/ltc.py b/basicswap/interface/ltc.py
index a6c3ba2..33693f9 100644
--- a/basicswap/interface/ltc.py
+++ b/basicswap/interface/ltc.py
@@ -2,6 +2,7 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2020-2023 tecnovert
+# Copyright (c) 2024-2025 The Basicswap developers
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
@@ -52,7 +53,6 @@ class LTCInterface(BTCInterface):
 
     def getWalletInfo(self):
         rv = super(LTCInterface, self).getWalletInfo()
-
         mweb_info = self.rpc_wallet_mweb("getwalletinfo")
         rv["mweb_balance"] = mweb_info["balance"]
         rv["mweb_unconfirmed"] = mweb_info["unconfirmed_balance"]
@@ -88,8 +88,8 @@ class LTCInterface(BTCInterface):
 
 
 class LTCInterfaceMWEB(LTCInterface):
-    @staticmethod
-    def coin_type():
+
+    def interface_type(self) -> int:
         return Coins.LTC_MWEB
 
     def __init__(self, coin_settings, network, swap_client=None):
diff --git a/basicswap/interface/nav.py b/basicswap/interface/nav.py
index 4f131e5..ba8f190 100644
--- a/basicswap/interface/nav.py
+++ b/basicswap/interface/nav.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2023 tecnovert
-# Copyright (c) 2024 The Basicswap developers
+# Copyright (c) 2024-2025 The Basicswap developers
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
@@ -666,6 +666,7 @@ class NAVInterface(BTCInterface):
         cb_swap_value: int,
         b_fee: int,
         restore_height: int,
+        spend_actual_balance: bool = False,
         lock_tx_vout=None,
     ) -> bytes:
         self._log.info("spendBLockTx %s:\n", chain_b_lock_txid.hex())
diff --git a/basicswap/interface/part.py b/basicswap/interface/part.py
index 894a371..df5c79f 100644
--- a/basicswap/interface/part.py
+++ b/basicswap/interface/part.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2020-2024 tecnovert
-# Copyright (c) 2024 The Basicswap developers
+# Copyright (c) 2024-2025 The Basicswap developers
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
@@ -187,6 +187,10 @@ class PARTInterface(BTCInterface):
 
 
 class PARTInterfaceBlind(PARTInterface):
+
+    def interface_type(self) -> int:
+        return Coins.PART_BLIND
+
     @staticmethod
     def balance_type():
         return BalanceTypes.BLIND
@@ -1174,6 +1178,10 @@ class PARTInterfaceBlind(PARTInterface):
 
 
 class PARTInterfaceAnon(PARTInterface):
+
+    def interface_type(self) -> int:
+        return Coins.PART_ANON
+
     @staticmethod
     def balance_type():
         return BalanceTypes.ANON
diff --git a/basicswap/protocols/xmr_swap_1.py b/basicswap/protocols/xmr_swap_1.py
index 9620346..e2a7276 100644
--- a/basicswap/protocols/xmr_swap_1.py
+++ b/basicswap/protocols/xmr_swap_1.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2020-2024 tecnovert
-# Copyright (c) 2024 The Basicswap developers
+# Copyright (c) 2024-2025 The Basicswap developers
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
@@ -15,9 +15,10 @@ from basicswap.chainparams import (
     Coins,
 )
 from basicswap.basicswap_util import (
+    EventLogTypes,
     KeyTypes,
     SwapTypes,
-    EventLogTypes,
+    TxTypes,
 )
 from . import ProtocolInterface
 from basicswap.contrib.test_framework.script import CScript, CScriptOp, OP_CHECKMULTISIG
@@ -55,7 +56,7 @@ def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, cursor=None):
         ensure(xmr_offer, "Adaptor-sig offer not found: {}.".format(bid.offer_id.hex()))
 
         # The no-script coin is always the follower
-        reverse_bid: bool = self.is_reverse_ads_bid(offer.coin_from)
+        reverse_bid: bool = self.is_reverse_ads_bid(offer.coin_from, offer.coin_to)
         ci_from = self.ci(Coins(offer.coin_from))
         ci_to = self.ci(Coins(offer.coin_to))
         ci_follower = ci_from if reverse_bid else ci_to
@@ -89,16 +90,20 @@ def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, cursor=None):
         summed_pkbs = ci_follower.getPubkey(vkbs)
         if summed_pkbs != xmr_swap.pkbs:
             err_msg: str = "Summed key does not match expected wallet spend pubkey"
-            have_pk = summed_pkbs.hex()
-            expect_pk = xmr_swap.pkbs.hex()
-            self.log.error(f"{err_msg}. Got: {have_pk}, Expect: {expect_pk}")
+            self.log.error(
+                f"{err_msg}. Got: {summed_pkbs.hex()}, Expect: {xmr_swap.pkbs.hex()}"
+            )
             raise ValueError(err_msg)
 
-        if ci_follower.coin_type() in (Coins.XMR, Coins.WOW):
+        coin_to: int = ci_follower.interface_type()
+        base_coin_to: int = ci_follower.coin_type()
+        if coin_to in (Coins.XMR, Coins.WOW):
             address_to = self.getCachedMainWalletAddress(ci_follower, use_cursor)
+        elif coin_to in (Coins.PART_BLIND, Coins.PART_ANON):
+            address_to = self.getCachedStealthAddressForCoin(base_coin_to, use_cursor)
         else:
-            address_to = self.getCachedStealthAddressForCoin(
-                ci_follower.coin_type(), use_cursor
+            address_to = self.getReceiveAddressFromPool(
+                base_coin_to, bid_id, TxTypes.XMR_SWAP_B_LOCK_SPEND, use_cursor
             )
         amount = bid.amount_to
         lock_tx_vout = bid.getLockTXBVout()
@@ -145,10 +150,11 @@ def getChainBSplitKey(swap_client, bid, xmr_swap, offer):
     was_sent: bool = bid.was_received if reverse_bid else bid.was_sent
 
     key_type = KeyTypes.KBSF if was_sent else KeyTypes.KBSL
+
     return ci_follower.encodeKey(
         swap_client.getPathKey(
-            ci_leader.coin_type(),
-            ci_follower.coin_type(),
+            ci_leader.interface_type(),
+            ci_follower.interface_type(),
             bid.created_at,
             xmr_swap.contract_count,
             key_type,
diff --git a/tests/basicswap/test_btc_xmr.py b/tests/basicswap/test_btc_xmr.py
index 69a7c36..02407a8 100644
--- a/tests/basicswap/test_btc_xmr.py
+++ b/tests/basicswap/test_btc_xmr.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2021-2024 tecnovert
-# Copyright (c) 2024 The Basicswap developers
+# Copyright (c) 2024-2025 The Basicswap developers
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
@@ -170,7 +170,11 @@ class TestFunctions(BaseTest):
         bid_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from)
 
         wait_for_bid(
-            test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED
+            test_delay_event,
+            swap_clients[id_offerer],
+            bid_id,
+            BidStates.BID_RECEIVED,
+            wait_for=(self.extra_wait_time + 40),
         )
 
         bid0 = read_json_api(1800 + id_offerer, f"bids/{bid_id.hex()}")
@@ -392,7 +396,7 @@ class TestFunctions(BaseTest):
         )
 
         swap_clients[id_follower].ci(
-            coin_from if reverse_bid else coin_to
+            coin_to if reverse_bid else coin_from
         )._altruistic = with_mercy
 
         amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
@@ -415,17 +419,10 @@ class TestFunctions(BaseTest):
             test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED
         )
 
-        debug_type = (
-            DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND2
-            if with_mercy
-            else DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND
-        )
-        swap_clients[id_leader].setBidDebugInd(bid_id, debug_type)
-        debug_type = (
-            DebugTypes.BID_DONT_SPEND_COIN_B_LOCK
-            if with_mercy
-            else DebugTypes.BID_STOP_AFTER_COIN_A_LOCK
+        swap_clients[id_leader].setBidDebugInd(
+            bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND2
         )
+        debug_type = DebugTypes.BID_DONT_SPEND_COIN_B_LOCK
         swap_clients[id_follower].setBidDebugInd(bid_id, debug_type)
 
         swap_clients[id_leader].setBidDebugInd(
@@ -442,7 +439,7 @@ class TestFunctions(BaseTest):
         expect_state = (
             (BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED, BidStates.SWAP_COMPLETED)
             if with_mercy
-            else BidStates.BID_STALLED_FOR_TEST
+            else (BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED_SWIPED)
         )
         wait_for_bid(
             test_delay_event,
@@ -473,6 +470,19 @@ class TestFunctions(BaseTest):
         wait_for_none_active(test_delay_event, 1800 + id_offerer)
         wait_for_none_active(test_delay_event, 1800 + id_bidder)
 
+        if with_mercy is False:
+            # Test manually redeeming the no-script lock tx
+            offerer_key = read_json_api(
+                1800 + id_offerer,
+                "bids/{}".format(bid_id.hex()),
+                {"chainbkeysplit": True},
+            )["splitkey"]
+            data = {"spendchainblocktx": True, "remote_key": offerer_key}
+            redeemed_txid = read_json_api(
+                1800 + id_bidder, "bids/{}".format(bid_id.hex()), data
+            )["txid"]
+            assert len(redeemed_txid) == 64
+
     def do_test_04_follower_recover_b_lock_tx(
         self, coin_from, coin_to, lock_value: int = 32
     ):
@@ -1601,7 +1611,13 @@ class BasicSwapTest(TestFunctions):
         offer = swap_clients[1].getOffer(offer_id)
         bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
 
-        wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED)
+        wait_for_bid(
+            test_delay_event,
+            swap_clients[2],
+            bid_id,
+            BidStates.BID_RECEIVED,
+            wait_for=(self.extra_wait_time + 40),
+        )
         swap_clients[2].acceptBid(bid_id)
 
         wait_for_bid(
@@ -1662,7 +1678,13 @@ class BasicSwapTest(TestFunctions):
         wait_for_offer(test_delay_event, swap_clients[1], offer_id)
         bid_id = swap_clients[1].postXmrBid(offer_id, amt_swap)
         swap_clients[1].abandonBid(bid_id)
-        wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_ACCEPTED)
+        wait_for_bid(
+            test_delay_event,
+            swap_clients[0],
+            bid_id,
+            BidStates.BID_ACCEPTED,
+            wait_for=(self.extra_wait_time + 40),
+        )
 
         try:
             swap_clients[0].setMockTimeOffset(7200)
diff --git a/tests/basicswap/test_partblind_xmr.py b/tests/basicswap/test_partblind_xmr.py
index 087fd49..52a63ce 100644
--- a/tests/basicswap/test_partblind_xmr.py
+++ b/tests/basicswap/test_partblind_xmr.py
@@ -2,16 +2,13 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2021-2023 tecnovert
-# Copyright (c) 2024 The Basicswap developers
+# Copyright (c) 2024-2025 The Basicswap developers
 # Distributed under the MIT software license, see the accompanying
 # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 
-import json
 import random
 import logging
 import unittest
-from urllib import parse
-from urllib.request import urlopen
 
 from basicswap.basicswap import (
     Coins,
@@ -27,7 +24,6 @@ from basicswap.util import (
     format_amount,
 )
 from tests.basicswap.util import (
-    post_json_req,
     read_json_api,
 )
 from tests.basicswap.common import (
@@ -61,9 +57,7 @@ class Test(BaseTest):
             "subfee": False,
             "type_to": "blind",
         }
-        json_rv = json.loads(
-            post_json_req("http://127.0.0.1:1800/json/wallets/part/withdraw", post_json)
-        )
+        json_rv = read_json_api(1800, "wallets/part/withdraw", post_json)
         assert len(json_rv["txid"]) == 64
 
         logging.info("Waiting for blind balance")
@@ -388,7 +382,7 @@ class Test(BaseTest):
 
         swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK)
         swap_clients[0].setBidDebugInd(
-            bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND
+            bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND2
         )
 
         swap_clients[0].acceptXmrBid(bid_id)
@@ -397,7 +391,7 @@ class Test(BaseTest):
             test_delay_event,
             swap_clients[0],
             bid_id,
-            BidStates.BID_STALLED_FOR_TEST,
+            (BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED_SWIPED),
             wait_for=180,
         )
         wait_for_bid(
@@ -422,21 +416,14 @@ class Test(BaseTest):
         wait_for_none_active(test_delay_event, 1800)
         wait_for_none_active(test_delay_event, 1801)
 
-        data = parse.urlencode({"chainbkeysplit": True}).encode()
-        offerer_key = json.loads(
-            urlopen(
-                "http://127.0.0.1:1800/json/bids/{}".format(bid_id.hex()), data=data
-            ).read()
+        offerer_key = read_json_api(
+            1800, "bids/{}".format(bid_id.hex()), {"chainbkeysplit": True}
         )["splitkey"]
 
-        data = parse.urlencode(
-            {"spendchainblocktx": True, "remote_key": offerer_key}
-        ).encode()
-        redeemed_txid = json.loads(
-            urlopen(
-                "http://127.0.0.1:1801/json/bids/{}".format(bid_id.hex()), data=data
-            ).read()
-        )["txid"]
+        data = {"spendchainblocktx": True, "remote_key": offerer_key}
+        redeemed_txid = read_json_api(1801, "bids/{}".format(bid_id.hex()), data)[
+            "txid"
+        ]
         assert len(redeemed_txid) == 64
 
     def do_test_04_follower_recover_b_lock_tx(self, coin_from, coin_to):