diff --git a/basicswap/bin/prepare.py b/basicswap/bin/prepare.py
index 98a4e18..233e30f 100755
--- a/basicswap/bin/prepare.py
+++ b/basicswap/bin/prepare.py
@@ -52,11 +52,17 @@ PARTICL_VERSION = os.getenv("PARTICL_VERSION", "23.2.7.0")
 PARTICL_VERSION_TAG = os.getenv("PARTICL_VERSION_TAG", "")
 PARTICL_LINUX_EXTRA = os.getenv("PARTICL_LINUX_EXTRA", "nousb")
 
+BITCOIN_VERSION = os.getenv("BITCOIN_VERSION", "28.0")
+BITCOIN_VERSION_TAG = os.getenv("BITCOIN_VERSION_TAG", "")
+
 LITECOIN_VERSION = os.getenv("LITECOIN_VERSION", "0.21.4")
 LITECOIN_VERSION_TAG = os.getenv("LITECOIN_VERSION_TAG", "")
 
-BITCOIN_VERSION = os.getenv("BITCOIN_VERSION", "28.0")
-BITCOIN_VERSION_TAG = os.getenv("BITCOIN_VERSION_TAG", "")
+DCR_VERSION = os.getenv("DCR_VERSION", "1.8.1")
+DCR_VERSION_TAG = os.getenv("DCR_VERSION_TAG", "")
+
+NMC_VERSION = os.getenv("NMC_VERSION", "28.0")
+NMC_VERSION_TAG = os.getenv("NMC_VERSION_TAG", "")
 
 MONERO_VERSION = os.getenv("MONERO_VERSION", "0.18.3.4")
 MONERO_VERSION_TAG = os.getenv("MONERO_VERSION_TAG", "")
@@ -82,12 +88,6 @@ FIRO_VERSION_TAG = os.getenv("FIRO_VERSION_TAG", "")
 NAV_VERSION = os.getenv("NAV_VERSION", "7.0.3")
 NAV_VERSION_TAG = os.getenv("NAV_VERSION_TAG", "")
 
-NMC_VERSION = os.getenv("NAV_VERSION", "28.0")
-NMC_VERSION_TAG = os.getenv("NAV_VERSION_TAG", "")
-
-DCR_VERSION = os.getenv("DCR_VERSION", "1.8.1")
-DCR_VERSION_TAG = os.getenv("DCR_VERSION_TAG", "")
-
 BITCOINCASH_VERSION = os.getenv("BITCOINCASH_VERSION", "28.0.1")
 BITCOINCASH_VERSION_TAG = os.getenv("BITCOINCASH_VERSION_TAG", "")
 
@@ -117,9 +117,7 @@ known_coins = {
     "dogecoin": (DOGECOIN_VERSION, DOGECOIN_VERSION_TAG, ("tecnovert",)),
 }
 
-disabled_coins = [
-    "navcoin"
-]
+disabled_coins = ["navcoin"]
 
 expected_key_ids = {
     "tecnovert": ("13F13651C9CF0D6B",),
@@ -184,6 +182,35 @@ PART_ONION_PORT = int(os.getenv("PART_ONION_PORT", 51734))
 PART_RPC_USER = os.getenv("PART_RPC_USER", "")
 PART_RPC_PWD = os.getenv("PART_RPC_PWD", "")
 
+BTC_RPC_HOST = os.getenv("BTC_RPC_HOST", "127.0.0.1")
+BTC_RPC_PORT = int(os.getenv("BTC_RPC_PORT", 19996))
+BTC_PORT = int(os.getenv("BTC_PORT", 8333))
+BTC_ONION_PORT = int(os.getenv("BTC_ONION_PORT", 8334))
+BTC_RPC_USER = os.getenv("BTC_RPC_USER", "")
+BTC_RPC_PWD = os.getenv("BTC_RPC_PWD", "")
+
+LTC_RPC_HOST = os.getenv("LTC_RPC_HOST", "127.0.0.1")
+LTC_RPC_PORT = int(os.getenv("LTC_RPC_PORT", 19895))
+LTC_ONION_PORT = int(os.getenv("LTC_ONION_PORT", 9333))
+LTC_RPC_USER = os.getenv("LTC_RPC_USER", "")
+LTC_RPC_PWD = os.getenv("LTC_RPC_PWD", "")
+
+DCR_RPC_HOST = os.getenv("DCR_RPC_HOST", "127.0.0.1")
+DCR_RPC_PORT = int(os.getenv("DCR_RPC_PORT", 9109))
+DCR_WALLET_RPC_HOST = os.getenv("DCR_WALLET_RPC_HOST", "127.0.0.1")
+DCR_WALLET_RPC_PORT = int(os.getenv("DCR_WALLET_RPC_PORT", 9209))
+DCR_WALLET_PWD = os.getenv(
+    "DCR_WALLET_PWD", random.randbytes(random.randint(14, 18)).hex()
+)
+DCR_RPC_USER = os.getenv("DCR_RPC_USER", "user")
+DCR_RPC_PWD = os.getenv("DCR_RPC_PWD", random.randbytes(random.randint(14, 18)).hex())
+
+NMC_RPC_HOST = os.getenv("NMC_RPC_HOST", "127.0.0.1")
+NMC_RPC_PORT = int(os.getenv("NMC_RPC_PORT", 19698))
+NMC_ONION_PORT = int(os.getenv("NMC_ONION_PORT", 9698))
+NMC_RPC_USER = os.getenv("NMC_RPC_USER", "")
+NMC_RPC_PWD = os.getenv("NMC_RPC_PWD", "")
+
 XMR_RPC_HOST = os.getenv("XMR_RPC_HOST", "127.0.0.1")
 XMR_RPC_PORT = int(os.getenv("XMR_RPC_PORT", 29798))
 XMR_ZMQ_PORT = int(os.getenv("XMR_ZMQ_PORT", 30898))
@@ -206,35 +233,6 @@ WOW_RPC_USER = os.getenv("WOW_RPC_USER", "")
 WOW_RPC_PWD = os.getenv("WOW_RPC_PWD", "")
 DEFAULT_WOW_RESTORE_HEIGHT = int(os.getenv("DEFAULT_WOW_RESTORE_HEIGHT", 450000))
 
-LTC_RPC_HOST = os.getenv("LTC_RPC_HOST", "127.0.0.1")
-LTC_RPC_PORT = int(os.getenv("LTC_RPC_PORT", 19895))
-LTC_ONION_PORT = int(os.getenv("LTC_ONION_PORT", 9333))
-LTC_RPC_USER = os.getenv("LTC_RPC_USER", "")
-LTC_RPC_PWD = os.getenv("LTC_RPC_PWD", "")
-
-BTC_RPC_HOST = os.getenv("BTC_RPC_HOST", "127.0.0.1")
-BTC_RPC_PORT = int(os.getenv("BTC_RPC_PORT", 19996))
-BTC_PORT = int(os.getenv("BTC_PORT", 8333))
-BTC_ONION_PORT = int(os.getenv("BTC_ONION_PORT", 8334))
-BTC_RPC_USER = os.getenv("BTC_RPC_USER", "")
-BTC_RPC_PWD = os.getenv("BTC_RPC_PWD", "")
-
-DCR_RPC_HOST = os.getenv("DCR_RPC_HOST", "127.0.0.1")
-DCR_RPC_PORT = int(os.getenv("DCR_RPC_PORT", 9109))
-DCR_WALLET_RPC_HOST = os.getenv("DCR_WALLET_RPC_HOST", "127.0.0.1")
-DCR_WALLET_RPC_PORT = int(os.getenv("DCR_WALLET_RPC_PORT", 9209))
-DCR_WALLET_PWD = os.getenv(
-    "DCR_WALLET_PWD", random.randbytes(random.randint(14, 18)).hex()
-)
-DCR_RPC_USER = os.getenv("DCR_RPC_USER", "user")
-DCR_RPC_PWD = os.getenv("DCR_RPC_PWD", random.randbytes(random.randint(14, 18)).hex())
-
-NMC_RPC_HOST = os.getenv("NMC_RPC_HOST", "127.0.0.1")
-NMC_RPC_PORT = int(os.getenv("NMC_RPC_PORT", 19698))
-NMC_ONION_PORT = int(os.getenv("NMC_ONION_PORT", 9698))
-NMC_RPC_USER = os.getenv("NMC_RPC_USER", "")
-NMC_RPC_PWD = os.getenv("NMC_RPC_PWD", "")
-
 PIVX_RPC_HOST = os.getenv("PIVX_RPC_HOST", "127.0.0.1")
 PIVX_RPC_PORT = int(os.getenv("PIVX_RPC_PORT", 51473))
 PIVX_ONION_PORT = int(os.getenv("PIVX_ONION_PORT", 51472))  # nDefaultPort
@@ -1400,8 +1398,10 @@ def prepareDataDir(coin, settings, chain, particl_mnemonic, extra_opts={}):
                     )
                 )
         elif coin == "namecoin":
