mirror of
https://github.com/basicswap/basicswap.git
synced 2026-06-08 04:01:41 +02:00
feat: automatically verify feerate
This commit is contained in:
@@ -4126,6 +4126,9 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
|||||||
msg_buf.fee_rate_to = ci_to.make_int(fee_rate)
|
msg_buf.fee_rate_to = ci_to.make_int(fee_rate)
|
||||||
|
|
||||||
if swap_type == SwapTypes.XMR_SWAP:
|
if swap_type == SwapTypes.XMR_SWAP:
|
||||||
|
ci_from.validateFeeRate(msg_buf.fee_rate_from)
|
||||||
|
ci_to.validateFeeRate(msg_buf.fee_rate_to)
|
||||||
|
|
||||||
xmr_offer = XmrOffer()
|
xmr_offer = XmrOffer()
|
||||||
|
|
||||||
chain_a_ci = ci_to if reverse_bid else ci_from
|
chain_a_ci = ci_to if reverse_bid else ci_from
|
||||||
@@ -6028,6 +6031,9 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
|||||||
if offer.swap_type != SwapTypes.XMR_SWAP:
|
if offer.swap_type != SwapTypes.XMR_SWAP:
|
||||||
raise ValueError(f"TODO: Unknown swap type {offer.swap_type.name}")
|
raise ValueError(f"TODO: Unknown swap type {offer.swap_type.name}")
|
||||||
|
|
||||||
|
ci_from.validateFeeRate(xmr_offer.a_fee_rate)
|
||||||
|
ci_to.validateFeeRate(xmr_offer.b_fee_rate)
|
||||||
|
|
||||||
if not (self.debug and extra_options.get("debug_skip_validation", False)):
|
if not (self.debug and extra_options.get("debug_skip_validation", False)):
|
||||||
self.validateBidValidTime(
|
self.validateBidValidTime(
|
||||||
offer.swap_type, coin_from, coin_to, valid_for_seconds
|
offer.swap_type, coin_from, coin_to, valid_for_seconds
|
||||||
@@ -10033,6 +10039,10 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
|||||||
ensure(len(offer_data.proof_signature) == 0, "Unexpected data")
|
ensure(len(offer_data.proof_signature) == 0, "Unexpected data")
|
||||||
ensure(len(offer_data.pkhash_seller) == 0, "Unexpected data")
|
ensure(len(offer_data.pkhash_seller) == 0, "Unexpected data")
|
||||||
ensure(len(offer_data.secret_hash) == 0, "Unexpected data")
|
ensure(len(offer_data.secret_hash) == 0, "Unexpected data")
|
||||||
|
|
||||||
|
ci_from.validateFeeRate(offer_data.fee_rate_from)
|
||||||
|
ci_to.validateFeeRate(offer_data.fee_rate_to)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unknown swap type {}.".format(offer_data.swap_type))
|
raise ValueError("Unknown swap type {}.".format(offer_data.swap_type))
|
||||||
|
|
||||||
@@ -10058,6 +10068,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp):
|
|||||||
# Check for sent
|
# Check for sent
|
||||||
existing_offer = self.getOffer(offer_id, cursor=cursor)
|
existing_offer = self.getOffer(offer_id, cursor=cursor)
|
||||||
if existing_offer is None:
|
if existing_offer is None:
|
||||||
|
|
||||||
bid_reversed: bool = (
|
bid_reversed: bool = (
|
||||||
offer_data.swap_type == SwapTypes.XMR_SWAP
|
offer_data.swap_type == SwapTypes.XMR_SWAP
|
||||||
and self.is_reverse_ads_bid(
|
and self.is_reverse_ads_bid(
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class CoinInterface:
|
|||||||
def compareFeeRates(a, b) -> bool:
|
def compareFeeRates(a, b) -> bool:
|
||||||
return abs(a - b) < 20
|
return abs(a - b) < 20
|
||||||
|
|
||||||
def __init__(self, network):
|
def __init__(self, network, **kwargs):
|
||||||
self.setDefaults()
|
self.setDefaults()
|
||||||
self._network = network
|
self._network = network
|
||||||
self._mx_wallet = threading.Lock()
|
self._mx_wallet = threading.Lock()
|
||||||
@@ -195,6 +195,9 @@ class AdaptorSigInterface:
|
|||||||
|
|
||||||
|
|
||||||
class Secp256k1Interface(CoinInterface, AdaptorSigInterface):
|
class Secp256k1Interface(CoinInterface, AdaptorSigInterface):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def curve_type():
|
def curve_type():
|
||||||
return Curves.secp256k1
|
return Curves.secp256k1
|
||||||
|
|||||||
@@ -71,8 +71,13 @@ class BCHInterface(BTCInterface):
|
|||||||
# TODO: BCH Watchonly: Remove when BCH watchonly works.
|
# TODO: BCH Watchonly: Remove when BCH watchonly works.
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super(BCHInterface, self).__init__(coin_settings, network, swap_client)
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
self.swap_client = swap_client
|
self.swap_client = swap_client
|
||||||
|
|
||||||
def has_segwit(self) -> bool:
|
def has_segwit(self) -> bool:
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ from basicswap.basicswap_util import (
|
|||||||
getVoutByScriptPubKey,
|
getVoutByScriptPubKey,
|
||||||
)
|
)
|
||||||
from basicswap.interface.base import Secp256k1Interface
|
from basicswap.interface.base import Secp256k1Interface
|
||||||
|
from basicswap.interface.utils import FeeValidator
|
||||||
from basicswap.util import (
|
from basicswap.util import (
|
||||||
b2i,
|
b2i,
|
||||||
ensure,
|
ensure,
|
||||||
@@ -184,7 +185,7 @@ def extractScriptLockRefundScriptValues(script_bytes: bytes):
|
|||||||
return pk1, pk2, csv_val, pk3
|
return pk1, pk2, csv_val, pk3
|
||||||
|
|
||||||
|
|
||||||
class BTCInterface(Secp256k1Interface):
|
class BTCInterface(FeeValidator, Secp256k1Interface):
|
||||||
_scantxoutset_lock = threading.Lock()
|
_scantxoutset_lock = threading.Lock()
|
||||||
_MAX_SCANTXOUTSET_RETRIES = 3
|
_MAX_SCANTXOUTSET_RETRIES = 3
|
||||||
|
|
||||||
@@ -278,8 +279,15 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
def depth_spendable() -> int:
|
def depth_spendable() -> int:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super().__init__(network)
|
self._sc = swap_client
|
||||||
|
self._log = self._sc.log if self._sc and self._sc.log else logging
|
||||||
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
self._rpc_host = coin_settings.get("rpchost", "127.0.0.1")
|
self._rpc_host = coin_settings.get("rpchost", "127.0.0.1")
|
||||||
self._rpcport = coin_settings["rpcport"]
|
self._rpcport = coin_settings["rpcport"]
|
||||||
self._rpcauth = coin_settings["rpcauth"]
|
self._rpcauth = coin_settings["rpcauth"]
|
||||||
@@ -304,8 +312,6 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
self.setConfTarget(coin_settings["conf_target"])
|
self.setConfTarget(coin_settings["conf_target"])
|
||||||
self._use_segwit = coin_settings["use_segwit"]
|
self._use_segwit = coin_settings["use_segwit"]
|
||||||
self._connection_type = coin_settings["connection_type"]
|
self._connection_type = coin_settings["connection_type"]
|
||||||
self._sc = swap_client
|
|
||||||
self._log = self._sc.log if self._sc and self._sc.log else logging
|
|
||||||
self._expect_seedid_hex = None
|
self._expect_seedid_hex = None
|
||||||
self._altruistic = coin_settings.get("altruistic", True)
|
self._altruistic = coin_settings.get("altruistic", True)
|
||||||
self._use_descriptors = coin_settings.get("use_descriptors", False)
|
self._use_descriptors = coin_settings.get("use_descriptors", False)
|
||||||
|
|||||||
@@ -24,8 +24,13 @@ class DASHInterface(BTCInterface):
|
|||||||
def coin_type():
|
def coin_type():
|
||||||
return Coins.DASH
|
return Coins.DASH
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super().__init__(coin_settings, network, swap_client)
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
self._wallet_passphrase = ""
|
self._wallet_passphrase = ""
|
||||||
self._have_checked_seed = False
|
self._have_checked_seed = False
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright (c) 2024 tecnovert
|
# Copyright (c) 2024 tecnovert
|
||||||
# Copyright (c) 2024-2025 The Basicswap developers
|
# Copyright (c) 2024-2026 The Basicswap developers
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@@ -20,9 +20,8 @@ from basicswap.chainparams import Coins
|
|||||||
from basicswap.contrib.test_framework.script import (
|
from basicswap.contrib.test_framework.script import (
|
||||||
CScriptNum,
|
CScriptNum,
|
||||||
)
|
)
|
||||||
from basicswap.interface.base import (
|
from basicswap.interface.base import Secp256k1Interface
|
||||||
Secp256k1Interface,
|
from basicswap.interface.utils import FeeValidator
|
||||||
)
|
|
||||||
from basicswap.interface.btc import (
|
from basicswap.interface.btc import (
|
||||||
extractScriptLockScriptValues,
|
extractScriptLockScriptValues,
|
||||||
extractScriptLockRefundScriptValues,
|
extractScriptLockRefundScriptValues,
|
||||||
@@ -181,7 +180,7 @@ def extract_sig_and_pk(sig_script: bytes) -> (bytes, bytes):
|
|||||||
return sig, pk
|
return sig, pk
|
||||||
|
|
||||||
|
|
||||||
class DCRInterface(Secp256k1Interface):
|
class DCRInterface(FeeValidator, Secp256k1Interface):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def coin_type():
|
def coin_type():
|
||||||
@@ -258,13 +257,13 @@ class DCRInterface(Secp256k1Interface):
|
|||||||
def depth_spendable() -> int:
|
def depth_spendable() -> int:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super().__init__(network)
|
self._sc = swap_client
|
||||||
|
self._log = self._sc.log if self._sc and self._sc.log else logging
|
||||||
|
super().__init__(coin_settings=coin_settings, network=network, **kwargs)
|
||||||
self._rpc_host = coin_settings.get("rpchost", "127.0.0.1")
|
self._rpc_host = coin_settings.get("rpchost", "127.0.0.1")
|
||||||
self._rpcport = coin_settings["rpcport"]
|
self._rpcport = coin_settings["rpcport"]
|
||||||
self._rpcauth = coin_settings["rpcauth"]
|
self._rpcauth = coin_settings["rpcauth"]
|
||||||
self._sc = swap_client
|
|
||||||
self._log = self._sc.log if self._sc and self._sc.log else logging
|
|
||||||
self.rpc = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
|
self.rpc = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
|
||||||
if "walletrpcport" in coin_settings:
|
if "walletrpcport" in coin_settings:
|
||||||
self._walletrpcport = coin_settings["walletrpcport"]
|
self._walletrpcport = coin_settings["walletrpcport"]
|
||||||
|
|||||||
@@ -32,8 +32,13 @@ class DOGEInterface(BTCInterface):
|
|||||||
def xmr_swap_b_lock_spend_tx_vsize() -> int:
|
def xmr_swap_b_lock_spend_tx_vsize() -> int:
|
||||||
return 192
|
return 192
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super(DOGEInterface, self).__init__(coin_settings, network, swap_client)
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
def getScriptDest(self, script: bytearray) -> bytearray:
|
def getScriptDest(self, script: bytearray) -> bytearray:
|
||||||
# P2SH
|
# P2SH
|
||||||
|
|||||||
@@ -38,8 +38,13 @@ class FIROInterface(BTCInterface):
|
|||||||
def coin_type():
|
def coin_type():
|
||||||
return Coins.FIRO
|
return Coins.FIRO
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super(FIROInterface, self).__init__(coin_settings, network, swap_client)
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
# No multiwallet support
|
# No multiwallet support
|
||||||
self.rpc_wallet = make_rpc_func(
|
self.rpc_wallet = make_rpc_func(
|
||||||
self._rpcport, self._rpcauth, host=self._rpc_host
|
self._rpcport, self._rpcauth, host=self._rpc_host
|
||||||
|
|||||||
@@ -16,8 +16,13 @@ class LTCInterface(BTCInterface):
|
|||||||
def coin_type():
|
def coin_type():
|
||||||
return Coins.LTC
|
return Coins.LTC
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super(LTCInterface, self).__init__(coin_settings, network, swap_client)
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
self._rpc_wallet_mweb = coin_settings.get("mweb_wallet_name", "mweb")
|
self._rpc_wallet_mweb = coin_settings.get("mweb_wallet_name", "mweb")
|
||||||
self.rpc_wallet_mweb = make_rpc_func(
|
self.rpc_wallet_mweb = make_rpc_func(
|
||||||
self._rpcport,
|
self._rpcport,
|
||||||
@@ -265,8 +270,13 @@ class LTCInterfaceMWEB(LTCInterface):
|
|||||||
def interface_type(self) -> int:
|
def interface_type(self) -> int:
|
||||||
return Coins.LTC_MWEB
|
return Coins.LTC_MWEB
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super(LTCInterfaceMWEB, self).__init__(coin_settings, network, swap_client)
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
self._rpc_wallet = coin_settings.get("mweb_wallet_name", "mweb")
|
self._rpc_wallet = coin_settings.get("mweb_wallet_name", "mweb")
|
||||||
self.rpc_wallet = make_rpc_func(
|
self.rpc_wallet = make_rpc_func(
|
||||||
self._rpcport, self._rpcauth, host=self._rpc_host, wallet=self._rpc_wallet
|
self._rpcport, self._rpcauth, host=self._rpc_host, wallet=self._rpc_wallet
|
||||||
|
|||||||
@@ -73,8 +73,13 @@ class NAVInterface(BTCInterface):
|
|||||||
def txoType():
|
def txoType():
|
||||||
return CTxOut
|
return CTxOut
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super(NAVInterface, self).__init__(coin_settings, network, swap_client)
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
# No multiwallet support
|
# No multiwallet support
|
||||||
self.rpc_wallet = make_rpc_func(
|
self.rpc_wallet = make_rpc_func(
|
||||||
self._rpcport, self._rpcauth, host=self._rpc_host
|
self._rpcport, self._rpcauth, host=self._rpc_host
|
||||||
|
|||||||
@@ -81,8 +81,17 @@ class PARTInterface(BTCInterface):
|
|||||||
def txoType():
|
def txoType():
|
||||||
return CTxOutPart
|
return CTxOutPart
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
@staticmethod
|
||||||
super().__init__(coin_settings, network, swap_client)
|
def defaultMaxFeeRate() -> int:
|
||||||
|
return PARTInterface.COIN() // 2
|
||||||
|
|
||||||
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
self.setAnonTxRingSize(int(coin_settings.get("anon_tx_ring_size", 12)))
|
self.setAnonTxRingSize(int(coin_settings.get("anon_tx_ring_size", 12)))
|
||||||
|
|
||||||
def use_tx_vsize(self) -> bool:
|
def use_tx_vsize(self) -> bool:
|
||||||
|
|||||||
@@ -10,8 +10,13 @@ from basicswap.contrib.test_framework.messages import CTxOut
|
|||||||
|
|
||||||
|
|
||||||
class PassthroughBTCInterface(BTCInterface):
|
class PassthroughBTCInterface(BTCInterface):
|
||||||
def __init__(self, coin_settings, network):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super().__init__(coin_settings, network)
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
self.txoType = CTxOut
|
self.txoType = CTxOut
|
||||||
self._network = network
|
self._network = network
|
||||||
self.blocks_confirmed = coin_settings["blocks_confirmed"]
|
self.blocks_confirmed = coin_settings["blocks_confirmed"]
|
||||||
|
|||||||
@@ -27,8 +27,13 @@ class PIVXInterface(BTCInterface):
|
|||||||
def coin_type():
|
def coin_type():
|
||||||
return Coins.PIVX
|
return Coins.PIVX
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super(PIVXInterface, self).__init__(coin_settings, network, swap_client)
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
# No multiwallet support
|
# No multiwallet support
|
||||||
self.rpc_wallet = make_rpc_func(
|
self.rpc_wallet = make_rpc_func(
|
||||||
self._rpcport, self._rpcauth, host=self._rpc_host
|
self._rpcport, self._rpcauth, host=self._rpc_host
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2026 The Basicswap developers
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
from basicswap.contrib.test_framework.messages import COIN
|
||||||
|
|
||||||
|
|
||||||
|
class FeeValidator:
|
||||||
|
@staticmethod
|
||||||
|
def defaultMaxFeeRate() -> int:
|
||||||
|
return COIN // 10
|
||||||
|
|
||||||
|
def makeIntFromSetting(
|
||||||
|
self, settings: dict, setting_name: str, default: int
|
||||||
|
) -> int:
|
||||||
|
# Return make_int(setting), or already integer default
|
||||||
|
if setting_name in settings:
|
||||||
|
return self.make_int(settings[setting_name])
|
||||||
|
return default
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
default_low_fee_conf_target: int = 24
|
||||||
|
default_low_fee_rate: int = 0
|
||||||
|
default_high_estimated_feerate_multiplier: float = 2.0
|
||||||
|
default_high_fee_rate: int = self.defaultMaxFeeRate()
|
||||||
|
if self._sc:
|
||||||
|
chain_client_settings = self._sc.getChainClientSettings(
|
||||||
|
self.coin_type()
|
||||||
|
) # basicswap.json
|
||||||
|
settings = self._sc.settings
|
||||||
|
default_low_fee_conf_target = int(
|
||||||
|
settings.get("low_fee_conf_target", default_low_fee_conf_target)
|
||||||
|
)
|
||||||
|
default_low_fee_rate = self.makeIntFromSetting(
|
||||||
|
settings, "low_feerate", default_low_fee_rate
|
||||||
|
)
|
||||||
|
default_high_estimated_feerate_multiplier = float(
|
||||||
|
settings.get(
|
||||||
|
"high_estimated_feerate_multiplier",
|
||||||
|
default_high_estimated_feerate_multiplier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
default_high_fee_rate = self.makeIntFromSetting(
|
||||||
|
settings, "high_feerate", default_high_fee_rate
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if kwargs.get("network") != "regtest":
|
||||||
|
raise ValueError("swapclient unset")
|
||||||
|
chain_client_settings = {}
|
||||||
|
|
||||||
|
self._low_fee_conf_target = int(
|
||||||
|
chain_client_settings.get(
|
||||||
|
"low_fee_conf_target", default_low_fee_conf_target
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self._low_feerate = self.makeIntFromSetting(
|
||||||
|
chain_client_settings, "low_feerate", default_low_fee_rate
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set below 1.0 to disable estimating the max feerate and use max_feerate
|
||||||
|
self._high_estimated_feerate_multiplier = float(
|
||||||
|
chain_client_settings.get(
|
||||||
|
"high_estimated_feerate_multiplier",
|
||||||
|
default_high_estimated_feerate_multiplier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self._high_feerate = self.makeIntFromSetting(
|
||||||
|
chain_client_settings, "high_feerate", default_high_fee_rate
|
||||||
|
)
|
||||||
|
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
def validateFeeRate(self, feerate: int) -> None:
|
||||||
|
if self._low_feerate > 0:
|
||||||
|
min_feerate_src = "set_value"
|
||||||
|
min_feerate = self._low_feerate
|
||||||
|
else:
|
||||||
|
min_feerate, min_feerate_src = self.get_fee_rate(self._low_fee_conf_target)
|
||||||
|
min_feerate = self.make_int(min_feerate)
|
||||||
|
|
||||||
|
if self._high_estimated_feerate_multiplier >= 1.0:
|
||||||
|
max_feerate, max_feerate_src = self.get_fee_rate()
|
||||||
|
max_feerate = (
|
||||||
|
self.make_int(max_feerate) * self._high_estimated_feerate_multiplier
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
max_feerate_src = "set_value"
|
||||||
|
max_feerate = self._high_feerate
|
||||||
|
|
||||||
|
if max_feerate_src in ("estimatesmartfee", "electrum"):
|
||||||
|
if max_feerate > self._high_feerate:
|
||||||
|
max_feerate_src = "clamped_to_set_value"
|
||||||
|
max_feerate = self._high_feerate
|
||||||
|
|
||||||
|
self._log.debug(
|
||||||
|
f"Verify {self.ticker()} fee rate {feerate}, min {min_feerate} {min_feerate_src}, max {max_feerate} {max_feerate_src}"
|
||||||
|
)
|
||||||
|
if feerate < min_feerate:
|
||||||
|
err_msg: str = (
|
||||||
|
f"Fee rate too low, {feerate} < {min_feerate}, {min_feerate_src}"
|
||||||
|
)
|
||||||
|
self._log.error(err_msg)
|
||||||
|
raise ValueError(err_msg)
|
||||||
|
if feerate > max_feerate:
|
||||||
|
err_msg: str = (
|
||||||
|
f"Fee rate too high, {feerate} > {max_feerate}, {max_feerate_src}"
|
||||||
|
)
|
||||||
|
self._log.error(err_msg)
|
||||||
|
raise ValueError(err_msg)
|
||||||
@@ -101,8 +101,13 @@ class XMRInterface(CoinInterface):
|
|||||||
return True
|
return True
|
||||||
return super().is_transient_error(ex)
|
return super().is_transient_error(ex)
|
||||||
|
|
||||||
def __init__(self, coin_settings, network, swap_client=None):
|
def __init__(self, coin_settings, network, swap_client=None, **kwargs):
|
||||||
super().__init__(network)
|
super().__init__(
|
||||||
|
coin_settings=coin_settings,
|
||||||
|
network=network,
|
||||||
|
swap_client=swap_client,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
self._addr_prefix = self.chainparams_network()["address_prefix"]
|
self._addr_prefix = self.chainparams_network()["address_prefix"]
|
||||||
|
|
||||||
@@ -857,3 +862,6 @@ class XMRInterface(CoinInterface):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._log.error(f"listWalletTransactions failed: {e}")
|
self._log.error(f"listWalletTransactions failed: {e}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def validateFeeRate(self, fee_rate: int) -> bool:
|
||||||
|
pass # Fee rate isn't used
|
||||||
|
|||||||
@@ -741,7 +741,7 @@ class Test(BaseTest):
|
|||||||
ci0 = cls.swap_clients[0].ci(cls.test_coin)
|
ci0 = cls.swap_clients[0].ci(cls.test_coin)
|
||||||
if not cls.restore_instance:
|
if not cls.restore_instance:
|
||||||
dcr_mining_addr = ci0.rpc_wallet("getnewaddress")
|
dcr_mining_addr = ci0.rpc_wallet("getnewaddress")
|
||||||
assert dcr_mining_addr in cls.dcr_mining_addrs
|
assert dcr_mining_addr == cls.dcr_mining_addr
|
||||||
cls.dcr_ticket_account = ci0.rpc_wallet(
|
cls.dcr_ticket_account = ci0.rpc_wallet(
|
||||||
"getaccount",
|
"getaccount",
|
||||||
[
|
[
|
||||||
|
|||||||
Reference in New Issue
Block a user