mirror of
https://github.com/basicswap/basicswap.git
synced 2024-11-16 15:58:17 +00:00
coins: Add LTC MWEB wallet
This commit is contained in:
parent
7547587d4e
commit
38fa498b0b
29 changed files with 987 additions and 517 deletions
|
@ -1,3 +1,3 @@
|
|||
name = "basicswap"
|
||||
|
||||
__version__ = "0.12.3"
|
||||
__version__ = "0.12.4"
|
||||
|
|
|
@ -256,6 +256,7 @@ class BasicSwap(BaseApp):
|
|||
self._is_locked = None
|
||||
|
||||
# TODO: Set dynamically
|
||||
self.balance_only_coins = (Coins.LTC_MWEB, )
|
||||
self.scriptless_coins = (Coins.XMR, Coins.PART_ANON, Coins.FIRO)
|
||||
self.adaptor_swap_only_coins = self.scriptless_coins + (Coins.PART_BLIND, )
|
||||
self.coins_without_segwit = (Coins.PIVX, Coins.DASH, Coins.NMC)
|
||||
|
@ -480,6 +481,9 @@ class BasicSwap(BaseApp):
|
|||
self.coin_clients[Coins.PART_ANON] = self.coin_clients[coin]
|
||||
self.coin_clients[Coins.PART_BLIND] = self.coin_clients[coin]
|
||||
|
||||
if coin == Coins.LTC:
|
||||
self.coin_clients[Coins.LTC_MWEB] = self.coin_clients[coin]
|
||||
|
||||
if self.coin_clients[coin]['connection_type'] == 'rpc':
|
||||
if coin == Coins.XMR:
|
||||
if chain_client_settings.get('automatically_select_daemon', False):
|
||||
|
@ -510,8 +514,8 @@ class BasicSwap(BaseApp):
|
|||
if current_daemon_url in remote_daemon_urls:
|
||||
self.log.info(f'Trying last used url {rpchost}:{rpcport}.')
|
||||
try:
|
||||
rpc_cb2 = make_xmr_rpc2_func(rpcport, daemon_login, rpchost)
|
||||
test = rpc_cb2('get_height', timeout=20)['height']
|
||||
rpc2 = make_xmr_rpc2_func(rpcport, daemon_login, rpchost)
|
||||
test = rpc2('get_height', timeout=20)['height']
|
||||
return True
|
||||
except Exception as e:
|
||||
self.log.warning(f'Failed to set XMR remote daemon to {rpchost}:{rpcport}, {e}')
|
||||
|
@ -520,8 +524,8 @@ class BasicSwap(BaseApp):
|
|||
self.log.info(f'Trying url {url}.')
|
||||
try:
|
||||
rpchost, rpcport = url.rsplit(':', 1)
|
||||
rpc_cb2 = make_xmr_rpc2_func(rpcport, daemon_login, rpchost)
|
||||
test = rpc_cb2('get_height', timeout=20)['height']
|
||||
rpc2 = make_xmr_rpc2_func(rpcport, daemon_login, rpchost)
|
||||
test = rpc2('get_height', timeout=20)['height']
|
||||
coin_settings['rpchost'] = rpchost
|
||||
coin_settings['rpcport'] = rpcport
|
||||
data = {
|
||||
|
@ -544,6 +548,9 @@ class BasicSwap(BaseApp):
|
|||
if coin == Coins.PART_BLIND:
|
||||
use_coinid = Coins.PART
|
||||
interface_ind = 'interface_blind'
|
||||
if coin == Coins.LTC_MWEB:
|
||||
use_coinid = Coins.LTC
|
||||
interface_ind = 'interface_mweb'
|
||||
|
||||
if use_coinid not in self.coin_clients:
|
||||
raise ValueError('Unknown coinid {}'.format(int(coin)))
|
||||
|
@ -558,6 +565,9 @@ class BasicSwap(BaseApp):
|
|||
if coin == Coins.PART_BLIND:
|
||||
use_coinid = Coins.PART
|
||||
interface_ind = 'interface_blind'
|
||||
if coin == Coins.LTC_MWEB:
|
||||
use_coinid = Coins.LTC
|
||||
interface_ind = 'interface_mweb'
|
||||
|
||||
if use_coinid not in self.coin_clients:
|
||||
raise ValueError('Unknown coinid {}'.format(int(coin)))
|
||||
|
@ -573,13 +583,18 @@ class BasicSwap(BaseApp):
|
|||
|
||||
def createInterface(self, coin):
|
||||
if coin == Coins.PART:
|
||||
return PARTInterface(self.coin_clients[coin], self.chain, self)
|
||||
interface = PARTInterface(self.coin_clients[coin], self.chain, self)
|
||||
self.coin_clients[coin]['interface_anon'] = PARTInterfaceAnon(self.coin_clients[coin], self.chain, self)
|
||||
self.coin_clients[coin]['interface_blind'] = PARTInterfaceBlind(self.coin_clients[coin], self.chain, self)
|
||||
return interface
|
||||
elif coin == Coins.BTC:
|
||||
from .interface.btc import BTCInterface
|
||||
return BTCInterface(self.coin_clients[coin], self.chain, self)
|
||||
elif coin == Coins.LTC:
|
||||
from .interface.ltc import LTCInterface
|
||||
return LTCInterface(self.coin_clients[coin], self.chain, self)
|
||||
from .interface.ltc import LTCInterface, LTCInterfaceMWEB
|
||||
interface = LTCInterface(self.coin_clients[coin], self.chain, self)
|
||||
self.coin_clients[coin]['interface_mweb'] = LTCInterfaceMWEB(self.coin_clients[coin], self.chain, self)
|
||||
return interface
|
||||
elif coin == Coins.NMC:
|
||||
from .interface.nmc import NMCInterface
|
||||
return NMCInterface(self.coin_clients[coin], self.chain, self)
|
||||
|
@ -662,9 +677,6 @@ class BasicSwap(BaseApp):
|
|||
def createCoinInterface(self, coin):
|
||||
if self.coin_clients[coin]['connection_type'] == 'rpc':
|
||||
self.coin_clients[coin]['interface'] = self.createInterface(coin)
|
||||
if coin == Coins.PART:
|
||||
self.coin_clients[coin]['interface_anon'] = PARTInterfaceAnon(self.coin_clients[coin], self.chain, self)
|
||||
self.coin_clients[coin]['interface_blind'] = PARTInterfaceBlind(self.coin_clients[coin], self.chain, self)
|
||||
elif self.coin_clients[coin]['connection_type'] == 'passthrough':
|
||||
self.coin_clients[coin]['interface'] = self.createPassthroughInterface(coin)
|
||||
|
||||
|
@ -685,13 +697,11 @@ class BasicSwap(BaseApp):
|
|||
self.createCoinInterface(c)
|
||||
|
||||
if self.coin_clients[c]['connection_type'] == 'rpc':
|
||||
if c in (Coins.BTC, ):
|
||||
self.waitForDaemonRPC(c, with_wallet=False)
|
||||
if len(self.callcoinrpc(c, 'listwallets')) >= 1:
|
||||
self.waitForDaemonRPC(c)
|
||||
else:
|
||||
self.waitForDaemonRPC(c)
|
||||
ci = self.ci(c)
|
||||
self.waitForDaemonRPC(c, with_wallet=False)
|
||||
if c not in (Coins.XMR,) and ci.checkWallets() >= 1:
|
||||
self.waitForDaemonRPC(c)
|
||||
|
||||
core_version = ci.getDaemonVersion()
|
||||
self.log.info('%s Core version %d', ci.coin_name(), core_version)
|
||||
self.coin_clients[c]['core_version'] = core_version
|
||||
|
@ -721,6 +731,11 @@ class BasicSwap(BaseApp):
|
|||
except Exception as e:
|
||||
self.log.warning('Can\'t open XMR wallet, could be locked.')
|
||||
continue
|
||||
elif c == Coins.LTC:
|
||||
ci_mweb = self.ci(Coins.LTC_MWEB)
|
||||
is_encrypted, _ = self.getLockedState()
|
||||
if not is_encrypted and not ci_mweb.has_mweb_wallet():
|
||||
ci_mweb.init_wallet()
|
||||
|
||||
self.checkWalletSeed(c)
|
||||
|
||||
|
@ -850,6 +865,16 @@ class BasicSwap(BaseApp):
|
|||
if self.coin_clients[c]['connection_type'] == 'rpc':
|
||||
yield c
|
||||
|
||||
def getListOfWalletCoins(self):
|
||||
coins_list = copy.deepcopy(self.activeCoins())
|
||||
# Always unlock Particl first
|
||||
if Coins.PART in coins_list:
|
||||
coins_list.pop(Coins.PART)
|
||||
coins_list = [Coins.PART,] + coins_list
|
||||
if Coins.LTC in coins_list:
|
||||
coins_list.append(Coins.LTC_MWEB)
|
||||
return coins_list
|
||||
|
||||
def changeWalletPasswords(self, old_password: str, new_password: str, coin=None) -> None:
|
||||
# Only the main wallet password is changed for monero, avoid issues by preventing until active swaps are complete
|
||||
if len(self.swaps_in_progress) > 0:
|
||||
|
@ -861,8 +886,10 @@ class BasicSwap(BaseApp):
|
|||
if len(new_password) < 4:
|
||||
raise ValueError('New password is too short')
|
||||
|
||||
coins_list = self.getListOfWalletCoins()
|
||||
|
||||
# Unlock wallets to ensure they all have the same password.
|
||||
for c in self.activeCoins():
|
||||
for c in coins_list:
|
||||
if coin and c != coin:
|
||||
continue
|
||||
ci = self.ci(c)
|
||||
|
@ -871,7 +898,7 @@ class BasicSwap(BaseApp):
|
|||
except Exception as e:
|
||||
raise ValueError('Failed to unlock {}'.format(ci.coin_name()))
|
||||
|
||||
for c in self.activeCoins():
|
||||
for c in coins_list:
|
||||
if coin and c != coin:
|
||||
continue
|
||||
self.ci(c).changeWalletPassword(old_password, new_password)
|
||||
|
@ -882,7 +909,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
def unlockWallets(self, password: str, coin=None) -> None:
|
||||
self._read_zmq_queue = False
|
||||
for c in self.activeCoins():
|
||||
for c in self.getListOfWalletCoins():
|
||||
if coin and c != coin:
|
||||
continue
|
||||
self.ci(c).unlockWallet(password)
|
||||
|
@ -896,7 +923,7 @@ class BasicSwap(BaseApp):
|
|||
self._read_zmq_queue = False
|
||||
self.swaps_in_progress.clear()
|
||||
|
||||
for c in self.activeCoins():
|
||||
for c in self.getListOfWalletCoins():
|
||||
if coin and c != coin:
|
||||
continue
|
||||
self.ci(c).lockWallet()
|
||||
|
@ -923,7 +950,6 @@ class BasicSwap(BaseApp):
|
|||
|
||||
root_key = self.getWalletKey(coin_type, 1)
|
||||
root_hash = ci.getSeedHash(root_key)
|
||||
|
||||
try:
|
||||
ci.initialiseWallet(root_key)
|
||||
except Exception as e:
|
||||
|
@ -931,6 +957,8 @@ class BasicSwap(BaseApp):
|
|||
self.log.error('initialiseWallet failed: {}'.format(str(e)))
|
||||
if raise_errors:
|
||||
raise e
|
||||
if self.debug:
|
||||
self.log.error(traceback.format_exc())
|
||||
return
|
||||
|
||||
try:
|
||||
|
@ -1167,6 +1195,11 @@ class BasicSwap(BaseApp):
|
|||
return coin_from in self.scriptless_coins + self.coins_without_segwit
|
||||
|
||||
def validateSwapType(self, coin_from, coin_to, swap_type):
|
||||
|
||||
for coin in (coin_from, coin_to):
|
||||
if coin in self.balance_only_coins:
|
||||
raise ValueError('Invalid coin: {}'.format(coin.name))
|
||||
|
||||
if swap_type == SwapTypes.XMR_SWAP:
|
||||
reverse_bid: bool = self.is_reverse_ads_bid(coin_from)
|
||||
itx_coin = coin_to if reverse_bid else coin_from
|
||||
|
@ -1812,6 +1845,14 @@ class BasicSwap(BaseApp):
|
|||
self.log.debug('In txn: {}'.format(txid))
|
||||
return txid
|
||||
|
||||
def withdrawLTC(self, type_from, value, addr_to, subfee):
|
||||
ci = self.ci(Coins.LTC)
|
||||
self.log.info('withdrawLTC %s %s to %s %s', value, ci.ticker(), addr_to, ' subfee' if subfee else '')
|
||||
|
||||
txid = ci.withdrawCoin(value, type_from, addr_to, subfee)
|
||||
self.log.debug('In txn: {}'.format(txid))
|
||||
return txid
|
||||
|
||||
def withdrawParticl(self, type_from, type_to, value, addr_to, subfee):
|
||||
self.log.info('withdrawParticl %s %s to %s %s %s', value, type_from, type_to, addr_to, ' subfee' if subfee else '')
|
||||
|
||||
|
@ -1827,7 +1868,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
def cacheNewAddressForCoin(self, coin_type):
|
||||
self.log.debug('cacheNewAddressForCoin %s', coin_type)
|
||||
key_str = 'receive_addr_' + chainparams[coin_type]['name']
|
||||
key_str = 'receive_addr_' + self.ci(coin_type).coin_name().lower()
|
||||
addr = self.getReceiveAddressForCoin(coin_type)
|
||||
self.setStringKV(key_str, addr)
|
||||
return addr
|
||||
|
@ -1864,7 +1905,7 @@ class BasicSwap(BaseApp):
|
|||
if expect_seedid is None:
|
||||
self.log.warning('Can\'t find expected wallet seed id for coin {}'.format(ci.coin_name()))
|
||||
return False
|
||||
if c == Coins.BTC and len(ci.rpc_callback('listwallets')) < 1:
|
||||
if c == Coins.BTC and len(ci.rpc('listwallets')) < 1:
|
||||
self.log.warning('Missing wallet for coin {}'.format(ci.coin_name()))
|
||||
return False
|
||||
if ci.checkExpectedSeed(expect_seedid):
|
||||
|
@ -1893,7 +1934,8 @@ class BasicSwap(BaseApp):
|
|||
self.log.debug('getCachedAddressForCoin %s', coin_type)
|
||||
# TODO: auto refresh after used
|
||||
|
||||
key_str = 'receive_addr_' + chainparams[coin_type]['name']
|
||||
ci = self.ci(coin_type)
|
||||
key_str = 'receive_addr_' + ci.coin_name().lower()
|
||||
session = self.openSession()
|
||||
try:
|
||||
try:
|
||||
|
@ -1908,9 +1950,22 @@ class BasicSwap(BaseApp):
|
|||
self.closeSession(session)
|
||||
return addr
|
||||
|
||||
def cacheNewStealthAddressForCoin(self, coin_type):
|
||||
self.log.debug('cacheNewStealthAddressForCoin %s', coin_type)
|
||||
|
||||
if coin_type == Coins.LTC_MWEB:
|
||||
coin_type = Coins.LTC
|
||||
ci = self.ci(coin_type)
|
||||
key_str = 'stealth_addr_' + ci.coin_name().lower()
|
||||
addr = ci.getNewStealthAddress()
|
||||
self.setStringKV(key_str, addr)
|
||||
return addr
|
||||
|
||||
def getCachedStealthAddressForCoin(self, coin_type):
|
||||
self.log.debug('getCachedStealthAddressForCoin %s', coin_type)
|
||||
|
||||
if coin_type == Coins.LTC_MWEB:
|
||||
coin_type = Coins.LTC
|
||||
ci = self.ci(coin_type)
|
||||
key_str = 'stealth_addr_' + ci.coin_name().lower()
|
||||
session = self.openSession()
|
||||
|
@ -2559,7 +2614,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
address_out = self.getReceiveAddressFromPool(coin_from, offer_id, TxTypes.XMR_SWAP_A_LOCK)
|
||||
if coin_from == Coins.PART_BLIND:
|
||||
addrinfo = ci_from.rpc_callback('getaddressinfo', [address_out])
|
||||
addrinfo = ci_from.rpc('getaddressinfo', [address_out])
|
||||
msg_buf.dest_af = bytes.fromhex(addrinfo['pubkey'])
|
||||
else:
|
||||
msg_buf.dest_af = ci_from.decodeAddress(address_out)
|
||||
|
@ -2870,7 +2925,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
address_out = self.getReceiveAddressFromPool(coin_from, bid.offer_id, TxTypes.XMR_SWAP_A_LOCK)
|
||||
if coin_from == Coins.PART_BLIND:
|
||||
addrinfo = ci_from.rpc_callback('getaddressinfo', [address_out])
|
||||
addrinfo = ci_from.rpc('getaddressinfo', [address_out])
|
||||
xmr_swap.dest_af = bytes.fromhex(addrinfo['pubkey'])
|
||||
else:
|
||||
xmr_swap.dest_af = ci_from.decodeAddress(address_out)
|
||||
|
@ -3339,7 +3394,8 @@ class BasicSwap(BaseApp):
|
|||
bid.participate_tx.chain_height = participate_txn_height
|
||||
|
||||
# Start checking for spends of participate_txn before fully confirmed
|
||||
self.log.debug('Watching %s chain for spend of output %s %d', chainparams[coin_type]['name'], txid_hex, vout)
|
||||
ci = self.ci(coin_type)
|
||||
self.log.debug('Watching %s chain for spend of output %s %d', ci.coin_name().lower(), txid_hex, vout)
|
||||
self.addWatchedOutput(coin_type, bid_id, txid_hex, vout, BidStates.SWAP_PARTICIPATING)
|
||||
|
||||
def participateTxnConfirmed(self, bid_id: bytes, bid, offer) -> None:
|
||||
|
@ -4151,7 +4207,7 @@ class BasicSwap(BaseApp):
|
|||
last_height_checked += 1
|
||||
if c['last_height_checked'] != last_height_checked:
|
||||
c['last_height_checked'] = last_height_checked
|
||||
self.setIntKV('last_height_checked_' + chainparams[coin_type]['name'], last_height_checked)
|
||||
self.setIntKV('last_height_checked_' + ci.coin_name().lower(), last_height_checked)
|
||||
|
||||
def expireMessages(self) -> None:
|
||||
if self._is_locked is True:
|
||||
|
@ -6413,6 +6469,11 @@ class BasicSwap(BaseApp):
|
|||
rv['main_address'] = self.getCachedMainWalletAddress(ci)
|
||||
elif coin == Coins.NAV:
|
||||
rv['immature'] = walletinfo['immature_balance']
|
||||
elif coin == Coins.LTC:
|
||||
rv['mweb_address'] = self.getCachedStealthAddressForCoin(Coins.LTC_MWEB)
|
||||
rv['mweb_balance'] = walletinfo['mweb_balance']
|
||||
rv['mweb_pending'] = walletinfo['mweb_unconfirmed'] + walletinfo['mweb_immature']
|
||||
rv['mweb_pending'] = walletinfo['mweb_unconfirmed'] + walletinfo['mweb_immature']
|
||||
|
||||
return rv
|
||||
except Exception as e:
|
||||
|
@ -6505,10 +6566,17 @@ class BasicSwap(BaseApp):
|
|||
wallet_data['lastupdated'] = row[3]
|
||||
wallet_data['updating'] = self._updating_wallets_info.get(coin_id, False)
|
||||
|
||||
# Ensure the latest deposit address is displayed
|
||||
q = session.execute('SELECT value FROM kv_string WHERE key = "receive_addr_{}"'.format(chainparams[coin_id]['name']))
|
||||
# Ensure the latest addresses are displayed
|
||||
q = session.execute('SELECT key, value FROM kv_string WHERE key = "receive_addr_{0}" OR key = "stealth_addr_{0}"'.format(chainparams[coin_id]['name']))
|
||||
for row in q:
|
||||
wallet_data['deposit_address'] = row[0]
|
||||
|
||||
if row[0].startswith('stealth'):
|
||||
if coin_id == Coins.LTC:
|
||||
wallet_data['mweb_address'] = row[1]
|
||||
else:
|
||||
wallet_data['stealth_address'] = row[1]
|
||||
else:
|
||||
wallet_data['deposit_address'] = row[1]
|
||||
|
||||
if coin_id in rv:
|
||||
rv[coin_id].update(wallet_data)
|
||||
|
|
|
@ -32,6 +32,7 @@ class Coins(IntEnum):
|
|||
DASH = 12
|
||||
FIRO = 13
|
||||
NAV = 14
|
||||
LTC_MWEB = 15
|
||||
|
||||
|
||||
chainparams = {
|
||||
|
|
|
@ -280,6 +280,8 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
coin_id = int(get_data_entry(form_data, 'coin_type'))
|
||||
if coin_id in (-2, -3, -4):
|
||||
coin_type = Coins(Coins.XMR)
|
||||
elif coin_id in (-5,):
|
||||
coin_type = Coins(Coins.LTC)
|
||||
else:
|
||||
coin_type = Coins(coin_id)
|
||||
except Exception:
|
||||
|
@ -295,20 +297,23 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
method = arr[0]
|
||||
params = json.loads(arr[1]) if len(arr) > 1 else []
|
||||
if coin_id == -4:
|
||||
rv = ci.rpc_wallet_cb(method, params)
|
||||
rv = ci.rpc_wallet(method, params)
|
||||
elif coin_id == -3:
|
||||
rv = ci.rpc_cb(method, params)
|
||||
rv = ci.rpc(method, params)
|
||||
elif coin_id == -2:
|
||||
if params == []:
|
||||
params = None
|
||||
rv = ci.rpc_cb2(method, params)
|
||||
rv = ci.rpc2(method, params)
|
||||
else:
|
||||
raise ValueError('Unknown XMR RPC variant')
|
||||
result = json.dumps(rv, indent=4)
|
||||
else:
|
||||
if call_type == 'http':
|
||||
method, params = parse_cmd(cmd, type_map)
|
||||
rv = swap_client.ci(coin_type).rpc_callback(method, params)
|
||||
if coin_id == -5:
|
||||
rv = swap_client.ci(coin_type).rpc_wallet_mweb(method, params)
|
||||
else:
|
||||
rv = swap_client.ci(coin_type).rpc_wallet(method, params)
|
||||
if not isinstance(rv, str):
|
||||
rv = json.dumps(rv, indent=4)
|
||||
result = cmd + '\n' + rv
|
||||
|
@ -323,6 +328,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
|
||||
coins = listAvailableCoins(swap_client, with_variants=False)
|
||||
coins = [c for c in coins if c[0] != Coins.XMR]
|
||||
coins.append((-5, 'Litecoin MWEB Wallet'))
|
||||
coins.append((-2, 'Monero'))
|
||||
coins.append((-3, 'Monero JSON'))
|
||||
coins.append((-4, 'Monero Wallet'))
|
||||
|
|
|
@ -195,7 +195,9 @@ class BTCInterface(CoinInterface):
|
|||
self._rpc_host = coin_settings.get('rpchost', '127.0.0.1')
|
||||
self._rpcport = coin_settings['rpcport']
|
||||
self._rpcauth = coin_settings['rpcauth']
|
||||
self.rpc_callback = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
|
||||
self.rpc = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host)
|
||||
self._rpc_wallet = 'wallet.dat'
|
||||
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host, wallet=self._rpc_wallet)
|
||||
self.blocks_confirmed = coin_settings['blocks_confirmed']
|
||||
self.setConfTarget(coin_settings['conf_target'])
|
||||
self._use_segwit = coin_settings['use_segwit']
|
||||
|
@ -204,6 +206,23 @@ class BTCInterface(CoinInterface):
|
|||
self._log = self._sc.log if self._sc and self._sc.log else logging
|
||||
self._expect_seedid_hex = None
|
||||
|
||||
def checkWallets(self) -> int:
|
||||
wallets = self.rpc('listwallets')
|
||||
|
||||
# Wallet name is "" for some LTC and PART installs on older cores
|
||||
if self._rpc_wallet not in wallets and len(wallets) > 0:
|
||||
self._log.debug('Changing {} wallet name.'.format(self.ticker()))
|
||||
for wallet_name in wallets:
|
||||
# Skip over other expected wallets
|
||||
if wallet_name in ('mweb', ):
|
||||
continue
|
||||
self._rpc_wallet = wallet_name
|
||||
self._log.info('Switched {} wallet name to {}.'.format(self.ticker(), self._rpc_wallet))
|
||||
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host, wallet=self._rpc_wallet)
|
||||
break
|
||||
|
||||
return len(wallets)
|
||||
|
||||
def using_segwit(self) -> bool:
|
||||
# Using btc native segwit
|
||||
return self._use_segwit
|
||||
|
@ -239,34 +258,34 @@ class BTCInterface(CoinInterface):
|
|||
self._conf_target = new_conf_target
|
||||
|
||||
def testDaemonRPC(self, with_wallet=True) -> None:
|
||||
self.rpc_callback('getwalletinfo' if with_wallet else 'getblockchaininfo')
|
||||
self.rpc_wallet('getwalletinfo' if with_wallet else 'getblockchaininfo')
|
||||
|
||||
def getDaemonVersion(self):
|
||||
return self.rpc_callback('getnetworkinfo')['version']
|
||||
return self.rpc('getnetworkinfo')['version']
|
||||
|
||||
def getBlockchainInfo(self):
|
||||
return self.rpc_callback('getblockchaininfo')
|
||||
return self.rpc('getblockchaininfo')
|
||||
|
||||
def getChainHeight(self) -> int:
|
||||
return self.rpc_callback('getblockcount')
|
||||
return self.rpc('getblockcount')
|
||||
|
||||
def getMempoolTx(self, txid):
|
||||
return self.rpc_callback('getrawtransaction', [txid.hex()])
|
||||
return self.rpc('getrawtransaction', [txid.hex()])
|
||||
|
||||
def getBlockHeaderFromHeight(self, height):
|
||||
block_hash = self.rpc_callback('getblockhash', [height])
|
||||
return self.rpc_callback('getblockheader', [block_hash])
|
||||
block_hash = self.rpc('getblockhash', [height])
|
||||
return self.rpc('getblockheader', [block_hash])
|
||||
|
||||
def getBlockHeader(self, block_hash):
|
||||
return self.rpc_callback('getblockheader', [block_hash])
|
||||
return self.rpc('getblockheader', [block_hash])
|
||||
|
||||
def getBlockHeaderAt(self, time: int, block_after=False):
|
||||
blockchaininfo = self.rpc_callback('getblockchaininfo')
|
||||
last_block_header = self.rpc_callback('getblockheader', [blockchaininfo['bestblockhash']])
|
||||
blockchaininfo = self.rpc('getblockchaininfo')
|
||||
last_block_header = self.rpc('getblockheader', [blockchaininfo['bestblockhash']])
|
||||
|
||||
max_tries = 5000
|
||||
for i in range(max_tries):
|
||||
prev_block_header = self.rpc_callback('getblock', [last_block_header['previousblockhash']])
|
||||
prev_block_header = self.rpc('getblock', [last_block_header['previousblockhash']])
|
||||
if prev_block_header['time'] <= time:
|
||||
return last_block_header if block_after else prev_block_header
|
||||
|
||||
|
@ -275,11 +294,10 @@ class BTCInterface(CoinInterface):
|
|||
|
||||
def initialiseWallet(self, key_bytes: bytes) -> None:
|
||||
key_wif = self.encodeKey(key_bytes)
|
||||
|
||||
self.rpc_callback('sethdseed', [True, key_wif])
|
||||
self.rpc_wallet('sethdseed', [True, key_wif])
|
||||
|
||||
def getWalletInfo(self):
|
||||
rv = self.rpc_callback('getwalletinfo')
|
||||
rv = self.rpc_wallet('getwalletinfo')
|
||||
rv['encrypted'] = 'unlocked_until' in rv
|
||||
rv['locked'] = rv.get('unlocked_until', 1) <= 0
|
||||
return rv
|
||||
|
@ -288,7 +306,7 @@ class BTCInterface(CoinInterface):
|
|||
return self._restore_height
|
||||
|
||||
def getWalletRestoreHeight(self) -> int:
|
||||
start_time = self.rpc_callback('getwalletinfo')['keypoololdest']
|
||||
start_time = self.rpc_wallet('getwalletinfo')['keypoololdest']
|
||||
|
||||
blockchaininfo = self.getBlockchainInfo()
|
||||
best_block = blockchaininfo['bestblockhash']
|
||||
|
@ -312,7 +330,7 @@ class BTCInterface(CoinInterface):
|
|||
raise ValueError('{} wallet restore height not found.'.format(self.coin_name()))
|
||||
|
||||
def getWalletSeedID(self) -> str:
|
||||
wi = self.rpc_callback('getwalletinfo')
|
||||
wi = self.rpc_wallet('getwalletinfo')
|
||||
return 'Not found' if 'hdseedid' not in wi else wi['hdseedid']
|
||||
|
||||
def checkExpectedSeed(self, expect_seedid) -> bool:
|
||||
|
@ -323,11 +341,11 @@ class BTCInterface(CoinInterface):
|
|||
args = [label]
|
||||
if use_segwit:
|
||||
args.append('bech32')
|
||||
return self.rpc_callback('getnewaddress', args)
|
||||
return self.rpc_wallet('getnewaddress', args)
|
||||
|
||||
def isValidAddress(self, address: str) -> bool:
|
||||
try:
|
||||
rv = self.rpc_callback('validateaddress', [address])
|
||||
rv = self.rpc_wallet('validateaddress', [address])
|
||||
if rv['isvalid'] is True:
|
||||
return True
|
||||
except Exception as ex:
|
||||
|
@ -347,13 +365,13 @@ class BTCInterface(CoinInterface):
|
|||
return False
|
||||
|
||||
def isAddressMine(self, address: str, or_watch_only: bool = False) -> bool:
|
||||
addr_info = self.rpc_callback('getaddressinfo', [address])
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [address])
|
||||
if not or_watch_only:
|
||||
return addr_info['ismine']
|
||||
return addr_info['ismine'] or addr_info['iswatchonly']
|
||||
|
||||
def checkAddressMine(self, address: str) -> None:
|
||||
addr_info = self.rpc_callback('getaddressinfo', [address])
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [address])
|
||||
ensure(addr_info['ismine'], 'ismine is false')
|
||||
if self.sc._restrict_unknown_seed_wallets:
|
||||
ensure(addr_info['hdseedid'] == self._expect_seedid_hex, 'unexpected seedid')
|
||||
|
@ -369,16 +387,16 @@ class BTCInterface(CoinInterface):
|
|||
|
||||
def try_get_fee_rate(self, conf_target):
|
||||
try:
|
||||
fee_rate = self.rpc_callback('estimatesmartfee', [conf_target])['feerate']
|
||||
fee_rate = self.rpc_wallet('estimatesmartfee', [conf_target])['feerate']
|
||||
assert (fee_rate > 0.0), 'Non positive feerate'
|
||||
return fee_rate, 'estimatesmartfee'
|
||||
except Exception:
|
||||
try:
|
||||
fee_rate = self.rpc_callback('getwalletinfo')['paytxfee']
|
||||
fee_rate = self.rpc_wallet('getwalletinfo')['paytxfee']
|
||||
assert (fee_rate > 0.0), 'Non positive feerate'
|
||||
return fee_rate, 'paytxfee'
|
||||
except Exception:
|
||||
return self.rpc_callback('getnetworkinfo')['relayfee'], 'relayfee'
|
||||
return self.rpc('getnetworkinfo')['relayfee'], 'relayfee'
|
||||
|
||||
fee_rate, rate_src = try_get_fee_rate(self, conf_target)
|
||||
if min_relay_fee and min_relay_fee > fee_rate:
|
||||
|
@ -734,7 +752,7 @@ class BTCInterface(CoinInterface):
|
|||
add_bytes = 0
|
||||
add_witness_bytes = getCompactSizeLen(len(tx.vin))
|
||||
for pi in tx.vin:
|
||||
ptx = self.rpc_callback('getrawtransaction', [i2h(pi.prevout.hash), True])
|
||||
ptx = self.rpc('getrawtransaction', [i2h(pi.prevout.hash), True])
|
||||
prevout = ptx['vout'][pi.prevout.n]
|
||||
inputs_value += make_int(prevout['value'])
|
||||
|
||||
|
@ -942,13 +960,13 @@ class BTCInterface(CoinInterface):
|
|||
'lockUnspents': True,
|
||||
'feeRate': feerate_str,
|
||||
}
|
||||
rv = self.rpc_callback('fundrawtransaction', [tx.hex(), options])
|
||||
rv = self.rpc_wallet('fundrawtransaction', [tx.hex(), options])
|
||||
return bytes.fromhex(rv['hex'])
|
||||
|
||||
def listInputs(self, tx_bytes):
|
||||
tx = self.loadTx(tx_bytes)
|
||||
|
||||
all_locked = self.rpc_callback('listlockunspent')
|
||||
all_locked = self.rpc_wallet('listlockunspent')
|
||||
inputs = []
|
||||
for pi in tx.vin:
|
||||
txid_hex = i2h(pi.prevout.hash)
|
||||
|
@ -962,19 +980,19 @@ class BTCInterface(CoinInterface):
|
|||
inputs = []
|
||||
for pi in tx.vin:
|
||||
inputs.append({'txid': i2h(pi.prevout.hash), 'vout': pi.prevout.n})
|
||||
self.rpc_callback('lockunspent', [True, inputs])
|
||||
self.rpc('lockunspent', [True, inputs])
|
||||
|
||||
def signTxWithWallet(self, tx: bytes) -> bytes:
|
||||
rv = self.rpc_callback('signrawtransactionwithwallet', [tx.hex()])
|
||||
rv = self.rpc_wallet('signrawtransactionwithwallet', [tx.hex()])
|
||||
return bytes.fromhex(rv['hex'])
|
||||
|
||||
def signTxWithKey(self, tx: bytes, key: bytes) -> bytes:
|
||||
key_wif = self.encodeKey(key)
|
||||
rv = self.rpc_callback('signrawtransactionwithkey', [tx.hex(), [key_wif, ]])
|
||||
rv = self.rpc('signrawtransactionwithkey', [tx.hex(), [key_wif, ]])
|
||||
return bytes.fromhex(rv['hex'])
|
||||
|
||||
def publishTx(self, tx: bytes):
|
||||
return self.rpc_callback('sendrawtransaction', [tx.hex()])
|
||||
return self.rpc('sendrawtransaction', [tx.hex()])
|
||||
|
||||
def encodeTx(self, tx) -> bytes:
|
||||
return tx.serialize()
|
||||
|
@ -1018,18 +1036,18 @@ class BTCInterface(CoinInterface):
|
|||
return self.getScriptForPubkeyHash(self.getPubkeyHash(K))
|
||||
|
||||
def scanTxOutset(self, dest):
|
||||
return self.rpc_callback('scantxoutset', ['start', ['raw({})'.format(dest.hex())]])
|
||||
return self.rpc('scantxoutset', ['start', ['raw({})'.format(dest.hex())]])
|
||||
|
||||
def getTransaction(self, txid: bytes):
|
||||
try:
|
||||
return bytes.fromhex(self.rpc_callback('getrawtransaction', [txid.hex()]))
|
||||
return bytes.fromhex(self.rpc('getrawtransaction', [txid.hex()]))
|
||||
except Exception as ex:
|
||||
# TODO: filter errors
|
||||
return None
|
||||
|
||||
def getWalletTransaction(self, txid: bytes):
|
||||
try:
|
||||
return bytes.fromhex(self.rpc_callback('gettransaction', [txid.hex()]))
|
||||
return bytes.fromhex(self.rpc('gettransaction', [txid.hex()]))
|
||||
except Exception as ex:
|
||||
# TODO: filter errors
|
||||
return None
|
||||
|
@ -1115,7 +1133,7 @@ class BTCInterface(CoinInterface):
|
|||
|
||||
def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee: int, restore_height: int) -> bytes:
|
||||
self._log.info('spendBLockTx %s:\n', chain_b_lock_txid.hex())
|
||||
wtx = self.rpc_callback('gettransaction', [chain_b_lock_txid.hex(), ])
|
||||
wtx = self.rpc_wallet('gettransaction', [chain_b_lock_txid.hex(), ])
|
||||
lock_tx = self.loadTx(bytes.fromhex(wtx['hex']))
|
||||
|
||||
Kbs = self.getPubkey(kbs)
|
||||
|
@ -1144,10 +1162,10 @@ class BTCInterface(CoinInterface):
|
|||
return bytes.fromhex(self.publishTx(b_lock_spend_tx))
|
||||
|
||||
def importWatchOnlyAddress(self, address: str, label: str):
|
||||
self.rpc_callback('importaddress', [address, label, False])
|
||||
self.rpc_wallet('importaddress', [address, label, False])
|
||||
|
||||
def isWatchOnlyAddress(self, address: str):
|
||||
addr_info = self.rpc_callback('getaddressinfo', [address])
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [address])
|
||||
return addr_info['iswatchonly']
|
||||
|
||||
def getSCLockScriptAddress(self, lock_script):
|
||||
|
@ -1161,11 +1179,11 @@ class BTCInterface(CoinInterface):
|
|||
self.importWatchOnlyAddress(dest_address, 'bid')
|
||||
self._log.info('Imported watch-only addr: {}'.format(dest_address))
|
||||
self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), rescan_from))
|
||||
self.rpc_callback('rescanblockchain', [rescan_from])
|
||||
self.rpc_wallet('rescanblockchain', [rescan_from])
|
||||
|
||||
return_txid = True if txid is None else False
|
||||
if txid is None:
|
||||
txns = self.rpc_callback('listunspent', [0, 9999999, [dest_address, ]])
|
||||
txns = self.rpc_wallet('listunspent', [0, 9999999, [dest_address, ]])
|
||||
|
||||
for tx in txns:
|
||||
if self.make_int(tx['amount']) == bid_amount:
|
||||
|
@ -1176,11 +1194,11 @@ class BTCInterface(CoinInterface):
|
|||
return None
|
||||
|
||||
try:
|
||||
tx = self.rpc_callback('gettransaction', [txid.hex()])
|
||||
tx = self.rpc_wallet('gettransaction', [txid.hex()])
|
||||
|
||||
block_height = 0
|
||||
if 'blockhash' in tx:
|
||||
block_header = self.rpc_callback('getblockheader', [tx['blockhash']])
|
||||
block_header = self.rpc('getblockheader', [tx['blockhash']])
|
||||
block_height = block_header['height']
|
||||
|
||||
rv = {
|
||||
|
@ -1192,7 +1210,7 @@ class BTCInterface(CoinInterface):
|
|||
return None
|
||||
|
||||
if find_index:
|
||||
tx_obj = self.rpc_callback('decoderawtransaction', [tx['hex']])
|
||||
tx_obj = self.rpc('decoderawtransaction', [tx['hex']])
|
||||
rv['index'] = find_vout_for_address_from_txobj(tx_obj, dest_address)
|
||||
|
||||
if return_txid:
|
||||
|
@ -1202,7 +1220,7 @@ class BTCInterface(CoinInterface):
|
|||
|
||||
def getOutput(self, txid, dest_script, expect_value, xmr_swap=None):
|
||||
# TODO: Use getrawtransaction if txindex is active
|
||||
utxos = self.rpc_callback('scantxoutset', ['start', ['raw({})'.format(dest_script.hex())]])
|
||||
utxos = self.rpc('scantxoutset', ['start', ['raw({})'.format(dest_script.hex())]])
|
||||
if 'height' in utxos: # chain_height not returned by v18 codebase
|
||||
chain_height = utxos['height']
|
||||
else:
|
||||
|
@ -1225,7 +1243,7 @@ class BTCInterface(CoinInterface):
|
|||
|
||||
def withdrawCoin(self, value, addr_to, subfee):
|
||||
params = [addr_to, value, '', '', subfee, True, self._conf_target]
|
||||
return self.rpc_callback('sendtoaddress', params)
|
||||
return self.rpc_wallet('sendtoaddress', params)
|
||||
|
||||
def signCompact(self, k, message):
|
||||
message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
|
||||
|
@ -1318,10 +1336,10 @@ class BTCInterface(CoinInterface):
|
|||
return length
|
||||
|
||||
def describeTx(self, tx_hex: str):
|
||||
return self.rpc_callback('decoderawtransaction', [tx_hex])
|
||||
return self.rpc('decoderawtransaction', [tx_hex])
|
||||
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getbalances')['mine']['trusted'])
|
||||
return self.make_int(self.rpc_wallet('getbalances')['mine']['trusted'])
|
||||
|
||||
def createUTXO(self, value_sats: int):
|
||||
# Create a new address and send value_sats to it
|
||||
|
@ -1334,7 +1352,7 @@ class BTCInterface(CoinInterface):
|
|||
return self.withdrawCoin(self.format_amount(value_sats), address, False), address
|
||||
|
||||
def createRawFundedTransaction(self, addr_to: str, amount: int, sub_fee: bool = False, lock_unspents: bool = True) -> str:
|
||||
txn = self.rpc_callback('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
|
||||
txn = self.rpc('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
|
||||
|
||||
options = {
|
||||
'lockUnspents': lock_unspents,
|
||||
|
@ -1342,18 +1360,18 @@ class BTCInterface(CoinInterface):
|
|||
}
|
||||
if sub_fee:
|
||||
options['subtractFeeFromOutputs'] = [0,]
|
||||
return self.rpc_callback('fundrawtransaction', [txn, options])['hex']
|
||||
return self.rpc_wallet('fundrawtransaction', [txn, options])['hex']
|
||||
|
||||
def createRawSignedTransaction(self, addr_to, amount) -> str:
|
||||
txn_funded = self.createRawFundedTransaction(addr_to, amount)
|
||||
return self.rpc_callback('signrawtransactionwithwallet', [txn_funded])['hex']
|
||||
return self.rpc_wallet('signrawtransactionwithwallet', [txn_funded])['hex']
|
||||
|
||||
def getBlockWithTxns(self, block_hash: str):
|
||||
return self.rpc_callback('getblock', [block_hash, 2])
|
||||
return self.rpc('getblock', [block_hash, 2])
|
||||
|
||||
def getUnspentsByAddr(self):
|
||||
unspent_addr = dict()
|
||||
unspent = self.rpc_callback('listunspent')
|
||||
unspent = self.rpc_wallet('listunspent')
|
||||
for u in unspent:
|
||||
if u['spendable'] is not True:
|
||||
continue
|
||||
|
@ -1361,11 +1379,11 @@ class BTCInterface(CoinInterface):
|
|||
return unspent_addr
|
||||
|
||||
def getUTXOBalance(self, address: str):
|
||||
num_blocks = self.rpc_callback('getblockcount')
|
||||
num_blocks = self.rpc('getblockcount')
|
||||
|
||||
sum_unspent = 0
|
||||
self._log.debug('[rm] scantxoutset start') # scantxoutset is slow
|
||||
ro = self.rpc_callback('scantxoutset', ['start', ['addr({})'.format(address)]]) # TODO: Use combo(address) where possible
|
||||
ro = self.rpc('scantxoutset', ['start', ['addr({})'.format(address)]]) # TODO: Use combo(address) where possible
|
||||
self._log.debug('[rm] scantxoutset end')
|
||||
for o in ro['unspents']:
|
||||
sum_unspent += self.make_int(o['amount'])
|
||||
|
@ -1391,7 +1409,7 @@ class BTCInterface(CoinInterface):
|
|||
sign_for_addr = self.pkh_to_address(pkh)
|
||||
self._log.debug('sign_for_addr converted %s', sign_for_addr)
|
||||
|
||||
signature = self.rpc_callback('signmessage', [sign_for_addr, sign_for_addr + '_swap_proof_' + extra_commit_bytes.hex()])
|
||||
signature = self.rpc_wallet('signmessage', [sign_for_addr, sign_for_addr + '_swap_proof_' + extra_commit_bytes.hex()])
|
||||
|
||||
prove_utxos = [] # TODO: Send specific utxos
|
||||
return (sign_for_addr, signature, prove_utxos)
|
||||
|
@ -1416,17 +1434,17 @@ class BTCInterface(CoinInterface):
|
|||
return self.getUTXOBalance(address)
|
||||
|
||||
def isWalletEncrypted(self) -> bool:
|
||||
wallet_info = self.rpc_callback('getwalletinfo')
|
||||
wallet_info = self.rpc_wallet('getwalletinfo')
|
||||
return 'unlocked_until' in wallet_info
|
||||
|
||||
def isWalletLocked(self) -> bool:
|
||||
wallet_info = self.rpc_callback('getwalletinfo')
|
||||
wallet_info = self.rpc_wallet('getwalletinfo')
|
||||
if 'unlocked_until' in wallet_info and wallet_info['unlocked_until'] <= 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def isWalletEncryptedLocked(self):
|
||||
wallet_info = self.rpc_callback('getwalletinfo')
|
||||
wallet_info = self.rpc_wallet('getwalletinfo')
|
||||
encrypted = 'unlocked_until' in wallet_info
|
||||
locked = encrypted and wallet_info['unlocked_until'] <= 0
|
||||
return encrypted, locked
|
||||
|
@ -1436,8 +1454,8 @@ class BTCInterface(CoinInterface):
|
|||
if old_password == '':
|
||||
if self.isWalletEncrypted():
|
||||
raise ValueError('Old password must be set')
|
||||
return self.rpc_callback('encryptwallet', [new_password])
|
||||
self.rpc_callback('walletpassphrasechange', [old_password, new_password])
|
||||
return self.rpc_wallet('encryptwallet', [new_password])
|
||||
self.rpc_wallet('walletpassphrasechange', [old_password, new_password])
|
||||
|
||||
def unlockWallet(self, password: str):
|
||||
if password == '':
|
||||
|
@ -1447,21 +1465,20 @@ class BTCInterface(CoinInterface):
|
|||
if self.coin_type() == Coins.BTC:
|
||||
# Recreate wallet if none found
|
||||
# Required when encrypting an existing btc wallet, workaround is to delete the btc wallet and recreate
|
||||
wallets = self.rpc_callback('listwallets')
|
||||
wallets = self.rpc('listwallets')
|
||||
if len(wallets) < 1:
|
||||
self._log.info('Creating wallet.dat for {}.'.format(self.coin_name()))
|
||||
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors
|
||||
self.rpc_callback('createwallet', ['wallet.dat', False, True, '', False, False])
|
||||
self.rpc_callback('encryptwallet', [password])
|
||||
self.rpc('createwallet', ['wallet.dat', False, True, '', False, False])
|
||||
self.rpc_wallet('encryptwallet', [password])
|
||||
|
||||
# Max timeout value, ~3 years
|
||||
self.rpc_callback('walletpassphrase', [password, 100000000])
|
||||
|
||||
self.rpc_wallet('walletpassphrase', [password, 100000000])
|
||||
self._sc.checkWalletSeed(self.coin_type())
|
||||
|
||||
def lockWallet(self):
|
||||
self._log.info('lockWallet - {}'.format(self.ticker()))
|
||||
self.rpc_callback('walletlock')
|
||||
self.rpc_wallet('walletlock')
|
||||
|
||||
def get_p2sh_script_pubkey(self, script: bytearray) -> bytearray:
|
||||
script_hash = hash160(script)
|
||||
|
@ -1474,7 +1491,7 @@ class BTCInterface(CoinInterface):
|
|||
def findTxnByHash(self, txid_hex: str):
|
||||
# Only works for wallet txns
|
||||
try:
|
||||
rv = self.rpc_callback('gettransaction', [txid_hex])
|
||||
rv = self.rpc_wallet('gettransaction', [txid_hex])
|
||||
except Exception as ex:
|
||||
self._log.debug('findTxnByHash getrawtransaction failed: {}'.format(txid_hex))
|
||||
return None
|
||||
|
|
|
@ -32,7 +32,7 @@ class DASHInterface(BTCInterface):
|
|||
words = self.seedToMnemonic(key)
|
||||
|
||||
mnemonic_passphrase = ''
|
||||
self.rpc_callback('upgradetohd', [words, mnemonic_passphrase, self._wallet_passphrase])
|
||||
self.rpc_wallet('upgradetohd', [words, mnemonic_passphrase, self._wallet_passphrase])
|
||||
self._have_checked_seed = False
|
||||
if self._wallet_passphrase != '':
|
||||
self.unlockWallet(self._wallet_passphrase)
|
||||
|
@ -42,7 +42,7 @@ class DASHInterface(BTCInterface):
|
|||
|
||||
def checkExpectedSeed(self, key_hash: str):
|
||||
try:
|
||||
rv = self.rpc_callback('dumphdinfo')
|
||||
rv = self.rpc_wallet('dumphdinfo')
|
||||
entropy = Mnemonic('english').to_entropy(rv['mnemonic'].split(' '))
|
||||
entropy_hash = self.getAddressHashFromKey(entropy)[::-1].hex()
|
||||
self._have_checked_seed = True
|
||||
|
@ -53,10 +53,10 @@ class DASHInterface(BTCInterface):
|
|||
|
||||
def withdrawCoin(self, value, addr_to, subfee):
|
||||
params = [addr_to, value, '', '', subfee, False, False, self._conf_target]
|
||||
return self.rpc_callback('sendtoaddress', params)
|
||||
return self.rpc_wallet('sendtoaddress', params)
|
||||
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getwalletinfo')['balance'])
|
||||
return self.make_int(self.rpc_wallet('getwalletinfo')['balance'])
|
||||
|
||||
def getScriptForPubkeyHash(self, pkh: bytes) -> bytearray:
|
||||
# Return P2PKH
|
||||
|
@ -72,7 +72,7 @@ class DASHInterface(BTCInterface):
|
|||
def findTxnByHash(self, txid_hex: str):
|
||||
# Only works for wallet txns
|
||||
try:
|
||||
rv = self.rpc_callback('gettransaction', [txid_hex])
|
||||
rv = self.rpc_wallet('gettransaction', [txid_hex])
|
||||
except Exception as ex:
|
||||
self._log.debug('findTxnByHash getrawtransaction failed: {}'.format(txid_hex))
|
||||
return None
|
||||
|
|
|
@ -13,6 +13,7 @@ from basicswap.util import (
|
|||
i2b,
|
||||
ensure,
|
||||
)
|
||||
from basicswap.rpc import make_rpc_func
|
||||
from basicswap.util.crypto import hash160
|
||||
from basicswap.util.address import decodeAddress
|
||||
from basicswap.chainparams import Coins
|
||||
|
@ -36,6 +37,14 @@ class FIROInterface(BTCInterface):
|
|||
def coin_type():
|
||||
return Coins.FIRO
|
||||
|
||||
def __init__(self, coin_settings, network, swap_client=None):
|
||||
super(FIROInterface, self).__init__(coin_settings, network, swap_client)
|
||||
# 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'
|
||||
|
||||
|
@ -44,9 +53,9 @@ class FIROInterface(BTCInterface):
|
|||
pass
|
||||
|
||||
def getNewAddress(self, use_segwit, label='swap_receive'):
|
||||
return self.rpc_callback('getnewaddress', [label])
|
||||
# addr_plain = self.rpc_callback('getnewaddress', [label])
|
||||
# return self.rpc_callback('addwitnessaddress', [addr_plain])
|
||||
return self.rpc('getnewaddress', [label])
|
||||
# addr_plain = self.rpc('getnewaddress', [label])
|
||||
# return self.rpc('addwitnessaddress', [addr_plain])
|
||||
|
||||
def decodeAddress(self, address):
|
||||
return decodeAddress(address)[1:]
|
||||
|
@ -58,11 +67,11 @@ class FIROInterface(BTCInterface):
|
|||
raise ValueError('TODO')
|
||||
|
||||
def isWatchOnlyAddress(self, address):
|
||||
addr_info = self.rpc_callback('validateaddress', [address])
|
||||
addr_info = self.rpc('validateaddress', [address])
|
||||
return addr_info['iswatchonly']
|
||||
|
||||
def isAddressMine(self, address: str, or_watch_only: bool = False) -> bool:
|
||||
addr_info = self.rpc_callback('validateaddress', [address])
|
||||
addr_info = self.rpc('validateaddress', [address])
|
||||
if not or_watch_only:
|
||||
return addr_info['ismine']
|
||||
return addr_info['ismine'] or addr_info['iswatchonly']
|
||||
|
@ -73,8 +82,8 @@ class FIROInterface(BTCInterface):
|
|||
|
||||
if not self.isAddressMine(address, or_watch_only=True):
|
||||
# Expects P2WSH nested in BIP16_P2SH
|
||||
ro = self.rpc_callback('importaddress', [lock_tx_dest.hex(), 'bid lock', False, True])
|
||||
addr_info = self.rpc_callback('validateaddress', [address])
|
||||
ro = self.rpc('importaddress', [lock_tx_dest.hex(), 'bid lock', False, True])
|
||||
addr_info = self.rpc('validateaddress', [address])
|
||||
|
||||
return address
|
||||
|
||||
|
@ -89,7 +98,7 @@ class FIROInterface(BTCInterface):
|
|||
|
||||
return_txid = True if txid is None else False
|
||||
if txid is None:
|
||||
txns = self.rpc_callback('listunspent', [0, 9999999, [dest_address, ]])
|
||||
txns = self.rpc('listunspent', [0, 9999999, [dest_address, ]])
|
||||
|
||||
for tx in txns:
|
||||
if self.make_int(tx['amount']) == bid_amount:
|
||||
|
@ -100,11 +109,11 @@ class FIROInterface(BTCInterface):
|
|||
return None
|
||||
|
||||
try:
|
||||
tx = self.rpc_callback('gettransaction', [txid.hex()])
|
||||
tx = self.rpc('gettransaction', [txid.hex()])
|
||||
|
||||
block_height = 0
|
||||
if 'blockhash' in tx:
|
||||
block_header = self.rpc_callback('getblockheader', [tx['blockhash']])
|
||||
block_header = self.rpc('getblockheader', [tx['blockhash']])
|
||||
block_height = block_header['height']
|
||||
|
||||
rv = {
|
||||
|
@ -116,7 +125,7 @@ class FIROInterface(BTCInterface):
|
|||
return None
|
||||
|
||||
if find_index:
|
||||
tx_obj = self.rpc_callback('decoderawtransaction', [tx['hex']])
|
||||
tx_obj = self.rpc('decoderawtransaction', [tx['hex']])
|
||||
rv['index'] = find_vout_for_address_from_txobj(tx_obj, dest_address)
|
||||
|
||||
if return_txid:
|
||||
|
@ -135,11 +144,11 @@ class FIROInterface(BTCInterface):
|
|||
return self.fundTx(tx_bytes, feerate)
|
||||
|
||||
def signTxWithWallet(self, tx):
|
||||
rv = self.rpc_callback('signrawtransaction', [tx.hex()])
|
||||
rv = self.rpc('signrawtransaction', [tx.hex()])
|
||||
return bytes.fromhex(rv['hex'])
|
||||
|
||||
def createRawFundedTransaction(self, addr_to: str, amount: int, sub_fee: bool = False, lock_unspents: bool = True) -> str:
|
||||
txn = self.rpc_callback('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
|
||||
txn = self.rpc('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
|
||||
fee_rate, fee_src = self.get_fee_rate(self._conf_target)
|
||||
self._log.debug(f'Fee rate: {fee_rate}, source: {fee_src}, block target: {self._conf_target}')
|
||||
options = {
|
||||
|
@ -148,11 +157,11 @@ class FIROInterface(BTCInterface):
|
|||
}
|
||||
if sub_fee:
|
||||
options['subtractFeeFromOutputs'] = [0,]
|
||||
return self.rpc_callback('fundrawtransaction', [txn, options])['hex']
|
||||
return self.rpc('fundrawtransaction', [txn, options])['hex']
|
||||
|
||||
def createRawSignedTransaction(self, addr_to, amount) -> str:
|
||||
txn_funded = self.createRawFundedTransaction(addr_to, amount)
|
||||
return self.rpc_callback('signrawtransaction', [txn_funded])['hex']
|
||||
return self.rpc('signrawtransaction', [txn_funded])['hex']
|
||||
|
||||
def getScriptForPubkeyHash(self, pkh: bytes) -> bytearray:
|
||||
# Return P2PKH
|
||||
|
@ -180,13 +189,13 @@ class FIROInterface(BTCInterface):
|
|||
|
||||
def withdrawCoin(self, value, addr_to, subfee):
|
||||
params = [addr_to, value, '', '', subfee]
|
||||
return self.rpc_callback('sendtoaddress', params)
|
||||
return self.rpc('sendtoaddress', params)
|
||||
|
||||
def getWalletSeedID(self):
|
||||
return self.rpc_callback('getwalletinfo')['hdmasterkeyid']
|
||||
return self.rpc('getwalletinfo')['hdmasterkeyid']
|
||||
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getwalletinfo')['balance'])
|
||||
return self.make_int(self.rpc('getwalletinfo')['balance'])
|
||||
|
||||
def getBLockSpendTxFee(self, tx, fee_rate: int) -> int:
|
||||
add_bytes = 107
|
||||
|
@ -197,13 +206,13 @@ class FIROInterface(BTCInterface):
|
|||
|
||||
def signTxWithKey(self, tx: bytes, key: bytes) -> bytes:
|
||||
key_wif = self.encodeKey(key)
|
||||
rv = self.rpc_callback('signrawtransaction', [tx.hex(), [], [key_wif, ]])
|
||||
rv = self.rpc('signrawtransaction', [tx.hex(), [], [key_wif, ]])
|
||||
return bytes.fromhex(rv['hex'])
|
||||
|
||||
def findTxnByHash(self, txid_hex: str):
|
||||
# Only works for wallet txns
|
||||
try:
|
||||
rv = self.rpc_callback('gettransaction', [txid_hex])
|
||||
rv = self.rpc('gettransaction', [txid_hex])
|
||||
except Exception as ex:
|
||||
self._log.debug('findTxnByHash getrawtransaction failed: {}'.format(txid_hex))
|
||||
return None
|
||||
|
@ -216,7 +225,7 @@ class FIROInterface(BTCInterface):
|
|||
# TODO: Lock unspent and use same output/s to fund bid
|
||||
|
||||
unspents_by_addr = dict()
|
||||
unspents = self.rpc_callback('listunspent')
|
||||
unspents = self.rpc('listunspent')
|
||||
for u in unspents:
|
||||
if u['spendable'] is not True:
|
||||
continue
|
||||
|
@ -276,7 +285,7 @@ class FIROInterface(BTCInterface):
|
|||
sign_for_addr = self.pkh_to_address(pkh)
|
||||
self._log.debug('sign_for_addr converted %s', sign_for_addr)
|
||||
|
||||
signature = self.rpc_callback('signmessage', [sign_for_addr, sign_for_addr + '_swap_proof_' + utxos_hash.hex() + extra_commit_bytes.hex()])
|
||||
signature = self.rpc('signmessage', [sign_for_addr, sign_for_addr + '_swap_proof_' + utxos_hash.hex() + extra_commit_bytes.hex()])
|
||||
|
||||
return (sign_for_addr, signature, prove_utxos)
|
||||
|
||||
|
@ -296,7 +305,7 @@ class FIROInterface(BTCInterface):
|
|||
|
||||
sum_value: int = 0
|
||||
for outpoint in utxos:
|
||||
txout = self.rpc_callback('gettxout', [outpoint[0].hex(), outpoint[1]])
|
||||
txout = self.rpc('gettxout', [outpoint[0].hex(), outpoint[1]])
|
||||
sum_value += self.make_int(txout['value'])
|
||||
|
||||
return sum_value
|
||||
|
@ -307,15 +316,15 @@ class FIROInterface(BTCInterface):
|
|||
chain_blocks: int = self.getChainHeight()
|
||||
|
||||
current_height: int = chain_blocks
|
||||
block_hash = self.rpc_callback('getblockhash', [current_height])
|
||||
block_hash = self.rpc('getblockhash', [current_height])
|
||||
|
||||
script_hash: bytes = self.decodeAddress(addr_find)
|
||||
find_scriptPubKey = self.getDestForScriptHash(script_hash)
|
||||
|
||||
while current_height > height_start:
|
||||
block_hash = self.rpc_callback('getblockhash', [current_height])
|
||||
block_hash = self.rpc('getblockhash', [current_height])
|
||||
|
||||
block = self.rpc_callback('getblock', [block_hash, False])
|
||||
block = self.rpc('getblock', [block_hash, False])
|
||||
decoded_block = CBlock()
|
||||
decoded_block = FromHex(decoded_block, block)
|
||||
for tx in decoded_block.vtx:
|
||||
|
@ -325,22 +334,22 @@ class FIROInterface(BTCInterface):
|
|||
txid = i2b(tx.sha256)
|
||||
self._log.info('Found output to addr: {} in tx {} in block {}'.format(addr_find, txid.hex(), block_hash))
|
||||
self._log.info('rescanblockchain hack invalidateblock {}'.format(block_hash))
|
||||
self.rpc_callback('invalidateblock', [block_hash])
|
||||
self.rpc_callback('reconsiderblock', [block_hash])
|
||||
self.rpc('invalidateblock', [block_hash])
|
||||
self.rpc('reconsiderblock', [block_hash])
|
||||
return
|
||||
current_height -= 1
|
||||
|
||||
def getBlockWithTxns(self, block_hash):
|
||||
# TODO: Bypass decoderawtransaction and getblockheader
|
||||
block = self.rpc_callback('getblock', [block_hash, False])
|
||||
block_header = self.rpc_callback('getblockheader', [block_hash])
|
||||
block = self.rpc('getblock', [block_hash, False])
|
||||
block_header = self.rpc('getblockheader', [block_hash])
|
||||
decoded_block = CBlock()
|
||||
decoded_block = FromHex(decoded_block, block)
|
||||
|
||||
tx_rv = []
|
||||
for tx in decoded_block.vtx:
|
||||
tx_hex = tx.serialize_with_witness().hex()
|
||||
tx_dec = self.rpc_callback('decoderawtransaction', [tx_hex])
|
||||
tx_dec = self.rpc('decoderawtransaction', [tx_hex])
|
||||
if 'hex' not in tx_dec:
|
||||
tx_dec['hex'] = tx_hex
|
||||
|
||||
|
|
|
@ -1,15 +1,117 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020 tecnovert
|
||||
# Copyright (c) 2020-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
from .btc import BTCInterface
|
||||
from basicswap.chainparams import Coins
|
||||
from basicswap.rpc import make_rpc_func
|
||||
from basicswap.chainparams import Coins, chainparams
|
||||
|
||||
|
||||
class LTCInterface(BTCInterface):
|
||||
@staticmethod
|
||||
def coin_type():
|
||||
return Coins.LTC
|
||||
|
||||
def __init__(self, coin_settings, network, swap_client=None):
|
||||
super(LTCInterface, self).__init__(coin_settings, network, swap_client)
|
||||
self._rpc_wallet_mweb = 'mweb'
|
||||
self.rpc_wallet_mweb = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host, wallet=self._rpc_wallet_mweb)
|
||||
|
||||
def getNewMwebAddress(self, use_segwit=False, label='swap_receive') -> str:
|
||||
return self.rpc_wallet_mweb('getnewaddress', [label, 'mweb'])
|
||||
|
||||
def getNewStealthAddress(self, label=''):
|
||||
return self.getNewMwebAddress(False, label)
|
||||
|
||||
def withdrawCoin(self, value, type_from: str, addr_to: str, subfee: bool) -> str:
|
||||
params = [addr_to, value, '', '', subfee, True, self._conf_target]
|
||||
if type_from == 'mweb':
|
||||
return self.rpc_wallet_mweb('sendtoaddress', params)
|
||||
return self.rpc_wallet('sendtoaddress', params)
|
||||
|
||||
def getWalletInfo(self):
|
||||
rv = self.rpc_wallet('getwalletinfo')
|
||||
rv['encrypted'] = 'unlocked_until' in rv
|
||||
rv['locked'] = rv.get('unlocked_until', 1) <= 0
|
||||
|
||||
mweb_info = self.rpc_wallet_mweb('getwalletinfo')
|
||||
rv['mweb_balance'] = mweb_info['balance']
|
||||
rv['mweb_unconfirmed'] = mweb_info['unconfirmed_balance']
|
||||
rv['mweb_immature'] = mweb_info['immature_balance']
|
||||
return rv
|
||||
|
||||
|
||||
class LTCInterfaceMWEB(LTCInterface):
|
||||
@staticmethod
|
||||
def coin_type():
|
||||
return Coins.LTC_MWEB
|
||||
|
||||
def __init__(self, coin_settings, network, swap_client=None):
|
||||
super(LTCInterfaceMWEB, self).__init__(coin_settings, network, swap_client)
|
||||
self._rpc_wallet = 'mweb'
|
||||
self.rpc_wallet = make_rpc_func(self._rpcport, self._rpcauth, host=self._rpc_host, wallet=self._rpc_wallet)
|
||||
|
||||
def chainparams(self):
|
||||
return chainparams[Coins.LTC]
|
||||
|
||||
def chainparams_network(self):
|
||||
return chainparams[Coins.LTC][self._network]
|
||||
|
||||
def coin_name(self) -> str:
|
||||
coin_chainparams = chainparams[Coins.LTC]
|
||||
if coin_chainparams.get('use_ticker_as_name', False):
|
||||
return coin_chainparams['ticker'] + ' MWEB'
|
||||
return coin_chainparams['name'].capitalize() + ' MWEB'
|
||||
|
||||
def ticker(self) -> str:
|
||||
ticker = chainparams[Coins.LTC]['ticker']
|
||||
if self._network == 'testnet':
|
||||
ticker = 't' + ticker
|
||||
elif self._network == 'regtest':
|
||||
ticker = 'rt' + ticker
|
||||
return ticker + '_MWEB'
|
||||
|
||||
def getNewAddress(self, use_segwit=False, label='swap_receive') -> str:
|
||||
return self.getNewMwebAddress()
|
||||
|
||||
def has_mweb_wallet(self) -> bool:
|
||||
return 'mweb' in self.rpc('listwallets')
|
||||
|
||||
def init_wallet(self, password=None):
|
||||
# If system is encrypted mweb wallet will be created at first unlock
|
||||
|
||||
self._log.info('init_wallet - {}'.format(self.ticker()))
|
||||
|
||||
self._log.info('Creating mweb wallet for {}.'.format(self.coin_name()))
|
||||
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors, load_on_startup
|
||||
self.rpc('createwallet', ['mweb', False, True, password, False, False, True])
|
||||
|
||||
if password is not None:
|
||||
# Max timeout value, ~3 years
|
||||
self.rpc_wallet('walletpassphrase', [password, 100000000])
|
||||
|
||||
if self.getWalletSeedID() == 'Not found':
|
||||
self._sc.initialiseWallet(self.coin_type())
|
||||
|
||||
# Workaround to trigger mweb_spk_man->LoadMWEBKeychain()
|
||||
self.rpc('unloadwallet', ['mweb'])
|
||||
self.rpc('loadwallet', ['mweb'])
|
||||
if password is not None:
|
||||
self.rpc_wallet('walletpassphrase', [password, 100000000])
|
||||
self.rpc_wallet('keypoolrefill')
|
||||
|
||||
def unlockWallet(self, password: str):
|
||||
if password == '':
|
||||
return
|
||||
self._log.info('unlockWallet - {}'.format(self.ticker()))
|
||||
|
||||
if not self.has_mweb_wallet():
|
||||
self.init_wallet(password)
|
||||
else:
|
||||
# Max timeout value, ~3 years
|
||||
self.rpc_wallet('walletpassphrase', [password, 100000000])
|
||||
|
||||
self._sc.checkWalletSeed(self.coin_type())
|
||||
|
|
|
@ -14,6 +14,7 @@ from coincurve.keys import (
|
|||
PrivateKey,
|
||||
)
|
||||
from .btc import BTCInterface, find_vout_for_address_from_txobj, findOutput
|
||||
from basicswap.rpc import make_rpc_func
|
||||
from basicswap.chainparams import Coins
|
||||
from basicswap.interface.contrib.nav_test_framework.mininode import (
|
||||
CTxIn,
|
||||
|
@ -63,6 +64,14 @@ class NAVInterface(BTCInterface):
|
|||
def txoType():
|
||||
return CTxOut
|
||||
|
||||
def __init__(self, coin_settings, network, swap_client=None):
|
||||
super(NAVInterface, self).__init__(coin_settings, network, swap_client)
|
||||
# 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
|
||||
|
@ -75,24 +84,24 @@ class NAVInterface(BTCInterface):
|
|||
pass
|
||||
|
||||
def getWalletSeedID(self):
|
||||
return self.rpc_callback('getwalletinfo')['hdmasterkeyid']
|
||||
return self.rpc('getwalletinfo')['hdmasterkeyid']
|
||||
|
||||
def withdrawCoin(self, value, addr_to: str, subfee: bool):
|
||||
strdzeel = ''
|
||||
params = [addr_to, value, '', '', strdzeel, subfee]
|
||||
return self.rpc_callback('sendtoaddress', params)
|
||||
return self.rpc('sendtoaddress', params)
|
||||
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getwalletinfo')['balance'])
|
||||
return self.make_int(self.rpc('getwalletinfo')['balance'])
|
||||
|
||||
def signTxWithWallet(self, tx: bytes) -> bytes:
|
||||
rv = self.rpc_callback('signrawtransaction', [tx.hex()])
|
||||
rv = self.rpc('signrawtransaction', [tx.hex()])
|
||||
|
||||
return bytes.fromhex(rv['hex'])
|
||||
|
||||
def checkExpectedSeed(self, key_hash: str):
|
||||
try:
|
||||
rv = self.rpc_callback('dumpmnemonic')
|
||||
rv = self.rpc('dumpmnemonic')
|
||||
entropy = Mnemonic('english').to_entropy(rv.split(' '))
|
||||
|
||||
entropy_hash = self.getAddressHashFromKey(entropy)[::-1].hex()
|
||||
|
@ -155,7 +164,7 @@ class NAVInterface(BTCInterface):
|
|||
# TODO: Lock unspent and use same output/s to fund bid
|
||||
|
||||
unspents_by_addr = dict()
|
||||
unspents = self.rpc_callback('listunspent')
|
||||
unspents = self.rpc('listunspent')
|
||||
for u in unspents:
|
||||
if u['spendable'] is not True:
|
||||
continue
|
||||
|
@ -211,13 +220,13 @@ class NAVInterface(BTCInterface):
|
|||
|
||||
if self.using_segwit(): # TODO: Use isSegwitAddress when scantxoutset can use combo
|
||||
# 'Address does not refer to key' for non p2pkh
|
||||
addr_info = self.rpc_callback('validateaddress', [addr, ])
|
||||
addr_info = self.rpc('validateaddress', [addr, ])
|
||||
if 'isscript' in addr_info and addr_info['isscript'] and 'hex' in addr_info:
|
||||
pkh = bytes.fromhex(addr_info['hex'])[2:]
|
||||
sign_for_addr = self.pkh_to_address(pkh)
|
||||
self._log.debug('sign_for_addr converted %s', sign_for_addr)
|
||||
|
||||
signature = self.rpc_callback('signmessage', [sign_for_addr, sign_for_addr + '_swap_proof_' + utxos_hash.hex() + extra_commit_bytes.hex()])
|
||||
signature = self.rpc('signmessage', [sign_for_addr, sign_for_addr + '_swap_proof_' + utxos_hash.hex() + extra_commit_bytes.hex()])
|
||||
|
||||
return (sign_for_addr, signature, prove_utxos)
|
||||
|
||||
|
@ -237,13 +246,13 @@ class NAVInterface(BTCInterface):
|
|||
|
||||
sum_value: int = 0
|
||||
for outpoint in utxos:
|
||||
txout = self.rpc_callback('gettxout', [outpoint[0].hex(), outpoint[1]])
|
||||
txout = self.rpc('gettxout', [outpoint[0].hex(), outpoint[1]])
|
||||
sum_value += self.make_int(txout['value'])
|
||||
|
||||
return sum_value
|
||||
|
||||
def createRawFundedTransaction(self, addr_to: str, amount: int, sub_fee: bool = False, lock_unspents: bool = True) -> str:
|
||||
txn = self.rpc_callback('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
|
||||
txn = self.rpc('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
|
||||
fee_rate, fee_src = self.get_fee_rate(self._conf_target)
|
||||
self._log.debug(f'Fee rate: {fee_rate}, source: {fee_src}, block target: {self._conf_target}')
|
||||
if sub_fee:
|
||||
|
@ -254,17 +263,17 @@ class NAVInterface(BTCInterface):
|
|||
return self.fundTx(txn, fee_rate, lock_unspents).hex()
|
||||
|
||||
def isAddressMine(self, address: str, or_watch_only: bool = False) -> bool:
|
||||
addr_info = self.rpc_callback('validateaddress', [address])
|
||||
addr_info = self.rpc('validateaddress', [address])
|
||||
if not or_watch_only:
|
||||
return addr_info['ismine']
|
||||
return addr_info['ismine'] or addr_info['iswatchonly']
|
||||
|
||||
def createRawSignedTransaction(self, addr_to, amount) -> str:
|
||||
txn_funded = self.createRawFundedTransaction(addr_to, amount)
|
||||
return self.rpc_callback('signrawtransaction', [txn_funded])['hex']
|
||||
return self.rpc('signrawtransaction', [txn_funded])['hex']
|
||||
|
||||
def getBlockchainInfo(self):
|
||||
rv = self.rpc_callback('getblockchaininfo')
|
||||
rv = self.rpc('getblockchaininfo')
|
||||
synced = round(rv['verificationprogress'], 3)
|
||||
if synced >= 0.997:
|
||||
rv['verificationprogress'] = 1.0
|
||||
|
@ -278,7 +287,7 @@ class NAVInterface(BTCInterface):
|
|||
return pubkeyToAddress(self.chainparams_network()['script_address'], script)
|
||||
|
||||
def find_prevout_info(self, txn_hex: str, txn_script: bytes):
|
||||
txjs = self.rpc_callback('decoderawtransaction', [txn_hex])
|
||||
txjs = self.rpc('decoderawtransaction', [txn_hex])
|
||||
n = getVoutByScriptPubKey(txjs, self.getScriptDest(txn_script).hex())
|
||||
|
||||
return {
|
||||
|
@ -290,9 +299,9 @@ class NAVInterface(BTCInterface):
|
|||
}
|
||||
|
||||
def getNewAddress(self, use_segwit: bool, label: str = 'swap_receive') -> str:
|
||||
address: str = self.rpc_callback('getnewaddress', [label,])
|
||||
address: str = self.rpc('getnewaddress', [label,])
|
||||
if use_segwit:
|
||||
return self.rpc_callback('addwitnessaddress', [address,])
|
||||
return self.rpc('addwitnessaddress', [address,])
|
||||
return address
|
||||
|
||||
def createRedeemTxn(self, prevout, output_addr: str, output_value: int, txn_script: bytes) -> str:
|
||||
|
@ -385,15 +394,15 @@ class NAVInterface(BTCInterface):
|
|||
chain_blocks: int = self.getChainHeight()
|
||||
|
||||
current_height: int = chain_blocks
|
||||
block_hash = self.rpc_callback('getblockhash', [current_height])
|
||||
block_hash = self.rpc('getblockhash', [current_height])
|
||||
|
||||
script_hash: bytes = self.decodeAddress(addr_find)
|
||||
find_scriptPubKey = self.getDestForScriptHash(script_hash)
|
||||
|
||||
while current_height > height_start:
|
||||
block_hash = self.rpc_callback('getblockhash', [current_height])
|
||||
block_hash = self.rpc('getblockhash', [current_height])
|
||||
|
||||
block = self.rpc_callback('getblock', [block_hash, False])
|
||||
block = self.rpc('getblock', [block_hash, False])
|
||||
decoded_block = CBlock()
|
||||
decoded_block = FromHex(decoded_block, block)
|
||||
for tx in decoded_block.vtx:
|
||||
|
@ -403,8 +412,8 @@ class NAVInterface(BTCInterface):
|
|||
txid = i2b(tx.sha256)
|
||||
self._log.info('Found output to addr: {} in tx {} in block {}'.format(addr_find, txid.hex(), block_hash))
|
||||
self._log.info('rescanblockchain hack invalidateblock {}'.format(block_hash))
|
||||
self.rpc_callback('invalidateblock', [block_hash])
|
||||
self.rpc_callback('reconsiderblock', [block_hash])
|
||||
self.rpc('invalidateblock', [block_hash])
|
||||
self.rpc('reconsiderblock', [block_hash])
|
||||
return
|
||||
current_height -= 1
|
||||
|
||||
|
@ -419,7 +428,7 @@ class NAVInterface(BTCInterface):
|
|||
|
||||
return_txid = True if txid is None else False
|
||||
if txid is None:
|
||||
txns = self.rpc_callback('listunspent', [0, 9999999, [dest_address, ]])
|
||||
txns = self.rpc('listunspent', [0, 9999999, [dest_address, ]])
|
||||
|
||||
for tx in txns:
|
||||
if self.make_int(tx['amount']) == bid_amount:
|
||||
|
@ -430,11 +439,11 @@ class NAVInterface(BTCInterface):
|
|||
return None
|
||||
|
||||
try:
|
||||
tx = self.rpc_callback('gettransaction', [txid.hex()])
|
||||
tx = self.rpc('gettransaction', [txid.hex()])
|
||||
|
||||
block_height = 0
|
||||
if 'blockhash' in tx:
|
||||
block_header = self.rpc_callback('getblockheader', [tx['blockhash']])
|
||||
block_header = self.rpc('getblockheader', [tx['blockhash']])
|
||||
block_height = block_header['height']
|
||||
|
||||
rv = {
|
||||
|
@ -446,7 +455,7 @@ class NAVInterface(BTCInterface):
|
|||
return None
|
||||
|
||||
if find_index:
|
||||
tx_obj = self.rpc_callback('decoderawtransaction', [tx['hex']])
|
||||
tx_obj = self.rpc('decoderawtransaction', [tx['hex']])
|
||||
rv['index'] = find_vout_for_address_from_txobj(tx_obj, dest_address)
|
||||
|
||||
if return_txid:
|
||||
|
@ -456,15 +465,15 @@ class NAVInterface(BTCInterface):
|
|||
|
||||
def getBlockWithTxns(self, block_hash):
|
||||
# TODO: Bypass decoderawtransaction and getblockheader
|
||||
block = self.rpc_callback('getblock', [block_hash, False])
|
||||
block_header = self.rpc_callback('getblockheader', [block_hash])
|
||||
block = self.rpc('getblock', [block_hash, False])
|
||||
block_header = self.rpc('getblockheader', [block_hash])
|
||||
decoded_block = CBlock()
|
||||
decoded_block = FromHex(decoded_block, block)
|
||||
|
||||
tx_rv = []
|
||||
for tx in decoded_block.vtx:
|
||||
tx_hex = tx.serialize_with_witness().hex()
|
||||
tx_dec = self.rpc_callback('decoderawtransaction', [tx_hex])
|
||||
tx_dec = self.rpc('decoderawtransaction', [tx_hex])
|
||||
if 'hex' not in tx_dec:
|
||||
tx_dec['hex'] = tx_hex
|
||||
|
||||
|
@ -505,7 +514,7 @@ class NAVInterface(BTCInterface):
|
|||
|
||||
def spendBLockTx(self, chain_b_lock_txid: bytes, address_to: str, kbv: bytes, kbs: bytes, cb_swap_value: int, b_fee: int, restore_height: int) -> bytes:
|
||||
self._log.info('spendBLockTx %s:\n', chain_b_lock_txid.hex())
|
||||
wtx = self.rpc_callback('gettransaction', [chain_b_lock_txid.hex(), ])
|
||||
wtx = self.rpc('gettransaction', [chain_b_lock_txid.hex(), ])
|
||||
lock_tx = self.loadTx(bytes.fromhex(wtx['hex']))
|
||||
|
||||
Kbs = self.getPubkey(kbs)
|
||||
|
@ -550,7 +559,7 @@ class NAVInterface(BTCInterface):
|
|||
def findTxnByHash(self, txid_hex: str):
|
||||
# Only works for wallet txns
|
||||
try:
|
||||
rv = self.rpc_callback('gettransaction', [txid_hex])
|
||||
rv = self.rpc('gettransaction', [txid_hex])
|
||||
except Exception as ex:
|
||||
self._log.debug('findTxnByHash getrawtransaction failed: {}'.format(txid_hex))
|
||||
return None
|
||||
|
@ -573,10 +582,10 @@ class NAVInterface(BTCInterface):
|
|||
'lockUnspents': lock_unspents,
|
||||
'feeRate': feerate_str,
|
||||
}
|
||||
rv = self.rpc_callback('fundrawtransaction', [tx_hex, options])
|
||||
rv = self.rpc('fundrawtransaction', [tx_hex, options])
|
||||
|
||||
# Sign transaction then strip witness data to fill scriptsig
|
||||
rv = self.rpc_callback('signrawtransaction', [rv['hex']])
|
||||
rv = self.rpc('signrawtransaction', [rv['hex']])
|
||||
|
||||
tx_signed = self.loadTx(bytes.fromhex(rv['hex']))
|
||||
if len(tx_signed.vin) != len(tx_signed.wit.vtxinwit):
|
||||
|
|
|
@ -19,7 +19,7 @@ class NMCInterface(BTCInterface):
|
|||
|
||||
def getLockTxHeight(self, txid, dest_address, bid_amount, rescan_from, find_index=False):
|
||||
self._log.debug('[rm] scantxoutset start') # scantxoutset is slow
|
||||
ro = self.rpc_callback('scantxoutset', ['start', ['addr({})'.format(dest_address)]]) # TODO: Use combo(address) where possible
|
||||
ro = self.rpc('scantxoutset', ['start', ['addr({})'.format(dest_address)]]) # TODO: Use combo(address) where possible
|
||||
self._log.debug('[rm] scantxoutset end')
|
||||
return_txid = True if txid is None else False
|
||||
for o in ro['unspents']:
|
||||
|
|
|
@ -83,14 +83,14 @@ class PARTInterface(BTCInterface):
|
|||
return True
|
||||
|
||||
def getNewAddress(self, use_segwit, label='swap_receive') -> str:
|
||||
return self.rpc_callback('getnewaddress', [label])
|
||||
return self.rpc_wallet('getnewaddress', [label])
|
||||
|
||||
def getNewStealthAddress(self, label='swap_stealth') -> str:
|
||||
return self.rpc_callback('getnewstealthaddress', [label])
|
||||
return self.rpc_wallet('getnewstealthaddress', [label])
|
||||
|
||||
def haveSpentIndex(self):
|
||||
version = self.getDaemonVersion()
|
||||
index_info = self.rpc_callback('getinsightinfo' if int(str(version)[:2]) > 19 else 'getindexinfo')
|
||||
index_info = self.rpc('getinsightinfo' if int(str(version)[:2]) > 19 else 'getindexinfo')
|
||||
return index_info['spentindex']
|
||||
|
||||
def initialiseWallet(self, key):
|
||||
|
@ -98,14 +98,14 @@ class PARTInterface(BTCInterface):
|
|||
|
||||
def withdrawCoin(self, value, addr_to, subfee):
|
||||
params = [addr_to, value, '', '', subfee, '', True, self._conf_target]
|
||||
return self.rpc_callback('sendtoaddress', params)
|
||||
return self.rpc_wallet('sendtoaddress', params)
|
||||
|
||||
def sendTypeTo(self, type_from, type_to, value, addr_to, subfee):
|
||||
params = [type_from, type_to,
|
||||
[{'address': addr_to, 'amount': value, 'subfee': subfee}, ],
|
||||
'', '', self._anon_tx_ring_size, 1, False,
|
||||
{'conf_target': self._conf_target}]
|
||||
return self.rpc_callback('sendtypeto', params)
|
||||
return self.rpc_wallet('sendtypeto', params)
|
||||
|
||||
def getScriptForPubkeyHash(self, pkh: bytes) -> CScript:
|
||||
return CScript([OP_DUP, OP_HASH160, pkh, OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
|
@ -122,7 +122,7 @@ class PARTInterface(BTCInterface):
|
|||
return length
|
||||
|
||||
def getWalletRestoreHeight(self) -> int:
|
||||
start_time = self.rpc_callback('getwalletinfo')['keypoololdest']
|
||||
start_time = self.rpc_wallet('getwalletinfo')['keypoololdest']
|
||||
|
||||
blockchaininfo = self.getBlockchainInfo()
|
||||
best_block = blockchaininfo['bestblockhash']
|
||||
|
@ -132,8 +132,8 @@ class PARTInterface(BTCInterface):
|
|||
raise ValueError('{} chain isn\'t synced.'.format(self.coin_name()))
|
||||
|
||||
self._log.debug('Finding block at time: {}'.format(start_time))
|
||||
block_hash = self.rpc_callback('getblockhashafter', [start_time])
|
||||
block_header = self.rpc_callback('getblockheader', [block_hash])
|
||||
block_hash = self.rpc('getblockhashafter', [start_time])
|
||||
block_header = self.rpc('getblockheader', [block_hash])
|
||||
return block_header['height']
|
||||
|
||||
def getHTLCSpendTxVSize(self, redeem: bool = True) -> int:
|
||||
|
@ -171,16 +171,16 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
if txo['type'] != 'blind':
|
||||
continue
|
||||
try:
|
||||
blinded_info = self.rpc_callback('rewindrangeproof', [txo['rangeproof'], txo['valueCommitment'], nonce.hex()])
|
||||
blinded_info = self.rpc('rewindrangeproof', [txo['rangeproof'], txo['valueCommitment'], nonce.hex()])
|
||||
output_n = txo['n']
|
||||
|
||||
self.rpc_callback('rewindrangeproof', [txo['rangeproof'], txo['valueCommitment'], nonce.hex()])
|
||||
self.rpc('rewindrangeproof', [txo['rangeproof'], txo['valueCommitment'], nonce.hex()])
|
||||
break
|
||||
except Exception as e:
|
||||
self._log.debug('Searching for locked output: {}'.format(str(e)))
|
||||
continue
|
||||
# Should not be possible for commitment not to match
|
||||
v = self.rpc_callback('verifycommitment', [txo['valueCommitment'], blinded_info['blind'], blinded_info['amount']])
|
||||
v = self.rpc('verifycommitment', [txo['valueCommitment'], blinded_info['blind'], blinded_info['amount']])
|
||||
ensure(v['result'] is True, 'verifycommitment failed')
|
||||
return output_n, blinded_info
|
||||
|
||||
|
@ -195,7 +195,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
inputs = []
|
||||
outputs = [{'type': 'blind', 'amount': self.format_amount(value), 'address': p2wsh_addr, 'nonce': nonce.hex(), 'data': ephemeral_pubkey.hex()}]
|
||||
params = [inputs, outputs]
|
||||
rv = self.rpc_callback('createrawparttransaction', params)
|
||||
rv = self.rpc_wallet('createrawparttransaction', params)
|
||||
|
||||
tx_bytes = bytes.fromhex(rv['hex'])
|
||||
return tx_bytes
|
||||
|
@ -207,11 +207,11 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
tx_hex = tx_bytes.hex()
|
||||
nonce = self.getScriptLockTxNonce(vkbv)
|
||||
|
||||
tx_obj = self.rpc_callback('decoderawtransaction', [tx_hex])
|
||||
tx_obj = self.rpc('decoderawtransaction', [tx_hex])
|
||||
|
||||
assert (len(tx_obj['vout']) == 1)
|
||||
txo = tx_obj['vout'][0]
|
||||
blinded_info = self.rpc_callback('rewindrangeproof', [txo['rangeproof'], txo['valueCommitment'], nonce.hex()])
|
||||
blinded_info = self.rpc('rewindrangeproof', [txo['rangeproof'], txo['valueCommitment'], nonce.hex()])
|
||||
|
||||
outputs_info = {0: {'value': blinded_info['amount'], 'blind': blinded_info['blind'], 'nonce': nonce.hex()}}
|
||||
|
||||
|
@ -219,11 +219,11 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
'lockUnspents': True,
|
||||
'feeRate': feerate_str,
|
||||
}
|
||||
rv = self.rpc_callback('fundrawtransactionfrom', ['blind', tx_hex, {}, outputs_info, options])
|
||||
rv = self.rpc('fundrawtransactionfrom', ['blind', tx_hex, {}, outputs_info, options])
|
||||
return bytes.fromhex(rv['hex'])
|
||||
|
||||
def createSCLockRefundTx(self, tx_lock_bytes, script_lock, Kal, Kaf, lock1_value, csv_val, tx_fee_rate, vkbv):
|
||||
lock_tx_obj = self.rpc_callback('decoderawtransaction', [tx_lock_bytes.hex()])
|
||||
lock_tx_obj = self.rpc('decoderawtransaction', [tx_lock_bytes.hex()])
|
||||
assert (self.getTxid(tx_lock_bytes).hex() == lock_tx_obj['txid'])
|
||||
# Nonce is derived from vkbv, ephemeral_key isn't used
|
||||
ephemeral_key = self.getNewSecretKey()
|
||||
|
@ -244,7 +244,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
inputs = [{'txid': tx_lock_id, 'vout': spend_n, 'sequence': lock1_value, 'blindingfactor': input_blinded_info['blind']}]
|
||||
outputs = [{'type': 'blind', 'amount': locked_coin, 'address': p2wsh_addr, 'nonce': output_nonce.hex(), 'data': ephemeral_pubkey.hex()}]
|
||||
params = [inputs, outputs]
|
||||
rv = self.rpc_callback('createrawparttransaction', params)
|
||||
rv = self.rpc_wallet('createrawparttransaction', params)
|
||||
lock_refund_tx_hex = rv['hex']
|
||||
|
||||
# Set dummy witness data for fee estimation
|
||||
|
@ -261,7 +261,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
'feeRate': self.format_amount(tx_fee_rate),
|
||||
'subtractFeeFromOutputs': [0, ]
|
||||
}
|
||||
rv = self.rpc_callback('fundrawtransactionfrom', ['blind', lock_refund_tx_hex, inputs_info, outputs_info, options])
|
||||
rv = self.rpc_wallet('fundrawtransactionfrom', ['blind', lock_refund_tx_hex, inputs_info, outputs_info, options])
|
||||
lock_refund_tx_hex = rv['hex']
|
||||
|
||||
for vout, txo in rv['output_amounts'].items():
|
||||
|
@ -275,7 +275,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
# The follower will sign the multisig path with a signature encumbered by the leader's coinB spend pubkey
|
||||
# If the leader publishes the decrypted signature the leader's coinB spend privatekey will be revealed to the follower
|
||||
|
||||
lock_refund_tx_obj = self.rpc_callback('decoderawtransaction', [tx_lock_refund_bytes.hex()])
|
||||
lock_refund_tx_obj = self.rpc('decoderawtransaction', [tx_lock_refund_bytes.hex()])
|
||||
# Nonce is derived from vkbv
|
||||
nonce = self.getScriptLockRefundTxNonce(vkbv)
|
||||
|
||||
|
@ -285,7 +285,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
|
||||
tx_lock_refund_id = lock_refund_tx_obj['txid']
|
||||
addr_out = self.pkh_to_address(pkh_refund_to)
|
||||
addr_info = self.rpc_callback('getaddressinfo', [addr_out])
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [addr_out])
|
||||
output_pubkey_hex = addr_info['pubkey']
|
||||
|
||||
# Follower won't be able to decode output to check amount, shouldn't matter as fee is public and output is to leader, sum has to balance
|
||||
|
@ -293,7 +293,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
inputs = [{'txid': tx_lock_refund_id, 'vout': spend_n, 'sequence': 0, 'blindingfactor': input_blinded_info['blind']}]
|
||||
outputs = [{'type': 'blind', 'amount': input_blinded_info['amount'], 'address': addr_out, 'pubkey': output_pubkey_hex}]
|
||||
params = [inputs, outputs]
|
||||
rv = self.rpc_callback('createrawparttransaction', params)
|
||||
rv = self.rpc_wallet('createrawparttransaction', params)
|
||||
lock_refund_spend_tx_hex = rv['hex']
|
||||
|
||||
# Set dummy witness data for fee estimation
|
||||
|
@ -311,7 +311,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
'subtractFeeFromOutputs': [0, ]
|
||||
}
|
||||
|
||||
rv = self.rpc_callback('fundrawtransactionfrom', ['blind', lock_refund_spend_tx_hex, inputs_info, outputs_info, options])
|
||||
rv = self.rpc_wallet('fundrawtransactionfrom', ['blind', lock_refund_spend_tx_hex, inputs_info, outputs_info, options])
|
||||
lock_refund_spend_tx_hex = rv['hex']
|
||||
|
||||
return bytes.fromhex(lock_refund_spend_tx_hex)
|
||||
|
@ -321,7 +321,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
Kal, Kaf,
|
||||
feerate,
|
||||
check_lock_tx_inputs, vkbv):
|
||||
lock_tx_obj = self.rpc_callback('decoderawtransaction', [tx_bytes.hex()])
|
||||
lock_tx_obj = self.rpc('decoderawtransaction', [tx_bytes.hex()])
|
||||
lock_txid_hex = lock_tx_obj['txid']
|
||||
self._log.info('Verifying lock tx: {}.'.format(lock_txid_hex))
|
||||
|
||||
|
@ -363,7 +363,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
def verifySCLockRefundTx(self, tx_bytes, lock_tx_bytes, script_out,
|
||||
prevout_id, prevout_n, prevout_seq, prevout_script,
|
||||
Kal, Kaf, csv_val_expect, swap_value, feerate, vkbv):
|
||||
lock_refund_tx_obj = self.rpc_callback('decoderawtransaction', [tx_bytes.hex()])
|
||||
lock_refund_tx_obj = self.rpc('decoderawtransaction', [tx_bytes.hex()])
|
||||
lock_refund_txid_hex = lock_refund_tx_obj['txid']
|
||||
self._log.info('Verifying lock refund tx: {}.'.format(lock_refund_txid_hex))
|
||||
|
||||
|
@ -396,10 +396,10 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
ensure(C == Kaf, 'Bad script pubkey')
|
||||
|
||||
# Check rangeproofs and commitments sum
|
||||
lock_tx_obj = self.rpc_callback('decoderawtransaction', [lock_tx_bytes.hex()])
|
||||
lock_tx_obj = self.rpc('decoderawtransaction', [lock_tx_bytes.hex()])
|
||||
prevout = lock_tx_obj['vout'][prevout_n]
|
||||
prevtxns = [{'txid': prevout_id.hex(), 'vout': prevout_n, 'scriptPubKey': prevout['scriptPubKey']['hex'], 'amount_commitment': prevout['valueCommitment']}]
|
||||
rv = self.rpc_callback('verifyrawtransaction', [tx_bytes.hex(), prevtxns])
|
||||
rv = self.rpc('verifyrawtransaction', [tx_bytes.hex(), prevtxns])
|
||||
ensure(rv['outputs_valid'] is True, 'Invalid outputs')
|
||||
ensure(rv['inputs_valid'] is True, 'Invalid inputs')
|
||||
|
||||
|
@ -422,7 +422,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
lock_refund_tx_id, prevout_script,
|
||||
Kal,
|
||||
prevout_n, prevout_value, feerate, vkbv):
|
||||
lock_refund_spend_tx_obj = self.rpc_callback('decoderawtransaction', [tx_bytes.hex()])
|
||||
lock_refund_spend_tx_obj = self.rpc('decoderawtransaction', [tx_bytes.hex()])
|
||||
lock_refund_spend_txid_hex = lock_refund_spend_tx_obj['txid']
|
||||
self._log.info('Verifying lock refund spend tx: {}.'.format(lock_refund_spend_txid_hex))
|
||||
|
||||
|
@ -441,10 +441,10 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
# Follower is not concerned with them as they pay to leader
|
||||
|
||||
# Check rangeproofs and commitments sum
|
||||
lock_refund_tx_obj = self.rpc_callback('decoderawtransaction', [lock_refund_tx_bytes.hex()])
|
||||
lock_refund_tx_obj = self.rpc('decoderawtransaction', [lock_refund_tx_bytes.hex()])
|
||||
prevout = lock_refund_tx_obj['vout'][prevout_n]
|
||||
prevtxns = [{'txid': lock_refund_tx_id.hex(), 'vout': prevout_n, 'scriptPubKey': prevout['scriptPubKey']['hex'], 'amount_commitment': prevout['valueCommitment']}]
|
||||
rv = self.rpc_callback('verifyrawtransaction', [tx_bytes.hex(), prevtxns])
|
||||
rv = self.rpc('verifyrawtransaction', [tx_bytes.hex(), prevtxns])
|
||||
ensure(rv['outputs_valid'] is True, 'Invalid outputs')
|
||||
ensure(rv['inputs_valid'] is True, 'Invalid inputs')
|
||||
|
||||
|
@ -459,28 +459,28 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
return True
|
||||
|
||||
def getLockTxSwapOutputValue(self, bid, xmr_swap):
|
||||
lock_tx_obj = self.rpc_callback('decoderawtransaction', [xmr_swap.a_lock_tx.hex()])
|
||||
lock_tx_obj = self.rpc('decoderawtransaction', [xmr_swap.a_lock_tx.hex()])
|
||||
nonce = self.getScriptLockTxNonce(xmr_swap.vkbv)
|
||||
output_n, _ = self.findOutputByNonce(lock_tx_obj, nonce)
|
||||
ensure(output_n is not None, 'Output not found in tx')
|
||||
return bytes.fromhex(lock_tx_obj['vout'][output_n]['valueCommitment'])
|
||||
|
||||
def getLockRefundTxSwapOutputValue(self, bid, xmr_swap):
|
||||
lock_refund_tx_obj = self.rpc_callback('decoderawtransaction', [xmr_swap.a_lock_refund_tx.hex()])
|
||||
lock_refund_tx_obj = self.rpc('decoderawtransaction', [xmr_swap.a_lock_refund_tx.hex()])
|
||||
nonce = self.getScriptLockRefundTxNonce(xmr_swap.vkbv)
|
||||
output_n, _ = self.findOutputByNonce(lock_refund_tx_obj, nonce)
|
||||
ensure(output_n is not None, 'Output not found in tx')
|
||||
return bytes.fromhex(lock_refund_tx_obj['vout'][output_n]['valueCommitment'])
|
||||
|
||||
def getLockRefundTxSwapOutput(self, xmr_swap):
|
||||
lock_refund_tx_obj = self.rpc_callback('decoderawtransaction', [xmr_swap.a_lock_refund_tx.hex()])
|
||||
lock_refund_tx_obj = self.rpc('decoderawtransaction', [xmr_swap.a_lock_refund_tx.hex()])
|
||||
nonce = self.getScriptLockRefundTxNonce(xmr_swap.vkbv)
|
||||
output_n, _ = self.findOutputByNonce(lock_refund_tx_obj, nonce)
|
||||
ensure(output_n is not None, 'Output not found in tx')
|
||||
return output_n
|
||||
|
||||
def createSCLockSpendTx(self, tx_lock_bytes: bytes, script_lock: bytes, pk_dest: bytes, tx_fee_rate: int, vkbv: bytes, fee_info={}) -> bytes:
|
||||
lock_tx_obj = self.rpc_callback('decoderawtransaction', [tx_lock_bytes.hex()])
|
||||
lock_tx_obj = self.rpc('decoderawtransaction', [tx_lock_bytes.hex()])
|
||||
lock_txid_hex = lock_tx_obj['txid']
|
||||
|
||||
ensure(lock_tx_obj['version'] == self.txVersion(), 'Bad version')
|
||||
|
@ -496,7 +496,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
inputs = [{'txid': lock_txid_hex, 'vout': spend_n, 'sequence': 0, 'blindingfactor': blinded_info['blind']}]
|
||||
outputs = [{'type': 'blind', 'amount': blinded_info['amount'], 'address': addr_out, 'pubkey': pk_dest.hex()}]
|
||||
params = [inputs, outputs]
|
||||
rv = self.rpc_callback('createrawparttransaction', params)
|
||||
rv = self.rpc_wallet('createrawparttransaction', params)
|
||||
lock_spend_tx_hex = rv['hex']
|
||||
|
||||
# Set dummy witness data for fee estimation
|
||||
|
@ -513,9 +513,9 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
'subtractFeeFromOutputs': [0, ]
|
||||
}
|
||||
|
||||
rv = self.rpc_callback('fundrawtransactionfrom', ['blind', lock_spend_tx_hex, inputs_info, outputs_info, options])
|
||||
rv = self.rpc_wallet('fundrawtransactionfrom', ['blind', lock_spend_tx_hex, inputs_info, outputs_info, options])
|
||||
lock_spend_tx_hex = rv['hex']
|
||||
lock_spend_tx_obj = self.rpc_callback('decoderawtransaction', [lock_spend_tx_hex])
|
||||
lock_spend_tx_obj = self.rpc('decoderawtransaction', [lock_spend_tx_hex])
|
||||
pay_fee = make_int(lock_spend_tx_obj['vout'][0]['ct_fee'])
|
||||
|
||||
# lock_spend_tx_hex does not include the dummy witness stack
|
||||
|
@ -535,7 +535,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
def verifySCLockSpendTx(self, tx_bytes,
|
||||
lock_tx_bytes, lock_tx_script,
|
||||
a_pk_f, feerate, vkbv):
|
||||
lock_spend_tx_obj = self.rpc_callback('decoderawtransaction', [tx_bytes.hex()])
|
||||
lock_spend_tx_obj = self.rpc('decoderawtransaction', [tx_bytes.hex()])
|
||||
lock_spend_txid_hex = lock_spend_tx_obj['txid']
|
||||
self._log.info('Verifying lock spend tx: {}.'.format(lock_spend_txid_hex))
|
||||
|
||||
|
@ -543,7 +543,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
ensure(lock_spend_tx_obj['locktime'] == 0, 'Bad nLockTime')
|
||||
ensure(len(lock_spend_tx_obj['vin']) == 1, 'tx doesn\'t have one input')
|
||||
|
||||
lock_tx_obj = self.rpc_callback('decoderawtransaction', [lock_tx_bytes.hex()])
|
||||
lock_tx_obj = self.rpc('decoderawtransaction', [lock_tx_bytes.hex()])
|
||||
lock_txid_hex = lock_tx_obj['txid']
|
||||
|
||||
# Find the output of the lock tx to verify
|
||||
|
@ -559,7 +559,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
ensure(len(lock_spend_tx_obj['vout']) == 3, 'tx doesn\'t have three outputs')
|
||||
|
||||
addr_out = self.pubkey_to_address(a_pk_f)
|
||||
privkey = self.rpc_callback('dumpprivkey', [addr_out])
|
||||
privkey = self.rpc_wallet('dumpprivkey', [addr_out])
|
||||
|
||||
# Find output:
|
||||
output_blinded_info = None
|
||||
|
@ -568,7 +568,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
if txo['type'] != 'blind':
|
||||
continue
|
||||
try:
|
||||
output_blinded_info = self.rpc_callback('rewindrangeproof', [txo['rangeproof'], txo['valueCommitment'], privkey, txo['data_hex']])
|
||||
output_blinded_info = self.rpc('rewindrangeproof', [txo['rangeproof'], txo['valueCommitment'], privkey, txo['data_hex']])
|
||||
output_n = txo['n']
|
||||
break
|
||||
except Exception as e:
|
||||
|
@ -577,13 +577,13 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
ensure(output_n is not None, 'Output not found in tx')
|
||||
|
||||
# Commitment
|
||||
v = self.rpc_callback('verifycommitment', [lock_spend_tx_obj['vout'][output_n]['valueCommitment'], output_blinded_info['blind'], output_blinded_info['amount']])
|
||||
v = self.rpc('verifycommitment', [lock_spend_tx_obj['vout'][output_n]['valueCommitment'], output_blinded_info['blind'], output_blinded_info['amount']])
|
||||
ensure(v['result'] is True, 'verifycommitment failed')
|
||||
|
||||
# Check rangeproofs and commitments sum
|
||||
prevout = lock_tx_obj['vout'][spend_n]
|
||||
prevtxns = [{'txid': lock_txid_hex, 'vout': spend_n, 'scriptPubKey': prevout['scriptPubKey']['hex'], 'amount_commitment': prevout['valueCommitment']}]
|
||||
rv = self.rpc_callback('verifyrawtransaction', [tx_bytes.hex(), prevtxns])
|
||||
rv = self.rpc('verifyrawtransaction', [tx_bytes.hex(), prevtxns])
|
||||
ensure(rv['outputs_valid'] is True, 'Invalid outputs')
|
||||
ensure(rv['inputs_valid'] is True, 'Invalid inputs')
|
||||
|
||||
|
@ -607,7 +607,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
def createSCLockRefundSpendToFTx(self, tx_lock_refund_bytes, script_lock_refund, pkh_dest, tx_fee_rate, vkbv):
|
||||
# lock refund swipe tx
|
||||
# Sends the coinA locked coin to the follower
|
||||
lock_refund_tx_obj = self.rpc_callback('decoderawtransaction', [tx_lock_refund_bytes.hex()])
|
||||
lock_refund_tx_obj = self.rpc('decoderawtransaction', [tx_lock_refund_bytes.hex()])
|
||||
nonce = self.getScriptLockRefundTxNonce(vkbv)
|
||||
|
||||
# Find the output of the lock refund tx to spend
|
||||
|
@ -616,7 +616,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
|
||||
tx_lock_refund_id = lock_refund_tx_obj['txid']
|
||||
addr_out = self.pkh_to_address(pkh_dest)
|
||||
addr_info = self.rpc_callback('getaddressinfo', [addr_out])
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [addr_out])
|
||||
output_pubkey_hex = addr_info['pubkey']
|
||||
|
||||
A, B, lock2_value, C = self.extractScriptLockRefundScriptValues(script_lock_refund)
|
||||
|
@ -626,7 +626,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
inputs = [{'txid': tx_lock_refund_id, 'vout': spend_n, 'sequence': lock2_value, 'blindingfactor': input_blinded_info['blind']}]
|
||||
outputs = [{'type': 'blind', 'amount': input_blinded_info['amount'], 'address': addr_out, 'pubkey': output_pubkey_hex}]
|
||||
params = [inputs, outputs]
|
||||
rv = self.rpc_callback('createrawparttransaction', params)
|
||||
rv = self.rpc_wallet('createrawparttransaction', params)
|
||||
|
||||
lock_refund_swipe_tx_hex = rv['hex']
|
||||
|
||||
|
@ -645,13 +645,13 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
'subtractFeeFromOutputs': [0, ]
|
||||
}
|
||||
|
||||
rv = self.rpc_callback('fundrawtransactionfrom', ['blind', lock_refund_swipe_tx_hex, inputs_info, outputs_info, options])
|
||||
rv = self.rpc_wallet('fundrawtransactionfrom', ['blind', lock_refund_swipe_tx_hex, inputs_info, outputs_info, options])
|
||||
lock_refund_swipe_tx_hex = rv['hex']
|
||||
|
||||
return bytes.fromhex(lock_refund_swipe_tx_hex)
|
||||
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getbalances')['mine']['blind_trusted'])
|
||||
return self.make_int(self.rpc_wallet('getbalances')['mine']['blind_trusted'])
|
||||
|
||||
def publishBLockTx(self, vkbv: bytes, Kbs: bytes, output_amount: int, feerate: int, delay_for: int = 10, unlock_time: int = 0) -> bytes:
|
||||
Kbv = self.getPubkey(vkbv)
|
||||
|
@ -664,7 +664,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
'', '', self._anon_tx_ring_size, 1, False,
|
||||
{'conf_target': self._conf_target, 'blind_watchonly_visible': True}]
|
||||
|
||||
txid = self.rpc_callback('sendtypeto', params)
|
||||
txid = self.rpc_wallet('sendtypeto', params)
|
||||
return bytes.fromhex(txid)
|
||||
|
||||
def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height: int, bid_sender: bool):
|
||||
|
@ -675,17 +675,17 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
if bid_sender:
|
||||
cb_swap_value *= -1
|
||||
else:
|
||||
addr_info = self.rpc_callback('getaddressinfo', [sx_addr])
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
|
||||
if not addr_info['iswatchonly']:
|
||||
wif_prefix = self.chainparams_network()['key_prefix']
|
||||
wif_scan_key = toWIF(wif_prefix, kbv)
|
||||
self.rpc_callback('importstealthaddress', [wif_scan_key, Kbs.hex()])
|
||||
self.rpc_wallet('importstealthaddress', [wif_scan_key, Kbs.hex()])
|
||||
self._log.info('Imported watch-only sx_addr: {}'.format(sx_addr))
|
||||
self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height))
|
||||
self.rpc_callback('rescanblockchain', [restore_height])
|
||||
self.rpc_wallet('rescanblockchain', [restore_height])
|
||||
|
||||
params = [{'include_watchonly': True, 'search': sx_addr}]
|
||||
txns = self.rpc_callback('filtertransactions', params)
|
||||
txns = self.rpc_wallet('filtertransactions', params)
|
||||
|
||||
if len(txns) == 1:
|
||||
tx = txns[0]
|
||||
|
@ -695,7 +695,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
if make_int(tx['outputs'][0]['amount']) == cb_swap_value:
|
||||
height = 0
|
||||
if tx['confirmations'] > 0:
|
||||
chain_height = self.rpc_callback('getblockcount')
|
||||
chain_height = self.rpc('getblockcount')
|
||||
height = chain_height - (tx['confirmations'] - 1)
|
||||
return {'txid': tx['txid'], 'amount': cb_swap_value, 'height': height}
|
||||
else:
|
||||
|
@ -707,20 +707,20 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
Kbv = self.getPubkey(kbv)
|
||||
Kbs = self.getPubkey(kbs)
|
||||
sx_addr = self.formatStealthAddress(Kbv, Kbs)
|
||||
addr_info = self.rpc_callback('getaddressinfo', [sx_addr])
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
|
||||
if not addr_info['ismine']:
|
||||
wif_prefix = self.chainparams_network()['key_prefix']
|
||||
wif_scan_key = toWIF(wif_prefix, kbv)
|
||||
wif_spend_key = toWIF(wif_prefix, kbs)
|
||||
self.rpc_callback('importstealthaddress', [wif_scan_key, wif_spend_key])
|
||||
self.rpc_wallet('importstealthaddress', [wif_scan_key, wif_spend_key])
|
||||
self._log.info('Imported spend key for sx_addr: {}'.format(sx_addr))
|
||||
self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height))
|
||||
self.rpc_callback('rescanblockchain', [restore_height])
|
||||
self.rpc_wallet('rescanblockchain', [restore_height])
|
||||
|
||||
# TODO: Remove workaround
|
||||
# utxos = self.rpc_callback('listunspentblind', [1, 9999999, [sx_addr]])
|
||||
# utxos = self.rpc_wallet('listunspentblind', [1, 9999999, [sx_addr]])
|
||||
utxos = []
|
||||
all_utxos = self.rpc_callback('listunspentblind', [1, 9999999])
|
||||
all_utxos = self.rpc_wallet('listunspentblind', [1, 9999999])
|
||||
for utxo in all_utxos:
|
||||
if utxo.get('stealth_address', '_') == sx_addr:
|
||||
utxos.append(utxo)
|
||||
|
@ -741,14 +741,14 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
[{'address': address_to, 'amount': self.format_amount(cb_swap_value), 'subfee': True}, ],
|
||||
'', '', self._anon_tx_ring_size, 1, False,
|
||||
{'conf_target': self._conf_target, 'inputs': inputs, 'show_fee': True}]
|
||||
rv = self.rpc_callback('sendtypeto', params)
|
||||
rv = self.rpc_wallet('sendtypeto', params)
|
||||
return bytes.fromhex(rv['txid'])
|
||||
|
||||
def findTxnByHash(self, txid_hex):
|
||||
# txindex is enabled for Particl
|
||||
|
||||
try:
|
||||
rv = self.rpc_callback('getrawtransaction', [txid_hex, True])
|
||||
rv = self.rpc('getrawtransaction', [txid_hex, True])
|
||||
except Exception as ex:
|
||||
self._log.debug('findTxnByHash getrawtransaction failed: {}'.format(txid_hex))
|
||||
return None
|
||||
|
@ -759,7 +759,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
return None
|
||||
|
||||
def createRawFundedTransaction(self, addr_to: str, amount: int, sub_fee: bool = False, lock_unspents: bool = True) -> str:
|
||||
txn = self.rpc_callback('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
|
||||
txn = self.rpc_wallet('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
|
||||
|
||||
options = {
|
||||
'lockUnspents': lock_unspents,
|
||||
|
@ -767,7 +767,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
}
|
||||
if sub_fee:
|
||||
options['subtractFeeFromOutputs'] = [0,]
|
||||
return self.rpc_callback('fundrawtransactionfrom', ['blind', txn, options])['hex']
|
||||
return self.rpc_wallet('fundrawtransactionfrom', ['blind', txn, options])['hex']
|
||||
|
||||
|
||||
class PARTInterfaceAnon(PARTInterface):
|
||||
|
@ -801,7 +801,7 @@ class PARTInterfaceAnon(PARTInterface):
|
|||
'', '', self._anon_tx_ring_size, 1, False,
|
||||
{'conf_target': self._conf_target, 'blind_watchonly_visible': True}]
|
||||
|
||||
txid = self.rpc_callback('sendtypeto', params)
|
||||
txid = self.rpc_wallet('sendtypeto', params)
|
||||
return bytes.fromhex(txid)
|
||||
|
||||
def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height, bid_sender):
|
||||
|
@ -813,17 +813,17 @@ class PARTInterfaceAnon(PARTInterface):
|
|||
if bid_sender:
|
||||
cb_swap_value *= -1
|
||||
else:
|
||||
addr_info = self.rpc_callback('getaddressinfo', [sx_addr])
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
|
||||
if not addr_info['iswatchonly']:
|
||||
wif_prefix = self.chainparams_network()['key_prefix']
|
||||
wif_scan_key = toWIF(wif_prefix, kbv)
|
||||
self.rpc_callback('importstealthaddress', [wif_scan_key, Kbs.hex()])
|
||||
self.rpc_wallet('importstealthaddress', [wif_scan_key, Kbs.hex()])
|
||||
self._log.info('Imported watch-only sx_addr: {}'.format(sx_addr))
|
||||
self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height))
|
||||
self.rpc_callback('rescanblockchain', [restore_height])
|
||||
self.rpc_wallet('rescanblockchain', [restore_height])
|
||||
|
||||
params = [{'include_watchonly': True, 'search': sx_addr}]
|
||||
txns = self.rpc_callback('filtertransactions', params)
|
||||
txns = self.rpc_wallet('filtertransactions', params)
|
||||
|
||||
if len(txns) == 1:
|
||||
tx = txns[0]
|
||||
|
@ -833,7 +833,7 @@ class PARTInterfaceAnon(PARTInterface):
|
|||
if make_int(tx['outputs'][0]['amount']) == cb_swap_value:
|
||||
height = 0
|
||||
if tx['confirmations'] > 0:
|
||||
chain_height = self.rpc_callback('getblockcount')
|
||||
chain_height = self.rpc('getblockcount')
|
||||
height = chain_height - (tx['confirmations'] - 1)
|
||||
return {'txid': tx['txid'], 'amount': cb_swap_value, 'height': height}
|
||||
else:
|
||||
|
@ -845,17 +845,17 @@ class PARTInterfaceAnon(PARTInterface):
|
|||
Kbv = self.getPubkey(kbv)
|
||||
Kbs = self.getPubkey(kbs)
|
||||
sx_addr = self.formatStealthAddress(Kbv, Kbs)
|
||||
addr_info = self.rpc_callback('getaddressinfo', [sx_addr])
|
||||
addr_info = self.rpc_wallet('getaddressinfo', [sx_addr])
|
||||
if not addr_info['ismine']:
|
||||
wif_prefix = self.chainparams_network()['key_prefix']
|
||||
wif_scan_key = toWIF(wif_prefix, kbv)
|
||||
wif_spend_key = toWIF(wif_prefix, kbs)
|
||||
self.rpc_callback('importstealthaddress', [wif_scan_key, wif_spend_key])
|
||||
self.rpc_wallet('importstealthaddress', [wif_scan_key, wif_spend_key])
|
||||
self._log.info('Imported spend key for sx_addr: {}'.format(sx_addr))
|
||||
self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height))
|
||||
self.rpc_callback('rescanblockchain', [restore_height])
|
||||
self.rpc_wallet('rescanblockchain', [restore_height])
|
||||
|
||||
autxos = self.rpc_callback('listunspentanon', [1, 9999999, [sx_addr]])
|
||||
autxos = self.rpc_wallet('listunspentanon', [1, 9999999, [sx_addr]])
|
||||
|
||||
if len(autxos) < 1:
|
||||
raise TemporaryError('No spendable outputs')
|
||||
|
@ -874,14 +874,14 @@ class PARTInterfaceAnon(PARTInterface):
|
|||
[{'address': address_to, 'amount': self.format_amount(cb_swap_value), 'subfee': True}, ],
|
||||
'', '', self._anon_tx_ring_size, 1, False,
|
||||
{'conf_target': self._conf_target, 'inputs': inputs, 'show_fee': True}]
|
||||
rv = self.rpc_callback('sendtypeto', params)
|
||||
rv = self.rpc_wallet('sendtypeto', params)
|
||||
return bytes.fromhex(rv['txid'])
|
||||
|
||||
def findTxnByHash(self, txid_hex: str):
|
||||
# txindex is enabled for Particl
|
||||
|
||||
try:
|
||||
rv = self.rpc_callback('getrawtransaction', [txid_hex, True])
|
||||
rv = self.rpc('getrawtransaction', [txid_hex, True])
|
||||
except Exception as ex:
|
||||
self._log.debug('findTxnByHash getrawtransaction failed: {}'.format(txid_hex))
|
||||
return None
|
||||
|
@ -892,4 +892,4 @@ class PARTInterfaceAnon(PARTInterface):
|
|||
return None
|
||||
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getbalances')['mine']['anon_trusted'])
|
||||
return self.make_int(self.rpc_wallet('getbalances')['mine']['anon_trusted'])
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
from io import BytesIO
|
||||
|
||||
from .btc import BTCInterface
|
||||
from basicswap.rpc import make_rpc_func
|
||||
from basicswap.chainparams import Coins
|
||||
from basicswap.util.address import decodeAddress
|
||||
from .contrib.pivx_test_framework.messages import (
|
||||
|
@ -29,12 +30,20 @@ class PIVXInterface(BTCInterface):
|
|||
def coin_type():
|
||||
return Coins.PIVX
|
||||
|
||||
def __init__(self, coin_settings, network, swap_client=None):
|
||||
super(PIVXInterface, self).__init__(coin_settings, network, swap_client)
|
||||
# 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_callback('signrawtransaction', [tx.hex()])
|
||||
rv = self.rpc('signrawtransaction', [tx.hex()])
|
||||
return bytes.fromhex(rv['hex'])
|
||||
|
||||
def createRawFundedTransaction(self, addr_to: str, amount: int, sub_fee: bool = False, lock_unspents: bool = True) -> str:
|
||||
txn = self.rpc_callback('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
|
||||
txn = self.rpc('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
|
||||
fee_rate, fee_src = self.get_fee_rate(self._conf_target)
|
||||
self._log.debug(f'Fee rate: {fee_rate}, source: {fee_src}, block target: {self._conf_target}')
|
||||
options = {
|
||||
|
@ -43,25 +52,25 @@ class PIVXInterface(BTCInterface):
|
|||
}
|
||||
if sub_fee:
|
||||
options['subtractFeeFromOutputs'] = [0,]
|
||||
return self.rpc_callback('fundrawtransaction', [txn, options])['hex']
|
||||
return self.rpc('fundrawtransaction', [txn, options])['hex']
|
||||
|
||||
def createRawSignedTransaction(self, addr_to, amount) -> str:
|
||||
txn_funded = self.createRawFundedTransaction(addr_to, amount)
|
||||
return self.rpc_callback('signrawtransaction', [txn_funded])['hex']
|
||||
return self.rpc('signrawtransaction', [txn_funded])['hex']
|
||||
|
||||
def decodeAddress(self, address):
|
||||
return decodeAddress(address)[1:]
|
||||
|
||||
def getBlockWithTxns(self, block_hash):
|
||||
# TODO: Bypass decoderawtransaction and getblockheader
|
||||
block = self.rpc_callback('getblock', [block_hash, False])
|
||||
block_header = self.rpc_callback('getblockheader', [block_hash])
|
||||
block = self.rpc('getblock', [block_hash, False])
|
||||
block_header = self.rpc('getblockheader', [block_hash])
|
||||
decoded_block = CBlock()
|
||||
decoded_block = FromHex(decoded_block, block)
|
||||
|
||||
tx_rv = []
|
||||
for tx in decoded_block.vtx:
|
||||
tx_dec = self.rpc_callback('decoderawtransaction', [ToHex(tx)])
|
||||
tx_dec = self.rpc('decoderawtransaction', [ToHex(tx)])
|
||||
tx_rv.append(tx_dec)
|
||||
|
||||
block_rv = {
|
||||
|
@ -77,10 +86,10 @@ class PIVXInterface(BTCInterface):
|
|||
|
||||
def withdrawCoin(self, value, addr_to, subfee):
|
||||
params = [addr_to, value, '', '', subfee]
|
||||
return self.rpc_callback('sendtoaddress', params)
|
||||
return self.rpc('sendtoaddress', params)
|
||||
|
||||
def getSpendableBalance(self) -> int:
|
||||
return self.make_int(self.rpc_callback('getwalletinfo')['balance'])
|
||||
return self.make_int(self.rpc('getwalletinfo')['balance'])
|
||||
|
||||
def loadTx(self, tx_bytes):
|
||||
# Load tx from bytes to internal representation
|
||||
|
@ -101,13 +110,13 @@ class PIVXInterface(BTCInterface):
|
|||
|
||||
def signTxWithKey(self, tx: bytes, key: bytes) -> bytes:
|
||||
key_wif = self.encodeKey(key)
|
||||
rv = self.rpc_callback('signrawtransaction', [tx.hex(), [], [key_wif, ]])
|
||||
rv = self.rpc('signrawtransaction', [tx.hex(), [], [key_wif, ]])
|
||||
return bytes.fromhex(rv['hex'])
|
||||
|
||||
def findTxnByHash(self, txid_hex: str):
|
||||
# Only works for wallet txns
|
||||
try:
|
||||
rv = self.rpc_callback('gettransaction', [txid_hex])
|
||||
rv = self.rpc('gettransaction', [txid_hex])
|
||||
except Exception as ex:
|
||||
self._log.debug('findTxnByHash getrawtransaction failed: {}'.format(txid_hex))
|
||||
return None
|
||||
|
|
|
@ -83,9 +83,9 @@ class XMRInterface(CoinInterface):
|
|||
daemon_login = None
|
||||
if coin_settings.get('rpcuser', '') != '':
|
||||
daemon_login = (coin_settings.get('rpcuser', ''), coin_settings.get('rpcpassword', ''))
|
||||
self.rpc_cb = make_xmr_rpc_func(coin_settings['rpcport'], daemon_login, host=coin_settings.get('rpchost', '127.0.0.1'))
|
||||
self.rpc_cb2 = make_xmr_rpc2_func(coin_settings['rpcport'], daemon_login, host=coin_settings.get('rpchost', '127.0.0.1')) # non-json endpoint
|
||||
self.rpc_wallet_cb = make_xmr_rpc_func(coin_settings['walletrpcport'], coin_settings['walletrpcauth'], host=coin_settings.get('walletrpchost', '127.0.0.1'))
|
||||
self.rpc = make_xmr_rpc_func(coin_settings['rpcport'], daemon_login, host=coin_settings.get('rpchost', '127.0.0.1'))
|
||||
self.rpc2 = make_xmr_rpc2_func(coin_settings['rpcport'], daemon_login, host=coin_settings.get('rpchost', '127.0.0.1')) # 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'))
|
||||
|
||||
self.blocks_confirmed = coin_settings['blocks_confirmed']
|
||||
self._restore_height = coin_settings.get('restore_height', 0)
|
||||
|
@ -95,6 +95,9 @@ class XMRInterface(CoinInterface):
|
|||
self._wallet_password = None
|
||||
self._have_checked_seed = False
|
||||
|
||||
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
|
||||
|
@ -105,7 +108,7 @@ class XMRInterface(CoinInterface):
|
|||
def createWallet(self, params):
|
||||
if self._wallet_password is not None:
|
||||
params['password'] = self._wallet_password
|
||||
rv = self.rpc_wallet_cb('generate_from_keys', params)
|
||||
rv = self.rpc_wallet('generate_from_keys', params)
|
||||
self._log.info('generate_from_keys %s', dumpj(rv))
|
||||
|
||||
def openWallet(self, filename):
|
||||
|
@ -115,10 +118,10 @@ class XMRInterface(CoinInterface):
|
|||
|
||||
try:
|
||||
# Can't reopen the same wallet in windows, !is_keys_file_locked()
|
||||
self.rpc_wallet_cb('close_wallet')
|
||||
self.rpc_wallet('close_wallet')
|
||||
except Exception:
|
||||
pass
|
||||
self.rpc_wallet_cb('open_wallet', params)
|
||||
self.rpc_wallet('open_wallet', params)
|
||||
|
||||
def initialiseWallet(self, key_view, key_spend, restore_height=None):
|
||||
with self._mx_wallet:
|
||||
|
@ -147,14 +150,14 @@ class XMRInterface(CoinInterface):
|
|||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
|
||||
def testDaemonRPC(self, with_wallet=True):
|
||||
self.rpc_wallet_cb('get_languages')
|
||||
def testDaemonRPC(self, with_wallet=True) -> None:
|
||||
self.rpc_wallet('get_languages')
|
||||
|
||||
def getDaemonVersion(self):
|
||||
return self.rpc_wallet_cb('get_version')['version']
|
||||
return self.rpc_wallet('get_version')['version']
|
||||
|
||||
def getBlockchainInfo(self):
|
||||
get_height = self.rpc_cb2('get_height', timeout=30)
|
||||
get_height = self.rpc2('get_height', timeout=30)
|
||||
rv = {
|
||||
'blocks': get_height['height'],
|
||||
'verificationprogress': 0.0,
|
||||
|
@ -165,7 +168,7 @@ class XMRInterface(CoinInterface):
|
|||
# get_block_count returns "Internal error" if bootstrap-daemon is active
|
||||
if get_height['untrusted'] is True:
|
||||
rv['bootstrapping'] = True
|
||||
get_info = self.rpc_cb2('get_info', timeout=30)
|
||||
get_info = self.rpc2('get_info', timeout=30)
|
||||
if 'height_without_bootstrap' in get_info:
|
||||
rv['blocks'] = get_info['height_without_bootstrap']
|
||||
|
||||
|
@ -173,7 +176,7 @@ class XMRInterface(CoinInterface):
|
|||
if rv['known_block_count'] > rv['blocks']:
|
||||
rv['verificationprogress'] = rv['blocks'] / rv['known_block_count']
|
||||
else:
|
||||
rv['known_block_count'] = self.rpc_cb('get_block_count', timeout=30)['count']
|
||||
rv['known_block_count'] = self.rpc('get_block_count', timeout=30)['count']
|
||||
rv['verificationprogress'] = rv['blocks'] / rv['known_block_count']
|
||||
except Exception as e:
|
||||
self._log.warning('XMR get_block_count failed with: %s', str(e))
|
||||
|
@ -182,7 +185,7 @@ class XMRInterface(CoinInterface):
|
|||
return rv
|
||||
|
||||
def getChainHeight(self):
|
||||
return self.rpc_cb2('get_height', timeout=30)['height']
|
||||
return self.rpc2('get_height', timeout=30)['height']
|
||||
|
||||
def getWalletInfo(self):
|
||||
with self._mx_wallet:
|
||||
|
@ -195,8 +198,8 @@ class XMRInterface(CoinInterface):
|
|||
raise e
|
||||
|
||||
rv = {}
|
||||
self.rpc_wallet_cb('refresh')
|
||||
balance_info = self.rpc_wallet_cb('get_balance')
|
||||
self.rpc_wallet('refresh')
|
||||
balance_info = self.rpc_wallet('get_balance')
|
||||
rv['balance'] = self.format_amount(balance_info['unlocked_balance'])
|
||||
rv['unconfirmed_balance'] = self.format_amount(balance_info['balance'] - balance_info['unlocked_balance'])
|
||||
rv['encrypted'] = False if self._wallet_password is None else True
|
||||
|
@ -209,13 +212,13 @@ class XMRInterface(CoinInterface):
|
|||
def getMainWalletAddress(self) -> str:
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
return self.rpc_wallet_cb('get_address')['address']
|
||||
return self.rpc_wallet('get_address')['address']
|
||||
|
||||
def getNewAddress(self, placeholder) -> str:
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
new_address = self.rpc_wallet_cb('create_address', {'account_index': 0})['address']
|
||||
self.rpc_wallet_cb('store')
|
||||
new_address = self.rpc_wallet('create_address', {'account_index': 0})['address']
|
||||
self.rpc_wallet('store')
|
||||
return new_address
|
||||
|
||||
def get_fee_rate(self, conf_target: int = 2):
|
||||
|
@ -280,7 +283,7 @@ class XMRInterface(CoinInterface):
|
|||
def publishBLockTx(self, kbv: bytes, Kbs: bytes, output_amount: int, feerate: int, delay_for: int = 10, unlock_time: int = 0) -> bytes:
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
self.rpc_wallet_cb('refresh')
|
||||
self.rpc_wallet('refresh')
|
||||
|
||||
Kbv = self.getPubkey(kbv)
|
||||
shared_addr = xmr_util.encode_address(Kbv, Kbs)
|
||||
|
@ -288,7 +291,7 @@ class XMRInterface(CoinInterface):
|
|||
params = {'destinations': [{'amount': output_amount, 'address': shared_addr}], 'unlock_time': unlock_time}
|
||||
if self._fee_priority > 0:
|
||||
params['priority'] = self._fee_priority
|
||||
rv = self.rpc_wallet_cb('transfer', params)
|
||||
rv = self.rpc_wallet('transfer', params)
|
||||
self._log.info('publishBLockTx %s to address_b58 %s', rv['tx_hash'], shared_addr)
|
||||
tx_hash = bytes.fromhex(rv['tx_hash'])
|
||||
|
||||
|
@ -296,7 +299,7 @@ class XMRInterface(CoinInterface):
|
|||
i = 0
|
||||
while not self._sc.delay_event.is_set():
|
||||
gt_params = {'out': True, 'pending': True, 'failed': True, 'pool': True, }
|
||||
rv = self.rpc_wallet_cb('get_transfers', gt_params)
|
||||
rv = self.rpc_wallet('get_transfers', gt_params)
|
||||
self._log.debug('get_transfers {}'.format(dumpj(rv)))
|
||||
if 'pending' not in rv:
|
||||
break
|
||||
|
@ -325,26 +328,26 @@ class XMRInterface(CoinInterface):
|
|||
self.createWallet(params)
|
||||
self.openWallet(address_b58)
|
||||
|
||||
self.rpc_wallet_cb('refresh', timeout=600)
|
||||
self.rpc_wallet('refresh', timeout=600)
|
||||
|
||||
'''
|
||||
# Debug
|
||||
try:
|
||||
current_height = self.rpc_wallet_cb('get_height')['height']
|
||||
current_height = self.rpc_wallet('get_height')['height']
|
||||
self._log.info('findTxB XMR current_height %d\nAddress: %s', current_height, address_b58)
|
||||
except Exception as e:
|
||||
self._log.info('rpc_cb failed %s', str(e))
|
||||
self._log.info('rpc failed %s', str(e))
|
||||
current_height = None # If the transfer is available it will be deep enough
|
||||
# and (current_height is None or current_height - transfer['block_height'] > cb_block_confirmed):
|
||||
'''
|
||||
params = {'transfer_type': 'available'}
|
||||
transfers = self.rpc_wallet_cb('incoming_transfers', params)
|
||||
transfers = self.rpc_wallet('incoming_transfers', params)
|
||||
rv = None
|
||||
if 'transfers' in transfers:
|
||||
for transfer in transfers['transfers']:
|
||||
# unlocked <- wallet->is_transfer_unlocked() checks unlock_time and CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE
|
||||
if not transfer['unlocked']:
|
||||
full_tx = self.rpc_wallet_cb('get_transfer_by_txid', {'txid': transfer['tx_hash']})
|
||||
full_tx = self.rpc_wallet('get_transfer_by_txid', {'txid': transfer['tx_hash']})
|
||||
unlock_time = full_tx['transfer']['unlock_time']
|
||||
if unlock_time != 0:
|
||||
self._log.warning('Coin b lock txn is locked: {}, unlock_time {}'.format(transfer['tx_hash'], unlock_time))
|
||||
|
@ -360,17 +363,17 @@ class XMRInterface(CoinInterface):
|
|||
def findTxnByHash(self, txid):
|
||||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
self.rpc_wallet_cb('refresh', timeout=600)
|
||||
self.rpc_wallet('refresh', timeout=600)
|
||||
|
||||
try:
|
||||
current_height = self.rpc_cb2('get_height', timeout=30)['height']
|
||||
current_height = self.rpc2('get_height', timeout=30)['height']
|
||||
self._log.info('findTxnByHash XMR current_height %d\nhash: %s', current_height, txid)
|
||||
except Exception as e:
|
||||
self._log.info('rpc_cb failed %s', str(e))
|
||||
self._log.info('rpc failed %s', str(e))
|
||||
current_height = None # If the transfer is available it will be deep enough
|
||||
|
||||
params = {'transfer_type': 'available'}
|
||||
rv = self.rpc_wallet_cb('incoming_transfers', params)
|
||||
rv = self.rpc_wallet('incoming_transfers', params)
|
||||
if 'transfers' in rv:
|
||||
for transfer in rv['transfers']:
|
||||
if transfer['tx_hash'] == txid \
|
||||
|
@ -405,11 +408,11 @@ class XMRInterface(CoinInterface):
|
|||
self.createWallet(params)
|
||||
self.openWallet(wallet_filename)
|
||||
|
||||
self.rpc_wallet_cb('refresh')
|
||||
rv = self.rpc_wallet_cb('get_balance')
|
||||
self.rpc_wallet('refresh')
|
||||
rv = self.rpc_wallet('get_balance')
|
||||
if rv['balance'] < cb_swap_value:
|
||||
self._log.warning('Balance is too low, checking for existing spend.')
|
||||
txns = self.rpc_wallet_cb('get_transfers', {'out': True})
|
||||
txns = self.rpc_wallet('get_transfers', {'out': True})
|
||||
if 'out' in txns:
|
||||
txns = txns['out']
|
||||
if len(txns) > 0:
|
||||
|
@ -434,7 +437,7 @@ class XMRInterface(CoinInterface):
|
|||
if self._fee_priority > 0:
|
||||
params['priority'] = self._fee_priority
|
||||
|
||||
rv = self.rpc_wallet_cb('sweep_all', params)
|
||||
rv = self.rpc_wallet('sweep_all', params)
|
||||
self._log.debug('sweep_all {}'.format(json.dumps(rv)))
|
||||
|
||||
return bytes.fromhex(rv['tx_hash_list'][0])
|
||||
|
@ -444,24 +447,24 @@ class XMRInterface(CoinInterface):
|
|||
value_sats = make_int(value, self.exp())
|
||||
|
||||
self.openWallet(self._wallet_filename)
|
||||
self.rpc_wallet_cb('refresh')
|
||||
self.rpc_wallet('refresh')
|
||||
|
||||
if subfee:
|
||||
balance = self.rpc_wallet_cb('get_balance')
|
||||
balance = self.rpc_wallet('get_balance')
|
||||
diff = balance['unlocked_balance'] - value_sats
|
||||
if diff >= 0 and diff <= 10:
|
||||
self._log.info('subfee enabled and value close to total, using sweep_all.')
|
||||
params = {'address': addr_to}
|
||||
if self._fee_priority > 0:
|
||||
params['priority'] = self._fee_priority
|
||||
rv = self.rpc_wallet_cb('sweep_all', params)
|
||||
rv = self.rpc_wallet('sweep_all', params)
|
||||
return rv['tx_hash_list'][0]
|
||||
raise ValueError('Withdraw value must be close to total to use subfee/sweep_all.')
|
||||
|
||||
params = {'destinations': [{'amount': value_sats, 'address': addr_to}]}
|
||||
if self._fee_priority > 0:
|
||||
params['priority'] = self._fee_priority
|
||||
rv = self.rpc_wallet_cb('transfer', params)
|
||||
rv = self.rpc_wallet('transfer', params)
|
||||
return rv['tx_hash']
|
||||
|
||||
def showLockTransfers(self, kbv, Kbs, restore_height):
|
||||
|
@ -488,9 +491,9 @@ class XMRInterface(CoinInterface):
|
|||
self.createWallet(params)
|
||||
self.openWallet(address_b58)
|
||||
|
||||
self.rpc_wallet_cb('refresh')
|
||||
self.rpc_wallet('refresh')
|
||||
|
||||
rv = self.rpc_wallet_cb('get_transfers', {'in': True, 'out': True, 'pending': True, 'failed': True})
|
||||
rv = self.rpc_wallet('get_transfers', {'in': True, 'out': True, 'pending': True, 'failed': True})
|
||||
rv['filename'] = wallet_file
|
||||
return rv
|
||||
except Exception as e:
|
||||
|
@ -500,8 +503,8 @@ class XMRInterface(CoinInterface):
|
|||
with self._mx_wallet:
|
||||
self.openWallet(self._wallet_filename)
|
||||
|
||||
self.rpc_wallet_cb('refresh')
|
||||
balance_info = self.rpc_wallet_cb('get_balance')
|
||||
self.rpc_wallet('refresh')
|
||||
balance_info = self.rpc_wallet('get_balance')
|
||||
return balance_info['unlocked_balance']
|
||||
|
||||
def changeWalletPassword(self, old_password, new_password):
|
||||
|
@ -511,7 +514,7 @@ class XMRInterface(CoinInterface):
|
|||
self._wallet_password = old_password
|
||||
try:
|
||||
self.openWallet(self._wallet_filename)
|
||||
self.rpc_wallet_cb('change_wallet_password', {'old_password': old_password, 'new_password': new_password})
|
||||
self.rpc_wallet('change_wallet_password', {'old_password': old_password, 'new_password': new_password})
|
||||
except Exception as e:
|
||||
self._wallet_password = orig_password
|
||||
raise e
|
||||
|
@ -536,4 +539,4 @@ class XMRInterface(CoinInterface):
|
|||
raise ValueError('Balance too low')
|
||||
|
||||
def getTransaction(self, txid: bytes):
|
||||
return self.rpc_cb2('get_transactions', {'txs_hashes': [txid.hex(), ]})
|
||||
return self.rpc2('get_transactions', {'txs_hashes': [txid.hex(), ]})
|
||||
|
|
|
@ -63,6 +63,9 @@ def withdraw_coin(swap_client, coin_type, post_string, is_json):
|
|||
type_from = get_data_entry_or(post_data, 'type_from', 'plain')
|
||||
type_to = get_data_entry_or(post_data, 'type_to', 'plain')
|
||||
txid_hex = swap_client.withdrawParticl(type_from, type_to, value, address, subfee)
|
||||
elif coin_type == Coins.LTC:
|
||||
type_from = get_data_entry_or(post_data, 'type_from', 'plain')
|
||||
txid_hex = swap_client.withdrawLTC(type_from, value, address, subfee)
|
||||
else:
|
||||
txid_hex = swap_client.withdrawCoin(coin_type, value, address, subfee)
|
||||
|
||||
|
@ -92,6 +95,8 @@ def js_coins(self, url_split, post_string, is_json) -> bytes:
|
|||
entry['variant'] = 'Anon'
|
||||
elif coin == Coins.PART_BLIND:
|
||||
entry['variant'] = 'Blind'
|
||||
elif coin == Coins.LTC_MWEB:
|
||||
entry['variant'] = 'MWEB'
|
||||
coins.append(entry)
|
||||
|
||||
return bytes(json.dumps(coins), 'UTF-8')
|
||||
|
@ -108,19 +113,30 @@ def js_wallets(self, url_split, post_string, is_json):
|
|||
cmd = url_split[4]
|
||||
if cmd == 'withdraw':
|
||||
return bytes(json.dumps(withdraw_coin(swap_client, coin_type, post_string, is_json)), 'UTF-8')
|
||||
if cmd == 'nextdepositaddr':
|
||||
elif cmd == 'nextdepositaddr':
|
||||
return bytes(json.dumps(swap_client.cacheNewAddressForCoin(coin_type)), 'UTF-8')
|
||||
if cmd == 'createutxo':
|
||||
elif cmd == 'createutxo':
|
||||
post_data = getFormData(post_string, is_json)
|
||||
ci = swap_client.ci(coin_type)
|
||||
value = ci.make_int(get_data_entry(post_data, 'value'))
|
||||
txid_hex, new_addr = ci.createUTXO(value)
|
||||
return bytes(json.dumps({'txid': txid_hex, 'address': new_addr}), 'UTF-8')
|
||||
if cmd == 'reseed':
|
||||
elif cmd == 'reseed':
|
||||
swap_client.reseedWallet(coin_type)
|
||||
return bytes(json.dumps({'reseeded': True}), 'UTF-8')
|
||||
elif cmd == 'newstealthaddress':
|
||||
if coin_type != Coins.PART:
|
||||
raise ValueError('Invalid coin for command')
|
||||
return bytes(json.dumps(swap_client.ci(coin_type).getNewStealthAddress()), 'UTF-8')
|
||||
elif cmd == 'newmwebaddress':
|
||||
if coin_type not in (Coins.LTC, Coins.LTC_MWEB):
|
||||
raise ValueError('Invalid coin for command')
|
||||
return bytes(json.dumps(swap_client.ci(coin_type).getNewMwebAddress()), 'UTF-8')
|
||||
|
||||
raise ValueError('Unknown command')
|
||||
|
||||
if coin_type == Coins.LTC_MWEB:
|
||||
coin_type = Coins.LTC
|
||||
rv = swap_client.getWalletInfo(coin_type)
|
||||
rv.update(swap_client.getBlockchainInfo(coin_type))
|
||||
ci = swap_client.ci(coin_type)
|
||||
|
@ -647,7 +663,7 @@ def js_setpassword(self, url_split, post_string, is_json) -> bytes:
|
|||
if have_data_entry(post_data, 'coin'):
|
||||
# Set password for one coin
|
||||
coin = getCoinType(get_data_entry(post_data, 'coin'))
|
||||
if coin in (Coins.PART_ANON, Coins.PART_BLIND):
|
||||
if coin in (Coins.PART_ANON, Coins.PART_BLIND, Coins.LTC_MWEB):
|
||||
raise ValueError('Invalid coin.')
|
||||
swap_client.changeWalletPasswords(old_password, new_password, coin)
|
||||
return bytes(json.dumps({'success': True}), 'UTF-8')
|
||||
|
|
12
basicswap/templates/style.html
Normal file
12
basicswap/templates/style.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
{% set select_box_arrow_svg = '<svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
|
||||
</svg>' %}
|
||||
|
||||
{% set select_box_class = 'hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0' %}
|
||||
|
||||
{% set circular_arrows_svg = '<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
|
||||
<g fill="#ffffff" class="nc-icon-wrapper">
|
||||
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
|
||||
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
|
||||
</g>
|
||||
</svg>' %}
|
|
@ -1,4 +1,6 @@
|
|||
{% include 'header.html' %}
|
||||
{% from 'style.html' import select_box_arrow_svg, select_box_class, circular_arrows_svg %}
|
||||
|
||||
<div class="container mx-auto">
|
||||
<section class="p-5 mt-5">
|
||||
<div class="flex flex-wrap items-center -m-2">
|
||||
|
@ -47,12 +49,7 @@
|
|||
<div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto">
|
||||
<a class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto">
|
||||
<a class="mr-5 flex flex-wrap justify-center px-5 py-3 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border dark:bg-gray-500 dark:hover:bg-gray-700 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="refresh" href="/wallet/{{ w.ticker }}">
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
|
||||
<g fill="#ffffff" class="nc-icon-wrapper">
|
||||
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
|
||||
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
{{ circular_arrows_svg }}
|
||||
<span>Refresh</span>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -165,7 +162,7 @@
|
|||
</td>
|
||||
<td class="py-3 px-6 bold coinname-value" data-coinname="{{ w.name }}">{{ w.balance }} {{ w.ticker }} (<span class="usd-value"></span>){% if w.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.unconfirmed }} {{ w.ticker }}</span>{% endif %}</td>
|
||||
</tr>
|
||||
{% if w.cid == '1' %}
|
||||
{% 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">
|
||||
|
@ -180,9 +177,21 @@
|
|||
<img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }} Anon">
|
||||
</span>Anon Balance:
|
||||
</td>
|
||||
<td class="py-3 px-6 bold coinname-value" data-coinname="{{ w.name }}">{{ w.anon_balance }} {{ w.ticker }} (<span class="usd-value"></span>) {% if w.anon_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.anon_pending }} {{ w.ticker }}</span>{% endif %}</td>
|
||||
<td class="py-3 px-6 bold coinname-value" data-coinname="{{ w.name }}">{{ w.anon_balance }} {{ w.ticker }} (<span class="usd-value"></span>) {% if w.anon_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.anon_pending }} {{ w.ticker }}</span>{% endif %}</td>
|
||||
<td class="usd-value"></td>
|
||||
</tr> {% endif %} <tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
|
||||
</tr>
|
||||
{% endif %} {# / PART #}
|
||||
{% if w.cid == '3' %} {# LTC #}
|
||||
<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 }} MWEB">
|
||||
</span>MWEB Balance:
|
||||
</td>
|
||||
<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 %}</td>
|
||||
</tr>
|
||||
{% endif %} {# / LTC #}
|
||||
<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">Blocks:</td>
|
||||
<td class="py-3 px-6">{{ w.blocks }} {% if w.known_block_count %} / {{ w.known_block_count }} {% endif %}</td>
|
||||
</tr>
|
||||
|
@ -192,13 +201,13 @@
|
|||
</tr> {% if w.bootstrapping %} <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">Bootstrapping:</td>
|
||||
<td class="py-3 px-6">{{ w.bootstrapping }}</td>
|
||||
</tr> {% endif %}
|
||||
</tr> {% endif %} {# / bootstrapping #}
|
||||
{% if w.encrypted %}
|
||||
<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:</td>
|
||||
<td class="py-3 px-6">{{ w.locked }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %} {# / encrypted #}
|
||||
<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">Expected Seed:</td>
|
||||
<td class="py-3 px-6">{{ w.expected_seed }}</td> {% if block_unknown_seeds and w.expected_seed != true %} {# Only show addresses if wallet seed is correct #}
|
||||
|
@ -235,13 +244,22 @@
|
|||
|
||||
{% else %}
|
||||
</tr>
|
||||
{% if w.cid == '1' %}
|
||||
{% 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">Stealth Address</td>
|
||||
<td colspan=2 class="py-3 px-6 monospace bold select-all">{{ w.stealth_address }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if w.cid == '6' %}
|
||||
{% endif %} {# / PART #}
|
||||
{% if w.cid == '3' %} {# LTC #}
|
||||
<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">
|
||||
<button type="submit" class="flex flex-wrap justify-center py-2 px-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="newmwebaddr_{{ w.cid }}" value="New MWEB Address">
|
||||
{{ circular_arrows_svg }} New MWEB Address</button>
|
||||
</td>
|
||||
<td colspan=2 class="py-3 px-6 monospace bold select-all">{{ w.mweb_address }}</td>
|
||||
</tr>
|
||||
{% endif %} {# / LTC #}
|
||||
{% if w.cid == '6' %} {# XMR #}
|
||||
<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">Main Address</td>
|
||||
<td colspan=2 class="py-3 px-6 monospace bold select-all">{{ w.main_address }}</td>
|
||||
|
@ -249,12 +267,7 @@
|
|||
<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">
|
||||
<button type="submit" class="flex flex-wrap justify-center py-2 px-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="newaddr_{{ w.cid }}" value="New Subaddress">
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
|
||||
<g fill="#ffffff" class="nc-icon-wrapper">
|
||||
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
|
||||
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
|
||||
</g>
|
||||
</svg> New {{ w.ticker }} Sub Address </button>
|
||||
{{ circular_arrows_svg }} New {{ w.ticker }} Sub Address </button>
|
||||
</td>
|
||||
<td colspan=2 class="py-3 px-6 monospace select-all">{{ w.deposit_address }}</td>
|
||||
</tr>
|
||||
|
@ -262,12 +275,7 @@
|
|||
<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">
|
||||
<button type="submit" class="flex flex-wrap justify-center py-2 px-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="newaddr_{{ w.cid }}" value="New Deposit Address">
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
|
||||
<g fill="#ffffff" class="nc-icon-wrapper">
|
||||
<path fill="#ffffff" d="M12,3c1.989,0,3.873,0.65,5.43,1.833l-3.604,3.393l9.167,0.983L22.562,0l-3.655,3.442 C16.957,1.862,14.545,1,12,1C5.935,1,1,5.935,1,12h2C3,7.037,7.037,3,12,3z"></path>
|
||||
<path data-color="color-2" d="M12,21c-1.989,0-3.873-0.65-5.43-1.833l3.604-3.393l-9.167-0.983L1.438,24l3.655-3.442 C7.043,22.138,9.455,23,12,23c6.065,0,11-4.935,11-11h-2C21,16.963,16.963,21,12,21z"></path>
|
||||
</g>
|
||||
</svg>New {{ w.ticker }} Deposit Address</button>
|
||||
{{ circular_arrows_svg }} New {{ w.ticker }} Deposit Address</button>
|
||||
</td>
|
||||
<td colspan=2 class="py-3 px-6 monospace bold select-all" id="deposit_address">{{ w.deposit_address }}</td>
|
||||
</tr>
|
||||
|
@ -342,16 +350,14 @@
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% if w.cid == '1' %}
|
||||
{% if w.cid == '1' %} {# PART #}
|
||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
|
||||
<td class="py-3 px-6 bold">Type From -> To:</td>
|
||||
<td class="py-3 px-6">
|
||||
<div class="w-full md:flex-1">
|
||||
<div class="relative">
|
||||
<svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
|
||||
</svg>
|
||||
<select class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="withdraw_type_from_{{ w.cid }}">
|
||||
{{ select_box_arrow_svg }}
|
||||
<select class="{{ select_box_class }}" name="withdraw_type_from_{{ w.cid }}">
|
||||
<option value="plain" {% if w.wd_type_from=='plain' %} selected{% endif %}>Plain</option>
|
||||
<option value="blind" {% if w.wd_type_from=='blind' %} selected{% endif %}>Blind</option>
|
||||
<option value="anon" {% if w.wd_type_from=='anon' %} selected{% endif %}>Anon</option>
|
||||
|
@ -362,10 +368,8 @@
|
|||
<td class="py-3 px-6">
|
||||
<div class="w-full md:flex-1">
|
||||
<div class="relative">
|
||||
<svg class="absolute right-4 top-1/2 transform -translate-y-1/2" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.3333 6.1133C11.2084 5.98913 11.0395 5.91943 10.8633 5.91943C10.6872 5.91943 10.5182 5.98913 10.3933 6.1133L8.00001 8.47329L5.64001 6.1133C5.5151 5.98913 5.34613 5.91943 5.17001 5.91943C4.99388 5.91943 4.82491 5.98913 4.70001 6.1133C4.63752 6.17527 4.58792 6.249 4.55408 6.33024C4.52023 6.41148 4.50281 6.49862 4.50281 6.58663C4.50281 6.67464 4.52023 6.76177 4.55408 6.84301C4.58792 6.92425 4.63752 6.99799 4.70001 7.05996L7.52667 9.88663C7.58865 9.94911 7.66238 9.99871 7.74362 10.0326C7.82486 10.0664 7.912 10.0838 8.00001 10.0838C8.08801 10.0838 8.17515 10.0664 8.25639 10.0326C8.33763 9.99871 8.41136 9.94911 8.47334 9.88663L11.3333 7.05996C11.3958 6.99799 11.4454 6.92425 11.4793 6.84301C11.5131 6.76177 11.5305 6.67464 11.5305 6.58663C11.5305 6.49862 11.5131 6.41148 11.4793 6.33024C11.4454 6.249 11.3958 6.17527 11.3333 6.1133Z" fill="#8896AB"></path>
|
||||
</svg>
|
||||
<select class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-white text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" name="withdraw_type_to_{{ w.cid }}">
|
||||
{{ select_box_arrow_svg }}
|
||||
<select class="{{ select_box_class }}" name="withdraw_type_to_{{ w.cid }}">
|
||||
<option value="plain" {% if w.wd_type_to=='plain' %} selected{% endif %}>Plain</option>
|
||||
<option value="blind" {% if w.wd_type_to=='blind' %} selected{% endif %}>Blind</option>
|
||||
<option value="anon" {% if w.wd_type_to=='anon' %} selected{% endif %}>Anon</option>
|
||||
|
@ -374,7 +378,23 @@
|
|||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %} {# / PART #}
|
||||
{% if w.cid == '3' %} {# LTC #}
|
||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
|
||||
<td class="py-3 px-6 bold">Type From:</td>
|
||||
<td class="py-3 px-6">
|
||||
<div class="w-full md:flex-1">
|
||||
<div class="relative">
|
||||
{{ select_box_arrow_svg }}
|
||||
<select class="{{ select_box_class }}" name="withdraw_type_from_{{ w.cid }}">
|
||||
<option value="plain" {% if w.wd_type_from=='plain' %} selected{% endif %}>Plain</option>
|
||||
<option value="mweb" {% if w.wd_type_from=='mweb' %} selected{% endif %}>MWEB</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %} {# / LTC #}
|
||||
<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">Fee Rate:</td>
|
||||
<td class="py-3 px-6 bold">{{ w.fee_rate }}</td>
|
||||
|
@ -392,7 +412,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% if w.cid != '6' %}
|
||||
{% if w.cid != '6' %} {# !XMR #}
|
||||
{% if w.show_utxo_groups %}
|
||||
<section class="p-6">
|
||||
<div class="flex flex-wrap items-center">
|
||||
|
@ -647,4 +667,4 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
<div class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 usd-value"></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if w.cid == '1' %}
|
||||
{% if w.cid == '1' %} {# PART #}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Blind Balance:</h4>
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 coinname-value" data-coinname="{{ w.name }}">{{ w.blind_balance }} {{ w.ticker }}</span>
|
||||
|
@ -130,7 +130,7 @@
|
|||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-bold text-green-500 dark:text-green-500">Blind Unconfirmed USD value:</h4>
|
||||
<div class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 usd-value"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Anon Balance:</h4>
|
||||
|
@ -149,9 +149,30 @@
|
|||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-bold text-green-500 dark:text-green-500">Anon Pending USD value:</h4>
|
||||
<div class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 usd-value"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %} {# / PART #}
|
||||
{% if w.cid == '3' %} {# LTC #}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">MWEB Balance:</h4>
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 coinname-value" data-coinname="{{ w.name }}">{{ w.mweb_balance }} {{ w.ticker }}</span>
|
||||
</div>
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">MWEB USD value:</h4>
|
||||
<div class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 usd-value"></div>
|
||||
</div>
|
||||
{% if w.mweb_pending %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-bold text-green-500 dark:text-green-500">MWEB Pending:</h4>
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 coinname-value" data-coinname="{{ w.name }}">
|
||||
+{{ w.mweb_pending }} {{ w.ticker }}</span>
|
||||
</div>
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-bold text-green-500 dark:text-green-500">MWEB Pending USD value:</h4>
|
||||
<div class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500 usd-value"></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %} {# / LTC #}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Blocks:</h4>
|
||||
<span class="inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200">{{ w.blocks }}{% if w.known_block_count %} / {{ w.known_block_count }}{% endif %}</span>
|
||||
|
@ -409,4 +430,4 @@ window.onload = async () => {
|
|||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -51,12 +51,16 @@ def format_wallet_data(swap_client, ci, w):
|
|||
|
||||
if ci.coin_type() == Coins.PART:
|
||||
wf['stealth_address'] = w.get('stealth_address', '?')
|
||||
wf['blind_balance'] = "{:.8f}".format(float(w['blind_balance']))
|
||||
wf['blind_balance'] = w.get('blind_balance', '?')
|
||||
if 'blind_unconfirmed' in w and float(w['blind_unconfirmed']) > 0.0:
|
||||
wf['blind_unconfirmed'] = w['blind_unconfirmed']
|
||||
wf['anon_balance'] = w.get('anon_balance', '?')
|
||||
if 'anon_pending' in w and float(w['anon_pending']) > 0.0:
|
||||
wf['anon_pending'] = w['anon_pending']
|
||||
elif ci.coin_type() == Coins.LTC:
|
||||
wf['mweb_address'] = w.get('mweb_address', '?')
|
||||
wf['mweb_balance'] = w.get('mweb_balance', '?')
|
||||
wf['mweb_pending'] = w.get('mweb_pending', '?')
|
||||
|
||||
checkAddressesOwned(swap_client, ci, wf)
|
||||
return wf
|
||||
|
@ -128,6 +132,8 @@ def page_wallet(self, url_split, post_string):
|
|||
|
||||
if bytes('newaddr_' + cid, 'utf-8') in form_data:
|
||||
swap_client.cacheNewAddressForCoin(coin_id)
|
||||
elif bytes('newmwebaddr_' + cid, 'utf-8') in form_data:
|
||||
swap_client.cacheNewStealthAddressForCoin(coin_id)
|
||||
elif bytes('reseed_' + cid, 'utf-8') in form_data:
|
||||
try:
|
||||
swap_client.reseedWallet(coin_id)
|
||||
|
@ -158,22 +164,28 @@ def page_wallet(self, url_split, post_string):
|
|||
page_data['wd_type_to_' + cid] = type_to
|
||||
except Exception as e:
|
||||
err_messages.append('Missing type')
|
||||
elif coin_id == Coins.LTC:
|
||||
try:
|
||||
type_from = form_data[bytes('withdraw_type_from_' + cid, 'utf-8')][0].decode('utf-8')
|
||||
page_data['wd_type_from_' + cid] = type_from
|
||||
except Exception as e:
|
||||
err_messages.append('Missing type')
|
||||
|
||||
if len(messages) == 0:
|
||||
ci = swap_client.ci(coin_id)
|
||||
ticker = ci.ticker()
|
||||
if coin_id == Coins.PART:
|
||||
try:
|
||||
try:
|
||||
if coin_id == Coins.PART:
|
||||
txid = swap_client.withdrawParticl(type_from, type_to, value, address, subfee)
|
||||
messages.append('Withdrew {} {} ({} to {}) to address {}<br/>In txid: {}'.format(value, ticker, type_from, type_to, address, txid))
|
||||
except Exception as e:
|
||||
err_messages.append(str(e))
|
||||
else:
|
||||
try:
|
||||
elif coin_id == Coins.LTC:
|
||||
txid = swap_client.withdrawLTC(type_from, value, address, subfee)
|
||||
messages.append('Withdrew {} {} (from {}) to address {}<br/>In txid: {}'.format(value, ticker, type_from, address, txid))
|
||||
else:
|
||||
txid = swap_client.withdrawCoin(coin_id, value, address, subfee)
|
||||
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
|
||||
except Exception as e:
|
||||
err_messages.append(str(e))
|
||||
except Exception as e:
|
||||
err_messages.append(str(e))
|
||||
swap_client.updateWalletsInfo(True, coin_id)
|
||||
elif have_data_entry(form_data, 'showutxogroups'):
|
||||
show_utxo_groups = True
|
||||
|
@ -227,6 +239,8 @@ def page_wallet(self, url_split, post_string):
|
|||
|
||||
if k == Coins.XMR:
|
||||
wallet_data['main_address'] = w.get('main_address', 'Refresh necessary')
|
||||
elif k == Coins.LTC:
|
||||
wallet_data['mweb_address'] = w.get('mweb_address', 'Refresh necessary')
|
||||
|
||||
if 'wd_type_from_' + cid in page_data:
|
||||
wallet_data['wd_type_from'] = page_data['wd_type_from_' + cid]
|
||||
|
|
|
@ -419,6 +419,8 @@ def getCoinName(c):
|
|||
return chainparams[Coins.PART]['name'].capitalize() + ' Anon'
|
||||
if c == Coins.PART_BLIND:
|
||||
return chainparams[Coins.PART]['name'].capitalize() + ' Blind'
|
||||
if c == Coins.LTC_MWEB:
|
||||
return chainparams[Coins.LTC]['name'].capitalize() + ' MWEB'
|
||||
|
||||
coin_chainparams = chainparams[c]
|
||||
if coin_chainparams.get('use_ticker_as_name', False):
|
||||
|
@ -441,6 +443,11 @@ def listAvailableCoins(swap_client, with_variants=True, split_from=False):
|
|||
coins.append((int(v), getCoinName(v)))
|
||||
if split_from and v not in invalid_coins_from:
|
||||
coins_from.append(coins[-1])
|
||||
if with_variants and k == Coins.LTC:
|
||||
for v in (Coins.LTC_MWEB, ):
|
||||
coins.append((int(v), getCoinName(v)))
|
||||
if split_from and v not in invalid_coins_from:
|
||||
coins_from.append(coins[-1])
|
||||
if split_from:
|
||||
return coins_from, coins
|
||||
return coins
|
||||
|
|
|
@ -42,7 +42,7 @@ PARTICL_VERSION = os.getenv('PARTICL_VERSION', '23.2.7.0')
|
|||
PARTICL_VERSION_TAG = os.getenv('PARTICL_VERSION_TAG', '')
|
||||
PARTICL_LINUX_EXTRA = os.getenv('PARTICL_LINUX_EXTRA', 'nousb')
|
||||
|
||||
LITECOIN_VERSION = os.getenv('LITECOIN_VERSION', '0.21.2')
|
||||
LITECOIN_VERSION = os.getenv('LITECOIN_VERSION', '0.21.2.2')
|
||||
LITECOIN_VERSION_TAG = os.getenv('LITECOIN_VERSION_TAG', '')
|
||||
|
||||
BITCOIN_VERSION = os.getenv('BITCOIN_VERSION', '23.0')
|
||||
|
@ -602,7 +602,7 @@ def prepareCore(coin, version_data, settings, data_dir, extra_opts={}):
|
|||
assert_url = 'https://raw.githubusercontent.com/particl/gitian.sigs/master/%s-%s/%s/%s' % (version + version_tag, os_dir_name, signing_key_name, assert_filename)
|
||||
elif coin == 'litecoin':
|
||||
release_url = 'https://download.litecoin.org/litecoin-{}/{}/{}'.format(version, os_name, release_filename)
|
||||
assert_filename = '{}-core-{}-{}-build.assert'.format(coin, os_name, version.rsplit('.', 1)[0])
|
||||
assert_filename = '{}-core-{}-{}-build.assert'.format(coin, os_name, '.'.join(version.split('.')[:2]))
|
||||
assert_url = 'https://raw.githubusercontent.com/litecoin-project/gitian.sigs.ltc/master/%s-%s/%s/%s' % (version, os_dir_name, signing_key_name, assert_filename)
|
||||
elif coin == 'bitcoin':
|
||||
release_url = 'https://bitcoincore.org/bin/bitcoin-core-{}/{}'.format(version, release_filename)
|
||||
|
@ -1141,6 +1141,12 @@ def test_particl_encryption(data_dir, settings, chain, use_tor_proxy):
|
|||
finalise_daemon(d)
|
||||
|
||||
|
||||
def encrypt_wallet(swap_client, coin_type) -> None:
|
||||
ci = swap_client.ci(coin_type)
|
||||
ci.changeWalletPassword('', WALLET_ENCRYPTION_PWD)
|
||||
ci.unlockWallet(WALLET_ENCRYPTION_PWD)
|
||||
|
||||
|
||||
def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings, chain, use_tor_proxy):
|
||||
swap_client = None
|
||||
daemons = []
|
||||
|
@ -1185,16 +1191,18 @@ def initialise_wallets(particl_wallet_mnemonic, with_coins, data_dir, settings,
|
|||
if len(wallets) < 1:
|
||||
logger.info('Creating wallet.dat for {}.'.format(getCoinName(c)))
|
||||
|
||||
if c == Coins.BTC:
|
||||
if c in (Coins.BTC, Coins.LTC):
|
||||
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors
|
||||
swap_client.callcoinrpc(c, 'createwallet', ['wallet.dat', False, True, '', False, False])
|
||||
swap_client.callcoinrpc(c, 'createwallet', ['wallet.dat', False, True, WALLET_ENCRYPTION_PWD, False, False])
|
||||
swap_client.ci(c).unlockWallet(WALLET_ENCRYPTION_PWD)
|
||||
else:
|
||||
swap_client.callcoinrpc(c, 'createwallet', ['wallet.dat'])
|
||||
if WALLET_ENCRYPTION_PWD != '':
|
||||
encrypt_wallet(swap_client, c)
|
||||
|
||||
if WALLET_ENCRYPTION_PWD != '':
|
||||
ci = swap_client.ci(c)
|
||||
ci.changeWalletPassword('', WALLET_ENCRYPTION_PWD)
|
||||
ci.unlockWallet(WALLET_ENCRYPTION_PWD)
|
||||
if c == Coins.LTC:
|
||||
password = WALLET_ENCRYPTION_PWD if WALLET_ENCRYPTION_PWD != '' else None
|
||||
swap_client.ci(Coins.LTC_MWEB).init_wallet(password)
|
||||
|
||||
if c == Coins.PART:
|
||||
if 'particl' in with_coins:
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
|
||||
0.12.4
|
||||
==============
|
||||
|
||||
- LTC creates a new wallet to hold MWEB balance.
|
||||
- MWEB wallet should be be automatically created at startup or when unlocked if system is encrypted.
|
||||
|
||||
|
||||
0.12.3
|
||||
==============
|
||||
|
||||
|
|
|
@ -672,7 +672,7 @@ class Test(unittest.TestCase):
|
|||
# Verify expected inputs were used
|
||||
bid, offer = swap_clients[2].getBidAndOffer(bid_id)
|
||||
assert (bid.initiate_tx)
|
||||
wtx = ci_from.rpc_callback('gettransaction', [bid.initiate_tx.txid.hex(),])
|
||||
wtx = ci_from.rpc_wallet('gettransaction', [bid.initiate_tx.txid.hex(),])
|
||||
itx_after = ci_from.describeTx(wtx['hex'])
|
||||
assert (len(itx_after['vin']) == len(itx_decoded['vin']))
|
||||
for i, txin in enumerate(itx_decoded['vin']):
|
||||
|
|
|
@ -902,7 +902,7 @@ class Test(TestFunctions):
|
|||
# Verify expected inputs were used
|
||||
bid, offer = swap_clients[2].getBidAndOffer(bid_id)
|
||||
assert (bid.initiate_tx)
|
||||
wtx = ci_from.rpc_callback('gettransaction', [bid.initiate_tx.txid.hex(),])
|
||||
wtx = ci_from.rpc('gettransaction', [bid.initiate_tx.txid.hex(),])
|
||||
itx_after = ci_from.describeTx(wtx['hex'])
|
||||
assert (len(itx_after['vin']) == len(itx_decoded['vin']))
|
||||
for i, txin in enumerate(itx_decoded['vin']):
|
||||
|
|
|
@ -677,7 +677,7 @@ class Test(unittest.TestCase):
|
|||
# Verify expected inputs were used
|
||||
bid, offer = swap_clients[2].getBidAndOffer(bid_id)
|
||||
assert (bid.initiate_tx)
|
||||
wtx = ci_from.rpc_callback('gettransaction', [bid.initiate_tx.txid.hex(),])
|
||||
wtx = ci_from.rpc('gettransaction', [bid.initiate_tx.txid.hex(),])
|
||||
itx_after = ci_from.describeTx(wtx['hex'])
|
||||
assert (len(itx_after['vin']) == len(itx_decoded['vin']))
|
||||
for i, txin in enumerate(itx_decoded['vin']):
|
||||
|
|
|
@ -60,6 +60,16 @@ class TestFunctions(BaseTest):
|
|||
node_a_id = 0
|
||||
node_b_id = 1
|
||||
|
||||
def callnoderpc(self, method, params=[], wallet=None, node_id=0):
|
||||
return callnoderpc(node_id, method, params, wallet, self.base_rpc_port)
|
||||
|
||||
def mineBlock(self, num_blocks=1):
|
||||
self.callnoderpc('generatetoaddress', [num_blocks, self.btc_addr])
|
||||
|
||||
def check_softfork_active(self, feature_name):
|
||||
deploymentinfo = self.callnoderpc('getdeploymentinfo')
|
||||
assert (deploymentinfo['deployments'][feature_name]['active'] is True)
|
||||
|
||||
def getBalance(self, js_wallets, coin) -> float:
|
||||
if coin == Coins.PART_BLIND:
|
||||
coin_ticker: str = 'PART'
|
||||
|
@ -79,12 +89,6 @@ class TestFunctions(BaseTest):
|
|||
|
||||
return float(js_wallets[coin_ticker][balance_type]) + float(js_wallets[coin_ticker][unconfirmed_name])
|
||||
|
||||
def callnoderpc(self, method, params=[], wallet=None, node_id=0):
|
||||
return callnoderpc(node_id, method, params, wallet, self.base_rpc_port)
|
||||
|
||||
def mineBlock(self, num_blocks=1):
|
||||
self.callnoderpc('generatetoaddress', [num_blocks, self.btc_addr])
|
||||
|
||||
def prepare_balance(self, coin, amount: float, port_target_node: int, port_take_from_node: int, test_balance: bool = True) -> None:
|
||||
delay_iterations = 100 if coin == Coins.NAV else 20
|
||||
delay_time = 5 if coin == Coins.NAV else 3
|
||||
|
@ -149,8 +153,8 @@ class TestFunctions(BaseTest):
|
|||
js_1 = read_json_api(1800 + id_bidder, 'wallets')
|
||||
node1_from_before: float = self.getBalance(js_1, coin_from)
|
||||
|
||||
node0_sent_messages_before: int = ci_part0.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
node1_sent_messages_before: int = ci_part1.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
node0_sent_messages_before: int = ci_part0.rpc('smsgoutbox', ['count',])['num_messages']
|
||||
node1_sent_messages_before: int = ci_part1.rpc('smsgoutbox', ['count',])['num_messages']
|
||||
|
||||
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
|
||||
|
@ -224,8 +228,8 @@ class TestFunctions(BaseTest):
|
|||
if False: # TODO: set stakeaddress and xmr rewards to non wallet addresses
|
||||
assert (node1_to_after < node1_to_before - amount_to_float)
|
||||
|
||||
node0_sent_messages_after: int = ci_part0.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
node1_sent_messages_after: int = ci_part1.rpc_callback('smsgoutbox', ['count',])['num_messages']
|
||||
node0_sent_messages_after: int = ci_part0.rpc('smsgoutbox', ['count',])['num_messages']
|
||||
node1_sent_messages_after: int = ci_part1.rpc('smsgoutbox', ['count',])['num_messages']
|
||||
node0_sent_messages: int = node0_sent_messages_after - node0_sent_messages_before
|
||||
node1_sent_messages: int = node1_sent_messages_after - node1_sent_messages_before
|
||||
split_msgs: int = 2 if (ci_from.curve_type() != Curves.secp256k1 or ci_to.curve_type() != Curves.secp256k1) else 0
|
||||
|
@ -434,21 +438,22 @@ class BasicSwapTest(TestFunctions):
|
|||
def test_001_nested_segwit(self):
|
||||
# p2sh-p2wpkh
|
||||
logging.info('---------- Test {} p2sh nested segwit'.format(self.test_coin_from.name))
|
||||
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||
|
||||
addr_p2sh_segwit = self.callnoderpc('getnewaddress', ['segwit test', 'p2sh-segwit'])
|
||||
addr_info = self.callnoderpc('getaddressinfo', [addr_p2sh_segwit, ])
|
||||
addr_p2sh_segwit = ci.rpc_wallet('getnewaddress', ['segwit test', 'p2sh-segwit'])
|
||||
addr_info = ci.rpc_wallet('getaddressinfo', [addr_p2sh_segwit, ])
|
||||
assert addr_info['script'] == 'witness_v0_keyhash'
|
||||
|
||||
txid = self.callnoderpc('sendtoaddress', [addr_p2sh_segwit, 1.0])
|
||||
txid = ci.rpc_wallet('sendtoaddress', [addr_p2sh_segwit, 1.0])
|
||||
assert len(txid) == 64
|
||||
|
||||
self.mineBlock()
|
||||
ro = self.callnoderpc('scantxoutset', ['start', ['addr({})'.format(addr_p2sh_segwit)]])
|
||||
ro = ci.rpc('scantxoutset', ['start', ['addr({})'.format(addr_p2sh_segwit)]])
|
||||
assert (len(ro['unspents']) == 1)
|
||||
assert (ro['unspents'][0]['txid'] == txid)
|
||||
|
||||
tx_wallet = self.callnoderpc('gettransaction', [txid, ])['hex']
|
||||
tx = self.callnoderpc('decoderawtransaction', [tx_wallet, ])
|
||||
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])['hex']
|
||||
tx = ci.rpc('decoderawtransaction', [tx_wallet, ])
|
||||
|
||||
prevout_n = -1
|
||||
for txo in tx['vout']:
|
||||
|
@ -457,14 +462,14 @@ class BasicSwapTest(TestFunctions):
|
|||
break
|
||||
assert prevout_n > -1
|
||||
|
||||
tx_funded = self.callnoderpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_p2sh_segwit: 0.99}])
|
||||
tx_signed = self.callnoderpc('signrawtransactionwithwallet', [tx_funded, ])['hex']
|
||||
tx_funded_decoded = self.callnoderpc('decoderawtransaction', [tx_funded, ])
|
||||
tx_signed_decoded = self.callnoderpc('decoderawtransaction', [tx_signed, ])
|
||||
tx_funded = ci.rpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_p2sh_segwit: 0.99}])
|
||||
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded, ])['hex']
|
||||
tx_funded_decoded = ci.rpc('decoderawtransaction', [tx_funded, ])
|
||||
tx_signed_decoded = ci.rpc('decoderawtransaction', [tx_signed, ])
|
||||
assert tx_funded_decoded['txid'] != tx_signed_decoded['txid']
|
||||
|
||||
# Add scriptsig for txids to match
|
||||
addr_p2sh_segwit_info = self.callnoderpc('getaddressinfo', [addr_p2sh_segwit, ])
|
||||
addr_p2sh_segwit_info = ci.rpc_wallet('getaddressinfo', [addr_p2sh_segwit, ])
|
||||
decoded_tx = FromHex(CTransaction(), tx_funded)
|
||||
decoded_tx.vin[0].scriptSig = bytes.fromhex('16' + addr_p2sh_segwit_info['hex'])
|
||||
txid_with_scriptsig = decoded_tx.rehash()
|
||||
|
@ -473,18 +478,19 @@ class BasicSwapTest(TestFunctions):
|
|||
def test_002_native_segwit(self):
|
||||
# p2wpkh
|
||||
logging.info('---------- Test {} p2sh native segwit'.format(self.test_coin_from.name))
|
||||
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||
|
||||
addr_segwit = self.callnoderpc('getnewaddress', ['segwit test', 'bech32'])
|
||||
addr_info = self.callnoderpc('getaddressinfo', [addr_segwit, ])
|
||||
addr_segwit = ci.rpc_wallet('getnewaddress', ['segwit test', 'bech32'])
|
||||
addr_info = ci.rpc_wallet('getaddressinfo', [addr_segwit, ])
|
||||
assert addr_info['iswitness'] is True
|
||||
|
||||
txid = self.callnoderpc('sendtoaddress', [addr_segwit, 1.0])
|
||||
txid = ci.rpc_wallet('sendtoaddress', [addr_segwit, 1.0])
|
||||
assert len(txid) == 64
|
||||
tx_wallet = self.callnoderpc('gettransaction', [txid, ])['hex']
|
||||
tx = self.callnoderpc('decoderawtransaction', [tx_wallet, ])
|
||||
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])['hex']
|
||||
tx = ci.rpc('decoderawtransaction', [tx_wallet, ])
|
||||
|
||||
self.mineBlock()
|
||||
ro = self.callnoderpc('scantxoutset', ['start', ['addr({})'.format(addr_segwit)]])
|
||||
ro = ci.rpc('scantxoutset', ['start', ['addr({})'.format(addr_segwit)]])
|
||||
assert (len(ro['unspents']) == 1)
|
||||
assert (ro['unspents'][0]['txid'] == txid)
|
||||
|
||||
|
@ -495,19 +501,17 @@ class BasicSwapTest(TestFunctions):
|
|||
break
|
||||
assert prevout_n > -1
|
||||
|
||||
tx_funded = self.callnoderpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_segwit: 0.99}])
|
||||
tx_signed = self.callnoderpc('signrawtransactionwithwallet', [tx_funded, ])['hex']
|
||||
tx_funded_decoded = self.callnoderpc('decoderawtransaction', [tx_funded, ])
|
||||
tx_signed_decoded = self.callnoderpc('decoderawtransaction', [tx_signed, ])
|
||||
tx_funded = ci.rpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_segwit: 0.99}])
|
||||
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded, ])['hex']
|
||||
tx_funded_decoded = ci.rpc('decoderawtransaction', [tx_funded, ])
|
||||
tx_signed_decoded = ci.rpc('decoderawtransaction', [tx_signed, ])
|
||||
assert tx_funded_decoded['txid'] == tx_signed_decoded['txid']
|
||||
|
||||
def test_003_cltv(self):
|
||||
logging.info('---------- Test {} cltv'.format(self.test_coin_from.name))
|
||||
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||
|
||||
deploymentinfo = self.callnoderpc('getdeploymentinfo')
|
||||
bip65_active = deploymentinfo['deployments']['bip65']['active']
|
||||
assert (bip65_active)
|
||||
self.check_softfork_active('bip65')
|
||||
|
||||
chain_height = self.callnoderpc('getblockcount')
|
||||
script = CScript([chain_height + 3, OP_CHECKLOCKTIMEVERIFY, ])
|
||||
|
@ -517,12 +521,12 @@ class BasicSwapTest(TestFunctions):
|
|||
tx.nVersion = ci.txVersion()
|
||||
tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest))
|
||||
tx_hex = ToHex(tx)
|
||||
tx_funded = self.callnoderpc('fundrawtransaction', [tx_hex])
|
||||
tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex])
|
||||
utxo_pos = 0 if tx_funded['changepos'] == 1 else 1
|
||||
tx_signed = self.callnoderpc('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
|
||||
txid = self.callnoderpc('sendrawtransaction', [tx_signed, ])
|
||||
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
|
||||
txid = ci.rpc('sendrawtransaction', [tx_signed, ])
|
||||
|
||||
addr_out = self.callnoderpc('getnewaddress', ['cltv test', 'bech32'])
|
||||
addr_out = ci.rpc_wallet('getnewaddress', ['cltv test', 'bech32'])
|
||||
pkh = ci.decodeSegwitAddress(addr_out)
|
||||
script_out = ci.getScriptForPubkeyHash(pkh)
|
||||
|
||||
|
@ -548,15 +552,15 @@ class BasicSwapTest(TestFunctions):
|
|||
|
||||
self.mineBlock(5)
|
||||
try:
|
||||
txid = self.callnoderpc('sendrawtransaction', [tx_spend_invalid_hex, ])
|
||||
txid = ci.rpc('sendrawtransaction', [tx_spend_invalid_hex, ])
|
||||
except Exception as e:
|
||||
assert ('Locktime requirement not satisfied' in str(e))
|
||||
else:
|
||||
assert False, 'Should fail'
|
||||
|
||||
txid = self.callnoderpc('sendrawtransaction', [tx_spend_hex, ])
|
||||
txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ])
|
||||
self.mineBlock()
|
||||
ro = self.callnoderpc('listreceivedbyaddress', [0, ])
|
||||
ro = ci.rpc_wallet('listreceivedbyaddress', [0, ])
|
||||
sum_addr = 0
|
||||
for entry in ro:
|
||||
if entry['address'] == addr_out:
|
||||
|
@ -564,7 +568,7 @@ class BasicSwapTest(TestFunctions):
|
|||
assert (sum_addr == 1.0999)
|
||||
|
||||
# Ensure tx was mined
|
||||
tx_wallet = self.callnoderpc('gettransaction', [txid, ])
|
||||
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])
|
||||
assert (len(tx_wallet['blockhash']) == 64)
|
||||
|
||||
def test_004_csv(self):
|
||||
|
@ -572,6 +576,8 @@ class BasicSwapTest(TestFunctions):
|
|||
swap_clients = self.swap_clients
|
||||
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||
|
||||
self.check_softfork_active('bip66')
|
||||
|
||||
script = CScript([3, OP_CHECKSEQUENCEVERIFY, ])
|
||||
|
||||
script_dest = ci.getScriptDest(script)
|
||||
|
@ -579,17 +585,17 @@ class BasicSwapTest(TestFunctions):
|
|||
tx.nVersion = ci.txVersion()
|
||||
tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest))
|
||||
tx_hex = ToHex(tx)
|
||||
tx_funded = self.callnoderpc('fundrawtransaction', [tx_hex])
|
||||
tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex])
|
||||
utxo_pos = 0 if tx_funded['changepos'] == 1 else 1
|
||||
tx_signed = self.callnoderpc('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
|
||||
txid = self.callnoderpc('sendrawtransaction', [tx_signed, ])
|
||||
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
|
||||
txid = ci.rpc('sendrawtransaction', [tx_signed, ])
|
||||
|
||||
addr_out = self.callnoderpc('getnewaddress', ['csv test', 'bech32'])
|
||||
addr_out = ci.rpc_wallet('getnewaddress', ['csv test', 'bech32'])
|
||||
pkh = ci.decodeSegwitAddress(addr_out)
|
||||
script_out = ci.getScriptForPubkeyHash(pkh)
|
||||
|
||||
# Double check output type
|
||||
prev_tx = self.callnoderpc('decoderawtransaction', [tx_signed, ])
|
||||
prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ])
|
||||
assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'witness_v0_scripthash')
|
||||
|
||||
tx_spend = CTransaction()
|
||||
|
@ -601,16 +607,16 @@ class BasicSwapTest(TestFunctions):
|
|||
tx_spend.wit.vtxinwit[0].scriptWitness.stack = [script, ]
|
||||
tx_spend_hex = ToHex(tx_spend)
|
||||
try:
|
||||
txid = self.callnoderpc('sendrawtransaction', [tx_spend_hex, ])
|
||||
txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ])
|
||||
except Exception as e:
|
||||
assert ('non-BIP68-final' in str(e))
|
||||
else:
|
||||
assert False, 'Should fail'
|
||||
|
||||
self.mineBlock(3)
|
||||
txid = self.callnoderpc('sendrawtransaction', [tx_spend_hex, ])
|
||||
txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ])
|
||||
self.mineBlock(1)
|
||||
ro = self.callnoderpc('listreceivedbyaddress', [0, ])
|
||||
ro = ci.rpc_wallet('listreceivedbyaddress', [0, ])
|
||||
sum_addr = 0
|
||||
for entry in ro:
|
||||
if entry['address'] == addr_out:
|
||||
|
@ -618,20 +624,22 @@ class BasicSwapTest(TestFunctions):
|
|||
assert (sum_addr == 1.0999)
|
||||
|
||||
# Ensure tx was mined
|
||||
tx_wallet = self.callnoderpc('gettransaction', [txid, ])
|
||||
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])
|
||||
assert (len(tx_wallet['blockhash']) == 64)
|
||||
|
||||
def test_005_watchonly(self):
|
||||
logging.info('---------- Test {} watchonly'.format(self.test_coin_from.name))
|
||||
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||
ci1 = self.swap_clients[1].ci(self.test_coin_from)
|
||||
|
||||
addr = self.callnoderpc('getnewaddress', ['watchonly test', 'bech32'])
|
||||
ro = self.callnoderpc('importaddress', [addr, '', False], node_id=1)
|
||||
txid = self.callnoderpc('sendtoaddress', [addr, 1.0])
|
||||
tx_hex = self.callnoderpc('getrawtransaction', [txid, ])
|
||||
self.callnoderpc('sendrawtransaction', [tx_hex, ], node_id=1)
|
||||
ro = self.callnoderpc('gettransaction', [txid, ], node_id=1)
|
||||
addr = ci.rpc_wallet('getnewaddress', ['watchonly test', 'bech32'])
|
||||
ro = ci1.rpc_wallet('importaddress', [addr, '', False])
|
||||
txid = ci.rpc_wallet('sendtoaddress', [addr, 1.0])
|
||||
tx_hex = ci.rpc('getrawtransaction', [txid, ])
|
||||
ci1.rpc_wallet('sendrawtransaction', [tx_hex, ])
|
||||
ro = ci1.rpc_wallet('gettransaction', [txid, ])
|
||||
assert (ro['txid'] == txid)
|
||||
balances = self.callnoderpc('getbalances', node_id=1)
|
||||
balances = ci1.rpc_wallet('getbalances')
|
||||
assert (balances['watchonly']['trusted'] + balances['watchonly']['untrusted_pending'] >= 1.0)
|
||||
|
||||
def test_006_getblock_verbosity(self):
|
||||
|
@ -643,6 +651,7 @@ class BasicSwapTest(TestFunctions):
|
|||
|
||||
def test_007_hdwallet(self):
|
||||
logging.info('---------- Test {} hdwallet'.format(self.test_coin_from.name))
|
||||
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||
|
||||
test_seed = '8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b'
|
||||
test_wif = self.swap_clients[0].ci(self.test_coin_from).encodeKey(bytes.fromhex(test_seed))
|
||||
|
@ -657,7 +666,7 @@ class BasicSwapTest(TestFunctions):
|
|||
self.swap_clients[0].initialiseWallet(Coins.BTC, raise_errors=True)
|
||||
assert self.swap_clients[0].checkWalletSeed(Coins.BTC) is True
|
||||
for i in range(1500):
|
||||
self.callnoderpc('getnewaddress')
|
||||
ci.rpc_wallet('getnewaddress')
|
||||
assert self.swap_clients[0].checkWalletSeed(Coins.BTC) is True
|
||||
|
||||
rv = read_json_api(1800, 'getcoinseed', {'coin': 'XMR'})
|
||||
|
@ -667,38 +676,44 @@ class BasicSwapTest(TestFunctions):
|
|||
logging.info('---------- Test {} gettxout'.format(self.test_coin_from.name))
|
||||
|
||||
swap_client = self.swap_clients[0]
|
||||
ci = swap_client.ci(self.test_coin_from)
|
||||
|
||||
addr_1 = self.callnoderpc('getnewaddress', ['gettxout test 1',])
|
||||
txid = self.callnoderpc('sendtoaddress', [addr_1, 1.0])
|
||||
addr_1 = ci.rpc_wallet('getnewaddress', ['gettxout test 1',])
|
||||
txid = ci.rpc_wallet('sendtoaddress', [addr_1, 1.0])
|
||||
assert len(txid) == 64
|
||||
|
||||
self.mineBlock()
|
||||
|
||||
unspents = self.callnoderpc('listunspent', [0, 999999999, [addr_1,]])
|
||||
unspents = ci.rpc_wallet('listunspent', [0, 999999999, [addr_1,]])
|
||||
assert (len(unspents) == 1)
|
||||
|
||||
utxo = unspents[0]
|
||||
txout = self.callnoderpc('gettxout', [utxo['txid'], utxo['vout']])
|
||||
assert (addr_1 == txout['scriptPubKey']['address'])
|
||||
txout = ci.rpc('gettxout', [utxo['txid'], utxo['vout']])
|
||||
if 'address' in txout:
|
||||
assert (addr_1 == txout['scriptPubKey']['address'])
|
||||
else:
|
||||
assert (addr_1 in txout['scriptPubKey']['addresses'])
|
||||
# Spend
|
||||
addr_2 = self.callnoderpc('getnewaddress', ['gettxout test 2',])
|
||||
tx_funded = self.callnoderpc('createrawtransaction', [[{'txid': utxo['txid'], 'vout': utxo['vout']}], {addr_2: 0.99}])
|
||||
tx_signed = self.callnoderpc('signrawtransactionwithwallet', [tx_funded,])['hex']
|
||||
self.callnoderpc('sendrawtransaction', [tx_signed,])
|
||||
addr_2 = ci.rpc_wallet('getnewaddress', ['gettxout test 2',])
|
||||
tx_funded = ci.rpc('createrawtransaction', [[{'txid': utxo['txid'], 'vout': utxo['vout']}], {addr_2: 0.99}])
|
||||
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded,])['hex']
|
||||
ci.rpc('sendrawtransaction', [tx_signed,])
|
||||
|
||||
# utxo should be unavailable when spent in the mempool
|
||||
txout = self.callnoderpc('gettxout', [utxo['txid'], utxo['vout']])
|
||||
txout = ci.rpc('gettxout', [utxo['txid'], utxo['vout']])
|
||||
assert (txout is None)
|
||||
|
||||
def test_009_scantxoutset(self):
|
||||
logging.info('---------- Test {} scantxoutset'.format(self.test_coin_from.name))
|
||||
addr_1 = self.callnoderpc('getnewaddress', ['scantxoutset test', ])
|
||||
txid = self.callnoderpc('sendtoaddress', [addr_1, 1.0])
|
||||
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||
|
||||
addr_1 = ci.rpc_wallet('getnewaddress', ['scantxoutset test', ])
|
||||
txid = ci.rpc_wallet('sendtoaddress', [addr_1, 1.0])
|
||||
assert len(txid) == 64
|
||||
|
||||
self.mineBlock()
|
||||
|
||||
ro = self.callnoderpc('scantxoutset', ['start', ['addr({})'.format(addr_1)]])
|
||||
ro = ci.rpc('scantxoutset', ['start', ['addr({})'.format(addr_1)]])
|
||||
assert (len(ro['unspents']) == 1)
|
||||
assert (ro['unspents'][0]['txid'] == txid)
|
||||
|
||||
|
@ -712,7 +727,7 @@ class BasicSwapTest(TestFunctions):
|
|||
amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
|
||||
# Record unspents before createSCLockTx as the used ones will be locked
|
||||
unspents = self.callnoderpc('listunspent')
|
||||
unspents = ci.rpc_wallet('listunspent')
|
||||
|
||||
# fee_rate is in sats/kvB
|
||||
fee_rate: int = 1000
|
||||
|
@ -728,10 +743,10 @@ class BasicSwapTest(TestFunctions):
|
|||
lock_tx = ci.fundSCLockTx(lock_tx, fee_rate)
|
||||
lock_tx = ci.signTxWithWallet(lock_tx)
|
||||
|
||||
unspents_after = self.callnoderpc('listunspent')
|
||||
unspents_after = ci.rpc_wallet('listunspent')
|
||||
assert (len(unspents) > len(unspents_after))
|
||||
|
||||
tx_decoded = self.callnoderpc('decoderawtransaction', [lock_tx.hex()])
|
||||
tx_decoded = ci.rpc('decoderawtransaction', [lock_tx.hex()])
|
||||
txid = tx_decoded['txid']
|
||||
|
||||
vsize = tx_decoded['vsize']
|
||||
|
@ -752,8 +767,8 @@ class BasicSwapTest(TestFunctions):
|
|||
break
|
||||
fee_value = in_value - out_value
|
||||
|
||||
self.callnoderpc('sendrawtransaction', [lock_tx.hex()])
|
||||
rv = self.callnoderpc('gettransaction', [txid])
|
||||
ci.rpc('sendrawtransaction', [lock_tx.hex()])
|
||||
rv = ci.rpc_wallet('gettransaction', [txid])
|
||||
wallet_tx_fee = -ci.make_int(rv['fee'])
|
||||
|
||||
assert (wallet_tx_fee == fee_value)
|
||||
|
@ -765,7 +780,7 @@ class BasicSwapTest(TestFunctions):
|
|||
lock_spend_tx = ci.createSCLockSpendTx(lock_tx, lock_tx_script, pkh_out, fee_rate, fee_info=fee_info)
|
||||
vsize_estimated: int = fee_info['vsize']
|
||||
|
||||
tx_decoded = self.callnoderpc('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
txid = tx_decoded['txid']
|
||||
|
||||
witness_stack = [
|
||||
|
@ -775,11 +790,11 @@ class BasicSwapTest(TestFunctions):
|
|||
lock_tx_script,
|
||||
]
|
||||
lock_spend_tx = ci.setTxSignature(lock_spend_tx, witness_stack)
|
||||
tx_decoded = self.callnoderpc('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
vsize_actual: int = tx_decoded['vsize']
|
||||
|
||||
assert (vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 4)
|
||||
assert (self.callnoderpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid)
|
||||
assert (ci.rpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid)
|
||||
|
||||
expect_vsize: int = ci.xmr_swap_a_lock_spend_tx_vsize()
|
||||
assert (expect_vsize >= vsize_actual)
|
||||
|
@ -796,7 +811,7 @@ class BasicSwapTest(TestFunctions):
|
|||
lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid)
|
||||
if lock_tx_b_spend is None:
|
||||
lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid)
|
||||
lock_tx_b_spend_decoded = self.callnoderpc('decoderawtransaction', [lock_tx_b_spend.hex()])
|
||||
lock_tx_b_spend_decoded = ci.rpc('decoderawtransaction', [lock_tx_b_spend.hex()])
|
||||
|
||||
expect_vsize: int = ci.xmr_swap_b_lock_spend_tx_vsize()
|
||||
assert (expect_vsize >= lock_tx_b_spend_decoded['vsize'])
|
||||
|
@ -816,17 +831,17 @@ class BasicSwapTest(TestFunctions):
|
|||
tx.nVersion = ci.txVersion()
|
||||
tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest))
|
||||
tx_hex = ToHex(tx)
|
||||
tx_funded = self.callnoderpc('fundrawtransaction', [tx_hex])
|
||||
tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex])
|
||||
utxo_pos = 0 if tx_funded['changepos'] == 1 else 1
|
||||
tx_signed = self.callnoderpc('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
|
||||
txid = self.callnoderpc('sendrawtransaction', [tx_signed, ])
|
||||
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
|
||||
txid = ci.rpc('sendrawtransaction', [tx_signed, ])
|
||||
|
||||
addr_out = self.callnoderpc('getnewaddress', ['csv test', 'bech32'])
|
||||
addr_out = ci.rpc_wallet('getnewaddress', ['csv test', 'bech32'])
|
||||
pkh = ci.decodeSegwitAddress(addr_out)
|
||||
script_out = ci.getScriptForPubkeyHash(pkh)
|
||||
|
||||
# Double check output type
|
||||
prev_tx = self.callnoderpc('decoderawtransaction', [tx_signed, ])
|
||||
prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ])
|
||||
assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash')
|
||||
|
||||
tx_spend = CTransaction()
|
||||
|
@ -836,9 +851,9 @@ class BasicSwapTest(TestFunctions):
|
|||
tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out))
|
||||
tx_spend_hex = ToHex(tx_spend)
|
||||
|
||||
txid = self.callnoderpc('sendrawtransaction', [tx_spend_hex, ])
|
||||
txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ])
|
||||
self.mineBlock(1)
|
||||
ro = self.callnoderpc('listreceivedbyaddress', [0, ])
|
||||
ro = ci.rpc_wallet('listreceivedbyaddress', [0, ])
|
||||
sum_addr = 0
|
||||
for entry in ro:
|
||||
if entry['address'] == addr_out:
|
||||
|
@ -846,7 +861,7 @@ class BasicSwapTest(TestFunctions):
|
|||
assert (sum_addr == 1.0999)
|
||||
|
||||
# Ensure tx was mined
|
||||
tx_wallet = self.callnoderpc('gettransaction', [txid, ])
|
||||
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])
|
||||
assert (len(tx_wallet['blockhash']) == 64)
|
||||
|
||||
def test_012_p2sh_p2wsh(self):
|
||||
|
@ -863,17 +878,17 @@ class BasicSwapTest(TestFunctions):
|
|||
tx.nVersion = ci.txVersion()
|
||||
tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest))
|
||||
tx_hex = ToHex(tx)
|
||||
tx_funded = self.callnoderpc('fundrawtransaction', [tx_hex])
|
||||
tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex])
|
||||
utxo_pos = 0 if tx_funded['changepos'] == 1 else 1
|
||||
tx_signed = self.callnoderpc('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
|
||||
txid = self.callnoderpc('sendrawtransaction', [tx_signed, ])
|
||||
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
|
||||
txid = ci.rpc('sendrawtransaction', [tx_signed, ])
|
||||
|
||||
addr_out = self.callnoderpc('getnewaddress', ['csv test', 'bech32'])
|
||||
addr_out = ci.rpc_wallet('getnewaddress', ['csv test', 'bech32'])
|
||||
pkh = ci.decodeSegwitAddress(addr_out)
|
||||
script_out = ci.getScriptForPubkeyHash(pkh)
|
||||
|
||||
# Double check output type
|
||||
prev_tx = self.callnoderpc('decoderawtransaction', [tx_signed, ])
|
||||
prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ])
|
||||
assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash')
|
||||
|
||||
tx_spend = CTransaction()
|
||||
|
@ -885,9 +900,9 @@ class BasicSwapTest(TestFunctions):
|
|||
tx_spend.wit.vtxinwit[0].scriptWitness.stack = [script, ]
|
||||
tx_spend_hex = ToHex(tx_spend)
|
||||
|
||||
txid = self.callnoderpc('sendrawtransaction', [tx_spend_hex, ])
|
||||
txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ])
|
||||
self.mineBlock(1)
|
||||
ro = self.callnoderpc('listreceivedbyaddress', [0, ])
|
||||
ro = ci.rpc_wallet('listreceivedbyaddress', [0, ])
|
||||
sum_addr = 0
|
||||
for entry in ro:
|
||||
if entry['address'] == addr_out:
|
||||
|
@ -895,7 +910,7 @@ class BasicSwapTest(TestFunctions):
|
|||
assert (sum_addr == 1.0999)
|
||||
|
||||
# Ensure tx was mined
|
||||
tx_wallet = self.callnoderpc('gettransaction', [txid, ])
|
||||
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])
|
||||
assert (len(tx_wallet['blockhash']) == 64)
|
||||
|
||||
def test_01_a_full_swap(self):
|
||||
|
@ -1045,7 +1060,7 @@ class BasicSwapTest(TestFunctions):
|
|||
# Verify expected inputs were used
|
||||
bid, _, _, _, _ = swap_clients[2].getXmrBidAndOffer(bid_id)
|
||||
assert (bid.xmr_a_lock_tx)
|
||||
wtx = ci.rpc_callback('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),])
|
||||
wtx = ci.rpc_wallet('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),])
|
||||
itx_after = ci.describeTx(wtx['hex'])
|
||||
assert (len(itx_after['vin']) == len(itx_decoded['vin']))
|
||||
for i, txin in enumerate(itx_decoded['vin']):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2021-2022 tecnovert
|
||||
# Copyright (c) 2021-2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -24,9 +24,10 @@ from tests.basicswap.common import (
|
|||
wait_for_bid,
|
||||
wait_for_offer,
|
||||
wait_for_in_progress,
|
||||
TEST_HTTP_PORT,
|
||||
LTC_BASE_RPC_PORT,
|
||||
)
|
||||
from .test_btc_xmr import BasicSwapTest, test_delay_event
|
||||
from .test_btc_xmr import BasicSwapTest, test_delay_event, callnoderpc
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
@ -37,9 +38,20 @@ class TestLTC(BasicSwapTest):
|
|||
start_ltc_nodes = True
|
||||
base_rpc_port = LTC_BASE_RPC_PORT
|
||||
|
||||
@classmethod
|
||||
def prepareExtraCoins(cls):
|
||||
logging.info('Mining {} chain to height 1352 to activate CVS (BIP66)'.format(cls.test_coin_from.name))
|
||||
chain_height = callnoderpc(0, 'getblockcount', base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
num_blocks: int = 1352 - chain_height
|
||||
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
|
||||
def mineBlock(self, num_blocks=1):
|
||||
self.callnoderpc('generatetoaddress', [num_blocks, self.ltc_addr])
|
||||
|
||||
def check_softfork_active(self, feature_name):
|
||||
deploymentinfo = self.callnoderpc('getblockchaininfo')
|
||||
assert (deploymentinfo['softforks'][feature_name]['active'] is True)
|
||||
|
||||
def test_001_nested_segwit(self):
|
||||
logging.info('---------- Test {} p2sh nested segwit'.format(self.test_coin_from.name))
|
||||
logging.info('Skipped')
|
||||
|
@ -47,17 +59,18 @@ class TestLTC(BasicSwapTest):
|
|||
def test_002_native_segwit(self):
|
||||
logging.info('---------- Test {} p2sh native segwit'.format(self.test_coin_from.name))
|
||||
|
||||
addr_segwit = self.callnoderpc('getnewaddress', ['segwit test', 'bech32'])
|
||||
addr_info = self.callnoderpc('getaddressinfo', [addr_segwit, ])
|
||||
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||
addr_segwit = ci.rpc_wallet('getnewaddress', ['segwit test', 'bech32'])
|
||||
addr_info = ci.rpc_wallet('getaddressinfo', [addr_segwit, ])
|
||||
assert addr_info['iswitness'] is True
|
||||
|
||||
txid = self.callnoderpc('sendtoaddress', [addr_segwit, 1.0])
|
||||
txid = ci.rpc_wallet('sendtoaddress', [addr_segwit, 1.0])
|
||||
assert len(txid) == 64
|
||||
tx_wallet = self.callnoderpc('gettransaction', [txid, ])['hex']
|
||||
tx = self.callnoderpc('decoderawtransaction', [tx_wallet, ])
|
||||
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])['hex']
|
||||
tx = ci.rpc('decoderawtransaction', [tx_wallet, ])
|
||||
|
||||
self.mineBlock()
|
||||
ro = self.callnoderpc('scantxoutset', ['start', ['addr({})'.format(addr_segwit)]])
|
||||
ro = ci.rpc('scantxoutset', ['start', ['addr({})'.format(addr_segwit)]])
|
||||
assert (len(ro['unspents']) == 1)
|
||||
assert (ro['unspents'][0]['txid'] == txid)
|
||||
|
||||
|
@ -68,10 +81,10 @@ class TestLTC(BasicSwapTest):
|
|||
break
|
||||
assert prevout_n > -1
|
||||
|
||||
tx_funded = self.callnoderpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_segwit: 0.99}])
|
||||
tx_signed = self.callnoderpc('signrawtransactionwithwallet', [tx_funded, ])['hex']
|
||||
tx_funded_decoded = self.callnoderpc('decoderawtransaction', [tx_funded, ])
|
||||
tx_signed_decoded = self.callnoderpc('decoderawtransaction', [tx_signed, ])
|
||||
tx_funded = ci.rpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_segwit: 0.99}])
|
||||
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded, ])['hex']
|
||||
tx_funded_decoded = ci.rpc('decoderawtransaction', [tx_funded, ])
|
||||
tx_signed_decoded = ci.rpc('decoderawtransaction', [tx_signed, ])
|
||||
assert tx_funded_decoded['txid'] == tx_signed_decoded['txid']
|
||||
|
||||
def test_007_hdwallet(self):
|
||||
|
@ -108,6 +121,115 @@ class TestLTC(BasicSwapTest):
|
|||
assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0)
|
||||
assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0)
|
||||
|
||||
def test_21_mweb(self):
|
||||
logging.info('---------- Test MWEB {}'.format(self.test_coin_from.name))
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
ci0 = swap_clients[0].ci(self.test_coin_from)
|
||||
ci1 = swap_clients[1].ci(self.test_coin_from)
|
||||
|
||||
mweb_addr_0 = ci0.rpc_wallet('getnewaddress', ['mweb addr test 0', 'mweb'])
|
||||
mweb_addr_1 = ci1.rpc_wallet('getnewaddress', ['mweb addr test 1', 'mweb'])
|
||||
|
||||
addr_info0 = ci0.rpc_wallet('getaddressinfo', [mweb_addr_0,])
|
||||
assert (addr_info0['ismweb'] is True)
|
||||
|
||||
addr_info1 = ci1.rpc_wallet('getaddressinfo', [mweb_addr_1,])
|
||||
assert (addr_info1['ismweb'] is True)
|
||||
|
||||
txid = ci0.rpc_wallet('sendtoaddress', [mweb_addr_0, 10.0])
|
||||
|
||||
self.mineBlock()
|
||||
|
||||
txns = ci0.rpc_wallet('listtransactions')
|
||||
|
||||
utxos = ci0.rpc_wallet('listunspent')
|
||||
balances = ci0.rpc_wallet('getbalances')
|
||||
wi = ci0.rpc_wallet('getwalletinfo')
|
||||
|
||||
txid = ci0.rpc_wallet('sendtoaddress', [mweb_addr_1, 10.0])
|
||||
|
||||
self.mineBlock()
|
||||
|
||||
txns = ci1.rpc_wallet('listtransactions')
|
||||
|
||||
utxos = ci1.rpc_wallet('listunspent')
|
||||
balances = ci1.rpc_wallet('getbalances')
|
||||
wi = ci1.rpc_wallet('getwalletinfo')
|
||||
|
||||
mweb_tx = None
|
||||
for utxo in utxos:
|
||||
if utxo.get('address', '') == mweb_addr_1:
|
||||
mweb_tx = utxo
|
||||
assert (mweb_tx is not None)
|
||||
|
||||
tx = ci1.rpc_wallet('gettransaction', [mweb_tx['txid'],])
|
||||
|
||||
blockhash = tx['blockhash']
|
||||
block = ci1.rpc('getblock', [blockhash, 3])
|
||||
block = ci1.rpc('getblock', [blockhash, 0])
|
||||
|
||||
# TODO
|
||||
|
||||
def test_22_mweb_balance(self):
|
||||
logging.info('---------- Test MWEB balance {}'.format(self.test_coin_from.name))
|
||||
swap_clients = self.swap_clients
|
||||
|
||||
ci_mweb = swap_clients[0].ci(Coins.LTC_MWEB)
|
||||
mweb_addr_0 = ci_mweb.getNewAddress()
|
||||
addr_info0 = ci_mweb.rpc_wallet('getaddressinfo', [mweb_addr_0,])
|
||||
assert (addr_info0['ismweb'] is True)
|
||||
|
||||
ltc_addr = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/nextdepositaddr')
|
||||
ltc_mweb_addr = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc_mweb/nextdepositaddr')
|
||||
ltc_mweb_addr2 = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/newmwebaddress')
|
||||
|
||||
assert (ci_mweb.rpc_wallet('getaddressinfo', [ltc_addr,])['ismweb'] is False)
|
||||
assert (ci_mweb.rpc_wallet('getaddressinfo', [ltc_mweb_addr,])['ismweb'] is True)
|
||||
assert (ci_mweb.rpc_wallet('getaddressinfo', [ltc_mweb_addr2,])['ismweb'] is True)
|
||||
|
||||
post_json = {
|
||||
'value': 10,
|
||||
'address': ltc_mweb_addr,
|
||||
'subfee': False,
|
||||
}
|
||||
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json)
|
||||
assert (len(json_rv['txid']) == 64)
|
||||
|
||||
self.mineBlock()
|
||||
|
||||
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc', post_json)
|
||||
assert (json_rv['mweb_balance'] == 10.0)
|
||||
mweb_address = json_rv['mweb_address']
|
||||
|
||||
post_json = {
|
||||
'value': 11,
|
||||
'address': mweb_address,
|
||||
'subfee': False,
|
||||
}
|
||||
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json)
|
||||
assert (len(json_rv['txid']) == 64)
|
||||
|
||||
self.mineBlock()
|
||||
|
||||
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc_mweb', post_json)
|
||||
assert (json_rv['mweb_balance'] == 21.0)
|
||||
assert (json_rv['mweb_address'] == mweb_address)
|
||||
ltc_address = json_rv['deposit_address']
|
||||
|
||||
# Check that spending the mweb balance takes from the correct wallet
|
||||
post_json = {
|
||||
'value': 1,
|
||||
'address': ltc_address,
|
||||
'subfee': False,
|
||||
'type_from': 'mweb',
|
||||
}
|
||||
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json)
|
||||
assert (len(json_rv['txid']) == 64)
|
||||
|
||||
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc', post_json)
|
||||
assert (json_rv['mweb_balance'] <= 20.0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -101,7 +101,7 @@ class Test(BaseTest):
|
|||
nonlocal ci
|
||||
i = 0
|
||||
while not delay_event.is_set():
|
||||
unspents = ci.rpc_callback('listunspentblind')
|
||||
unspents = ci.rpc_wallet('listunspentblind')
|
||||
if len(unspents) >= 1:
|
||||
return
|
||||
delay_event.wait(delay_time)
|
||||
|
@ -113,8 +113,8 @@ class Test(BaseTest):
|
|||
amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
|
||||
# Record unspents before createSCLockTx as the used ones will be locked
|
||||
unspents = ci.rpc_callback('listunspentblind')
|
||||
locked_utxos_before = ci.rpc_callback('listlockunspent')
|
||||
unspents = ci.rpc_wallet('listunspentblind')
|
||||
locked_utxos_before = ci.rpc_wallet('listlockunspent')
|
||||
|
||||
# fee_rate is in sats/kvB
|
||||
fee_rate: int = 1000
|
||||
|
@ -131,33 +131,33 @@ class Test(BaseTest):
|
|||
lock_tx = ci.fundSCLockTx(lock_tx, fee_rate, vkbv)
|
||||
lock_tx = ci.signTxWithWallet(lock_tx)
|
||||
|
||||
unspents_after = ci.rpc_callback('listunspentblind')
|
||||
locked_utxos_after = ci.rpc_callback('listlockunspent')
|
||||
unspents_after = ci.rpc_wallet('listunspentblind')
|
||||
locked_utxos_after = ci.rpc_wallet('listlockunspent')
|
||||
|
||||
assert (len(unspents) > len(unspents_after))
|
||||
assert (len(locked_utxos_after) > len(locked_utxos_before))
|
||||
lock_tx_decoded = ci.rpc_callback('decoderawtransaction', [lock_tx.hex()])
|
||||
lock_tx_decoded = ci.rpc_wallet('decoderawtransaction', [lock_tx.hex()])
|
||||
txid = lock_tx_decoded['txid']
|
||||
|
||||
vsize = lock_tx_decoded['vsize']
|
||||
expect_fee_int = round(fee_rate * vsize / 1000)
|
||||
expect_fee = ci.format_amount(expect_fee_int)
|
||||
|
||||
ci.rpc_callback('sendrawtransaction', [lock_tx.hex()])
|
||||
rv = ci.rpc_callback('gettransaction', [txid])
|
||||
ci.rpc_wallet('sendrawtransaction', [lock_tx.hex()])
|
||||
rv = ci.rpc_wallet('gettransaction', [txid])
|
||||
wallet_tx_fee = -ci.make_int(rv['details'][0]['fee'])
|
||||
|
||||
assert (wallet_tx_fee >= expect_fee_int)
|
||||
assert (wallet_tx_fee - expect_fee_int < 20)
|
||||
|
||||
addr_out = ci.getNewAddress(True)
|
||||
addrinfo = ci.rpc_callback('getaddressinfo', [addr_out,])
|
||||
addrinfo = ci.rpc_wallet('getaddressinfo', [addr_out,])
|
||||
pk_out = bytes.fromhex(addrinfo['pubkey'])
|
||||
fee_info = {}
|
||||
lock_spend_tx = ci.createSCLockSpendTx(lock_tx, lock_tx_script, pk_out, fee_rate, vkbv, fee_info=fee_info)
|
||||
vsize_estimated: int = fee_info['vsize']
|
||||
|
||||
spend_tx_decoded = ci.rpc_callback('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
spend_tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
txid = spend_tx_decoded['txid']
|
||||
|
||||
nonce = ci.getScriptLockTxNonce(vkbv)
|
||||
|
@ -172,12 +172,12 @@ class Test(BaseTest):
|
|||
lock_tx_script,
|
||||
]
|
||||
lock_spend_tx = ci.setTxSignature(lock_spend_tx, witness_stack)
|
||||
tx_decoded = ci.rpc_callback('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
vsize_actual: int = tx_decoded['vsize']
|
||||
|
||||
# Note: The fee is set allowing 9 bytes for the encoded fee amount, causing a small overestimate
|
||||
assert (vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 10)
|
||||
assert (ci.rpc_callback('sendrawtransaction', [lock_spend_tx.hex()]) == txid)
|
||||
assert (ci.rpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid)
|
||||
|
||||
# Test chain b (no-script) lock tx size
|
||||
v = ci.getNewSecretKey()
|
||||
|
@ -198,7 +198,7 @@ class Test(BaseTest):
|
|||
lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid)
|
||||
if lock_tx_b_spend is None:
|
||||
lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid)
|
||||
lock_tx_b_spend_decoded = ci.rpc_callback('decoderawtransaction', [lock_tx_b_spend.hex()])
|
||||
lock_tx_b_spend_decoded = ci.rpc('decoderawtransaction', [lock_tx_b_spend.hex()])
|
||||
|
||||
expect_vsize: int = ci.xmr_swap_b_lock_spend_tx_vsize()
|
||||
assert (expect_vsize >= lock_tx_b_spend_decoded['vsize'])
|
||||
|
@ -472,7 +472,7 @@ class Test(BaseTest):
|
|||
# Verify expected inputs were used
|
||||
bid, _, _, _, _ = swap_clients[2].getXmrBidAndOffer(bid_id)
|
||||
assert (bid.xmr_a_lock_tx)
|
||||
wtx = ci.rpc_callback('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),])
|
||||
wtx = ci.rpc_wallet('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),])
|
||||
itx_after = ci.describeTx(wtx['hex'])
|
||||
assert (len(itx_after['vin']) == len(itx_decoded['vin']))
|
||||
for i, txin in enumerate(itx_decoded['vin']):
|
||||
|
|
|
@ -80,10 +80,10 @@ class Test(BaseTest):
|
|||
super(Test, cls).setUpClass()
|
||||
|
||||
btc_addr1 = callnoderpc(1, 'getnewaddress', ['initial funds', 'bech32'], base_rpc_port=BTC_BASE_RPC_PORT)
|
||||
ltc_addr1 = callnoderpc(1, 'getnewaddress', ['initial funds', 'bech32'], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
ltc_addr1 = callnoderpc(1, 'getnewaddress', ['initial funds', 'bech32'], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
|
||||
callnoderpc(0, 'sendtoaddress', [btc_addr1, 1000], base_rpc_port=BTC_BASE_RPC_PORT)
|
||||
callnoderpc(0, 'sendtoaddress', [ltc_addr1, 1000], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
callnoderpc(0, 'sendtoaddress', [ltc_addr1, 1000], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
|
||||
wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/btc', 'balance', 1000.0)
|
||||
wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/ltc', 'balance', 1000.0)
|
||||
|
@ -182,6 +182,9 @@ class Test(BaseTest):
|
|||
rv = read_json_api(1800, 'automationstrategies/1')
|
||||
assert (rv['label'] == 'Accept All')
|
||||
|
||||
sx_addr = read_json_api(1800, 'wallets/part/newstealthaddress')
|
||||
assert (callnoderpc(0, 'getaddressinfo', [sx_addr, ])['isstealthaddress'] is True)
|
||||
|
||||
def test_004_validateSwapType(self):
|
||||
logging.info('---------- Test validateSwapType')
|
||||
|
||||
|
@ -570,7 +573,7 @@ class Test(BaseTest):
|
|||
def test_12_withdrawal(self):
|
||||
logging.info('---------- Test LTC withdrawals')
|
||||
|
||||
ltc_addr = callnoderpc(0, 'getnewaddress', ['Withdrawal test', 'legacy'], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
ltc_addr = callnoderpc(0, 'getnewaddress', ['Withdrawal test', 'legacy'], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
wallets0 = read_json_api(TEST_HTTP_PORT + 0, 'wallets')
|
||||
assert (float(wallets0['LTC']['balance']) > 100)
|
||||
|
||||
|
@ -712,7 +715,7 @@ class Test(BaseTest):
|
|||
# Verify expected inputs were used
|
||||
bid, offer = swap_clients[2].getBidAndOffer(bid_id)
|
||||
assert (bid.initiate_tx)
|
||||
wtx = ci.rpc_callback('gettransaction', [bid.initiate_tx.txid.hex(),])
|
||||
wtx = ci.rpc('gettransaction', [bid.initiate_tx.txid.hex(),])
|
||||
itx_after = ci.describeTx(wtx['hex'])
|
||||
assert (len(itx_after['vin']) == len(itx_decoded['vin']))
|
||||
for i, txin in enumerate(itx_decoded['vin']):
|
||||
|
|
|
@ -530,29 +530,29 @@ class BaseTest(unittest.TestCase):
|
|||
|
||||
if cls.start_ltc_nodes:
|
||||
num_blocks = 400
|
||||
cls.ltc_addr = callnoderpc(0, 'getnewaddress', ['mining_addr', 'bech32'], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
cls.ltc_addr = callnoderpc(0, 'getnewaddress', ['mining_addr', 'bech32'], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
logging.info('Mining %d Litecoin blocks to %s', num_blocks, cls.ltc_addr)
|
||||
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
|
||||
num_blocks = 31
|
||||
cls.ltc_addr = cls.swap_clients[0].ci(Coins.LTC).pubkey_to_address(void_block_rewards_pubkey)
|
||||
logging.info('Mining %d Litecoin blocks to %s', num_blocks, cls.ltc_addr)
|
||||
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
|
||||
# https://github.com/litecoin-project/litecoin/issues/807
|
||||
# Block 432 is when MWEB activates. It requires a peg-in. You'll need to generate an mweb address and send some coins to it. Then it will allow you to mine the next block.
|
||||
mweb_addr = callnoderpc(2, 'getnewaddress', ['mweb_addr', 'mweb'], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
callnoderpc(0, 'sendtoaddress', [mweb_addr, 1], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
mweb_addr = callnoderpc(2, 'getnewaddress', ['mweb_addr', 'mweb'], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
callnoderpc(0, 'sendtoaddress', [mweb_addr, 1], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
|
||||
ltc_addr1 = callnoderpc(1, 'getnewaddress', ['initial addr'], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
ltc_addr1 = callnoderpc(1, 'getnewaddress', ['initial addr'], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
for i in range(5):
|
||||
callnoderpc(0, 'sendtoaddress', [ltc_addr1, 100], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
callnoderpc(0, 'sendtoaddress', [ltc_addr1, 100], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
|
||||
num_blocks = 69
|
||||
cls.ltc_addr = cls.swap_clients[0].ci(Coins.LTC).pubkey_to_address(void_block_rewards_pubkey)
|
||||
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT)
|
||||
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')
|
||||
|
||||
checkForks(callnoderpc(0, 'getblockchaininfo', base_rpc_port=LTC_BASE_RPC_PORT))
|
||||
checkForks(callnoderpc(0, 'getblockchaininfo', base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat'))
|
||||
|
||||
num_blocks = 100
|
||||
if cls.start_xmr_nodes:
|
||||
|
@ -682,7 +682,7 @@ class Test(BaseTest):
|
|||
amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1)
|
||||
|
||||
# Record unspents before createSCLockTx as the used ones will be locked
|
||||
unspents = ci.rpc_callback('listunspent')
|
||||
unspents = ci.rpc('listunspent')
|
||||
|
||||
# fee_rate is in sats/kvB
|
||||
fee_rate: int = 1000
|
||||
|
@ -698,10 +698,10 @@ class Test(BaseTest):
|
|||
lock_tx = ci.fundSCLockTx(lock_tx, fee_rate)
|
||||
lock_tx = ci.signTxWithWallet(lock_tx)
|
||||
|
||||
unspents_after = ci.rpc_callback('listunspent')
|
||||
unspents_after = ci.rpc('listunspent')
|
||||
assert (len(unspents) > len(unspents_after))
|
||||
|
||||
tx_decoded = ci.rpc_callback('decoderawtransaction', [lock_tx.hex()])
|
||||
tx_decoded = ci.rpc('decoderawtransaction', [lock_tx.hex()])
|
||||
txid = tx_decoded['txid']
|
||||
|
||||
vsize = tx_decoded['vsize']
|
||||
|
@ -722,8 +722,8 @@ class Test(BaseTest):
|
|||
break
|
||||
fee_value = in_value - out_value
|
||||
|
||||
ci.rpc_callback('sendrawtransaction', [lock_tx.hex()])
|
||||
rv = ci.rpc_callback('gettransaction', [txid])
|
||||
ci.rpc('sendrawtransaction', [lock_tx.hex()])
|
||||
rv = ci.rpc('gettransaction', [txid])
|
||||
wallet_tx_fee = -ci.make_int(rv['fee'])
|
||||
|
||||
assert (wallet_tx_fee == fee_value)
|
||||
|
@ -735,7 +735,7 @@ class Test(BaseTest):
|
|||
lock_spend_tx = ci.createSCLockSpendTx(lock_tx, lock_tx_script, pkh_out, fee_rate, fee_info=fee_info)
|
||||
vsize_estimated: int = fee_info['vsize']
|
||||
|
||||
tx_decoded = ci.rpc_callback('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
txid = tx_decoded['txid']
|
||||
|
||||
witness_stack = [
|
||||
|
@ -745,11 +745,11 @@ class Test(BaseTest):
|
|||
lock_tx_script,
|
||||
]
|
||||
lock_spend_tx = ci.setTxSignature(lock_spend_tx, witness_stack)
|
||||
tx_decoded = ci.rpc_callback('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()])
|
||||
vsize_actual: int = tx_decoded['vsize']
|
||||
|
||||
assert (vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 4)
|
||||
assert (ci.rpc_callback('sendrawtransaction', [lock_spend_tx.hex()]) == txid)
|
||||
assert (ci.rpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid)
|
||||
|
||||
expect_vsize: int = ci.xmr_swap_a_lock_spend_tx_vsize()
|
||||
assert (expect_vsize >= vsize_actual)
|
||||
|
@ -766,7 +766,7 @@ class Test(BaseTest):
|
|||
lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid)
|
||||
if lock_tx_b_spend is None:
|
||||
lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid)
|
||||
lock_tx_b_spend_decoded = ci.rpc_callback('decoderawtransaction', [lock_tx_b_spend.hex()])
|
||||
lock_tx_b_spend_decoded = ci.rpc('decoderawtransaction', [lock_tx_b_spend.hex()])
|
||||
|
||||
expect_vsize: int = ci.xmr_swap_b_lock_spend_tx_vsize()
|
||||
assert (expect_vsize >= lock_tx_b_spend_decoded['vsize'])
|
||||
|
@ -1354,7 +1354,7 @@ class Test(BaseTest):
|
|||
lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid)
|
||||
if lock_tx_b_spend is None:
|
||||
lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid)
|
||||
lock_tx_b_spend_decoded = ci.rpc_callback('decoderawtransaction', [lock_tx_b_spend.hex()])
|
||||
lock_tx_b_spend_decoded = ci.rpc('decoderawtransaction', [lock_tx_b_spend.hex()])
|
||||
|
||||
expect_vsize: int = ci.xmr_swap_b_lock_spend_tx_vsize()
|
||||
assert (expect_vsize >= lock_tx_b_spend_decoded['vsize'])
|
||||
|
@ -1501,7 +1501,7 @@ class Test(BaseTest):
|
|||
# Verify expected inputs were used
|
||||
bid, _, _, _, _ = swap_clients[2].getXmrBidAndOffer(bid_id)
|
||||
assert (bid.xmr_a_lock_tx)
|
||||
wtx = ci.rpc_callback('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),])
|
||||
wtx = ci.rpc('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),])
|
||||
itx_after = ci.describeTx(wtx['hex'])
|
||||
assert (len(itx_after['vin']) == len(itx_decoded['vin']))
|
||||
for i, txin in enumerate(itx_decoded['vin']):
|
||||
|
|
Loading…
Reference in a new issue