-            fp.write("deprecatedrpc=create_bdb\n")
             fp.write("prune=2000\n")
+            fp.write("deprecatedrpc=create_bdb\n")
+            fp.write("addresstype=bech32\n")
+            fp.write("changetype=bech32\n")
         elif coin == "pivx":
             params_dir = os.path.join(data_dir, "pivx-params")
             downloadPIVXParams(params_dir)
diff --git a/basicswap/chainparams.py b/basicswap/chainparams.py
index 82d7ad4..f4e36d5 100644
--- a/basicswap/chainparams.py
+++ b/basicswap/chainparams.py
@@ -256,6 +256,8 @@ chainparams = {
             "bip44": 7,
             "min_amount": 100000,
             "max_amount": 10000000 * COIN,
+            "ext_public_key_prefix": 0x0488B21E,  # base58Prefixes[EXT_PUBLIC_KEY]
+            "ext_secret_key_prefix": 0x0488ADE4,
         },
         "testnet": {
             "rpcport": 18336,
@@ -267,6 +269,8 @@ chainparams = {
             "min_amount": 100000,
             "max_amount": 10000000 * COIN,
             "name": "testnet3",
+            "ext_public_key_prefix": 0x043587CF,
+            "ext_secret_key_prefix": 0x04358394,
         },
         "regtest": {
             "rpcport": 18443,
@@ -277,6 +281,8 @@ chainparams = {
             "bip44": 1,
             "min_amount": 100000,
             "max_amount": 10000000 * COIN,
+            "ext_public_key_prefix": 0x043587CF,
+            "ext_secret_key_prefix": 0x04358394,
         },
     },
     Coins.XMR: {
diff --git a/basicswap/interface/nmc.py b/basicswap/interface/nmc.py
index cf9bae7..19aa48e 100644
--- a/basicswap/interface/nmc.py
+++ b/basicswap/interface/nmc.py
@@ -2,6 +2,7 @@
 # -*- coding: utf-8 -*-
 
 # Copyright (c) 2020-2022 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.
 
@@ -14,38 +15,56 @@ class NMCInterface(BTCInterface):
     def coin_type():
         return Coins.NMC
 
-    def getLockTxHeight(
-        self,
-        txid,
-        dest_address,
-        bid_amount,
-        rescan_from,
-        find_index: bool = False,
-        vout: int = -1,
-    ):
-        self._log.debug("[rm] scantxoutset start")  # scantxoutset is slow
-        ro = self.rpc(
-            "scantxoutset", ["start", ["addr({})".format(dest_address)]]
-        )  # TODO: Use combo(address) where possible
-        self._log.debug("[rm] scantxoutset end")
-        return_txid = True if txid is None else False
-        for o in ro["unspents"]:
-            if txid and o["txid"] != txid.hex():
-                continue
-            # Verify amount
-            if self.make_int(o["amount"]) != int(bid_amount):
-                self._log.warning(
-                    "Found output to lock tx address of incorrect value: %s, %s",
-                    str(o["amount"]),
-                    o["txid"],
-                )
-                continue
+    def lockNonSegwitPrevouts(self) -> None:
+        # For tests
+        # NMC Seems to ignore utxo locks
+        unspent = self.rpc_wallet("listunspent")
 
-            rv = {"depth": 0, "height": o["height"]}
-            if o["height"] > 0:
-                rv["depth"] = ro["height"] - o["height"]
-            if find_index:
-                rv["index"] = o["vout"]
-            if return_txid:
-                rv["txid"] = o["txid"]
-            return rv
+        to_lock = []
+        for u in unspent:
+            if u.get("spendable", False) is False:
+                continue
+            if "desc" in u:
+                desc = u["desc"]
+                if self.use_p2shp2wsh():
+                    if not desc.startswith("sh(wpkh"):
+                        to_lock.append(
+                            {
+                                "txid": u["txid"],
+                                "vout": u["vout"],
+                                "amount": u["amount"],
+                            }
+                        )
+                else:
+                    if not desc.startswith("wpkh"):
+                        to_lock.append(
+                            {
+                                "txid": u["txid"],
+                                "vout": u["vout"],
+                                "amount": u["amount"],
+                            }
+                        )
+
+        if len(to_lock) > 0:
+            self._log.debug(f"Spending {len(to_lock)} non segwit prevouts")
+            addr_out = self.rpc_wallet(
+                "getnewaddress", ["convert non segwit", "bech32"]
+            )
+            prevouts = []
+            sum_amount: int = 0
+            for utxo in to_lock:
+                prevouts.append(
+                    {
+                        "txid": utxo["txid"],
+                        "vout": utxo["vout"],
+                    }
+                )
+                sum_amount += self.make_int(utxo["amount"])
+
+            fee = 100000 * len(prevouts)
+            funded_tx = self.rpc(
+                "createrawtransaction",
+                [prevouts, {addr_out: self.format_amount(sum_amount - fee)}],
+            )
+            signed_tx = self.rpc_wallet("signrawtransactionwithwallet", [funded_tx])
+            self.rpc("sendrawtransaction", [signed_tx["hex"]])
diff --git a/tests/basicswap/extended/test_dcr.py b/tests/basicswap/extended/test_dcr.py
index d063160..e3c7bfe 100644
--- a/tests/basicswap/extended/test_dcr.py
+++ b/tests/basicswap/extended/test_dcr.py
@@ -138,7 +138,6 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins):
 
     # Verify lock tx spends are found in the expected wallets
     bid, offer = swap_clients[node_from].getBidAndOffer(bid_id)
-    max_fee: int = 10000
     itx_spend = bid.initiate_tx.spend_txid.hex()
     node_to_ci_from = swap_clients[node_to].ci(coin_from)
     wtx = node_to_ci_from.rpc_wallet(
@@ -147,7 +146,9 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins):
             itx_spend,
         ],
     )
