mirror of
https://github.com/basicswap/basicswap.git
synced 2025-01-03 09:19:26 +00:00
Decred: Add to test_xmr_persistent
This commit is contained in:
parent
2a8c04b285
commit
446d6fe357
19 changed files with 394 additions and 188 deletions
|
@ -1,3 +1,3 @@
|
||||||
name = "basicswap"
|
name = "basicswap"
|
||||||
|
|
||||||
__version__ = "0.13.0"
|
__version__ = "0.13.1"
|
||||||
|
|
|
@ -774,9 +774,7 @@ class BasicSwap(BaseApp):
|
||||||
|
|
||||||
if self.coin_clients[c]['connection_type'] == 'rpc':
|
if self.coin_clients[c]['connection_type'] == 'rpc':
|
||||||
ci = self.ci(c)
|
ci = self.ci(c)
|
||||||
self.waitForDaemonRPC(c, with_wallet=False)
|
self.waitForDaemonRPC(c)
|
||||||
if c not in (Coins.XMR,) and ci.checkWallets() >= 1:
|
|
||||||
self.waitForDaemonRPC(c)
|
|
||||||
|
|
||||||
core_version = ci.getDaemonVersion()
|
core_version = ci.getDaemonVersion()
|
||||||
self.log.info('%s Core version %d', ci.coin_name(), core_version)
|
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)
|
self.log.info('Scanned %d unread messages.', nm)
|
||||||
|
|
||||||
def stopDaemon(self, coin) -> None:
|
def stopDaemon(self, coin) -> None:
|
||||||
if coin == Coins.XMR:
|
if coin in (Coins.XMR, Coins.DCR):
|
||||||
return
|
return
|
||||||
num_tries = 10
|
num_tries = 10
|
||||||
authcookiepath = os.path.join(self.getChainDatadirPath(coin), '.cookie')
|
authcookiepath = os.path.join(self.getChainDatadirPath(coin), '.cookie')
|
||||||
|
@ -893,6 +891,17 @@ class BasicSwap(BaseApp):
|
||||||
self.stopDaemon(c)
|
self.stopDaemon(c)
|
||||||
|
|
||||||
def waitForDaemonRPC(self, coin_type, with_wallet: bool = True) -> None:
|
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
|
startup_tries = self.startup_tries
|
||||||
chain_client_settings = self.getChainClientSettings(coin_type)
|
chain_client_settings = self.getChainClientSettings(coin_type)
|
||||||
if 'startup_tries' in chain_client_settings:
|
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)
|
self.log.debug('Generated new receive address %s for %s', new_addr, Coins(coin_type).name)
|
||||||
return new_addr
|
return new_addr
|
||||||
|
|
||||||
def getRelayFeeRateForCoin(self, coin_type):
|
|
||||||
return self.callcoinrpc(coin_type, 'getnetworkinfo')['relayfee']
|
|
||||||
|
|
||||||
def getFeeRateForCoin(self, coin_type, conf_target: int = 2):
|
def getFeeRateForCoin(self, coin_type, conf_target: int = 2):
|
||||||
return self.ci(coin_type).get_fee_rate(conf_target)
|
return self.ci(coin_type).get_fee_rate(conf_target)
|
||||||
|
|
||||||
|
@ -3376,11 +3382,11 @@ class BasicSwap(BaseApp):
|
||||||
txn_script]
|
txn_script]
|
||||||
redeem_txn = ci.setTxSignature(bytes.fromhex(redeem_txn), witness_stack).hex()
|
redeem_txn = ci.setTxSignature(bytes.fromhex(redeem_txn), witness_stack).hex()
|
||||||
else:
|
else:
|
||||||
script = (len(redeem_sig) // 2).to_bytes(1) + bytes.fromhex(redeem_sig)
|
script = (len(redeem_sig) // 2).to_bytes(1, 'big') + bytes.fromhex(redeem_sig)
|
||||||
script += (33).to_bytes(1) + pubkey
|
script += (33).to_bytes(1, 'big') + pubkey
|
||||||
script += (32).to_bytes(1) + secret
|
script += (32).to_bytes(1, 'big') + secret
|
||||||
script += (OpCodes.OP_1).to_bytes(1)
|
script += (OpCodes.OP_1).to_bytes(1, 'big')
|
||||||
script += (OpCodes.OP_PUSHDATA1).to_bytes(1) + (len(txn_script)).to_bytes(1) + txn_script
|
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()
|
redeem_txn = ci.setTxScriptSig(bytes.fromhex(redeem_txn), 0, script).hex()
|
||||||
|
|
||||||
if coin_type in (Coins.NAV, Coins.DCR):
|
if coin_type in (Coins.NAV, Coins.DCR):
|
||||||
|
@ -3488,10 +3494,10 @@ class BasicSwap(BaseApp):
|
||||||
txn_script]
|
txn_script]
|
||||||
refund_txn = ci.setTxSignature(bytes.fromhex(refund_txn), witness_stack).hex()
|
refund_txn = ci.setTxSignature(bytes.fromhex(refund_txn), witness_stack).hex()
|
||||||
else:
|
else:
|
||||||
script = (len(refund_sig) // 2).to_bytes(1) + bytes.fromhex(refund_sig)
|
script = (len(refund_sig) // 2).to_bytes(1, 'big') + bytes.fromhex(refund_sig)
|
||||||
script += (33).to_bytes(1) + pubkey
|
script += (33).to_bytes(1, 'big') + pubkey
|
||||||
script += (OpCodes.OP_0).to_bytes(1)
|
script += (OpCodes.OP_0).to_bytes(1, 'big')
|
||||||
script += (OpCodes.OP_PUSHDATA1).to_bytes(1) + (len(txn_script)).to_bytes(1) + txn_script
|
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)
|
refund_txn = ci.setTxScriptSig(bytes.fromhex(refund_txn), 0, script)
|
||||||
|
|
||||||
if coin_type in (Coins.NAV, Coins.DCR):
|
if coin_type in (Coins.NAV, Coins.DCR):
|
||||||
|
@ -4517,8 +4523,8 @@ class BasicSwap(BaseApp):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if 'Block not available (pruned data)' in str(e):
|
if 'Block not available (pruned data)' in str(e):
|
||||||
# TODO: Better solution?
|
# TODO: Better solution?
|
||||||
bci = self.callcoinrpc(coin_type, 'getblockchaininfo')
|
bci = ci.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'])
|
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']
|
last_height_checked = bci['pruneheight']
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -153,16 +153,19 @@ class CoinInterface:
|
||||||
def use_tx_vsize(self) -> bool:
|
def use_tx_vsize(self) -> bool:
|
||||||
return self._use_segwit
|
return self._use_segwit
|
||||||
|
|
||||||
def getLockTxSwapOutputValue(self, bid, xmr_swap):
|
def getLockTxSwapOutputValue(self, bid, xmr_swap) -> int:
|
||||||
return bid.amount
|
return bid.amount
|
||||||
|
|
||||||
def getLockRefundTxSwapOutputValue(self, bid, xmr_swap):
|
def getLockRefundTxSwapOutputValue(self, bid, xmr_swap) -> int:
|
||||||
return xmr_swap.a_swap_refund_value
|
return xmr_swap.a_swap_refund_value
|
||||||
|
|
||||||
def getLockRefundTxSwapOutput(self, xmr_swap):
|
def getLockRefundTxSwapOutput(self, xmr_swap) -> int:
|
||||||
# Only one prevout exists
|
# Only one prevout exists
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
def checkWallets(self) -> int:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
class AdaptorSigInterface():
|
class AdaptorSigInterface():
|
||||||
def getScriptLockTxDummyWitness(self, script: bytes):
|
def getScriptLockTxDummyWitness(self, script: bytes):
|
||||||
|
|
|
@ -109,7 +109,7 @@ def DCRSignatureHash(sign_script: bytes, hash_type: SigHashType, tx: CTransactio
|
||||||
for txi_n, txi in enumerate(sign_vins):
|
for txi_n, txi in enumerate(sign_vins):
|
||||||
hash_buffer += txi.prevout.hash.to_bytes(32, 'little')
|
hash_buffer += txi.prevout.hash.to_bytes(32, 'little')
|
||||||
hash_buffer += txi.prevout.n.to_bytes(4, '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.
|
# 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
|
if (masked_hash_type == SigHashType.SigHashNone
|
||||||
|
@ -308,14 +308,19 @@ class DCRInterface(Secp256k1Interface):
|
||||||
def getChainHeight(self) -> int:
|
def getChainHeight(self) -> int:
|
||||||
return self.rpc('getblockcount')
|
return self.rpc('getblockcount')
|
||||||
|
|
||||||
def checkWallets(self) -> int:
|
|
||||||
# Only one wallet possible?
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def initialiseWallet(self, key: bytes) -> None:
|
def initialiseWallet(self, key: bytes) -> None:
|
||||||
# Load with --create
|
# Load with --create
|
||||||
pass
|
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):
|
def getDaemonVersion(self):
|
||||||
return self.rpc('getnetworkinfo')['version']
|
return self.rpc('getnetworkinfo')['version']
|
||||||
|
|
||||||
|
@ -368,7 +373,7 @@ class DCRInterface(Secp256k1Interface):
|
||||||
def encodeKey(self, key_bytes: bytes) -> str:
|
def encodeKey(self, key_bytes: bytes) -> str:
|
||||||
wif_prefix = self.chainparams_network()['key_prefix']
|
wif_prefix = self.chainparams_network()['key_prefix']
|
||||||
key_type = 0 # STEcdsaSecp256k1
|
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]
|
b += blake256(b)[:4]
|
||||||
return b58encode(b)
|
return b58encode(b)
|
||||||
|
|
||||||
|
@ -433,7 +438,7 @@ class DCRInterface(Secp256k1Interface):
|
||||||
script_hash = self.pkh(script)
|
script_hash = self.pkh(script)
|
||||||
assert len(script_hash) == 20
|
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:
|
def encodeScriptDest(self, script_dest: bytes) -> str:
|
||||||
script_hash = script_dest[2:-1] # Extract hash from script
|
script_hash = script_dest[2:-1] # Extract hash from script
|
||||||
|
@ -442,7 +447,7 @@ class DCRInterface(Secp256k1Interface):
|
||||||
def getPubkeyHashDest(self, pkh: bytes) -> bytes:
|
def getPubkeyHashDest(self, pkh: bytes) -> bytes:
|
||||||
# P2PKH
|
# P2PKH
|
||||||
assert len(pkh) == 20
|
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:
|
def getPkDest(self, K: bytes) -> bytearray:
|
||||||
return self.getPubkeyHashDest(self.pkh(K))
|
return self.getPubkeyHashDest(self.pkh(K))
|
||||||
|
@ -532,7 +537,7 @@ class DCRInterface(Secp256k1Interface):
|
||||||
prove_utxos.append(outpoint)
|
prove_utxos.append(outpoint)
|
||||||
hasher.update(outpoint[0])
|
hasher.update(outpoint[0])
|
||||||
hasher.update(outpoint[1].to_bytes(2, 'big'))
|
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:
|
if sum_value >= amount_for:
|
||||||
break
|
break
|
||||||
utxos_hash = hasher.digest()
|
utxos_hash = hasher.digest()
|
||||||
|
@ -554,7 +559,7 @@ class DCRInterface(Secp256k1Interface):
|
||||||
def encodeProofUtxos(self, proof_utxos):
|
def encodeProofUtxos(self, proof_utxos):
|
||||||
packed_utxos = bytes()
|
packed_utxos = bytes()
|
||||||
for utxo in proof_utxos:
|
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
|
return packed_utxos
|
||||||
|
|
||||||
def decodeProofUtxos(self, msg_utxos):
|
def decodeProofUtxos(self, msg_utxos):
|
||||||
|
@ -573,7 +578,7 @@ class DCRInterface(Secp256k1Interface):
|
||||||
for outpoint in utxos:
|
for outpoint in utxos:
|
||||||
hasher.update(outpoint[0])
|
hasher.update(outpoint[0])
|
||||||
hasher.update(outpoint[1].to_bytes(2, 'big'))
|
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()
|
utxos_hash = hasher.digest()
|
||||||
|
|
||||||
passed = self.verifyMessage(address, address + '_swap_proof_' + utxos_hash.hex() + extra_commit_bytes.hex(), signature)
|
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)
|
Kaf_enc = Kaf if len(Kaf) == 33 else self.encodePubkey(Kaf)
|
||||||
|
|
||||||
script = bytearray()
|
script = bytearray()
|
||||||
script += OP_IF.to_bytes(1)
|
script += bytes((OP_IF,))
|
||||||
push_script_data(script, bytes((2,)))
|
push_script_data(script, bytes((2,)))
|
||||||
push_script_data(script, Kal_enc)
|
push_script_data(script, Kal_enc)
|
||||||
push_script_data(script, Kaf_enc)
|
push_script_data(script, Kaf_enc)
|
||||||
push_script_data(script, bytes((2,)))
|
push_script_data(script, bytes((2,)))
|
||||||
script += OP_CHECKMULTISIG.to_bytes(1)
|
script += bytes((OP_CHECKMULTISIG,))
|
||||||
script += OP_ELSE.to_bytes(1)
|
script += bytes((OP_ELSE,))
|
||||||
script += CScriptNum.encode(CScriptNum(csv_val))
|
script += CScriptNum.encode(CScriptNum(csv_val))
|
||||||
script += OP_CHECKSEQUENCEVERIFY.to_bytes(1)
|
script += bytes((OP_CHECKSEQUENCEVERIFY,))
|
||||||
script += OP_DROP.to_bytes(1)
|
script += bytes((OP_DROP,))
|
||||||
push_script_data(script, Kaf_enc)
|
push_script_data(script, Kaf_enc)
|
||||||
script += OP_CHECKSIG.to_bytes(1)
|
script += bytes((OP_CHECKSIG,))
|
||||||
script += OP_ENDIF.to_bytes(1)
|
script += bytes((OP_ENDIF,))
|
||||||
|
|
||||||
return script
|
return script
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ class CTransaction:
|
||||||
for txi in self.vin:
|
for txi in self.vin:
|
||||||
data += txi.prevout.hash.to_bytes(32, 'little')
|
data += txi.prevout.hash.to_bytes(32, 'little')
|
||||||
data += txi.prevout.n.to_bytes(4, '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 += txi.sequence.to_bytes(4, 'little')
|
||||||
|
|
||||||
data += encode_compactsize(len(self.vout))
|
data += encode_compactsize(len(self.vout))
|
||||||
|
|
|
@ -39,7 +39,7 @@ def push_script_data(data_array: bytearray, data: bytes) -> None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if len_data < OP_PUSHDATA1:
|
if len_data < OP_PUSHDATA1:
|
||||||
data_array += len_data.to_bytes(1)
|
data_array += len_data.to_bytes(1, 'little')
|
||||||
elif len_data <= 0xff:
|
elif len_data <= 0xff:
|
||||||
data_array += bytes((OP_PUSHDATA1, len_data))
|
data_array += bytes((OP_PUSHDATA1, len_data))
|
||||||
elif len_data <= 0xffff:
|
elif len_data <= 0xffff:
|
||||||
|
|
50
basicswap/interface/dcr/util.py
Normal file
50
basicswap/interface/dcr/util.py
Normal 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()
|
|
@ -42,9 +42,6 @@ class FIROInterface(BTCInterface):
|
||||||
# No multiwallet support
|
# No multiwallet support
|
||||||
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
|
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):
|
def getExchangeName(self, exchange_name):
|
||||||
return 'zcoin'
|
return 'zcoin'
|
||||||
|
|
||||||
|
|
|
@ -73,9 +73,6 @@ class NAVInterface(BTCInterface):
|
||||||
# No multiwallet support
|
# No multiwallet support
|
||||||
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
|
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:
|
def use_p2shp2wsh(self) -> bool:
|
||||||
# p2sh-p2wsh
|
# p2sh-p2wsh
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -35,9 +35,6 @@ class PIVXInterface(BTCInterface):
|
||||||
# No multiwallet support
|
# No multiwallet support
|
||||||
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
|
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
|
||||||
|
|
||||||
def checkWallets(self) -> int:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def signTxWithWallet(self, tx):
|
def signTxWithWallet(self, tx):
|
||||||
rv = self.rpc('signrawtransaction', [tx.hex()])
|
rv = self.rpc('signrawtransaction', [tx.hex()])
|
||||||
return bytes.fromhex(rv['hex'])
|
return bytes.fromhex(rv['hex'])
|
||||||
|
|
|
@ -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.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 ')
|
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):
|
def setFeePriority(self, new_priority):
|
||||||
ensure(new_priority >= 0 and new_priority < 4, 'Invalid fee_priority value')
|
ensure(new_priority >= 0 and new_priority < 4, 'Invalid fee_priority value')
|
||||||
self._fee_priority = new_priority
|
self._fee_priority = new_priority
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% include 'header.html' %}
|
{% 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>
|
<script src="/static/js/libs//qrcode.js"></script>
|
||||||
<div class="container mx-auto">
|
<div class="container mx-auto">
|
||||||
<section class="p-5 mt-5">
|
<section class="p-5 mt-5">
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% include 'inc_messages.html' %}
|
{% include 'inc_messages.html' %}
|
||||||
{% if w.updating %}
|
{% if w.updating %}
|
||||||
<section class="py-4" id="messages_updating" role="alert">
|
<section class="py-4" id="messages_updating" role="alert">
|
||||||
<div class="container px-4 mx-auto">
|
<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-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>
|
<li class="font-medium text-sm text-blue-500">Please wait...</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-auto p-2">
|
<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>
|
<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>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if w.havedata %}
|
{% if w.havedata %}
|
||||||
{% if w.error %}
|
{% if w.error %}
|
||||||
<section class="py-4" id="messages_error" role="alert">
|
<section class="py-4" id="messages_error" role="alert">
|
||||||
<div class="container px-4 mx-auto">
|
<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">
|
<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> {% 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">
|
<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"> <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 %}
|
{% 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>
|
<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 %}
|
{% 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>)
|
<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 %}
|
{% 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>
|
<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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# / LTC #}
|
{# / LTC #}
|
||||||
{% if w.locked_utxos %}
|
{% if w.locked_utxos %}
|
||||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
|
<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>
|
<td class="py-3 px-6 bold">Locked Outputs:</td>
|
||||||
|
@ -202,9 +202,11 @@
|
||||||
<div class="container mt-5 mx-auto">
|
<div class="container mt-5 mx-auto">
|
||||||
<div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
|
<div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
|
||||||
<div class="px-6">
|
<div class="px-6">
|
||||||
|
{% if w.cid != '4' %} {# DCR #}
|
||||||
<div class="flex flex-wrap justify-end">
|
<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 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>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -369,7 +371,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# / LTC #}
|
{# / LTC #}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -383,7 +385,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Particl Stealth
|
// Particl Stealth
|
||||||
var stealthAddress = "{{ w.stealth_address }}";
|
var stealthAddress = "{{ w.stealth_address }}";
|
||||||
|
|
||||||
var qrCodeStealth = new QRCode(document.getElementById("qrcode-stealth"), {
|
var qrCodeStealth = new QRCode(document.getElementById("qrcode-stealth"), {
|
||||||
text: stealthAddress,
|
text: stealthAddress,
|
||||||
width: 170,
|
width: 170,
|
||||||
|
@ -399,7 +401,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Litecoin MWEB
|
// Litecoin MWEB
|
||||||
var mwebAddress = "{{ w.mweb_address }}";
|
var mwebAddress = "{{ w.mweb_address }}";
|
||||||
|
|
||||||
var qrCodeMWEB = new QRCode(document.getElementById("qrcode-mweb"), {
|
var qrCodeMWEB = new QRCode(document.getElementById("qrcode-mweb"), {
|
||||||
text: mwebAddress,
|
text: mwebAddress,
|
||||||
width: 170,
|
width: 170,
|
||||||
|
@ -408,14 +410,14 @@
|
||||||
colorLight: "#ffffff",
|
colorLight: "#ffffff",
|
||||||
correctLevel: QRCode.CorrectLevel.L
|
correctLevel: QRCode.CorrectLevel.L
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if w.cid == '6' %}
|
{% if w.cid == '6' %}
|
||||||
{# XMR #}
|
{# XMR #}
|
||||||
<script>
|
<script>
|
||||||
// Monero Sub
|
// Monero Sub
|
||||||
var moneroSubAddress = "{{ w.deposit_address }}";
|
var moneroSubAddress = "{{ w.deposit_address }}";
|
||||||
|
|
||||||
var qrCodeMoneroSub = new QRCode(document.getElementById("qrcode-monero-sub"), {
|
var qrCodeMoneroSub = new QRCode(document.getElementById("qrcode-monero-sub"), {
|
||||||
text: moneroSubAddress,
|
text: moneroSubAddress,
|
||||||
width: 170,
|
width: 170,
|
||||||
|
@ -428,7 +430,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Monero Main
|
// Monero Main
|
||||||
var moneroMainAddress = "{{ w.main_address }}";
|
var moneroMainAddress = "{{ w.main_address }}";
|
||||||
|
|
||||||
var qrCodeMoneroMain = new QRCode(document.getElementById("qrcode-monero-main"), {
|
var qrCodeMoneroMain = new QRCode(document.getElementById("qrcode-monero-main"), {
|
||||||
text: moneroMainAddress,
|
text: moneroMainAddress,
|
||||||
width: 170,
|
width: 170,
|
||||||
|
@ -442,7 +444,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Default
|
// Default
|
||||||
var defaultAddress = "{{ w.deposit_address }}";
|
var defaultAddress = "{{ w.deposit_address }}";
|
||||||
|
|
||||||
var qrCodeDepost = new QRCode(document.getElementById("qrcode-deposit"), {
|
var qrCodeDepost = new QRCode(document.getElementById("qrcode-deposit"), {
|
||||||
text: defaultAddress,
|
text: defaultAddress,
|
||||||
width: 170,
|
width: 170,
|
||||||
|
@ -462,48 +464,48 @@
|
||||||
document.execCommand('copy');
|
document.execCommand('copy');
|
||||||
document.body.removeChild(el);
|
document.body.removeChild(el);
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyAndShowMessage(elementId) {
|
function copyAndShowMessage(elementId) {
|
||||||
const addressElement = document.getElementById(elementId);
|
const addressElement = document.getElementById(elementId);
|
||||||
if (!addressElement) return;
|
if (!addressElement) return;
|
||||||
const addressText = addressElement.innerText.trim();
|
const addressText = addressElement.innerText.trim();
|
||||||
copyToClipboard(addressText);
|
copyToClipboard(addressText);
|
||||||
addressElement.innerText = 'Copied to clipboard';
|
addressElement.innerText = 'Copied to clipboard';
|
||||||
|
|
||||||
const originalWidth = addressElement.offsetWidth;
|
const originalWidth = addressElement.offsetWidth;
|
||||||
|
|
||||||
addressElement.classList.add('copying');
|
addressElement.classList.add('copying');
|
||||||
|
|
||||||
addressElement.parentElement.style.width = `${originalWidth}px`;
|
addressElement.parentElement.style.width = `${originalWidth}px`;
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
addressElement.innerText = addressText;
|
addressElement.innerText = addressText;
|
||||||
addressElement.classList.remove('copying');
|
addressElement.classList.remove('copying');
|
||||||
addressElement.parentElement.style.width = '';
|
addressElement.parentElement.style.width = '';
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
const stealthAddressElement = document.getElementById('stealth_address');
|
const stealthAddressElement = document.getElementById('stealth_address');
|
||||||
if (stealthAddressElement) {
|
if (stealthAddressElement) {
|
||||||
stealthAddressElement.addEventListener('click', function () {
|
stealthAddressElement.addEventListener('click', function () {
|
||||||
copyAndShowMessage('stealth_address');
|
copyAndShowMessage('stealth_address');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const mainDepositAddressElement = document.getElementById('main_deposit_address');
|
const mainDepositAddressElement = document.getElementById('main_deposit_address');
|
||||||
if (mainDepositAddressElement) {
|
if (mainDepositAddressElement) {
|
||||||
mainDepositAddressElement.addEventListener('click', function () {
|
mainDepositAddressElement.addEventListener('click', function () {
|
||||||
copyAndShowMessage('main_deposit_address');
|
copyAndShowMessage('main_deposit_address');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const moneroMainAddressElement = document.getElementById('monero_main_address');
|
const moneroMainAddressElement = document.getElementById('monero_main_address');
|
||||||
if (moneroMainAddressElement) {
|
if (moneroMainAddressElement) {
|
||||||
moneroMainAddressElement.addEventListener('click', function () {
|
moneroMainAddressElement.addEventListener('click', function () {
|
||||||
copyAndShowMessage('monero_main_address');
|
copyAndShowMessage('monero_main_address');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const moneroSubAddressElement = document.getElementById('monero_sub_address');
|
const moneroSubAddressElement = document.getElementById('monero_sub_address');
|
||||||
if (moneroSubAddressElement) {
|
if (moneroSubAddressElement) {
|
||||||
moneroSubAddressElement.addEventListener('click', function () {
|
moneroSubAddressElement.addEventListener('click', function () {
|
||||||
|
@ -572,7 +574,7 @@
|
||||||
var selectedType = typeSelect.value;
|
var selectedType = typeSelect.value;
|
||||||
var floatBalance;
|
var floatBalance;
|
||||||
var calculatedAmount;
|
var calculatedAmount;
|
||||||
|
|
||||||
switch(selectedType) {
|
switch(selectedType) {
|
||||||
case 'plain':
|
case 'plain':
|
||||||
floatBalance = parseFloat(balance);
|
floatBalance = parseFloat(balance);
|
||||||
|
@ -591,7 +593,7 @@
|
||||||
calculatedAmount = floatBalance * percent;
|
calculatedAmount = floatBalance * percent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
amountInput.value = calculatedAmount.toFixed(8);
|
amountInput.value = calculatedAmount.toFixed(8);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -606,7 +608,7 @@
|
||||||
var selectedType = typeSelect.value;
|
var selectedType = typeSelect.value;
|
||||||
var floatBalance;
|
var floatBalance;
|
||||||
var calculatedAmount;
|
var calculatedAmount;
|
||||||
|
|
||||||
switch(selectedType) {
|
switch(selectedType) {
|
||||||
case 'plain':
|
case 'plain':
|
||||||
floatBalance = parseFloat(balance);
|
floatBalance = parseFloat(balance);
|
||||||
|
@ -621,7 +623,7 @@
|
||||||
calculatedAmount = floatBalance * percent;
|
calculatedAmount = floatBalance * percent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
amountInput.value = calculatedAmount.toFixed(8);
|
amountInput.value = calculatedAmount.toFixed(8);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -633,10 +635,10 @@
|
||||||
var amountInput = document.getElementById('amount');
|
var amountInput = document.getElementById('amount');
|
||||||
var floatBalance;
|
var floatBalance;
|
||||||
var calculatedAmount;
|
var calculatedAmount;
|
||||||
|
|
||||||
floatBalance = parseFloat(balance);
|
floatBalance = parseFloat(balance);
|
||||||
calculatedAmount = floatBalance * percent;
|
calculatedAmount = floatBalance * percent;
|
||||||
|
|
||||||
if (cid === '6' && percent === 1) {
|
if (cid === '6' && percent === 1) {
|
||||||
amountInput.setAttribute('data-hidden', 'true');
|
amountInput.setAttribute('data-hidden', 'true');
|
||||||
amountInput.placeholder = 'Sweep All';
|
amountInput.placeholder = 'Sweep All';
|
||||||
|
@ -652,7 +654,7 @@
|
||||||
amountInput.placeholder = '';
|
amountInput.placeholder = '';
|
||||||
amountInput.disabled = false;
|
amountInput.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cid === '6' && percent === 1) {
|
if (cid === '6' && percent === 1) {
|
||||||
var sweepAllCheckbox = document.getElementById('sweepall');
|
var sweepAllCheckbox = document.getElementById('sweepall');
|
||||||
if (sweepAllCheckbox) {
|
if (sweepAllCheckbox) {
|
||||||
|
@ -665,7 +667,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</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" 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>
|
<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 %}
|
{% endif %}
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if w.cid == '1' %}
|
{% if w.cid == '1' %}
|
||||||
|
@ -855,7 +857,7 @@
|
||||||
'DECRED': 'DCR',
|
'DECRED': 'DCR',
|
||||||
'WOWNERO': 'WOW'
|
'WOWNERO': 'WOW'
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUsdValue = (cryptoValue, coinSymbol) => fetch(`https://min-api.cryptocompare.com/data/price?fsym=${coinSymbol}&tsyms=USD`)
|
const getUsdValue = (cryptoValue, coinSymbol) => fetch(`https://min-api.cryptocompare.com/data/price?fsym=${coinSymbol}&tsyms=USD`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
@ -866,16 +868,16 @@
|
||||||
throw new Error(`Invalid exchange rate for ${coinSymbol}`);
|
throw new Error(`Invalid exchange rate for ${coinSymbol}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateUsdValue = async (cryptoCell, coinFullName, usdValueSpan) => {
|
const updateUsdValue = async (cryptoCell, coinFullName, usdValueSpan) => {
|
||||||
const coinSymbol = coinNameToSymbol[coinFullName] || '';
|
const coinSymbol = coinNameToSymbol[coinFullName] || '';
|
||||||
if (!coinSymbol) {
|
if (!coinSymbol) {
|
||||||
console.error(`Coin symbol not found for full name: ${coinFullName}`);
|
console.error(`Coin symbol not found for full name: ${coinFullName}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cryptoValue = parseFloat(cryptoCell.textContent);
|
const cryptoValue = parseFloat(cryptoCell.textContent);
|
||||||
|
|
||||||
if (!isNaN(cryptoValue) && cryptoValue !== 0) {
|
if (!isNaN(cryptoValue) && cryptoValue !== 0) {
|
||||||
try {
|
try {
|
||||||
const usdValue = await getUsdValue(cryptoValue, coinSymbol);
|
const usdValue = await getUsdValue(cryptoValue, coinSymbol);
|
||||||
|
@ -894,19 +896,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateTotalUsdValue = async () => {
|
const calculateTotalUsdValue = async () => {
|
||||||
const coinNameValues = document.querySelectorAll('.coinname-value');
|
const coinNameValues = document.querySelectorAll('.coinname-value');
|
||||||
let totalUsdValue = 0;
|
let totalUsdValue = 0;
|
||||||
|
|
||||||
for (const coinNameValue of coinNameValues) {
|
for (const coinNameValue of coinNameValues) {
|
||||||
const coinFullName = coinNameValue.getAttribute('data-coinname');
|
const coinFullName = coinNameValue.getAttribute('data-coinname');
|
||||||
const cryptoValue = parseFloat(coinNameValue.textContent);
|
const cryptoValue = parseFloat(coinNameValue.textContent);
|
||||||
const coinSymbol = coinNameToSymbol[coinFullName];
|
const coinSymbol = coinNameToSymbol[coinFullName];
|
||||||
|
|
||||||
if (coinSymbol) {
|
if (coinSymbol) {
|
||||||
const usdValueSpan = coinNameValue.querySelector('.usd-value');
|
const usdValueSpan = coinNameValue.querySelector('.usd-value');
|
||||||
|
|
||||||
if (!isNaN(cryptoValue) && cryptoValue !== 0) {
|
if (!isNaN(cryptoValue) && cryptoValue !== 0) {
|
||||||
try {
|
try {
|
||||||
const usdValue = await getUsdValue(cryptoValue, coinSymbol);
|
const usdValue = await getUsdValue(cryptoValue, coinSymbol);
|
||||||
|
@ -926,24 +928,24 @@
|
||||||
console.error(`Coin symbol not found for full name: ${coinFullName}`);
|
console.error(`Coin symbol not found for full name: ${coinFullName}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalUsdValueElement = document.getElementById('total-usd-value');
|
const totalUsdValueElement = document.getElementById('total-usd-value');
|
||||||
if (totalUsdValueElement) {
|
if (totalUsdValueElement) {
|
||||||
totalUsdValueElement.textContent = `$${totalUsdValue.toFixed(2)}`;
|
totalUsdValueElement.textContent = `$${totalUsdValue.toFixed(2)}`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const coinNameValues = document.querySelectorAll('.coinname-value');
|
const coinNameValues = document.querySelectorAll('.coinname-value');
|
||||||
|
|
||||||
for (const coinNameValue of coinNameValues) {
|
for (const coinNameValue of coinNameValues) {
|
||||||
const coinFullName = coinNameValue.getAttribute('data-coinname');
|
const coinFullName = coinNameValue.getAttribute('data-coinname');
|
||||||
const usdValueSpan = coinNameValue.querySelector('.usd-value');
|
const usdValueSpan = coinNameValue.querySelector('.usd-value');
|
||||||
updateUsdValue(coinNameValue, coinFullName, usdValueSpan);
|
updateUsdValue(coinNameValue, coinFullName, usdValueSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateTotalUsdValue();
|
calculateTotalUsdValue();
|
||||||
|
|
||||||
function set_sweep_all(element) {
|
function set_sweep_all(element) {
|
||||||
let input = document.getElementById('amount');
|
let input = document.getElementById('amount');
|
||||||
if (element.checked) {
|
if (element.checked) {
|
||||||
|
@ -952,7 +954,7 @@
|
||||||
input.disabled = false;
|
input.disabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let cb_sweepall = document.getElementById('sweepall');
|
let cb_sweepall = document.getElementById('sweepall');
|
||||||
if (cb_sweepall) {
|
if (cb_sweepall) {
|
||||||
set_sweep_all(cb_sweepall);
|
set_sweep_all(cb_sweepall);
|
||||||
|
@ -960,7 +962,7 @@
|
||||||
set_sweep_all(event.currentTarget);
|
set_sweep_all(event.currentTarget);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% include 'footer.html' %}
|
{% include 'footer.html' %}
|
||||||
|
@ -968,11 +970,11 @@
|
||||||
function confirmReseed() {
|
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.");
|
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() {
|
function confirmWithdrawal() {
|
||||||
return confirm("Are you sure?");
|
return confirm("Are you sure?");
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmUTXOResize() {
|
function confirmUTXOResize() {
|
||||||
return confirm("Are you sure?");
|
return confirm("Are you sure?");
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ from coincurve.keys import (
|
||||||
|
|
||||||
|
|
||||||
def BIP32Hash(chaincode: bytes, child_no: int, key_data_type: int, keydata: bytes):
|
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:
|
def hash160_dcr(data: bytes) -> bytes:
|
||||||
|
@ -85,7 +85,7 @@ class ExtKeyPair():
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def encode_v(self) -> bytes:
|
def encode_v(self) -> bytes:
|
||||||
return self._depth.to_bytes(1) + \
|
return self._depth.to_bytes(1, 'big') + \
|
||||||
self._fingerprint + \
|
self._fingerprint + \
|
||||||
self._child_no.to_bytes(4, 'big') + \
|
self._child_no.to_bytes(4, 'big') + \
|
||||||
self._chaincode + \
|
self._chaincode + \
|
||||||
|
@ -94,7 +94,7 @@ class ExtKeyPair():
|
||||||
|
|
||||||
def encode_p(self) -> bytes:
|
def encode_p(self) -> bytes:
|
||||||
pubkey = PublicKey.from_secret(self._key).format() if self._pubkey is None else self._pubkey
|
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._fingerprint + \
|
||||||
self._child_no.to_bytes(4, 'big') + \
|
self._child_no.to_bytes(4, 'big') + \
|
||||||
self._chaincode + \
|
self._chaincode + \
|
||||||
|
|
|
@ -5,37 +5,40 @@
|
||||||
# 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.
|
||||||
|
|
||||||
import os
|
import contextlib
|
||||||
import sys
|
|
||||||
import json
|
|
||||||
import time
|
|
||||||
import mmap
|
|
||||||
import stat
|
|
||||||
import gnupg
|
import gnupg
|
||||||
import socks
|
import hashlib
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import mmap
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
import random
|
||||||
import shutil
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
import socket
|
import socket
|
||||||
import hashlib
|
import socks
|
||||||
|
import stat
|
||||||
|
import sys
|
||||||
import tarfile
|
import tarfile
|
||||||
import zipfile
|
import threading
|
||||||
import logging
|
import time
|
||||||
import platform
|
|
||||||
import contextlib
|
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
import zipfile
|
||||||
|
|
||||||
from urllib.error import ContentTooShortError
|
from urllib.error import ContentTooShortError
|
||||||
from urllib.request import Request, urlopen
|
|
||||||
from urllib.parse import _splittype
|
from urllib.parse import _splittype
|
||||||
|
from urllib.request import Request, urlopen
|
||||||
|
|
||||||
import basicswap.config as cfg
|
import basicswap.config as cfg
|
||||||
from basicswap import __version__
|
|
||||||
from basicswap.base import getaddrinfo_tor
|
from basicswap.base import getaddrinfo_tor
|
||||||
from basicswap.basicswap import BasicSwap
|
from basicswap.basicswap import BasicSwap
|
||||||
from basicswap.chainparams import Coins
|
from basicswap.chainparams import Coins
|
||||||
|
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
|
||||||
|
from basicswap import __version__
|
||||||
from basicswap.ui.util import getCoinName
|
from basicswap.ui.util import getCoinName
|
||||||
from basicswap.util import toBool
|
from basicswap.util import toBool
|
||||||
from basicswap.util.rfc2440 import rfc2440_hash_password
|
from basicswap.util.rfc2440 import rfc2440_hash_password
|
||||||
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
|
|
||||||
from bin.basicswap_run import startDaemon, startXmrWalletDaemon
|
from bin.basicswap_run import startDaemon, startXmrWalletDaemon
|
||||||
|
|
||||||
PARTICL_VERSION = os.getenv('PARTICL_VERSION', '23.2.7.0')
|
PARTICL_VERSION = os.getenv('PARTICL_VERSION', '23.2.7.0')
|
||||||
|
@ -92,7 +95,6 @@ known_coins = {
|
||||||
disabled_coins = [
|
disabled_coins = [
|
||||||
'navcoin',
|
'navcoin',
|
||||||
'namecoin', # Needs update
|
'namecoin', # Needs update
|
||||||
'decred', # In-progress
|
|
||||||
]
|
]
|
||||||
|
|
||||||
expected_key_ids = {
|
expected_key_ids = {
|
||||||
|
@ -169,8 +171,11 @@ BTC_RPC_PWD = os.getenv('BTC_RPC_PWD', '')
|
||||||
|
|
||||||
DCR_RPC_HOST = os.getenv('DCR_RPC_HOST', '127.0.0.1')
|
DCR_RPC_HOST = os.getenv('DCR_RPC_HOST', '127.0.0.1')
|
||||||
DCR_RPC_PORT = int(os.getenv('DCR_RPC_PORT', 9109))
|
DCR_RPC_PORT = int(os.getenv('DCR_RPC_PORT', 9109))
|
||||||
DCR_RPC_USER = os.getenv('DCR_RPC_USER', '')
|
DCR_WALLET_RPC_HOST = os.getenv('DCR_WALLET_RPC_HOST', '127.0.0.1')
|
||||||
DCR_RPC_PWD = os.getenv('DCR_RPC_PWD', '')
|
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_HOST = os.getenv('NMC_RPC_HOST', '127.0.0.1')
|
||||||
NMC_RPC_PORT = int(os.getenv('NMC_RPC_PORT', 19698))
|
NMC_RPC_PORT = int(os.getenv('NMC_RPC_PORT', 19698))
|
||||||
|
@ -367,16 +372,16 @@ def setConnectionParameters(timeout: int = 5, allow_set_tor: bool = True):
|
||||||
socket.setdefaulttimeout(timeout)
|
socket.setdefaulttimeout(timeout)
|
||||||
|
|
||||||
|
|
||||||
def popConnectionParameters():
|
def popConnectionParameters() -> None:
|
||||||
if use_tor_proxy:
|
if use_tor_proxy:
|
||||||
socket.socket = default_socket
|
socket.socket = default_socket
|
||||||
socket.getaddrinfo = default_socket_getaddrinfo
|
socket.getaddrinfo = default_socket_getaddrinfo
|
||||||
socket.setdefaulttimeout(default_socket_timeout)
|
socket.setdefaulttimeout(default_socket_timeout)
|
||||||
|
|
||||||
|
|
||||||
def downloadFile(url, path, timeout=5, resume_from=0):
|
def downloadFile(url: str, path: str, timeout=5, resume_from=0) -> None:
|
||||||
logger.info('Downloading file %s', url)
|
logger.info(f'Downloading file {url}')
|
||||||
logger.info('To %s', path)
|
logger.info(f'To {path}')
|
||||||
try:
|
try:
|
||||||
setConnectionParameters(timeout=timeout)
|
setConnectionParameters(timeout=timeout)
|
||||||
urlretrieve(url, path, make_reporthook(resume_from), resume_from=resume_from)
|
urlretrieve(url, path, make_reporthook(resume_from), resume_from=resume_from)
|
||||||
|
@ -397,13 +402,12 @@ def importPubkeyFromUrls(gpg, pubkeyurls):
|
||||||
try:
|
try:
|
||||||
logger.info('Importing public key from url: ' + url)
|
logger.info('Importing public key from url: ' + url)
|
||||||
rv = gpg.import_keys(downloadBytes(url))
|
rv = gpg.import_keys(downloadBytes(url))
|
||||||
|
for key in rv.fingerprints:
|
||||||
|
gpg.trust_keys(key, 'TRUST_FULLY')
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.warning('Import from url failed: %s', str(e))
|
logging.warning('Import from url failed: %s', str(e))
|
||||||
|
|
||||||
for key in rv.fingerprints:
|
|
||||||
gpg.trust_keys(key, 'TRUST_FULLY')
|
|
||||||
|
|
||||||
|
|
||||||
def testTorConnection():
|
def testTorConnection():
|
||||||
test_url = 'https://check.torproject.org/'
|
test_url = 'https://check.torproject.org/'
|
||||||
|
@ -773,6 +777,8 @@ def prepareCore(coin, version_data, settings, data_dir, extra_opts={}):
|
||||||
|
|
||||||
if coin in ('navcoin', ):
|
if coin in ('navcoin', ):
|
||||||
pubkey_filename = '{}_builder.pgp'.format(coin)
|
pubkey_filename = '{}_builder.pgp'.format(coin)
|
||||||
|
elif coin in ('decred', ):
|
||||||
|
pubkey_filename = '{}_release.pgp'.format(coin)
|
||||||
else:
|
else:
|
||||||
pubkey_filename = '{}_{}.pgp'.format(coin, signing_key_name)
|
pubkey_filename = '{}_{}.pgp'.format(coin, signing_key_name)
|
||||||
pubkeyurls = [
|
pubkeyurls = [
|
||||||
|
@ -914,6 +920,40 @@ def prepareDataDir(coin, settings, chain, particl_mnemonic, extra_opts={}):
|
||||||
fp.write(opt_line + '\n')
|
fp.write(opt_line + '\n')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if coin == 'decred':
|
||||||
|
chainname = 'simnet' if chain == 'regtest' else chain
|
||||||
|
core_conf_path = os.path.join(data_dir, 'dcrd.conf')
|
||||||
|
if os.path.exists(core_conf_path):
|
||||||
|
exitWithError('{} exists'.format(core_conf_path))
|
||||||
|
with open(core_conf_path, 'w') as fp:
|
||||||
|
if chain != 'mainnet':
|
||||||
|
fp.write(chainname + '=1\n')
|
||||||
|
fp.write('debuglevel=debug\n')
|
||||||
|
fp.write('notls=1\n')
|
||||||
|
|
||||||
|
fp.write('rpclisten={}:{}\n'.format(core_settings['rpchost'], core_settings['rpcport']))
|
||||||
|
|
||||||
|
fp.write('rpcuser={}\n'.format(core_settings['rpcuser']))
|
||||||
|
fp.write('rpcpass={}\n'.format(core_settings['rpcpassword']))
|
||||||
|
|
||||||
|
wallet_conf_path = os.path.join(data_dir, 'dcrwallet.conf')
|
||||||
|
if os.path.exists(wallet_conf_path):
|
||||||
|
exitWithError('{} exists'.format(wallet_conf_path))
|
||||||
|
with open(wallet_conf_path, 'w') as fp:
|
||||||
|
if chain != 'mainnet':
|
||||||
|
fp.write(chainname + '=1\n')
|
||||||
|
fp.write('debuglevel=debug\n')
|
||||||
|
fp.write('noservertls=1\n')
|
||||||
|
fp.write('noclienttls=1\n')
|
||||||
|
|
||||||
|
fp.write('rpcconnect={}:{}\n'.format(core_settings['rpchost'], core_settings['rpcport']))
|
||||||
|
fp.write('rpclisten={}:{}\n'.format(core_settings['walletrpchost'], core_settings['walletrpcport']))
|
||||||
|
|
||||||
|
fp.write('username={}\n'.format(core_settings['rpcuser']))
|
||||||
|
fp.write('password={}\n'.format(core_settings['rpcpassword']))
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
core_conf_path = os.path.join(data_dir, coin + '.conf')
|
core_conf_path = os.path.join(data_dir, coin + '.conf')
|
||||||
if os.path.exists(core_conf_path):
|
if os.path.exists(core_conf_path):
|
||||||
exitWithError('{} exists'.format(core_conf_path))
|
exitWithError('{} exists'.format(core_conf_path))
|
||||||
|
@ -1253,6 +1293,8 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
|
||||||
if coin_settings['manage_wallet_daemon']:
|
if coin_settings['manage_wallet_daemon']:
|
||||||
filename = 'monero-wallet-rpc' + ('.exe' if os.name == 'nt' else '')
|
filename = 'monero-wallet-rpc' + ('.exe' if os.name == 'nt' else '')
|
||||||
daemons.append(startXmrWalletDaemon(coin_settings['datadir'], coin_settings['bindir'], filename))
|
daemons.append(startXmrWalletDaemon(coin_settings['datadir'], coin_settings['bindir'], filename))
|
||||||
|
elif c == Coins.DCR:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
if coin_settings['manage_daemon']:
|
if coin_settings['manage_daemon']:
|
||||||
filename = coin_name + 'd' + ('.exe' if os.name == 'nt' else '')
|
filename = coin_name + 'd' + ('.exe' if os.name == 'nt' else '')
|
||||||
|
@ -1266,6 +1308,17 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
|
||||||
swap_client.setCoinRunParams(c)
|
swap_client.setCoinRunParams(c)
|
||||||
swap_client.createCoinInterface(c)
|
swap_client.createCoinInterface(c)
|
||||||
|
|
||||||
|
if c == Coins.DCR:
|
||||||
|
if coin_settings['manage_wallet_daemon']:
|
||||||
|
from basicswap.interface.dcr.util import createDCRWallet
|
||||||
|
extra_opts = ['--appdata="{}"'.format(coin_settings['datadir']),
|
||||||
|
'--pass={}'.format(coin_settings['wallet_pwd']),
|
||||||
|
]
|
||||||
|
|
||||||
|
filename = 'dcrwallet' + ('.exe' if os.name == 'nt' else '')
|
||||||
|
args = [os.path.join(coin_settings['bindir'], filename), '--create'] + extra_opts
|
||||||
|
hex_seed = swap_client.getWalletKey(Coins.DCR, 1).hex()
|
||||||
|
createDCRWallet(args, hex_seed, logger, threading.Event())
|
||||||
if c in coins_to_create_wallets_for:
|
if c in coins_to_create_wallets_for:
|
||||||
swap_client.waitForDaemonRPC(c, with_wallet=False)
|
swap_client.waitForDaemonRPC(c, with_wallet=False)
|
||||||
# Create wallet if it doesn't exist yet
|
# Create wallet if it doesn't exist yet
|
||||||
|
@ -1300,7 +1353,9 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
|
||||||
c = swap_client.getCoinIdFromName(coin_name)
|
c = swap_client.getCoinIdFromName(coin_name)
|
||||||
if c in (Coins.PART, ):
|
if c in (Coins.PART, ):
|
||||||
continue
|
continue
|
||||||
swap_client.waitForDaemonRPC(c)
|
if c not in (Coins.DCR, ):
|
||||||
|
# initialiseWallet only sets main_wallet_seedid_
|
||||||
|
swap_client.waitForDaemonRPC(c)
|
||||||
try:
|
try:
|
||||||
swap_client.initialiseWallet(c, raise_errors=True)
|
swap_client.initialiseWallet(c, raise_errors=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -1320,11 +1375,11 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
|
||||||
|
|
||||||
print('')
|
print('')
|
||||||
for pair in coins_failed_to_initialise:
|
for pair in coins_failed_to_initialise:
|
||||||
c, _ = pair
|
c, e = pair
|
||||||
if c in (Coins.PIVX, ):
|
if c in (Coins.PIVX, ):
|
||||||
print(f'NOTE - Unable to initialise wallet for {getCoinName(c)}. To complete setup click \'Reseed Wallet\' from the ui page once chain is synced.')
|
print(f'NOTE - Unable to initialise wallet for {getCoinName(c)}. To complete setup click \'Reseed Wallet\' from the ui page once chain is synced.')
|
||||||
else:
|
else:
|
||||||
print(f'WARNING - Failed to initialise wallet for {getCoinName(c)}')
|
print(f'WARNING - Failed to initialise wallet for {getCoinName(c)}: {e}')
|
||||||
|
|
||||||
if particl_wallet_mnemonic is not None:
|
if particl_wallet_mnemonic is not None:
|
||||||
if particl_wallet_mnemonic:
|
if particl_wallet_mnemonic:
|
||||||
|
@ -1637,10 +1692,17 @@ def main():
|
||||||
'decred': {
|
'decred': {
|
||||||
'connection_type': 'rpc' if 'decred' in with_coins else 'none',
|
'connection_type': 'rpc' if 'decred' in with_coins else 'none',
|
||||||
'manage_daemon': True if ('decred' in with_coins and DCR_RPC_HOST == '127.0.0.1') else False,
|
'manage_daemon': True if ('decred' in with_coins and DCR_RPC_HOST == '127.0.0.1') else False,
|
||||||
|
'manage_wallet_daemon': True if ('decred' in with_coins and DCR_WALLET_RPC_HOST == '127.0.0.1') else False,
|
||||||
|
'wallet_pwd': DCR_WALLET_PWD,
|
||||||
'rpchost': DCR_RPC_HOST,
|
'rpchost': DCR_RPC_HOST,
|
||||||
'rpcport': DCR_RPC_PORT + port_offset,
|
'rpcport': DCR_RPC_PORT + port_offset,
|
||||||
|
'walletrpchost': DCR_WALLET_RPC_HOST,
|
||||||
|
'walletrpcport': DCR_WALLET_RPC_PORT + port_offset,
|
||||||
|
'rpcuser': DCR_RPC_USER,
|
||||||
|
'rpcpassword': DCR_RPC_PWD,
|
||||||
'datadir': os.getenv('DCR_DATA_DIR', os.path.join(data_dir, 'decred')),
|
'datadir': os.getenv('DCR_DATA_DIR', os.path.join(data_dir, 'decred')),
|
||||||
'bindir': os.path.join(bin_dir, 'decred'),
|
'bindir': os.path.join(bin_dir, 'decred'),
|
||||||
|
'use_csv': True,
|
||||||
'use_segwit': True,
|
'use_segwit': True,
|
||||||
'blocks_confirmed': 2,
|
'blocks_confirmed': 2,
|
||||||
'conf_target': 2,
|
'conf_target': 2,
|
||||||
|
|
|
@ -236,7 +236,33 @@ def runClient(fp, data_dir, chain, start_only_coins):
|
||||||
pid = daemons[-1].handle.pid
|
pid = daemons[-1].handle.pid
|
||||||
swap_client.log.info('Started {} {}'.format(filename, pid))
|
swap_client.log.info('Started {} {}'.format(filename, pid))
|
||||||
|
|
||||||
continue
|
continue # /monero
|
||||||
|
|
||||||
|
if c == 'decred':
|
||||||
|
appdata = v['datadir']
|
||||||
|
extra_opts = [f'--appdata="{appdata}"', ]
|
||||||
|
if v['manage_daemon'] is True:
|
||||||
|
swap_client.log.info(f'Starting {display_name} daemon')
|
||||||
|
filename = 'dcrd' + ('.exe' if os.name == 'nt' else '')
|
||||||
|
|
||||||
|
extra_config = {'add_datadir': False, 'stdout_to_file': True, 'stdout_filename': 'dcrd_stdout.log'}
|
||||||
|
daemons.append(startDaemon(appdata, v['bindir'], filename, opts=extra_opts, extra_config=extra_config))
|
||||||
|
pid = daemons[-1].handle.pid
|
||||||
|
swap_client.log.info('Started {} {}'.format(filename, pid))
|
||||||
|
|
||||||
|
if v['manage_wallet_daemon'] is True:
|
||||||
|
swap_client.log.info(f'Starting {display_name} wallet daemon')
|
||||||
|
filename = 'dcrwallet' + ('.exe' if os.name == 'nt' else '')
|
||||||
|
|
||||||
|
wallet_pwd = v['wallet_pwd']
|
||||||
|
extra_opts.append(f'--pass="{wallet_pwd}"')
|
||||||
|
extra_config = {'add_datadir': False, 'stdout_to_file': True, 'stdout_filename': 'dcrwallet_stdout.log'}
|
||||||
|
daemons.append(startDaemon(appdata, v['bindir'], filename, opts=extra_opts, extra_config=extra_config))
|
||||||
|
pid = daemons[-1].handle.pid
|
||||||
|
swap_client.log.info('Started {} {}'.format(filename, pid))
|
||||||
|
|
||||||
|
continue # /decred
|
||||||
|
|
||||||
if v['manage_daemon'] is True:
|
if v['manage_daemon'] is True:
|
||||||
swap_client.log.info(f'Starting {display_name} daemon')
|
swap_client.log.info(f'Starting {display_name} daemon')
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright (c) 2020-2023 tecnovert
|
# Copyright (c) 2020-2024 tecnovert
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
|
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -35,6 +35,10 @@ LTC_BASE_PORT = 34792
|
||||||
LTC_BASE_RPC_PORT = 35792
|
LTC_BASE_RPC_PORT = 35792
|
||||||
LTC_BASE_ZMQ_PORT = 36792
|
LTC_BASE_ZMQ_PORT = 36792
|
||||||
|
|
||||||
|
DCR_BASE_PORT = 18555
|
||||||
|
DCR_BASE_RPC_PORT = 9110
|
||||||
|
|
||||||
|
|
||||||
PIVX_BASE_PORT = 34892
|
PIVX_BASE_PORT = 34892
|
||||||
PIVX_BASE_RPC_PORT = 35892
|
PIVX_BASE_RPC_PORT = 35892
|
||||||
PIVX_BASE_ZMQ_PORT = 36892
|
PIVX_BASE_ZMQ_PORT = 36892
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright (c) 2020-2022 tecnovert
|
# Copyright (c) 2020-2024 tecnovert
|
||||||
# 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.
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ from tests.basicswap.common import (
|
||||||
BASE_PORT, BASE_RPC_PORT,
|
BASE_PORT, BASE_RPC_PORT,
|
||||||
BTC_BASE_PORT, BTC_BASE_RPC_PORT, BTC_BASE_TOR_PORT,
|
BTC_BASE_PORT, BTC_BASE_RPC_PORT, BTC_BASE_TOR_PORT,
|
||||||
LTC_BASE_PORT, LTC_BASE_RPC_PORT,
|
LTC_BASE_PORT, LTC_BASE_RPC_PORT,
|
||||||
|
DCR_BASE_PORT, DCR_BASE_RPC_PORT,
|
||||||
PIVX_BASE_PORT,
|
PIVX_BASE_PORT,
|
||||||
)
|
)
|
||||||
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
|
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
|
||||||
|
@ -46,6 +47,7 @@ BITCOIN_RPC_PORT_BASE = int(os.getenv('BITCOIN_RPC_PORT_BASE', BTC_BASE_RPC_PORT
|
||||||
BITCOIN_TOR_PORT_BASE = int(os.getenv('BITCOIN_TOR_PORT_BASE', BTC_BASE_TOR_PORT))
|
BITCOIN_TOR_PORT_BASE = int(os.getenv('BITCOIN_TOR_PORT_BASE', BTC_BASE_TOR_PORT))
|
||||||
|
|
||||||
LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT))
|
LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT))
|
||||||
|
DECRED_RPC_PORT_BASE = int(os.getenv('DECRED_RPC_PORT_BASE', DCR_BASE_RPC_PORT))
|
||||||
|
|
||||||
FIRO_BASE_PORT = 34832
|
FIRO_BASE_PORT = 34832
|
||||||
FIRO_BASE_RPC_PORT = 35832
|
FIRO_BASE_RPC_PORT = 35832
|
||||||
|
@ -93,11 +95,14 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
|
||||||
os.environ['PART_RPC_PORT'] = str(PARTICL_RPC_PORT_BASE)
|
os.environ['PART_RPC_PORT'] = str(PARTICL_RPC_PORT_BASE)
|
||||||
os.environ['BTC_RPC_PORT'] = str(BITCOIN_RPC_PORT_BASE)
|
os.environ['BTC_RPC_PORT'] = str(BITCOIN_RPC_PORT_BASE)
|
||||||
os.environ['LTC_RPC_PORT'] = str(LITECOIN_RPC_PORT_BASE)
|
os.environ['LTC_RPC_PORT'] = str(LITECOIN_RPC_PORT_BASE)
|
||||||
|
os.environ['DCR_RPC_PORT'] = str(DECRED_RPC_PORT_BASE)
|
||||||
os.environ['FIRO_RPC_PORT'] = str(FIRO_RPC_PORT_BASE)
|
os.environ['FIRO_RPC_PORT'] = str(FIRO_RPC_PORT_BASE)
|
||||||
|
|
||||||
os.environ['XMR_RPC_USER'] = 'xmr_user'
|
os.environ['XMR_RPC_USER'] = 'xmr_user'
|
||||||
os.environ['XMR_RPC_PWD'] = 'xmr_pwd'
|
os.environ['XMR_RPC_PWD'] = 'xmr_pwd'
|
||||||
|
|
||||||
|
os.environ['DCR_RPC_PWD'] = 'dcr_pwd'
|
||||||
|
|
||||||
import bin.basicswap_prepare as prepareSystem
|
import bin.basicswap_prepare as prepareSystem
|
||||||
# Hack: Reload module to set env vars as the basicswap_prepare module is initialised if imported from elsewhere earlier
|
# Hack: Reload module to set env vars as the basicswap_prepare module is initialised if imported from elsewhere earlier
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
|
@ -126,9 +131,10 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
|
||||||
with open(config_path) as fs:
|
with open(config_path) as fs:
|
||||||
settings = json.load(fs)
|
settings = json.load(fs)
|
||||||
|
|
||||||
with open(os.path.join(datadir_path, 'particl', 'particl.conf'), 'r') as fp:
|
config_filename = os.path.join(datadir_path, 'particl', 'particl.conf')
|
||||||
|
with open(config_filename, 'r') as fp:
|
||||||
lines = fp.readlines()
|
lines = fp.readlines()
|
||||||
with open(os.path.join(datadir_path, 'particl', 'particl.conf'), 'w') as fp:
|
with open(config_filename, 'w') as fp:
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if not line.startswith('staking'):
|
if not line.startswith('staking'):
|
||||||
fp.write(line)
|
fp.write(line)
|
||||||
|
@ -158,9 +164,10 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
|
||||||
|
|
||||||
if 'bitcoin' in coins_array:
|
if 'bitcoin' in coins_array:
|
||||||
# Pruned nodes don't provide blocks
|
# Pruned nodes don't provide blocks
|
||||||
with open(os.path.join(datadir_path, 'bitcoin', 'bitcoin.conf'), 'r') as fp:
|
config_filename = os.path.join(datadir_path, 'bitcoin', 'bitcoin.conf')
|
||||||
|
with open(config_filename, 'r') as fp:
|
||||||
lines = fp.readlines()
|
lines = fp.readlines()
|
||||||
with open(os.path.join(datadir_path, 'bitcoin', 'bitcoin.conf'), 'w') as fp:
|
with open(config_filename, 'w') as fp:
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if not line.startswith('prune'):
|
if not line.startswith('prune'):
|
||||||
fp.write(line)
|
fp.write(line)
|
||||||
|
@ -188,9 +195,10 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
|
||||||
|
|
||||||
if 'litecoin' in coins_array:
|
if 'litecoin' in coins_array:
|
||||||
# Pruned nodes don't provide blocks
|
# Pruned nodes don't provide blocks
|
||||||
with open(os.path.join(datadir_path, 'litecoin', 'litecoin.conf'), 'r') as fp:
|
config_filename = os.path.join(datadir_path, 'litecoin', 'litecoin.conf')
|
||||||
|
with open(config_filename, 'r') as fp:
|
||||||
lines = fp.readlines()
|
lines = fp.readlines()
|
||||||
with open(os.path.join(datadir_path, 'litecoin', 'litecoin.conf'), 'w') as fp:
|
with open(config_filename, 'w') as fp:
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if not line.startswith('prune'):
|
if not line.startswith('prune'):
|
||||||
fp.write(line)
|
fp.write(line)
|
||||||
|
@ -213,11 +221,34 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
|
||||||
for opt in EXTRA_CONFIG_JSON.get('ltc{}'.format(node_id), []):
|
for opt in EXTRA_CONFIG_JSON.get('ltc{}'.format(node_id), []):
|
||||||
fp.write(opt + '\n')
|
fp.write(opt + '\n')
|
||||||
|
|
||||||
|
if 'decred' in coins_array:
|
||||||
|
# Pruned nodes don't provide blocks
|
||||||
|
config_filename = os.path.join(datadir_path, 'decred', 'dcrd.conf')
|
||||||
|
with open(config_filename, 'r') as fp:
|
||||||
|
lines = fp.readlines()
|
||||||
|
with open(config_filename, 'w') as fp:
|
||||||
|
for line in lines:
|
||||||
|
if not line.startswith('prune'):
|
||||||
|
fp.write(line)
|
||||||
|
fp.write('listen=127.0.0.1:{}\n'.format(DCR_BASE_PORT + node_id + port_ofs))
|
||||||
|
fp.write('noseeders=1\n')
|
||||||
|
fp.write('nodnsseed=1\n')
|
||||||
|
fp.write('nodiscoverip=1\n')
|
||||||
|
if node_id == 0:
|
||||||
|
fp.write('miningaddr=SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH\n')
|
||||||
|
for ip in range(num_nodes):
|
||||||
|
if ip != node_id:
|
||||||
|
fp.write('addpeer=127.0.0.1:{}\n'.format(DCR_BASE_PORT + ip + port_ofs))
|
||||||
|
config_filename = os.path.join(datadir_path, 'decred', 'dcrwallet.conf')
|
||||||
|
with open(config_filename, 'a') as fp:
|
||||||
|
fp.write('enablevoting=1\n')
|
||||||
|
|
||||||
if 'pivx' in coins_array:
|
if 'pivx' in coins_array:
|
||||||
# Pruned nodes don't provide blocks
|
# Pruned nodes don't provide blocks
|
||||||
with open(os.path.join(datadir_path, 'pivx', 'pivx.conf'), 'r') as fp:
|
config_filename = os.path.join(datadir_path, 'pivx', 'pivx.conf')
|
||||||
|
with open(config_filename, 'r') as fp:
|
||||||
lines = fp.readlines()
|
lines = fp.readlines()
|
||||||
with open(os.path.join(datadir_path, 'pivx', 'pivx.conf'), 'w') as fp:
|
with open(config_filename, 'w') as fp:
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if not line.startswith('prune'):
|
if not line.startswith('prune'):
|
||||||
fp.write(line)
|
fp.write(line)
|
||||||
|
@ -242,9 +273,10 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
|
||||||
|
|
||||||
if 'firo' in coins_array:
|
if 'firo' in coins_array:
|
||||||
# Pruned nodes don't provide blocks
|
# Pruned nodes don't provide blocks
|
||||||
with open(os.path.join(datadir_path, 'firo', 'firo.conf'), 'r') as fp:
|
config_filename = os.path.join(datadir_path, 'firo', 'firo.conf')
|
||||||
|
with open(config_filename, 'r') as fp:
|
||||||
lines = fp.readlines()
|
lines = fp.readlines()
|
||||||
with open(os.path.join(datadir_path, 'firo', 'firo.conf'), 'w') as fp:
|
with open(config_filename, 'w') as fp:
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if not line.startswith('prune'):
|
if not line.startswith('prune'):
|
||||||
fp.write(line)
|
fp.write(line)
|
||||||
|
|
|
@ -9,8 +9,7 @@ import copy
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import select
|
|
||||||
import subprocess
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import basicswap.config as cfg
|
import basicswap.config as cfg
|
||||||
|
@ -36,6 +35,9 @@ from basicswap.interface.dcr.messages import (
|
||||||
SigHashType,
|
SigHashType,
|
||||||
TxSerializeType,
|
TxSerializeType,
|
||||||
)
|
)
|
||||||
|
from basicswap.interface.dcr.util import (
|
||||||
|
createDCRWallet,
|
||||||
|
)
|
||||||
from tests.basicswap.common import (
|
from tests.basicswap.common import (
|
||||||
compare_bid_states,
|
compare_bid_states,
|
||||||
compare_bid_states_unordered,
|
compare_bid_states_unordered,
|
||||||
|
@ -466,6 +468,9 @@ def prepareDCDDataDir(datadir, node_id, conf_file, dir_prefix, num_nodes=3):
|
||||||
f'rpcuser=test{node_id}\n',
|
f'rpcuser=test{node_id}\n',
|
||||||
f'rpcpass=test_pass{node_id}\n',
|
f'rpcpass=test_pass{node_id}\n',
|
||||||
'notls=1\n',
|
'notls=1\n',
|
||||||
|
'noseeders=1\n',
|
||||||
|
'nodnsseed=1\n',
|
||||||
|
'nodiscoverip=1\n',
|
||||||
'miningaddr=SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH\n',]
|
'miningaddr=SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH\n',]
|
||||||
|
|
||||||
for i in range(0, num_nodes):
|
for i in range(0, num_nodes):
|
||||||
|
@ -511,8 +516,8 @@ class Test(BaseTest):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def prepareExtraCoins(cls):
|
def prepareExtraCoins(cls):
|
||||||
|
ci0 = cls.swap_clients[0].ci(cls.test_coin)
|
||||||
if not cls.restore_instance:
|
if not cls.restore_instance:
|
||||||
ci0 = cls.swap_clients[0].ci(cls.test_coin)
|
|
||||||
assert (ci0.rpc_wallet('getnewaddress') == cls.dcr_mining_addr)
|
assert (ci0.rpc_wallet('getnewaddress') == cls.dcr_mining_addr)
|
||||||
cls.dcr_ticket_account = ci0.rpc_wallet('getaccount', [cls.dcr_mining_addr, ])
|
cls.dcr_ticket_account = ci0.rpc_wallet('getaccount', [cls.dcr_mining_addr, ])
|
||||||
ci0.rpc('generate', [110,])
|
ci0.rpc('generate', [110,])
|
||||||
|
@ -567,42 +572,9 @@ class Test(BaseTest):
|
||||||
|
|
||||||
waitForRPC(make_rpc_func(i, base_rpc_port=DCR_BASE_RPC_PORT), test_delay_event, rpc_command='getnetworkinfo', max_tries=12)
|
waitForRPC(make_rpc_func(i, base_rpc_port=DCR_BASE_RPC_PORT), test_delay_event, rpc_command='getnetworkinfo', max_tries=12)
|
||||||
|
|
||||||
logging.info('Creating wallet')
|
|
||||||
extra_opts.append('--pass=test_pass')
|
extra_opts.append('--pass=test_pass')
|
||||||
args = [os.path.join(DCR_BINDIR, DCR_WALLET), '--create'] + extra_opts
|
args = [os.path.join(DCR_BINDIR, DCR_WALLET), '--create'] + extra_opts
|
||||||
(pipe_r, pipe_w) = os.pipe() # subprocess.PIPE is buffered, blocks when read
|
createDCRWallet(args, cls.hex_seeds[i], logging, test_delay_event)
|
||||||
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 = (cls.hex_seeds[i] + '\n').encode('utf-8')
|
|
||||||
elif 'Seed input successful' in buf:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
raise ValueError(f'Unexpected output: {buf}')
|
|
||||||
if response is not None:
|
|
||||||
p.stdin.write(response)
|
|
||||||
p.stdin.flush()
|
|
||||||
test_delay_event.wait(0.1)
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(f'{DCR_WALLET} --create failed: {e}')
|
|
||||||
finally:
|
|
||||||
if p.poll() is None:
|
|
||||||
p.terminate()
|
|
||||||
os.close(pipe_r)
|
|
||||||
os.close(pipe_w)
|
|
||||||
p.stdin.close()
|
|
||||||
|
|
||||||
test_delay_event.wait(1.0)
|
test_delay_event.wait(1.0)
|
||||||
|
|
||||||
|
@ -769,7 +741,7 @@ class Test(BaseTest):
|
||||||
|
|
||||||
script = bytearray()
|
script = bytearray()
|
||||||
push_script_data(script, bytes((3,)))
|
push_script_data(script, bytes((3,)))
|
||||||
script += OP_CHECKSEQUENCEVERIFY.to_bytes(1)
|
script += bytes((OP_CHECKSEQUENCEVERIFY,))
|
||||||
|
|
||||||
script_dest = ci0.getScriptDest(script)
|
script_dest = ci0.getScriptDest(script)
|
||||||
script_info = ci0.rpc_wallet('decodescript', [script_dest.hex(),])
|
script_info = ci0.rpc_wallet('decodescript', [script_dest.hex(),])
|
||||||
|
|
|
@ -49,6 +49,7 @@ from tests.basicswap.common_xmr import (
|
||||||
prepare_nodes,
|
prepare_nodes,
|
||||||
XMR_BASE_RPC_PORT,
|
XMR_BASE_RPC_PORT,
|
||||||
)
|
)
|
||||||
|
from basicswap.interface.dcr.rpc import callrpc as callrpc_dcr
|
||||||
import bin.basicswap_run as runSystem
|
import bin.basicswap_run as runSystem
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +62,7 @@ UI_PORT = 12700 + PORT_OFS
|
||||||
PARTICL_RPC_PORT_BASE = int(os.getenv('PARTICL_RPC_PORT_BASE', BASE_RPC_PORT))
|
PARTICL_RPC_PORT_BASE = int(os.getenv('PARTICL_RPC_PORT_BASE', BASE_RPC_PORT))
|
||||||
BITCOIN_RPC_PORT_BASE = int(os.getenv('BITCOIN_RPC_PORT_BASE', BTC_BASE_RPC_PORT))
|
BITCOIN_RPC_PORT_BASE = int(os.getenv('BITCOIN_RPC_PORT_BASE', BTC_BASE_RPC_PORT))
|
||||||
LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT))
|
LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT))
|
||||||
|
DECRED_WALLET_RPC_PORT_BASE = int(os.getenv('DECRED_WALLET_RPC_PORT_BASE', 9210))
|
||||||
XMR_BASE_RPC_PORT = int(os.getenv('XMR_BASE_RPC_PORT', XMR_BASE_RPC_PORT))
|
XMR_BASE_RPC_PORT = int(os.getenv('XMR_BASE_RPC_PORT', XMR_BASE_RPC_PORT))
|
||||||
TEST_COINS_LIST = os.getenv('TEST_COINS_LIST', 'bitcoin,monero')
|
TEST_COINS_LIST = os.getenv('TEST_COINS_LIST', 'bitcoin,monero')
|
||||||
|
|
||||||
|
@ -88,6 +90,11 @@ def callltcrpc(node_id, method, params=[], wallet=None, base_rpc_port=LITECOIN_R
|
||||||
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
|
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
|
||||||
|
|
||||||
|
|
||||||
|
def calldcrrpc(node_id, method, params=[], wallet=None, base_rpc_port=DECRED_WALLET_RPC_PORT_BASE):
|
||||||
|
auth = 'user:dcr_pwd'
|
||||||
|
return callrpc_dcr(base_rpc_port + node_id, auth, method, params)
|
||||||
|
|
||||||
|
|
||||||
def updateThread(cls):
|
def updateThread(cls):
|
||||||
while not cls.delay_event.is_set():
|
while not cls.delay_event.is_set():
|
||||||
try:
|
try:
|
||||||
|
@ -98,7 +105,7 @@ def updateThread(cls):
|
||||||
cls.delay_event.wait(random.randrange(cls.update_min, cls.update_max))
|
cls.delay_event.wait(random.randrange(cls.update_min, cls.update_max))
|
||||||
|
|
||||||
|
|
||||||
def updateThreadXmr(cls):
|
def updateThreadXMR(cls):
|
||||||
xmr_auth = None
|
xmr_auth = None
|
||||||
if os.getenv('XMR_RPC_USER', '') != '':
|
if os.getenv('XMR_RPC_USER', '') != '':
|
||||||
xmr_auth = (os.getenv('XMR_RPC_USER', ''), os.getenv('XMR_RPC_PWD', ''))
|
xmr_auth = (os.getenv('XMR_RPC_USER', ''), os.getenv('XMR_RPC_PWD', ''))
|
||||||
|
@ -108,10 +115,38 @@ def updateThreadXmr(cls):
|
||||||
if cls.xmr_addr is not None:
|
if cls.xmr_addr is not None:
|
||||||
callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': cls.xmr_addr, 'amount_of_blocks': 1}, auth=xmr_auth)
|
callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': cls.xmr_addr, 'amount_of_blocks': 1}, auth=xmr_auth)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('updateThreadXmr error', str(e))
|
print('updateThreadXMR error', str(e))
|
||||||
cls.delay_event.wait(random.randrange(cls.xmr_update_min, cls.xmr_update_max))
|
cls.delay_event.wait(random.randrange(cls.xmr_update_min, cls.xmr_update_max))
|
||||||
|
|
||||||
|
|
||||||
|
def updateThreadDCR(cls):
|
||||||
|
while not cls.delay_event.is_set():
|
||||||
|
try:
|
||||||
|
pass
|
||||||
|
num_passed: int = 0
|
||||||
|
for i in range(30):
|
||||||
|
try:
|
||||||
|
calldcrrpc(0, 'purchaseticket', [cls.dcr_acc, 0.1, 0])
|
||||||
|
num_passed += 1
|
||||||
|
if num_passed >= 5:
|
||||||
|
break
|
||||||
|
cls.delay_event.wait(0.1)
|
||||||
|
except Exception as e:
|
||||||
|
if 'double spend' in str(e):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
logging.warning('updateThreadDCR purchaseticket {}'.format(e))
|
||||||
|
cls.delay_event.wait(0.5)
|
||||||
|
try:
|
||||||
|
if num_passed >= 5:
|
||||||
|
calldcrrpc(0, 'generate', [1,])
|
||||||
|
except Exception as e:
|
||||||
|
logging.warning('updateThreadDCR generate {}'.format(e))
|
||||||
|
except Exception as e:
|
||||||
|
print('updateThreadDCR error', str(e))
|
||||||
|
cls.delay_event.wait(random.randrange(cls.dcr_update_min, cls.dcr_update_max))
|
||||||
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
@ -123,12 +158,18 @@ class Test(unittest.TestCase):
|
||||||
cls.xmr_update_min = int(os.getenv('XMR_UPDATE_THREAD_MIN_WAIT', '1'))
|
cls.xmr_update_min = int(os.getenv('XMR_UPDATE_THREAD_MIN_WAIT', '1'))
|
||||||
cls.xmr_update_max = cls.xmr_update_min * 4
|
cls.xmr_update_max = cls.xmr_update_min * 4
|
||||||
|
|
||||||
|
cls.dcr_update_min = int(os.getenv('DCR_UPDATE_THREAD_MIN_WAIT', '1'))
|
||||||
|
cls.dcr_update_max = cls.dcr_update_min * 4
|
||||||
|
|
||||||
cls.delay_event = threading.Event()
|
cls.delay_event = threading.Event()
|
||||||
cls.update_thread = None
|
cls.update_thread = None
|
||||||
cls.update_thread_xmr = None
|
cls.update_thread_xmr = None
|
||||||
|
cls.update_thread_dcr = None
|
||||||
cls.processes = []
|
cls.processes = []
|
||||||
cls.btc_addr = None
|
cls.btc_addr = None
|
||||||
cls.xmr_addr = None
|
cls.xmr_addr = None
|
||||||
|
cls.dcr_addr = 'SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH'
|
||||||
|
cls.dcr_acc = None
|
||||||
|
|
||||||
random.seed(time.time())
|
random.seed(time.time())
|
||||||
|
|
||||||
|
@ -197,13 +238,25 @@ class Test(unittest.TestCase):
|
||||||
have_blocks: int = callltcrpc(0, 'getblockcount')
|
have_blocks: int = callltcrpc(0, 'getblockcount')
|
||||||
callltcrpc(0, 'generatetoaddress', [500 - have_blocks, self.ltc_addr], wallet='wallet.dat')
|
callltcrpc(0, 'generatetoaddress', [500 - have_blocks, self.ltc_addr], wallet='wallet.dat')
|
||||||
|
|
||||||
|
if 'decred' in TEST_COINS_LIST:
|
||||||
|
if RESET_TEST:
|
||||||
|
addr = calldcrrpc(0, 'getnewaddress')
|
||||||
|
# assert (addr == self.dcr_addr)
|
||||||
|
self.dcr_acc = calldcrrpc(0, 'getaccount', [self.dcr_addr, ])
|
||||||
|
addr = calldcrrpc(0, 'generate', [110,])
|
||||||
|
else:
|
||||||
|
self.dcr_acc = calldcrrpc(0, 'getaccount', [self.dcr_addr, ])
|
||||||
|
|
||||||
|
self.update_thread_dcr = threading.Thread(target=updateThreadDCR, args=(self,))
|
||||||
|
self.update_thread_dcr.start()
|
||||||
|
|
||||||
# Lower output split threshold for more stakeable outputs
|
# Lower output split threshold for more stakeable outputs
|
||||||
for i in range(NUM_NODES):
|
for i in range(NUM_NODES):
|
||||||
callpartrpc(i, 'walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}])
|
callpartrpc(i, 'walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}])
|
||||||
self.update_thread = threading.Thread(target=updateThread, args=(self,))
|
self.update_thread = threading.Thread(target=updateThread, args=(self,))
|
||||||
self.update_thread.start()
|
self.update_thread.start()
|
||||||
|
|
||||||
self.update_thread_xmr = threading.Thread(target=updateThreadXmr, args=(self,))
|
self.update_thread_xmr = threading.Thread(target=updateThreadXMR, args=(self,))
|
||||||
self.update_thread_xmr.start()
|
self.update_thread_xmr.start()
|
||||||
|
|
||||||
# Wait for height, or sequencelock is thrown off by genesis blocktime
|
# Wait for height, or sequencelock is thrown off by genesis blocktime
|
||||||
|
@ -228,12 +281,15 @@ class Test(unittest.TestCase):
|
||||||
cls.update_thread.join()
|
cls.update_thread.join()
|
||||||
if cls.update_thread_xmr:
|
if cls.update_thread_xmr:
|
||||||
cls.update_thread_xmr.join()
|
cls.update_thread_xmr.join()
|
||||||
|
if cls.update_thread_dcr:
|
||||||
|
cls.update_thread_dcr.join()
|
||||||
for p in cls.processes:
|
for p in cls.processes:
|
||||||
p.terminate()
|
p.terminate()
|
||||||
for p in cls.processes:
|
for p in cls.processes:
|
||||||
p.join()
|
p.join()
|
||||||
cls.update_thread = None
|
cls.update_thread = None
|
||||||
cls.update_thread_xmr = None
|
cls.update_thread_xmr = None
|
||||||
|
cls.update_thread_dcr = None
|
||||||
cls.processes = []
|
cls.processes = []
|
||||||
|
|
||||||
def test_persistent(self):
|
def test_persistent(self):
|
||||||
|
|
Loading…
Reference in a new issue