Decred: Add to test_xmr_persistent

This commit is contained in:
tecnovert
2024-05-20 16:29:14 +02:00
parent 2a8c04b285
commit 446d6fe357
19 changed files with 394 additions and 188 deletions

View File

@@ -1,3 +1,3 @@
name = "basicswap"
__version__ = "0.13.0"
__version__ = "0.13.1"

View File

@@ -774,9 +774,7 @@ class BasicSwap(BaseApp):
if self.coin_clients[c]['connection_type'] == 'rpc':
ci = self.ci(c)
self.waitForDaemonRPC(c, with_wallet=False)
if c not in (Coins.XMR,) and ci.checkWallets() >= 1:
self.waitForDaemonRPC(c)
self.waitForDaemonRPC(c)
core_version = ci.getDaemonVersion()
self.log.info('%s Core version %d', ci.coin_name(), core_version)
@@ -857,7 +855,7 @@ class BasicSwap(BaseApp):
self.log.info('Scanned %d unread messages.', nm)
def stopDaemon(self, coin) -> None:
if coin == Coins.XMR:
if coin in (Coins.XMR, Coins.DCR):
return
num_tries = 10
authcookiepath = os.path.join(self.getChainDatadirPath(coin), '.cookie')
@@ -893,6 +891,17 @@ class BasicSwap(BaseApp):
self.stopDaemon(c)
def waitForDaemonRPC(self, coin_type, with_wallet: bool = True) -> None:
if with_wallet:
self.waitForDaemonRPC(coin_type, with_wallet=False)
if coin_type in (Coins.XMR,):
return
ci = self.ci(coin_type)
# checkWallets can adjust the wallet name.
if ci.checkWallets() < 1:
self.log.error('No wallets found for coin {}.'.format(ci.coin_name()))
self.stopRunning(1) # systemd will try to restart the process if fail_code != 0
startup_tries = self.startup_tries
chain_client_settings = self.getChainClientSettings(coin_type)
if 'startup_tries' in chain_client_settings:
@@ -1938,9 +1947,6 @@ class BasicSwap(BaseApp):
self.log.debug('Generated new receive address %s for %s', new_addr, Coins(coin_type).name)
return new_addr
def getRelayFeeRateForCoin(self, coin_type):
return self.callcoinrpc(coin_type, 'getnetworkinfo')['relayfee']
def getFeeRateForCoin(self, coin_type, conf_target: int = 2):
return self.ci(coin_type).get_fee_rate(conf_target)
@@ -3376,11 +3382,11 @@ class BasicSwap(BaseApp):
txn_script]
redeem_txn = ci.setTxSignature(bytes.fromhex(redeem_txn), witness_stack).hex()
else:
script = (len(redeem_sig) // 2).to_bytes(1) + bytes.fromhex(redeem_sig)
script += (33).to_bytes(1) + pubkey
script += (32).to_bytes(1) + secret
script += (OpCodes.OP_1).to_bytes(1)
script += (OpCodes.OP_PUSHDATA1).to_bytes(1) + (len(txn_script)).to_bytes(1) + txn_script
script = (len(redeem_sig) // 2).to_bytes(1, 'big') + bytes.fromhex(redeem_sig)
script += (33).to_bytes(1, 'big') + pubkey
script += (32).to_bytes(1, 'big') + secret
script += (OpCodes.OP_1).to_bytes(1, 'big')
script += (OpCodes.OP_PUSHDATA1).to_bytes(1, 'big') + (len(txn_script)).to_bytes(1, 'big') + txn_script
redeem_txn = ci.setTxScriptSig(bytes.fromhex(redeem_txn), 0, script).hex()
if coin_type in (Coins.NAV, Coins.DCR):
@@ -3488,10 +3494,10 @@ class BasicSwap(BaseApp):
txn_script]
refund_txn = ci.setTxSignature(bytes.fromhex(refund_txn), witness_stack).hex()
else:
script = (len(refund_sig) // 2).to_bytes(1) + bytes.fromhex(refund_sig)
script += (33).to_bytes(1) + pubkey
script += (OpCodes.OP_0).to_bytes(1)
script += (OpCodes.OP_PUSHDATA1).to_bytes(1) + (len(txn_script)).to_bytes(1) + txn_script
script = (len(refund_sig) // 2).to_bytes(1, 'big') + bytes.fromhex(refund_sig)
script += (33).to_bytes(1, 'big') + pubkey
script += (OpCodes.OP_0).to_bytes(1, 'big')
script += (OpCodes.OP_PUSHDATA1).to_bytes(1, 'big') + (len(txn_script)).to_bytes(1, 'big') + txn_script
refund_txn = ci.setTxScriptSig(bytes.fromhex(refund_txn), 0, script)
if coin_type in (Coins.NAV, Coins.DCR):
@@ -4517,8 +4523,8 @@ class BasicSwap(BaseApp):
except Exception as e:
if 'Block not available (pruned data)' in str(e):
# TODO: Better solution?
bci = self.callcoinrpc(coin_type, 'getblockchaininfo')
self.log.error('Coin %s last_height_checked %d set to pruneheight %d', self.ci(coin_type).coin_name(), last_height_checked, bci['pruneheight'])
bci = ci.getBlockchainInfo()
self.log.error('Coin %s last_height_checked %d set to pruneheight %d', ci.coin_name(), last_height_checked, bci['pruneheight'])
last_height_checked = bci['pruneheight']
continue
else:

View File

@@ -153,16 +153,19 @@ class CoinInterface:
def use_tx_vsize(self) -> bool:
return self._use_segwit
def getLockTxSwapOutputValue(self, bid, xmr_swap):
def getLockTxSwapOutputValue(self, bid, xmr_swap) -> int:
return bid.amount
def getLockRefundTxSwapOutputValue(self, bid, xmr_swap):
def getLockRefundTxSwapOutputValue(self, bid, xmr_swap) -> int:
return xmr_swap.a_swap_refund_value
def getLockRefundTxSwapOutput(self, xmr_swap):
def getLockRefundTxSwapOutput(self, xmr_swap) -> int:
# Only one prevout exists
return 0
def checkWallets(self) -> int:
return 1
class AdaptorSigInterface():
def getScriptLockTxDummyWitness(self, script: bytes):

View File

@@ -109,7 +109,7 @@ def DCRSignatureHash(sign_script: bytes, hash_type: SigHashType, tx: CTransactio
for txi_n, txi in enumerate(sign_vins):
hash_buffer += txi.prevout.hash.to_bytes(32, 'little')
hash_buffer += txi.prevout.n.to_bytes(4, 'little')
hash_buffer += txi.prevout.tree.to_bytes(1)
hash_buffer += txi.prevout.tree.to_bytes(1, 'little')
# In the case of SigHashNone and SigHashSingle, commit to 0 for everything that is not the input being signed instead.
if (masked_hash_type == SigHashType.SigHashNone
@@ -308,14 +308,19 @@ class DCRInterface(Secp256k1Interface):
def getChainHeight(self) -> int:
return self.rpc('getblockcount')
def checkWallets(self) -> int:
# Only one wallet possible?
return 1
def initialiseWallet(self, key: bytes) -> None:
# Load with --create
pass
def getWalletSeedID(self):
masterpubkey = self.rpc_wallet('getmasterpubkey')
masterpubkey_data = self.decode_address(masterpubkey)[4:]
return hash160(masterpubkey_data).hex()
def checkExpectedSeed(self, expect_seedid) -> bool:
self._expect_seedid_hex = expect_seedid
return expect_seedid == self.getWalletSeedID()
def getDaemonVersion(self):
return self.rpc('getnetworkinfo')['version']
@@ -368,7 +373,7 @@ class DCRInterface(Secp256k1Interface):
def encodeKey(self, key_bytes: bytes) -> str:
wif_prefix = self.chainparams_network()['key_prefix']
key_type = 0 # STEcdsaSecp256k1
b = wif_prefix.to_bytes(2, 'big') + key_type.to_bytes(1) + key_bytes
b = wif_prefix.to_bytes(2, 'big') + key_type.to_bytes(1, 'big') + key_bytes
b += blake256(b)[:4]
return b58encode(b)
@@ -433,7 +438,7 @@ class DCRInterface(Secp256k1Interface):
script_hash = self.pkh(script)
assert len(script_hash) == 20
return OP_HASH160.to_bytes(1) + len(script_hash).to_bytes(1) + script_hash + OP_EQUAL.to_bytes(1)
return bytes((OP_HASH160,)) + bytes((len(script_hash),)) + script_hash + bytes((OP_EQUAL,))
def encodeScriptDest(self, script_dest: bytes) -> str:
script_hash = script_dest[2:-1] # Extract hash from script
@@ -442,7 +447,7 @@ class DCRInterface(Secp256k1Interface):
def getPubkeyHashDest(self, pkh: bytes) -> bytes:
# P2PKH
assert len(pkh) == 20
return OP_DUP.to_bytes(1) + OP_HASH160.to_bytes(1) + len(pkh).to_bytes(1) + pkh + OP_EQUALVERIFY.to_bytes(1) + OP_CHECKSIG.to_bytes(1)
return bytes((OP_DUP,)) + bytes((OP_HASH160,)) + bytes((len(pkh),)) + pkh + bytes((OP_EQUALVERIFY,)) + bytes((OP_CHECKSIG,))
def getPkDest(self, K: bytes) -> bytearray:
return self.getPubkeyHashDest(self.pkh(K))
@@ -532,7 +537,7 @@ class DCRInterface(Secp256k1Interface):
prove_utxos.append(outpoint)
hasher.update(outpoint[0])
hasher.update(outpoint[1].to_bytes(2, 'big'))
hasher.update(outpoint[2].to_bytes(1))
hasher.update(outpoint[2].to_bytes(1, 'big'))
if sum_value >= amount_for:
break
utxos_hash = hasher.digest()
@@ -554,7 +559,7 @@ class DCRInterface(Secp256k1Interface):
def encodeProofUtxos(self, proof_utxos):
packed_utxos = bytes()
for utxo in proof_utxos:
packed_utxos += utxo[0] + utxo[1].to_bytes(2, 'big') + utxo[2].to_bytes(1)
packed_utxos += utxo[0] + utxo[1].to_bytes(2, 'big') + utxo[2].to_bytes(1, 'big')
return packed_utxos
def decodeProofUtxos(self, msg_utxos):
@@ -573,7 +578,7 @@ class DCRInterface(Secp256k1Interface):
for outpoint in utxos:
hasher.update(outpoint[0])
hasher.update(outpoint[1].to_bytes(2, 'big'))
hasher.update(outpoint[2].to_bytes(1))
hasher.update(outpoint[2].to_bytes(1, 'big'))
utxos_hash = hasher.digest()
passed = self.verifyMessage(address, address + '_swap_proof_' + utxos_hash.hex() + extra_commit_bytes.hex(), signature)
@@ -841,19 +846,19 @@ class DCRInterface(Secp256k1Interface):
Kaf_enc = Kaf if len(Kaf) == 33 else self.encodePubkey(Kaf)
script = bytearray()
script += OP_IF.to_bytes(1)
script += bytes((OP_IF,))
push_script_data(script, bytes((2,)))
push_script_data(script, Kal_enc)
push_script_data(script, Kaf_enc)
push_script_data(script, bytes((2,)))
script += OP_CHECKMULTISIG.to_bytes(1)
script += OP_ELSE.to_bytes(1)
script += bytes((OP_CHECKMULTISIG,))
script += bytes((OP_ELSE,))
script += CScriptNum.encode(CScriptNum(csv_val))
script += OP_CHECKSEQUENCEVERIFY.to_bytes(1)
script += OP_DROP.to_bytes(1)
script += bytes((OP_CHECKSEQUENCEVERIFY,))
script += bytes((OP_DROP,))
push_script_data(script, Kaf_enc)
script += OP_CHECKSIG.to_bytes(1)
script += OP_ENDIF.to_bytes(1)
script += bytes((OP_CHECKSIG,))
script += bytes((OP_ENDIF,))
return script

View File

@@ -162,7 +162,7 @@ class CTransaction:
for txi in self.vin:
data += txi.prevout.hash.to_bytes(32, 'little')
data += txi.prevout.n.to_bytes(4, 'little')
data += txi.prevout.tree.to_bytes(1)
data += txi.prevout.tree.to_bytes(1, 'little')
data += txi.sequence.to_bytes(4, 'little')
data += encode_compactsize(len(self.vout))

View File

@@ -39,7 +39,7 @@ def push_script_data(data_array: bytearray, data: bytes) -> None:
return
if len_data < OP_PUSHDATA1:
data_array += len_data.to_bytes(1)
data_array += len_data.to_bytes(1, 'little')
elif len_data <= 0xff:
data_array += bytes((OP_PUSHDATA1, len_data))
elif len_data <= 0xffff:

View File

@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import os
import select
import subprocess
def createDCRWallet(args, hex_seed, logging, delay_event):
logging.info('Creating DCR wallet')
(pipe_r, pipe_w) = os.pipe() # subprocess.PIPE is buffered, blocks when read
p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=pipe_w, stderr=pipe_w)
try:
while p.poll() is None:
while len(select.select([pipe_r], [], [], 0)[0]) == 1:
buf = os.read(pipe_r, 1024).decode('utf-8')
logging.debug(f'dcrwallet {buf}')
response = None
if 'Use the existing configured private passphrase' in buf:
response = b'y\n'
elif 'Do you want to add an additional layer of encryption' in buf:
response = b'n\n'
elif 'Do you have an existing wallet seed' in buf:
response = b'y\n'
elif 'Enter existing wallet seed' in buf:
response = (hex_seed + '\n').encode('utf-8')
elif 'Seed input successful' in buf:
pass
elif 'Upgrading database from version' in buf:
pass
elif 'Ticket commitments db upgrade done' in buf:
pass
else:
raise ValueError(f'Unexpected output: {buf}')
if response is not None:
p.stdin.write(response)
p.stdin.flush()
delay_event.wait(0.1)
except Exception as e:
logging.error(f'dcrwallet --create failed: {e}')
finally:
if p.poll() is None:
p.terminate()
os.close(pipe_r)
os.close(pipe_w)
p.stdin.close()

View File

@@ -42,9 +42,6 @@ class FIROInterface(BTCInterface):
# No multiwallet support
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
def checkWallets(self) -> int:
return 1
def getExchangeName(self, exchange_name):
return 'zcoin'

View File

@@ -73,9 +73,6 @@ class NAVInterface(BTCInterface):
# No multiwallet support
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
def checkWallets(self) -> int:
return 1
def use_p2shp2wsh(self) -> bool:
# p2sh-p2wsh
return True

View File

@@ -35,9 +35,6 @@ class PIVXInterface(BTCInterface):
# No multiwallet support
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
def checkWallets(self) -> int:
return 1
def signTxWithWallet(self, tx):
rv = self.rpc('signrawtransaction', [tx.hex()])
return bytes.fromhex(rv['hex'])

View File

@@ -129,9 +129,6 @@ class XMRInterface(CoinInterface):
self.rpc2 = make_xmr_rpc2_func(coin_settings['rpcport'], daemon_login, host=rpchost, proxy_host=proxy_host, proxy_port=proxy_port, default_timeout=self._rpctimeout, tag='Node ') # non-json endpoint
self.rpc_wallet = make_xmr_rpc_func(coin_settings['walletrpcport'], coin_settings['walletrpcauth'], host=coin_settings.get('walletrpchost', '127.0.0.1'), default_timeout=self._walletrpctimeout, tag='Wallet ')
def checkWallets(self) -> int:
return 1
def setFeePriority(self, new_priority):
ensure(new_priority >= 0 and new_priority < 4, 'Invalid fee_priority value')
self._fee_priority = new_priority

View File

@@ -1,5 +1,5 @@
{% include 'header.html' %}
{% from 'style.html' import select_box_arrow_svg, select_box_class, circular_arrows_svg, circular_error_svg, circular_info_svg, cross_close_svg, breadcrumb_line_svg, withdraw_svg, utxo_groups_svg, create_utxo_svg, red_cross_close_svg, blue_cross_close_svg, circular_update_messages_svg, circular_error_messages_svg %}
{% from 'style.html' import select_box_arrow_svg, select_box_class, circular_arrows_svg, circular_error_svg, circular_info_svg, cross_close_svg, breadcrumb_line_svg, withdraw_svg, utxo_groups_svg, create_utxo_svg, red_cross_close_svg, blue_cross_close_svg, circular_update_messages_svg, circular_error_messages_svg %}
<script src="/static/js/libs//qrcode.js"></script>
<div class="container mx-auto">
<section class="p-5 mt-5">
@@ -27,7 +27,7 @@
</div>
</div>
</section>
{% include 'inc_messages.html' %}
{% include 'inc_messages.html' %}
{% if w.updating %}
<section class="py-4" id="messages_updating" role="alert">
<div class="container px-4 mx-auto">
@@ -42,7 +42,7 @@
<li class="font-semibold text-sm text-blue-500 error_msg"><span class="bold">UPDATING:</span></li>
<li class="font-medium text-sm text-blue-500">Please wait...</li>
</ul>
</div>
</div>
</div>
<div class="w-auto p-2">
<button type="button" class="ms-auto bg-blue-50 text-blue-500 rounded-lg focus:ring-0 focus:ring-blue-400 p-1.5 hover:bg-blue-200 inline-flex items-center justify-center h-8 w-8 focus:outline-none dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700" data-dismiss-target="#messages_updating" aria-label="Close"><span class="sr-only">Close</span>
@@ -55,7 +55,7 @@
</section>
{% endif %}
{% if w.havedata %}
{% if w.error %}
{% if w.error %}
<section class="py-4" id="messages_error" role="alert">
<div class="container px-4 mx-auto">
<div class="p-6 text-green-800 rounded-lg bg-red-50 border border-red-400 dark:bg-gray-500 dark:text-red-400 rounded-md">
@@ -113,7 +113,7 @@
</tr> {% if w.cid == '1' %} {# PART #}
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
<td class="py-3 px-6 bold"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }} Blind"> </span>Blind Balance: </td>
<td class="py-3 px-6 bold coinname-value" data-coinname="{{ w.name }}">{{ w.blind_balance }} {{ w.ticker }} (<span class="usd-value"></span>)
<td class="py-3 px-6 bold coinname-value" data-coinname="{{ w.name }}">{{ w.blind_balance }} {{ w.ticker }} (<span class="usd-value"></span>)
{% if w.blind_unconfirmed %}
<span class="inline-block py-1 px-2 rounded-full bg-green-100 text-green-500 dark:bg-gray-500 dark:text-green-500">Unconfirmed: +{{ w.blind_unconfirmed }} {{ w.ticker }}</span>
{% endif %}
@@ -136,11 +136,11 @@
<td class="py-3 px-6 bold coinname-value" data-coinname="{{ w.name }}">{{ w.mweb_balance }} {{ w.ticker }} (<span class="usd-value"></span>)
{% if w.mweb_pending %}
<span class="inline-block py-1 px-2 rounded-full bg-green-100 text-green-500 dark:bg-gray-500 dark:text-green-500">Pending: +{{ w.mweb_pending }} {{ w.ticker }} </span>
{% endif %}
{% endif %}
</td>
</tr>
{% endif %}
{# / LTC #}
{# / LTC #}
{% if w.locked_utxos %}
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
<td class="py-3 px-6 bold">Locked Outputs:</td>
@@ -202,9 +202,11 @@
<div class="container mt-5 mx-auto">
<div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-6">
{% if w.cid != '4' %} {# DCR #}
<div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5"> <input class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-white hover:text-red border border-red-500 hover:border-red-500 hover:bg-red-600 bg-red-500 rounded-md shadow-button focus:ring-0 focus:outline-none cursor-pointer" type="submit" name="reseed_{{ w.cid }}" value="Reseed wallet" onclick="return confirmReseed();"> </div>
</div>
{% endif %}
</div>
</div>
</div>
@@ -369,7 +371,7 @@
</div>
</div>
</div>
{% endif %}
{% endif %}
{# / LTC #}
</div>
</div>
@@ -383,7 +385,7 @@
<script>
// Particl Stealth
var stealthAddress = "{{ w.stealth_address }}";
var qrCodeStealth = new QRCode(document.getElementById("qrcode-stealth"), {
text: stealthAddress,
width: 170,
@@ -399,7 +401,7 @@
<script>
// Litecoin MWEB
var mwebAddress = "{{ w.mweb_address }}";
var qrCodeMWEB = new QRCode(document.getElementById("qrcode-mweb"), {
text: mwebAddress,
width: 170,
@@ -408,14 +410,14 @@
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.L
});
</script>
</script>
{% endif %}
{% if w.cid == '6' %}
{# XMR #}
<script>
// Monero Sub
var moneroSubAddress = "{{ w.deposit_address }}";
var qrCodeMoneroSub = new QRCode(document.getElementById("qrcode-monero-sub"), {
text: moneroSubAddress,
width: 170,
@@ -428,7 +430,7 @@
<script>
// Monero Main
var moneroMainAddress = "{{ w.main_address }}";
var qrCodeMoneroMain = new QRCode(document.getElementById("qrcode-monero-main"), {
text: moneroMainAddress,
width: 170,
@@ -442,7 +444,7 @@
<script>
// Default
var defaultAddress = "{{ w.deposit_address }}";
var qrCodeDepost = new QRCode(document.getElementById("qrcode-deposit"), {
text: defaultAddress,
width: 170,
@@ -462,48 +464,48 @@
document.execCommand('copy');
document.body.removeChild(el);
}
function copyAndShowMessage(elementId) {
const addressElement = document.getElementById(elementId);
if (!addressElement) return;
const addressText = addressElement.innerText.trim();
copyToClipboard(addressText);
addressElement.innerText = 'Copied to clipboard';
const originalWidth = addressElement.offsetWidth;
addressElement.classList.add('copying');
addressElement.parentElement.style.width = `${originalWidth}px`;
setTimeout(function () {
addressElement.innerText = addressText;
addressElement.classList.remove('copying');
addressElement.parentElement.style.width = '';
}, 2000);
}
const stealthAddressElement = document.getElementById('stealth_address');
if (stealthAddressElement) {
stealthAddressElement.addEventListener('click', function () {
copyAndShowMessage('stealth_address');
});
}
const mainDepositAddressElement = document.getElementById('main_deposit_address');
if (mainDepositAddressElement) {
mainDepositAddressElement.addEventListener('click', function () {
copyAndShowMessage('main_deposit_address');
});
}
const moneroMainAddressElement = document.getElementById('monero_main_address');
if (moneroMainAddressElement) {
moneroMainAddressElement.addEventListener('click', function () {
copyAndShowMessage('monero_main_address');
});
}
const moneroSubAddressElement = document.getElementById('monero_sub_address');
if (moneroSubAddressElement) {
moneroSubAddressElement.addEventListener('click', function () {
@@ -572,7 +574,7 @@
var selectedType = typeSelect.value;
var floatBalance;
var calculatedAmount;
switch(selectedType) {
case 'plain':
floatBalance = parseFloat(balance);
@@ -591,7 +593,7 @@
calculatedAmount = floatBalance * percent;
break;
}
amountInput.value = calculatedAmount.toFixed(8);
}
</script>
@@ -606,7 +608,7 @@
var selectedType = typeSelect.value;
var floatBalance;
var calculatedAmount;
switch(selectedType) {
case 'plain':
floatBalance = parseFloat(balance);
@@ -621,7 +623,7 @@
calculatedAmount = floatBalance * percent;
break;
}
amountInput.value = calculatedAmount.toFixed(8);
}
</script>
@@ -633,10 +635,10 @@
var amountInput = document.getElementById('amount');
var floatBalance;
var calculatedAmount;
floatBalance = parseFloat(balance);
calculatedAmount = floatBalance * percent;
if (cid === '6' && percent === 1) {
amountInput.setAttribute('data-hidden', 'true');
amountInput.placeholder = 'Sweep All';
@@ -652,7 +654,7 @@
amountInput.placeholder = '';
amountInput.disabled = false;
}
if (cid === '6' && percent === 1) {
var sweepAllCheckbox = document.getElementById('sweepall');
if (sweepAllCheckbox) {
@@ -665,7 +667,7 @@
}
}
}
</script>
{% endif %}
</div>
@@ -677,7 +679,7 @@
<td class="py-3 px-6"> <input class="hover:border-blue-500 w-5 h-5 form-check-input text-blue-600 bg-gray-50 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-1 dark:bg-gray-500 dark:border-gray-400" type="checkbox" id="sweepall" name="sweepall_{{ w.cid }}" {% if w.wd_sweepall==true %} checked=checked{% endif %}> </td> {% else %} <td class="py-3 px-6 bold">Subtract Fee:</td>
<td class="py-3 px-6"> <input class="hover:border-blue-500 w-5 h-5 form-check-input text-blue-600 bg-gray-50 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-1 dark:bg-gray-500 dark:border-gray-400" type="checkbox" name="subfee_{{ w.cid }}" {% if w.wd_subfee==true %} checked=checked{% endif %}> </td>
{% endif %}
<td>
<td>
</td>
</tr>
{% if w.cid == '1' %}
@@ -855,7 +857,7 @@
'DECRED': 'DCR',
'WOWNERO': 'WOW'
};
const getUsdValue = (cryptoValue, coinSymbol) => fetch(`https://min-api.cryptocompare.com/data/price?fsym=${coinSymbol}&tsyms=USD`)
.then(response => response.json())
.then(data => {
@@ -866,16 +868,16 @@
throw new Error(`Invalid exchange rate for ${coinSymbol}`);
}
});
const updateUsdValue = async (cryptoCell, coinFullName, usdValueSpan) => {
const coinSymbol = coinNameToSymbol[coinFullName] || '';
if (!coinSymbol) {
console.error(`Coin symbol not found for full name: ${coinFullName}`);
return;
}
const cryptoValue = parseFloat(cryptoCell.textContent);
if (!isNaN(cryptoValue) && cryptoValue !== 0) {
try {
const usdValue = await getUsdValue(cryptoValue, coinSymbol);
@@ -894,19 +896,19 @@
}
}
};
const calculateTotalUsdValue = async () => {
const coinNameValues = document.querySelectorAll('.coinname-value');
let totalUsdValue = 0;
for (const coinNameValue of coinNameValues) {
const coinFullName = coinNameValue.getAttribute('data-coinname');
const cryptoValue = parseFloat(coinNameValue.textContent);
const coinSymbol = coinNameToSymbol[coinFullName];
if (coinSymbol) {
const usdValueSpan = coinNameValue.querySelector('.usd-value');
if (!isNaN(cryptoValue) && cryptoValue !== 0) {
try {
const usdValue = await getUsdValue(cryptoValue, coinSymbol);
@@ -926,24 +928,24 @@
console.error(`Coin symbol not found for full name: ${coinFullName}`);
}
}
const totalUsdValueElement = document.getElementById('total-usd-value');
if (totalUsdValueElement) {
totalUsdValueElement.textContent = `$${totalUsdValue.toFixed(2)}`;
}
};
document.addEventListener('DOMContentLoaded', () => {
const coinNameValues = document.querySelectorAll('.coinname-value');
for (const coinNameValue of coinNameValues) {
const coinFullName = coinNameValue.getAttribute('data-coinname');
const usdValueSpan = coinNameValue.querySelector('.usd-value');
updateUsdValue(coinNameValue, coinFullName, usdValueSpan);
}
calculateTotalUsdValue();
function set_sweep_all(element) {
let input = document.getElementById('amount');
if (element.checked) {
@@ -952,7 +954,7 @@
input.disabled = false;
}
}
let cb_sweepall = document.getElementById('sweepall');
if (cb_sweepall) {
set_sweep_all(cb_sweepall);
@@ -960,7 +962,7 @@
set_sweep_all(event.currentTarget);
});
}
});
</script>
{% include 'footer.html' %}
@@ -968,11 +970,11 @@
function confirmReseed() {
return confirm("Are you sure?\nBackup your wallet before and after.\nWon't detect used keys.\nShould only be used for new wallets.");
}
function confirmWithdrawal() {
return confirm("Are you sure?");
}
function confirmUTXOResize() {
return confirm("Are you sure?");
}

View File

@@ -13,7 +13,7 @@ from coincurve.keys import (
def BIP32Hash(chaincode: bytes, child_no: int, key_data_type: int, keydata: bytes):
return hmac_sha512(chaincode, key_data_type.to_bytes(1) + keydata + child_no.to_bytes(4, 'big'))
return hmac_sha512(chaincode, key_data_type.to_bytes(1, 'big') + keydata + child_no.to_bytes(4, 'big'))
def hash160_dcr(data: bytes) -> bytes:
@@ -85,7 +85,7 @@ class ExtKeyPair():
return out
def encode_v(self) -> bytes:
return self._depth.to_bytes(1) + \
return self._depth.to_bytes(1, 'big') + \
self._fingerprint + \
self._child_no.to_bytes(4, 'big') + \
self._chaincode + \
@@ -94,7 +94,7 @@ class ExtKeyPair():
def encode_p(self) -> bytes:
pubkey = PublicKey.from_secret(self._key).format() if self._pubkey is None else self._pubkey
return self._depth.to_bytes(1) + \
return self._depth.to_bytes(1, 'big') + \
self._fingerprint + \
self._child_no.to_bytes(4, 'big') + \
self._chaincode + \