-    assert amt_swap - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee
+    assert (
+        amt_swap - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < self.max_fee
+    )
 
     node_from_ci_to = swap_clients[node_from].ci(coin_to)
     ptx_spend = bid.participate_tx.spend_txid.hex()
@@ -158,7 +159,8 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins):
         ],
     )
     assert (
-        bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee
+        bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"])
+        < self.max_fee
     )
 
     js_0 = read_json_api(1800 + node_from)
@@ -235,7 +237,6 @@ def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins):
 
     # Verify lock tx spends are found in the expected wallets
     bid, offer = swap_clients[node_from].getBidAndOffer(bid_id)
-    max_fee: int = 10000
     itx_spend = bid.initiate_tx.spend_txid.hex()
     node_from_ci_from = swap_clients[node_from].ci(coin_from)
     wtx = node_from_ci_from.rpc_wallet(
@@ -244,7 +245,10 @@ def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins):
             itx_spend,
         ],
     )
-    assert amt_swap - node_from_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee
+    assert (
+        amt_swap - node_from_ci_from.make_int(wtx["details"][0]["amount"])
+        < self.max_fee
+    )
 
     node_to_ci_to = swap_clients[node_to].ci(coin_to)
     bid, offer = swap_clients[node_to].getBidAndOffer(bid_id)
@@ -255,7 +259,10 @@ def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins):
             ptx_spend,
         ],
     )
-    assert bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee
+    assert (
+        bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"])
+        < self.max_fee
+    )
 
     bid_id_hex = bid_id.hex()
     path = f"bids/{bid_id_hex}/states"
@@ -338,7 +345,6 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins):
 
     # Verify lock tx spends are found in the expected wallets
     bid, offer = swap_clients[node_from].getBidAndOffer(bid_id)
-    max_fee: int = 10000
     itx_spend = bid.initiate_tx.spend_txid.hex()
     node_from_ci_from = swap_clients[node_from].ci(coin_from)
     wtx = node_from_ci_from.rpc_wallet(
@@ -348,7 +354,8 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins):
         ],
     )
     assert (
-        swap_value - node_from_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee
+        swap_value - node_from_ci_from.make_int(wtx["details"][0]["amount"])
+        < self.max_fee
     )
 
     node_from_ci_to = swap_clients[node_from].ci(coin_to)
@@ -360,7 +367,8 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins):
         ],
     )
     assert (
-        bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee
+        bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"])
+        < self.max_fee
     )
 
 
@@ -425,7 +433,6 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins):
     bid, xmr_swap = swap_clients[id_offerer].getXmrBid(bid_id)
 
     node_from_ci_to = swap_clients[0].ci(coin_to)
-    max_fee: int = 10000
     if node_from_ci_to.coin_type() in (Coins.XMR, Coins.WOW):
         pass
     else:
@@ -437,7 +444,7 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins):
         )
         assert (
             bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"])
-            < max_fee
+            < self.max_fee
         )
 
     node_to_ci_from = swap_clients[1].ci(coin_from)
@@ -451,7 +458,8 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins):
             ],
         )
         assert (
-            bid.amount - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee
+            bid.amount - node_to_ci_from.make_int(wtx["details"][0]["amount"])
+            < self.max_fee
         )
 
     bid_id_hex = bid_id.hex()
