mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-06 10:48:11 +01:00
ui: Improve fee estimation.
This commit is contained in:
@@ -155,9 +155,13 @@ class BTCInterface(CoinInterface):
|
||||
return abs(a - b) < 20
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_alock_spend_tx_vsize() -> int:
|
||||
def xmr_swap_a_lock_spend_tx_vsize() -> int:
|
||||
return 147
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_b_lock_spend_tx_vsize() -> int:
|
||||
return 110
|
||||
|
||||
@staticmethod
|
||||
def txoType():
|
||||
return CTxOut
|
||||
@@ -986,14 +990,14 @@ class BTCInterface(CoinInterface):
|
||||
def scanTxOutset(self, dest):
|
||||
return self.rpc_callback('scantxoutset', ['start', ['raw({})'.format(dest.hex())]])
|
||||
|
||||
def getTransaction(self, txid):
|
||||
def getTransaction(self, txid: bytes):
|
||||
try:
|
||||
return bytes.fromhex(self.rpc_callback('getrawtransaction', [txid.hex()]))
|
||||
except Exception as ex:
|
||||
# TODO: filter errors
|
||||
return None
|
||||
|
||||
def getWalletTransaction(self, txid):
|
||||
def getWalletTransaction(self, txid: bytes):
|
||||
try:
|
||||
return bytes.fromhex(self.rpc_callback('gettransaction', [txid.hex()]))
|
||||
except Exception as ex:
|
||||
@@ -1460,7 +1464,7 @@ class BTCInterface(CoinInterface):
|
||||
tx.rehash()
|
||||
return tx.serialize().hex()
|
||||
|
||||
def ensureFunds(self, amount):
|
||||
def ensureFunds(self, amount: int) -> None:
|
||||
if self.getSpendableBalance() < amount:
|
||||
raise ValueError('Balance too low')
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ class FIROInterface(BTCInterface):
|
||||
|
||||
return rv
|
||||
|
||||
def createSCLockTx(self, value: int, script: bytearray, vkbv=None) -> bytes:
|
||||
def createSCLockTx(self, value: int, script: bytearray, vkbv: bytes = None) -> bytes:
|
||||
tx = CTransaction()
|
||||
tx.nVersion = self.txVersion()
|
||||
tx.vout.append(self.txoType()(value, self.getScriptDest(script)))
|
||||
|
||||
@@ -59,8 +59,12 @@ class PARTInterface(BTCInterface):
|
||||
return 0xa0
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_alock_spend_tx_vsize() -> int:
|
||||
return 213
|
||||
def xmr_swap_a_lock_spend_tx_vsize() -> int:
|
||||
return 200
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_b_lock_spend_tx_vsize() -> int:
|
||||
return 138
|
||||
|
||||
@staticmethod
|
||||
def txoType():
|
||||
@@ -111,8 +115,8 @@ class PARTInterface(BTCInterface):
|
||||
|
||||
return encodeStealthAddress(prefix_byte, scan_pubkey, spend_pubkey)
|
||||
|
||||
def getWitnessStackSerialisedLength(self, witness_stack):
|
||||
length = getCompactSizeLen(len(witness_stack))
|
||||
def getWitnessStackSerialisedLength(self, witness_stack) -> int:
|
||||
length: int = getCompactSizeLen(len(witness_stack))
|
||||
for e in witness_stack:
|
||||
length += getWitnessElementLen(len(e))
|
||||
return length
|
||||
@@ -138,7 +142,15 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
def balance_type():
|
||||
return BalanceTypes.BLIND
|
||||
|
||||
def coin_name(self):
|
||||
@staticmethod
|
||||
def xmr_swap_a_lock_spend_tx_vsize() -> int:
|
||||
return 1032
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_b_lock_spend_tx_vsize() -> int:
|
||||
return 980
|
||||
|
||||
def coin_name(self) -> str:
|
||||
return super().coin_name() + ' Blind'
|
||||
|
||||
def getScriptLockTxNonce(self, data):
|
||||
@@ -167,7 +179,7 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
ensure(v['result'] is True, 'verifycommitment failed')
|
||||
return output_n, blinded_info
|
||||
|
||||
def createSCLockTx(self, value: int, script: bytearray, vkbv) -> bytes:
|
||||
def createSCLockTx(self, value: int, script: bytearray, vkbv: bytes) -> bytes:
|
||||
|
||||
# Nonce is derived from vkbv, ephemeral_key isn't used
|
||||
ephemeral_key = self.getNewSecretKey()
|
||||
@@ -183,7 +195,7 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
tx_bytes = bytes.fromhex(rv['hex'])
|
||||
return tx_bytes
|
||||
|
||||
def fundSCLockTx(self, tx_bytes, feerate, vkbv):
|
||||
def fundSCLockTx(self, tx_bytes: bytes, feerate: int, vkbv: bytes) -> bytes:
|
||||
feerate_str = self.format_amount(feerate)
|
||||
# TODO: unlock unspents if bid cancelled
|
||||
|
||||
@@ -462,7 +474,7 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
ensure(output_n is not None, 'Output not found in tx')
|
||||
return output_n
|
||||
|
||||
def createSCLockSpendTx(self, tx_lock_bytes, script_lock, pk_dest, tx_fee_rate, vkbv):
|
||||
def createSCLockSpendTx(self, tx_lock_bytes: bytes, script_lock: bytes, pk_dest: bytes, tx_fee_rate: int, vkbv: bytes, fee_info={}) -> bytes:
|
||||
lock_tx_obj = self.rpc_callback('decoderawtransaction', [tx_lock_bytes.hex()])
|
||||
lock_txid_hex = lock_tx_obj['txid']
|
||||
|
||||
@@ -499,13 +511,20 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
rv = self.rpc_callback('fundrawtransactionfrom', ['blind', lock_spend_tx_hex, inputs_info, outputs_info, options])
|
||||
lock_spend_tx_hex = rv['hex']
|
||||
lock_spend_tx_obj = self.rpc_callback('decoderawtransaction', [lock_spend_tx_hex])
|
||||
|
||||
vsize = lock_spend_tx_obj['vsize']
|
||||
pay_fee = make_int(lock_spend_tx_obj['vout'][0]['ct_fee'])
|
||||
|
||||
# lock_spend_tx_hex does not include the dummy witness stack
|
||||
witness_bytes = self.getWitnessStackSerialisedLength(dummy_witness_stack)
|
||||
vsize = self.getTxVSize(self.loadTx(bytes.fromhex(lock_spend_tx_hex)), add_witness_bytes=witness_bytes)
|
||||
actual_tx_fee_rate = pay_fee * 1000 // vsize
|
||||
self._log.info('createSCLockSpendTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.',
|
||||
lock_spend_tx_obj['txid'], actual_tx_fee_rate, vsize, pay_fee)
|
||||
|
||||
fee_info['vsize'] = vsize
|
||||
fee_info['fee_paid'] = pay_fee
|
||||
fee_info['rate_input'] = tx_fee_rate
|
||||
fee_info['rate_actual'] = actual_tx_fee_rate
|
||||
|
||||
return bytes.fromhex(lock_spend_tx_hex)
|
||||
|
||||
def verifySCLockSpendTx(self, tx_bytes,
|
||||
@@ -629,7 +648,7 @@ class PARTInterfaceBlind(PARTInterface):
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getbalances')['mine']['blind_trusted'])
|
||||
|
||||
def publishBLockTx(self, vkbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
|
||||
def publishBLockTx(self, vkbv: bytes, Kbs: bytes, output_amount: int, feerate: int, delay_for: int = 10, unlock_time: int = 0) -> bytes:
|
||||
Kbv = self.getPubkey(vkbv)
|
||||
sx_addr = self.formatStealthAddress(Kbv, Kbs)
|
||||
self._log.debug('sx_addr: {}'.format(sx_addr))
|
||||
@@ -751,14 +770,23 @@ class PARTInterfaceAnon(PARTInterface):
|
||||
def balance_type():
|
||||
return BalanceTypes.ANON
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_a_lock_spend_tx_vsize() -> int:
|
||||
raise ValueError('Not possible')
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_b_lock_spend_tx_vsize() -> int:
|
||||
# TODO: Estimate with ringsize
|
||||
return 1153
|
||||
|
||||
@staticmethod
|
||||
def depth_spendable() -> int:
|
||||
return 12
|
||||
|
||||
def coin_name(self):
|
||||
def coin_name(self) -> str:
|
||||
return super().coin_name() + ' Anon'
|
||||
|
||||
def publishBLockTx(self, kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
|
||||
def publishBLockTx(self, kbv: bytes, Kbs: bytes, output_amount: int, feerate: int, delay_for: int = 10, unlock_time: int = 0) -> bytes:
|
||||
Kbv = self.getPubkey(kbv)
|
||||
sx_addr = self.formatStealthAddress(Kbv, Kbs)
|
||||
|
||||
|
||||
@@ -69,6 +69,15 @@ class XMRInterface(CoinInterface):
|
||||
def depth_spendable() -> int:
|
||||
return 10
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_a_lock_spend_tx_vsize() -> int:
|
||||
raise ValueError('Not possible')
|
||||
|
||||
@staticmethod
|
||||
def xmr_swap_b_lock_spend_tx_vsize() -> int:
|
||||
# TODO: Estimate with ringsize
|
||||
return 1507
|
||||
|
||||
def __init__(self, coin_settings, network, swap_client=None):
|
||||
super().__init__(network)
|
||||
daemon_login = None
|
||||
@@ -266,7 +275,7 @@ class XMRInterface(CoinInterface):
|
||||
def encodeSharedAddress(self, Kbv: bytes, Kbs: bytes) -> str:
|
||||
return xmr_util.encode_address(Kbv, Kbs)
|
||||
|
||||
def publishBLockTx(self, kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
|
||||
def publishBLockTx(self, kbv: bytes, Kbs: bytes, output_amount: int, feerate: int, delay_for: int = 10, unlock_time: int = 0) -> bytes:
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
self.rpc_wallet_cb('refresh')
|
||||
@@ -368,7 +377,7 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
return None
|
||||
|
||||
def spendBLockTx(self, chain_b_lock_txid, address_to, kbv, kbs, cb_swap_value, b_fee_rate, restore_height, spend_actual_balance=False):
|
||||
def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee_rate: int, restore_height: int, spend_actual_balance: bool = False) -> bytes:
|
||||
'''
|
||||
Notes:
|
||||
"Error: No unlocked balance in the specified subaddress(es)" can mean not enough funds after tx fee.
|
||||
@@ -520,6 +529,9 @@ class XMRInterface(CoinInterface):
|
||||
# TODO
|
||||
return True
|
||||
|
||||
def ensureFunds(self, amount):
|
||||
def ensureFunds(self, amount: int) -> None:
|
||||
if self.getSpendableBalance() < amount:
|
||||
raise ValueError('Balance too low')
|
||||
|
||||
def getTransaction(self, txid: bytes):
|
||||
return self.rpc_cb2('get_transactions', {'txs_hashes': [txid.hex(), ]})
|
||||
|
||||
Reference in New Issue
Block a user