@@ -550,7 +558,6 @@ def run_test_ads_both_refund(
     bid, xmr_swap = swap_clients[id_bidder].getXmrBid(bid_id)
 
     node_from_ci_from = swap_clients[0].ci(coin_from)
-    max_fee: int = 10000
     if node_from_ci_from.coin_type() in (Coins.XMR, Coins.WOW):
         pass
     else:
@@ -562,7 +569,7 @@ def run_test_ads_both_refund(
         )
         assert (
             bid.amount - node_from_ci_from.make_int(wtx["details"][0]["amount"])
-            < max_fee
+            < self.max_fee
         )
 
     node_to_ci_to = swap_clients[1].ci(coin_to)
@@ -577,7 +584,7 @@ def run_test_ads_both_refund(
         )
         assert (
             bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"])
-            < max_fee
+            < self.max_fee
         )
 
     bid_id_hex = bid_id.hex()
@@ -720,6 +727,7 @@ class Test(BaseTest):
     start_xmr_nodes = True
     dcr_mining_addr = "SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH"
     extra_wait_time = 0
+    max_fee: int = 10000
 
     hex_seeds = [
         "e8574b2a94404ee62d8acc0258cab4c0defcfab8a5dfc2f4954c1f9d7e09d72a",
diff --git a/tests/basicswap/extended/test_nmc.py b/tests/basicswap/extended/test_nmc.py
index 1bee5a1..ac839e9 100644
--- a/tests/basicswap/extended/test_nmc.py
+++ b/tests/basicswap/extended/test_nmc.py
@@ -11,67 +11,38 @@ basicswap]$ python tests/basicswap/extended/test_nmc.py
 
 """
 
-import json
 import logging
 import os
-import shutil
-import signal
+import random
 import sys
-import threading
-import time
 import unittest
 
 import basicswap.config as cfg
 from basicswap.basicswap import (
-    BasicSwap,
     Coins,
-    SwapTypes,
-    BidStates,
-    TxStates,
 )
 from basicswap.util import (
-    COIN,
-)
-from basicswap.basicswap_util import (
-    TxLockTypes,
-)
-from basicswap.util.address import (
-    toWIF,
-)
-from basicswap.rpc import (
-    callrpc_cli,
-)
-from basicswap.contrib.key import (
-    ECKey,
+    toBool,
 )
+from basicswap.bin.run import startDaemon
 from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
-from basicswap.http_server import (
-    HttpThread,
-)
-from tests.basicswap.util import (
-    read_json_api,
-)
 from tests.basicswap.common import (
-    checkForks,
     stopDaemons,
-    wait_for_offer,
-    wait_for_bid,
-    wait_for_bid_tx_state,
-    wait_for_in_progress,
-    TEST_HTTP_HOST,
-    TEST_HTTP_PORT,
-    BASE_PORT,
-    BASE_RPC_PORT,
-    BASE_ZMQ_PORT,
-    PREFIX_SECRET_KEY_REGTEST,
     waitForRPC,
     make_rpc_func,
 )
-from basicswap.bin.run import startDaemon
+
+from tests.basicswap.test_btc_xmr import BasicSwapTest, test_delay_event
+from tests.basicswap.test_xmr import NUM_NODES
+from tests.basicswap.extended.test_dcr import (
+    run_test_success_path,
+    run_test_bad_ptx,
+    run_test_itx_refund,
+)
 
 
-logger = logging.getLogger()
-logger.level = logging.DEBUG
+logger = logging.getLogger("BSX Tests")
+
 if not len(logger.handlers):
     logger.addHandler(logging.StreamHandler(sys.stdout))
 
@@ -83,19 +54,14 @@ NAMECOIND = os.getenv("NAMECOIND", "namecoind" + cfg.bin_suffix)
 NAMECOIN_CLI = os.getenv("NAMECOIN_CLI", "namecoin-cli" + cfg.bin_suffix)
 NAMECOIN_TX = os.getenv("NAMECOIN_TX", "namecoin-tx" + cfg.bin_suffix)
 
+USE_DESCRIPTOR_WALLETS = toBool(os.getenv("USE_DESCRIPTOR_WALLETS", False))
+
 NMC_BASE_PORT = 8136
-NMC_BASE_RPC_PORT= 8146
-
-NUM_NODES = 3
-NMC_NODE = 3
-BTC_NODE = 4
-
-delay_event = threading.Event()
-stop_test = False
+NMC_BASE_RPC_PORT = 8146
 
 
-def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"):
-    node_dir = os.path.join(datadir, str(nodeId))
+def prepareNMCDataDir(datadir, nodeId, conf_file="namecoin.conf"):
+    node_dir = os.path.join(datadir, "nmc_" + str(nodeId))
     if not os.path.exists(node_dir):
         os.makedirs(node_dir)
     filePath = os.path.join(node_dir, conf_file)
@@ -104,20 +70,16 @@ def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"):
         fp.write("regtest=1\n")
         fp.write("[regtest]\n")
 
-        if conf_file == "bitcoin.conf":
-            fp.write("port=" + str(BASE_PORT + nodeId) + "\n")
-            fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n")
-        else:
-            fp.write("port=" + str(NMC_BASE_PORT + nodeId) + "\n")
-            fp.write("rpcport=" + str(NMC_BASE_RPC_PORT + nodeId) + "\n")
-            salt = generate_salt(16)
-            fp.write(
-                "rpcauth={}:{}${}\n".format(
-                    "test" + str(nodeId),
-                    salt,
-                    password_to_hmac(salt, "test_pass" + str(nodeId)),
-                )
+        fp.write("port=" + str(NMC_BASE_PORT + nodeId) + "\n")
+        fp.write("rpcport=" + str(NMC_BASE_RPC_PORT + nodeId) + "\n")
+        salt = generate_salt(16)
+        fp.write(
+            "rpcauth={}:{}${}\n".format(
+                "test" + str(nodeId),
+                salt,
+                password_to_hmac(salt, "test_pass" + str(nodeId)),
             )
+        )
 
         fp.write("daemon=0\n")
         fp.write("printtoconsole=0\n")
@@ -125,592 +87,171 @@ def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"):
         fp.write("discover=0\n")
         fp.write("listenonion=0\n")
         fp.write("bind=127.0.0.1\n")
-        fp.write("findpeers=0\n")
         fp.write("debug=1\n")
         fp.write("debugexclude=libevent\n")
 
         fp.write("fallbackfee=0.01\n")
         fp.write("acceptnonstdtxn=0\n")
         fp.write("deprecatedrpc=create_bdb\n")
-        fp.write("wallet=wallet.dat\n")
-
-
-def prepareDir(datadir, nodeId, network_key, network_pubkey):
-    node_dir = os.path.join(datadir, str(nodeId))
-    if not os.path.exists(node_dir):
-        os.makedirs(node_dir)
-    filePath = os.path.join(node_dir, "particl.conf")
-
-    with open(filePath, "w+") as fp:
-        fp.write("regtest=1\n")
-        fp.write("[regtest]\n")
-        fp.write("port=" + str(BASE_PORT + nodeId) + "\n")
-        fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n")
-
-        fp.write("daemon=0\n")
-        fp.write("printtoconsole=0\n")
-        fp.write("server=1\n")
-        fp.write("discover=0\n")
-        fp.write("listenonion=0\n")
-        fp.write("bind=127.0.0.1\n")
-        fp.write("findpeers=0\n")
-        fp.write("debug=1\n")
-        fp.write("debugexclude=libevent\n")
-        fp.write("zmqpubsmsg=tcp://127.0.0.1:" + str(BASE_ZMQ_PORT + nodeId) + "\n")
-        fp.write("wallet=wallet.dat\n")
-        fp.write("fallbackfee=0.01\n")
-
-        fp.write("acceptnonstdtxn=0\n")
-        fp.write("minstakeinterval=5\n")
-        fp.write("smsgsregtestadjust=0\n")
+        fp.write("addresstype=bech32\n")
+        fp.write("changetype=bech32\n")
 
         for i in range(0, NUM_NODES):
             if nodeId == i:
                 continue
-            fp.write("addnode=127.0.0.1:%d\n" % (BASE_PORT + i))
-
-        if nodeId < 2:
-            fp.write("spentindex=1\n")
-            fp.write("txindex=1\n")
-
-    basicswap_dir = os.path.join(datadir, str(nodeId), "basicswap")
-    if not os.path.exists(basicswap_dir):
-        os.makedirs(basicswap_dir)
-
-    nmcdatadir = os.path.join(datadir, str(NMC_NODE))
-    btcdatadir = os.path.join(datadir, str(BTC_NODE))
-    settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
-    settings = {
-        "debug": True,
-        "zmqhost": "tcp://127.0.0.1",
-        "zmqport": BASE_ZMQ_PORT + nodeId,
-        "htmlhost": "127.0.0.1",
-        "htmlport": 12700 + nodeId,
-        "network_key": network_key,
-        "network_pubkey": network_pubkey,
-        "chainclients": {
-            "particl": {
-                "connection_type": "rpc",
-                "manage_daemon": False,
-                "rpcport": BASE_RPC_PORT + nodeId,
-                "datadir": node_dir,
-                "bindir": cfg.PARTICL_BINDIR,
-                "blocks_confirmed": 2,  # Faster testing
-            },
-            "namecoin": {
-                "connection_type": "rpc",
-                "manage_daemon": False,
-                "rpcport": NMC_BASE_RPC_PORT + NMC_NODE,
-                "datadir": nmcdatadir,
-                "bindir": NAMECOIN_BINDIR,
-                "use_csv": True,
-                "use_segwit": True,
-            },
-            "bitcoin": {
-                "connection_type": "rpc",
-                "manage_daemon": False,
-                "rpcport": BASE_RPC_PORT + BTC_NODE,
-                "datadir": btcdatadir,
-                "bindir": cfg.BITCOIN_BINDIR,
-                "use_segwit": True,
-            },
-        },
-        "check_progress_seconds": 2,
-        "check_watched_seconds": 4,
-        "check_expired_seconds": 60,
-        "restrict_unknown_seed_wallets": False,
-    }
-    with open(settings_path, "w") as fp:
-        json.dump(settings, fp, indent=4)
+            fp.write("addnode=127.0.0.1:{}\n".format(NMC_BASE_PORT + i))
 
 
-def partRpc(cmd, node_id=0):
-    return callrpc_cli(
-        cfg.PARTICL_BINDIR,
-        os.path.join(cfg.TEST_DATADIRS, str(node_id)),
-        "regtest",
-        cmd,
-        cfg.PARTICL_CLI,
-    )
+class TestNMC(BasicSwapTest):
+    __test__ = True
+    test_coin = Coins.NMC
+    test_coin_from = Coins.NMC
+    nmc_daemons = []
+    start_ltc_nodes = False
+    start_xmr_nodes = True
+    base_rpc_port = NMC_BASE_RPC_PORT
+    nmc_addr = None
+    max_fee: int = 200000
+    test_fee_rate: int = 10000  # sats/kvB
 
-
-def btcRpc(cmd):
-    return callrpc_cli(
-        cfg.BITCOIN_BINDIR,
-        os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)),
-        "regtest",
-        cmd,
-        cfg.BITCOIN_CLI,
-    )
-
-
-def nmcRpc(cmd):
-    return callrpc_cli(
-        NAMECOIN_BINDIR,
-        os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)),
-        "regtest",
-        cmd,
-        NAMECOIN_CLI,
-    )
-
-
-def signal_handler(sig, frame):
-    global stop_test
-    os.write(sys.stdout.fileno(), f"Signal {sig} detected.\n".encode("utf-8"))
-    stop_test = True
-    delay_event.set()
-
-
-def run_coins_loop(cls):
-    while not stop_test:
-        try:
-            nmcRpc("generatetoaddress 1 {}".format(cls.nmc_addr))
-            btcRpc("generatetoaddress 1 {}".format(cls.btc_addr))
-        except Exception as e:
-            logging.warning("run_coins_loop " + str(e))
-        time.sleep(1.0)
-
-
-def run_loop(self):
-    while not stop_test:
-        for c in self.swap_clients:
-            c.update()
-        time.sleep(1)
-
-
-def make_part_cli_rpc_func(node_id):
-    node_id = node_id
-
-    def rpc_func(method, params=None, wallet=None):
-        cmd = method
-        if params:
-            for p in params:
-                cmd += ' "' + p + '"'
-        return partRpc(cmd, node_id)
-
-    return rpc_func
-
-
-class Test(unittest.TestCase):
+    def mineBlock(self, num_blocks: int = 1) -> None:
+        self.callnoderpc("generatetoaddress", [num_blocks, self.nmc_addr])
 
     @classmethod
-    def setUpClass(cls):
-        super(Test, cls).setUpClass()
+    def tearDownClass(cls):
+        logging.info("Finalising Namecoin Test")
+        stopDaemons(cls.nmc_daemons)
+        cls.nmc_daemons.clear()
 
-        eckey = ECKey()
-        eckey.generate()
-        cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST, eckey.get_bytes())
-        cls.network_pubkey = eckey.get_pubkey().get_bytes().hex()
+        super(TestNMC, cls).tearDownClass()
 
-        if os.path.isdir(cfg.TEST_DATADIRS):
-            logging.info("Removing " + cfg.TEST_DATADIRS)
-            shutil.rmtree(cfg.TEST_DATADIRS)
+    @classmethod
+    def coins_loop(cls):
+        super(TestNMC, cls).coins_loop()
+        ci0 = cls.swap_clients[0].ci(cls.test_coin)
+        try:
+            if cls.nmc_addr is not None:
+                ci0.rpc_wallet("generatetoaddress", [1, cls.nmc_addr])
+        except Exception as e:
+            logging.warning(f"coins_loop generate {e}")
 
-        for i in range(NUM_NODES):
-            prepareDir(cfg.TEST_DATADIRS, i, cls.network_key, cls.network_pubkey)
+    @classmethod
+    def prepareExtraDataDir(cls, i: int) -> None:
+        if not cls.restore_instance:
+            prepareNMCDataDir(cfg.TEST_DATADIRS, i)
 
-        prepareOtherDir(cfg.TEST_DATADIRS, NMC_NODE)
-        prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, "bitcoin.conf")
-
-        cls.daemons = []
-        cls.swap_clients = []
-        cls.http_threads = []
-
-        btc_data_dir = os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE))
-        if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")):
-            callrpc_cli(
-                cfg.BITCOIN_BINDIR,
-                btc_data_dir,
-                "regtest",
-                "-wallet=wallet.dat -legacy create",
-                "bitcoin-wallet",
-            )
-        cls.daemons.append(startDaemon(btc_data_dir, cfg.BITCOIN_BINDIR, cfg.BITCOIND))
-        logging.info("Started %s %d", cfg.BITCOIND, cls.daemons[-1].handle.pid)
-        cls.daemons.append(
+        cls.nmc_daemons.append(
             startDaemon(
-                os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)),
+                os.path.join(cfg.TEST_DATADIRS, "nmc_" + str(i)),
                 NAMECOIN_BINDIR,
                 NAMECOIND,
             )
         )
-        logging.info("Started %s %d", NAMECOIND, cls.daemons[-1].handle.pid)
-        nmcRpc2 = make_rpc_func(NMC_NODE, base_rpc_port=NMC_BASE_RPC_PORT)
-        waitForRPC(nmcRpc2, delay_event, rpc_command="getblockchaininfo")
-        if len(nmcRpc2("listwallets")) < 1:
-            nmcRpc2("createwallet", ["wallet.dat", False, False, "", False, False])
+        logging.info("Started {} {}".format(NAMECOIND, cls.nmc_daemons[-1].handle.pid))
 
-        for i in range(NUM_NODES):
-            data_dir = os.path.join(cfg.TEST_DATADIRS, str(i))
-            if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, "particl-wallet")):
-                callrpc_cli(
-                    cfg.PARTICL_BINDIR,
-                    data_dir,
-                    "regtest",
-                    "-wallet=wallet.dat -legacy create",
-                    "particl-wallet",
-                )
-            cls.daemons.append(startDaemon(data_dir, cfg.PARTICL_BINDIR, cfg.PARTICLD))
-            logging.info("Started %s %d", cfg.PARTICLD, cls.daemons[-1].handle.pid)
-
-        for i in range(NUM_NODES):
-            rpc = make_part_cli_rpc_func(i)
-            waitForRPC(rpc, delay_event)
-            if i == 0:
-                rpc(
-                    "extkeyimportmaster",
-                    [
-                        "abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb"
-                    ],
-                )
-            elif i == 1:
-                rpc(
-                    "extkeyimportmaster",
-                    [
-                        "pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic",
-                        "",
-                        "true",
-                    ],
-                )
-                rpc("getnewextaddress", ["lblExtTest"])
-                rpc("rescanblockchain")
-            else:
-                rpc("extkeyimportmaster", [rpc("mnemonic", ["new"])["master"]])
-            rpc(
-                "walletsettings",
-                [
-                    "stakingoptions",
-                    json.dumps(
-                        {"stakecombinethreshold": 100, "stakesplitthreshold": 200}
-                    ).replace('"', '\\"'),
-                ],
+        nmc_rpc = make_rpc_func(i, base_rpc_port=NMC_BASE_RPC_PORT)
+        waitForRPC(
+            nmc_rpc,
+            test_delay_event,
+            rpc_command="getnetworkinfo",
+            max_tries=12,
+        )
+        waitForRPC(nmc_rpc, test_delay_event, rpc_command="getblockchaininfo")
+        if len(nmc_rpc("listwallets")) < 1:
+            nmc_rpc(
+                "createwallet",
+                ["wallet.dat", False, False, "", False, USE_DESCRIPTOR_WALLETS],
             )
-            rpc("reservebalance", ["false"])
-
-            basicswap_dir = os.path.join(
-                os.path.join(cfg.TEST_DATADIRS, str(i)), "basicswap"
-            )
-            settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
-            with open(settings_path) as fs:
-                settings = json.load(fs)
-            sc = BasicSwap(
-                basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i)
-            )
-            cls.swap_clients.append(sc)
-
-            sc.setDaemonPID(Coins.BTC, cls.daemons[0].handle.pid)
-            sc.setDaemonPID(Coins.NMC, cls.daemons[1].handle.pid)
-            sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].handle.pid)
-            sc.start()
-
-            t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
-            cls.http_threads.append(t)
-            t.start()
-
-        num_blocks = 500
-        logging.info("Mining %d namecoin blocks", num_blocks)
-        cls.nmc_addr = nmcRpc("getnewaddress mining_addr bech32")
-        nmcRpc("generatetoaddress {} {}".format(num_blocks, cls.nmc_addr))
-
-        ro = nmcRpc("getblockchaininfo")
-        try:
-            assert ro["bip9_softforks"]["csv"]["status"] == "active"
-        except Exception:
-            logging.info("nmc: csv is not active")
-        try:
-            assert ro["bip9_softforks"]["segwit"]["status"] == "active"
-        except Exception:
-            logging.info("nmc: segwit is not active")
-
-        waitForRPC(btcRpc, delay_event)
-        cls.btc_addr = btcRpc("getnewaddress mining_addr bech32")
-        logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr)
-        btcRpc("generatetoaddress {} {}".format(num_blocks, cls.btc_addr))
-
-        ro = btcRpc("getblockchaininfo")
-        checkForks(ro)
-
-        ro = nmcRpc("getwalletinfo")
-        print("nmcRpc", ro)
-
-        signal.signal(signal.SIGINT, signal_handler)
-        cls.update_thread = threading.Thread(target=run_loop, args=(cls,))
-        cls.update_thread.start()
-
-        cls.coins_update_thread = threading.Thread(target=run_coins_loop, args=(cls,))
-        cls.coins_update_thread.start()
-
-        # Wait for height, or sequencelock is thrown off by genesis blocktime
-        num_blocks = 3
-        logging.info("Waiting for Particl chain height %d", num_blocks)
-        for i in range(60):
-            particl_blocks = cls.swap_clients[0].callrpc("getblockcount")
-            print("particl_blocks", particl_blocks)
-            if particl_blocks >= num_blocks:
-                break
-            delay_event.wait(1)
-        assert particl_blocks >= num_blocks
 
     @classmethod
-    def tearDownClass(cls):
-        global stop_test
-        logging.info("Finalising")
-        stop_test = True
-        cls.update_thread.join()
-        cls.coins_update_thread.join()
-        for t in cls.http_threads:
-            t.stop()
-            t.join()
-        for c in cls.swap_clients:
-            c.finalise()
+    def addPIDInfo(cls, sc, i):
+        sc.setDaemonPID(Coins.DCR, cls.nmc_daemons[i].handle.pid)
 
-        stopDaemons(cls.daemons)
-        cls.http_threads.clear()
-        cls.swap_clients.clear()
-        cls.daemons.clear()
+    @classmethod
+    def addCoinSettings(cls, settings, datadir, node_id):
+        settings["chainclients"]["namecoin"] = {
+            "connection_type": "rpc",
+            "manage_daemon": False,
+            "rpcport": NMC_BASE_RPC_PORT + node_id,
+            "rpcuser": "test" + str(node_id),
+            "rpcpassword": "test_pass" + str(node_id),
+            "datadir": os.path.join(datadir, "nmc_" + str(node_id)),
+            "bindir": NAMECOIN_BINDIR,
+            "use_csv": True,
+            "use_segwit": True,
+            "blocks_confirmed": 1,
+        }
 
-        super(Test, cls).tearDownClass()
-
-    def test_02_part_nmc(self):
-        logging.info("---------- Test PART to NMC")
-        swap_clients = self.swap_clients
-
-        offer_id = swap_clients[0].postOffer(
-            Coins.PART,
-            Coins.NMC,
-            100 * COIN,
-            0.1 * COIN,
-            100 * COIN,
-            SwapTypes.SELLER_FIRST
-        )
-
-        wait_for_offer(delay_event, swap_clients[1], offer_id)
-        offer = swap_clients[1].getOffer(offer_id)
-        bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
-
-        wait_for_bid(delay_event, swap_clients[0], bid_id)
-
-        swap_clients[0].acceptBid(bid_id)
-
-        wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True)
-
-        wait_for_bid(
-            delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
-        )
-        wait_for_bid(
-            delay_event,
-            swap_clients[1],
-            bid_id,
-            BidStates.SWAP_COMPLETED,
-            sent=True,
-            wait_for=60,
-        )
-
-        js_0 = read_json_api(1800)
-        js_1 = read_json_api(1801)
-        assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
-        assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
-
-    def test_03_nmc_part(self):
-        logging.info("---------- Test NMC to PART")
-        swap_clients = self.swap_clients
-
-        offer_id = swap_clients[1].postOffer(
-            Coins.NMC,
-            Coins.PART,
-            10 * COIN,
-            9.0 * COIN,
-            10 * COIN,
-            SwapTypes.SELLER_FIRST
-        )
-
-        wait_for_offer(delay_event, swap_clients[0], offer_id)
-        offer = swap_clients[0].getOffer(offer_id)
-        bid_id = swap_clients[0].postBid(offer_id, offer.amount_from)
-
-        wait_for_bid(delay_event, swap_clients[1], bid_id)
-        swap_clients[1].acceptBid(bid_id)
-
-        wait_for_in_progress(delay_event, swap_clients[0], bid_id, sent=True)
-
-        wait_for_bid(
-            delay_event,
-            swap_clients[0],
-            bid_id,
-            BidStates.SWAP_COMPLETED,
-            sent=True,
-            wait_for=60,
-        )
-        wait_for_bid(
-            delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
-        )
-
-        js_0 = read_json_api(1800)
-        js_1 = read_json_api(1801)
-        assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
-        assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
-
-    def test_04_nmc_btc(self):
-        logging.info("---------- Test NMC to BTC")
-        swap_clients = self.swap_clients
-
-        offer_id = swap_clients[0].postOffer(
-            Coins.NMC,
-            Coins.BTC,
-            10 * COIN,
-            0.1 * COIN,
-            10 * COIN,
-            SwapTypes.SELLER_FIRST
-        )
-
-        wait_for_offer(delay_event, swap_clients[1], offer_id)
-        offer = swap_clients[1].getOffer(offer_id)
-        bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
-
-        wait_for_bid(delay_event, swap_clients[0], bid_id)
-        swap_clients[0].acceptBid(bid_id)
-
-        wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True)
-
-        wait_for_bid(
-            delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
-        )
-        wait_for_bid(
-            delay_event,
-            swap_clients[1],
-            bid_id,
-            BidStates.SWAP_COMPLETED,
-            sent=True,
-            wait_for=60,
-        )
-
-        js_0 = read_json_api(1800)
-        js_1 = read_json_api(1801)
-
-        assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
-        assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
-
-    def test_05_refund(self):
-        # Seller submits initiate txn, buyer doesn't respond
-        logging.info("---------- Test refund, NMC to BTC")
-        swap_clients = self.swap_clients
-
-        offer_id = swap_clients[0].postOffer(
-            Coins.NMC,
-            Coins.BTC,
-            10 * COIN,
-            0.1 * COIN,
-            10 * COIN,
-            SwapTypes.SELLER_FIRST,
-            TxLockTypes.SEQUENCE_LOCK_BLOCKS,
-            10,
-        )
-
-        wait_for_offer(delay_event, swap_clients[1], offer_id)
-        offer = swap_clients[1].getOffer(offer_id)
-        bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
-
-        wait_for_bid(delay_event, swap_clients[0], bid_id)
-        swap_clients[1].abandonBid(bid_id)
-        swap_clients[0].acceptBid(bid_id)
-
-        wait_for_bid(
-            delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
-        )
-        wait_for_bid(
-            delay_event,
-            swap_clients[1],
-            bid_id,
-            BidStates.BID_ABANDONED,
-            sent=True,
-            wait_for=60,
-        )
-
-        js_0 = read_json_api(1800)
-        js_1 = read_json_api(1801)
-        assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
-        assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
-
-    def test_06_self_bid(self):
-        logging.info("---------- Test same client, BTC to NMC")
-        swap_clients = self.swap_clients
-
-        js_0_before = read_json_api(1800)
-
-        offer_id = swap_clients[0].postOffer(
-            Coins.NMC,
-            Coins.BTC,
-            10 * COIN,
-            10 * COIN,
-            10 * COIN,
-            SwapTypes.SELLER_FIRST
-        )
-
-        wait_for_offer(delay_event, swap_clients[0], offer_id)
-        offer = swap_clients[0].getOffer(offer_id)
-        bid_id = swap_clients[0].postBid(offer_id, offer.amount_from)
-
-        wait_for_bid(delay_event, swap_clients[0], bid_id)
-        swap_clients[0].acceptBid(bid_id)
-
-        wait_for_bid_tx_state(
-            delay_event,
-            swap_clients[0],
-            bid_id,
-            TxStates.TX_REDEEMED,
-            TxStates.TX_REDEEMED,
-            wait_for=60,
-        )
-        wait_for_bid(
-            delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
-        )
-
-        js_0 = read_json_api(1800)
-        assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
-        assert (
-            js_0["num_recv_bids"] == js_0_before["num_recv_bids"] + 1
-            and js_0["num_sent_bids"] == js_0_before["num_sent_bids"] + 1
-        )
-
-    def test_07_error(self):
-        logging.info("---------- Test error, BTC to NMC, set fee above bid value")
-        swap_clients = self.swap_clients
-
-        offer_id = swap_clients[0].postOffer(
-            Coins.NMC,
-            Coins.BTC,
-            0.01 * COIN,
-            1.0 * COIN,
-            0.01 * COIN,
-            SwapTypes.SELLER_FIRST
-        )
-
-        wait_for_offer(delay_event, swap_clients[0], offer_id)
-        offer = swap_clients[0].getOffer(offer_id)
-        bid_id = swap_clients[0].postBid(offer_id, offer.amount_from)
-
-        wait_for_bid(delay_event, swap_clients[0], bid_id)
-        swap_clients[0].acceptBid(bid_id)
-        try:
-            swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] = 100.0
-            swap_clients[0].getChainClientSettings(Coins.NMC)["override_feerate"] = 100.0
-            wait_for_bid(
-                delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60
+    @classmethod
+    def prepareExtraCoins(cls):
+        ci0 = cls.swap_clients[0].ci(cls.test_coin)
+        if not cls.restore_instance:
+            cls.nmc_addr = ci0.rpc_wallet("getnewaddress", ["mining_addr", "bech32"])
+        else:
+            addrs = ci0.rpc_wallet(
+                "getaddressesbylabel",
+                [
+                    "mining_addr",
+                ],
             )
-            swap_clients[0].abandonBid(bid_id)
-        finally:
-            del swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"]
-            del swap_clients[0].getChainClientSettings(Coins.NMC)["override_feerate"]
+            cls.nmc_addr = addrs.keys()[0]
 
-    def pass_99_delay(self):
-        global stop_test
-        logging.info("Delay")
-        for i in range(60 * 5):
-            if stop_test:
-                break
-            time.sleep(1)
-            print("delay", i)
-        stop_test = True
+        num_blocks: int = 500
+        if ci0.rpc("getblockcount") < num_blocks:
+            logging.info(f"Mining {num_blocks} Namecoin blocks to {cls.nmc_addr}")
+            ci0.rpc("generatetoaddress", [num_blocks, cls.nmc_addr])
+        logging.info("NMC blocks: {}".format(ci0.rpc("getblockcount")))
+
+    def test_007_hdwallet(self):
+        logging.info("---------- Test {} hdwallet".format(self.test_coin_from.name))
+
+        test_seed = "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b"
+        test_wif = (
+            self.swap_clients[0]
+            .ci(self.test_coin_from)
+            .encodeKey(bytes.fromhex(test_seed))
+        )
+        new_wallet_name = random.randbytes(10).hex()
+        self.callnoderpc(
+            "createwallet",
+            [new_wallet_name, False, False, "", False, USE_DESCRIPTOR_WALLETS],
+        )
+        self.callnoderpc("sethdseed", [True, test_wif], wallet=new_wallet_name)
+        addr = self.callnoderpc(
+            "getnewaddress", ["add test", "bech32"], wallet=new_wallet_name
+        )
+        self.callnoderpc("unloadwallet", [new_wallet_name])
+        assert addr == "ncrt1qps7hnjd866e9ynxadgseprkc2l56m00dxkl7pk"
+
+    def test_012_p2sh_p2wsh(self):
+        # Fee rate
+        pass
+
+    def test_02_sh_part_coin(self):
+        self.prepare_balance(self.test_coin, 200.0, 1801, 1800)
+        run_test_success_path(self, Coins.PART, self.test_coin)
+
+    def test_03_sh_coin_part(self):
+        run_test_success_path(self, self.test_coin, Coins.PART)
+
+    def test_04_sh_part_coin_bad_ptx(self):
+        self.prepare_balance(self.test_coin, 200.0, 1801, 1800)
+        run_test_bad_ptx(self, Coins.PART, self.test_coin)
+
+    def test_05_sh_coin_part_bad_ptx(self):
+        self.prepare_balance(self.test_coin, 200.0, 1801, 1800)
+        run_test_bad_ptx(self, self.test_coin, Coins.PART)
+
+    def test_06_sh_part_coin_itx_refund(self):
+        run_test_itx_refund(self, Coins.PART, self.test_coin)
+
+    def test_07_sh_coin_part_itx_refund(self):
+        self.prepare_balance(self.test_coin, 200.0, 1801, 1800)
+        run_test_itx_refund(self, self.test_coin, Coins.PART)
+
+    def test_01_b_full_swap_reverse(self):
+        self.prepare_balance(self.test_coin, 100.0, 1801, 1800)
+        self.do_test_01_full_swap(Coins.XMR, self.test_coin_from)
 
 
 if __name__ == "__main__":
diff --git a/tests/basicswap/test_btc_xmr.py b/tests/basicswap/test_btc_xmr.py
index 866fbed..32d2082 100644
--- a/tests/basicswap/test_btc_xmr.py
+++ b/tests/basicswap/test_btc_xmr.py
@@ -59,7 +59,6 @@ from basicswap.contrib.test_framework.script import (
 from .test_xmr import BaseTest, test_delay_event, callnoderpc
 
 logger = logging.getLogger()
-
 test_seed = "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b"
 
 
@@ -666,7 +665,7 @@ class TestFunctions(BaseTest):
         balance_from_before: float = self.getBalance(jsw, coin_from)
         self.prepare_balance(
             coin_to,
-            balance_from_before + 1,
+            balance_from_before * 3,
             1800 + id_bidder,
             1801 if coin_to in (Coins.XMR,) else 1800,
         )
@@ -718,6 +717,7 @@ class TestFunctions(BaseTest):
             assert False, "Should fail"
 
         amt_swap -= ci_from.make_int(1)
+        rate_swap = ci_to.make_int(1.0, r=1)
         offer_id = swap_clients[id_offerer].postOffer(
             coin_from,
             coin_to,
@@ -770,6 +770,8 @@ class TestFunctions(BaseTest):
 
 class BasicSwapTest(TestFunctions):
 
+    test_fee_rate: int = 1000  # sats/kvB
+
     @classmethod
     def setUpClass(cls):
         super(BasicSwapTest, cls).setUpClass()
@@ -1236,12 +1238,7 @@ class BasicSwapTest(TestFunctions):
         swap_client = self.swap_clients[0]
         ci = swap_client.ci(self.test_coin_from)
 
-        addr_1 = ci.rpc_wallet(
-            "getnewaddress",
-            [
-                "gettxout test 1",
-            ],
-        )
+        addr_1 = ci.getNewAddress(True, "gettxout test 1")
         txid = ci.rpc_wallet("sendtoaddress", [addr_1, 1.0])
         assert len(txid) == 64
 
@@ -1266,12 +1263,7 @@ class BasicSwapTest(TestFunctions):
         else:
             assert addr_1 in txout["scriptPubKey"]["addresses"]
         # Spend
-        addr_2 = ci.rpc_wallet(
-            "getnewaddress",
-            [
-                "gettxout test 2",
-            ],
-        )
+        addr_2 = ci.getNewAddress(True, "gettxout test 2")
         tx_funded = ci.rpc(
             "createrawtransaction",
             [[{"txid": utxo["txid"], "vout": utxo["vout"]}], {addr_2: 0.99}],
@@ -1297,12 +1289,7 @@ class BasicSwapTest(TestFunctions):
         logging.info("---------- Test {} scantxoutset".format(self.test_coin_from.name))
         ci = self.swap_clients[0].ci(self.test_coin_from)
 
-        addr_1 = ci.rpc_wallet(
-            "getnewaddress",
-            [
-                "scantxoutset test",
-            ],
-        )
+        addr_1 = ci.getNewAddress(True, "scantxoutset test")
         txid = ci.rpc_wallet("sendtoaddress", [addr_1, 1.0])
         assert len(txid) == 64
 
@@ -1324,9 +1311,6 @@ class BasicSwapTest(TestFunctions):
         # Record unspents before createSCLockTx as the used ones will be locked
         unspents = ci.rpc_wallet("listunspent")
 
-        # fee_rate is in sats/kvB
-        fee_rate: int = 1000
-
         a = ci.getNewRandomKey()
         b = ci.getNewRandomKey()
 
@@ -1335,7 +1319,7 @@ class BasicSwapTest(TestFunctions):
         lock_tx_script = pi.genScriptLockTxScript(ci, A, B)
 
         lock_tx = ci.createSCLockTx(amount, lock_tx_script)
-        lock_tx = ci.fundSCLockTx(lock_tx, fee_rate)
+        lock_tx = ci.fundSCLockTx(lock_tx, self.test_fee_rate)
         lock_tx = ci.signTxWithWallet(lock_tx)
 
         unspents_after = ci.rpc_wallet("listunspent")
@@ -1345,7 +1329,7 @@ class BasicSwapTest(TestFunctions):
         txid = tx_decoded["txid"]
 
         vsize = tx_decoded["vsize"]
-        expect_fee_int = round(fee_rate * vsize / 1000)
+        expect_fee_int = round(self.test_fee_rate * vsize / 1000)
 
         out_value: int = 0
         for txo in tx_decoded["vout"]:
@@ -1372,7 +1356,7 @@ class BasicSwapTest(TestFunctions):
         pkh_out = ci.decodeAddress(addr_out)
         fee_info = {}
         lock_spend_tx = ci.createSCLockSpendTx(
-            lock_tx, lock_tx_script, pkh_out, fee_rate, fee_info=fee_info
+            lock_tx, lock_tx_script, pkh_out, self.test_fee_rate, fee_info=fee_info
         )
         vsize_estimated: int = fee_info["vsize"]
 
@@ -1400,11 +1384,11 @@ class BasicSwapTest(TestFunctions):
         v = ci.getNewRandomKey()
         s = ci.getNewRandomKey()
         S = ci.getPubkey(s)
-        lock_tx_b_txid = ci.publishBLockTx(v, S, amount, fee_rate)
+        lock_tx_b_txid = ci.publishBLockTx(v, S, amount, self.test_fee_rate)
 
         addr_out = ci.getNewAddress(True)
         lock_tx_b_spend_txid = ci.spendBLockTx(
-            lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0
+            lock_tx_b_txid, addr_out, v, s, amount, self.test_fee_rate, 0
         )
         lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid)
         if lock_tx_b_spend is None:
@@ -1635,7 +1619,9 @@ class BasicSwapTest(TestFunctions):
             wallet=new_wallet_name,
         )
 
-        addr = self.callnoderpc("getnewaddress", wallet=new_wallet_name)
+        addr = self.callnoderpc(
+            "getnewaddress", ["test descriptors"], wallet=new_wallet_name
+        )
         addr_info = self.callnoderpc(
             "getaddressinfo",
             [
@@ -1645,7 +1631,8 @@ class BasicSwapTest(TestFunctions):
         )
         assert addr_info["hdmasterfingerprint"] == "a55b7ea9"
         assert addr_info["hdkeypath"] == "m/0h/0h/0h"
-        assert addr == "bcrt1qps7hnjd866e9ynxadgseprkc2l56m00dvwargr"
+        if self.test_coin_from == Coins.BTC:
+            assert addr == "bcrt1qps7hnjd866e9ynxadgseprkc2l56m00dvwargr"
 
         addr_change = self.callnoderpc("getrawchangeaddress", wallet=new_wallet_name)
         addr_info = self.callnoderpc(
@@ -1657,7 +1644,8 @@ class BasicSwapTest(TestFunctions):
         )
         assert addr_info["hdmasterfingerprint"] == "a55b7ea9"
         assert addr_info["hdkeypath"] == "m/0h/1h/0h"
-        assert addr_change == "bcrt1qdl9ryxkqjltv42lhfnqgdjf9tagxsjpp2xak9a"
+        if self.test_coin_from == Coins.BTC:
+            assert addr_change == "bcrt1qdl9ryxkqjltv42lhfnqgdjf9tagxsjpp2xak9a"
 
         desc_watch = descsum_create(f"addr({addr})")
         self.callnoderpc(
@@ -1683,7 +1671,13 @@ class BasicSwapTest(TestFunctions):
 
         # Test that addresses can be generated beyond range in listdescriptors
         for i in range(2000):
-            self.callnoderpc("getnewaddress", wallet=new_wallet_name)
+            self.callnoderpc(
+                "getnewaddress",
+                [
+                    f"t{i}",
+                ],
+                wallet=new_wallet_name,
+            )
 
         self.callnoderpc("unloadwallet", [new_wallet_name])
         self.callnoderpc("unloadwallet", [new_watch_wallet_name])