api: Add wallet lock/unlock commands and getcoinseed.
This commit is contained in:
parent
020a65db8a
commit
fc31615a97
@ -1,3 +1,3 @@
|
||||
name = "basicswap"
|
||||
|
||||
__version__ = "0.11.45"
|
||||
__version__ = "0.11.46"
|
||||
|
@ -41,9 +41,10 @@ from . import __version__
|
||||
from .rpc_xmr import make_xmr_rpc2_func
|
||||
from .ui.util import getCoinName
|
||||
from .util import (
|
||||
AutomationConstraint,
|
||||
LockedCoinError,
|
||||
TemporaryError,
|
||||
InactiveCoin,
|
||||
AutomationConstraint,
|
||||
format_amount,
|
||||
format_timestamp,
|
||||
DeserialiseNum,
|
||||
@ -679,11 +680,9 @@ class BasicSwap(BaseApp):
|
||||
raise ValueError('Could not stop {}'.format(str(coin)))
|
||||
|
||||
def stopDaemons(self):
|
||||
for c in Coins:
|
||||
if c not in chainparams:
|
||||
continue
|
||||
for c in self.activeCoins():
|
||||
chain_client_settings = self.getChainClientSettings(c)
|
||||
if self.coin_clients[c]['connection_type'] == 'rpc' and chain_client_settings['manage_daemon'] is True:
|
||||
if chain_client_settings['manage_daemon'] is True:
|
||||
self.stopDaemon(c)
|
||||
|
||||
def waitForDaemonRPC(self, coin_type, with_wallet=True):
|
||||
@ -710,6 +709,39 @@ class BasicSwap(BaseApp):
|
||||
if synced < 1.0:
|
||||
raise ValueError('{} chain is still syncing, currently at {}.'.format(self.coin_clients[c]['name'], synced))
|
||||
|
||||
def checkSystemStatus(self):
|
||||
ci = self.ci(Coins.PART)
|
||||
if ci.isWalletLocked():
|
||||
raise LockedCoinError(Coins.PART)
|
||||
|
||||
def activeCoins(self):
|
||||
for c in Coins:
|
||||
if c not in chainparams:
|
||||
continue
|
||||
chain_client_settings = self.getChainClientSettings(c)
|
||||
if self.coin_clients[c]['connection_type'] == 'rpc':
|
||||
yield c
|
||||
|
||||
def changeWalletPasswords(self, old_password, new_password):
|
||||
# Unlock all wallets to ensure they all have the same password.
|
||||
for c in self.activeCoins():
|
||||
ci = self.ci(c)
|
||||
try:
|
||||
ci.unlockWallet(old_password)
|
||||
except Exception as e:
|
||||
raise ValueError('Failed to unlock {}'.format(ci.coin_name()))
|
||||
|
||||
for c in self.activeCoins():
|
||||
self.ci(c).changeWalletPassword(old_password, new_password)
|
||||
|
||||
def unlockWallets(self, password):
|
||||
for c in self.activeCoins():
|
||||
self.ci(c).unlockWallet(password)
|
||||
|
||||
def lockWallets(self):
|
||||
for c in self.activeCoins():
|
||||
self.ci(c).lockWallet()
|
||||
|
||||
def initialiseWallet(self, coin_type, raise_errors=False):
|
||||
if coin_type == Coins.PART:
|
||||
return
|
||||
@ -5356,6 +5388,8 @@ class BasicSwap(BaseApp):
|
||||
'balance': format_amount(make_int(walletinfo['balance'], scale), scale),
|
||||
'unconfirmed': format_amount(make_int(walletinfo.get('unconfirmed_balance'), scale), scale),
|
||||
'expected_seed': ci.knownWalletSeed(),
|
||||
'encrypted': walletinfo['encrypted'],
|
||||
'locked': walletinfo['locked'],
|
||||
}
|
||||
|
||||
if coin == Coins.PART:
|
||||
@ -5428,16 +5462,13 @@ class BasicSwap(BaseApp):
|
||||
|
||||
def getWalletsInfo(self, opts=None):
|
||||
rv = {}
|
||||
for c in Coins:
|
||||
if c not in chainparams:
|
||||
continue
|
||||
if self.coin_clients[c]['connection_type'] == 'rpc':
|
||||
key = chainparams[c]['ticker'] if opts.get('ticker_key', False) else c
|
||||
try:
|
||||
rv[key] = self.getWalletInfo(c)
|
||||
rv[key].update(self.getBlockchainInfo(c))
|
||||
except Exception as ex:
|
||||
rv[key] = {'name': getCoinName(c), 'error': str(ex)}
|
||||
for c in self.activeCoins():
|
||||
key = chainparams[c]['ticker'] if opts.get('ticker_key', False) else c
|
||||
try:
|
||||
rv[key] = self.getWalletInfo(c)
|
||||
rv[key].update(self.getBlockchainInfo(c))
|
||||
except Exception as ex:
|
||||
rv[key] = {'name': getCoinName(c), 'error': str(ex)}
|
||||
return rv
|
||||
|
||||
def getCachedWalletsInfo(self, opts=None):
|
||||
@ -5480,17 +5511,14 @@ class BasicSwap(BaseApp):
|
||||
if opts is not None and 'coin_id' in opts:
|
||||
return rv
|
||||
|
||||
for c in Coins:
|
||||
if c not in chainparams:
|
||||
continue
|
||||
if self.coin_clients[c]['connection_type'] == 'rpc':
|
||||
coin_id = int(c)
|
||||
if coin_id not in rv:
|
||||
rv[coin_id] = {
|
||||
'name': getCoinName(c),
|
||||
'no_data': True,
|
||||
'updating': self._updating_wallets_info.get(coin_id, False),
|
||||
}
|
||||
for c in self.activeCoins():
|
||||
coin_id = int(c)
|
||||
if coin_id not in rv:
|
||||
rv[coin_id] = {
|
||||
'name': getCoinName(c),
|
||||
'no_data': True,
|
||||
'updating': self._updating_wallets_info.get(coin_id, False),
|
||||
}
|
||||
|
||||
return rv
|
||||
|
||||
|
@ -185,6 +185,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def page_explorers(self, url_split, post_string):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
result = None
|
||||
@ -231,6 +232,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def page_rpc(self, url_split, post_string):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
result = None
|
||||
@ -295,6 +297,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def page_debug(self, url_split, post_string):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
result = None
|
||||
@ -319,6 +322,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def page_active(self, url_split, post_string):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
active_swaps = swap_client.listSwapsInProgress()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
@ -331,6 +335,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def page_settings(self, url_split, post_string):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
messages = []
|
||||
@ -412,6 +417,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def page_watched(self, url_split, post_string):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
watched_outputs, last_scanned = swap_client.listWatchedOutputs()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
@ -425,6 +431,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def page_smsgaddresses(self, url_split, post_string):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
page_data = {}
|
||||
@ -502,6 +509,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
ensure(len(url_split) > 2, 'Address not specified')
|
||||
identity_address = url_split[2]
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
page_data = {'identity_address': identity_address}
|
||||
@ -557,6 +565,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def page_index(self, url_split):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
shutdown_token = os.urandom(8).hex()
|
||||
@ -587,6 +596,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
self.end_headers()
|
||||
|
||||
def handle_http(self, status_code, path, post_string='', is_json=False):
|
||||
swap_client = self.server.swap_client
|
||||
parsed = parse.urlparse(self.path)
|
||||
url_split = parsed.path.split('/')
|
||||
if post_string == '' and len(parsed.query) > 0:
|
||||
@ -597,14 +607,13 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
func = js_url_to_function(url_split)
|
||||
return func(self, url_split, post_string, is_json)
|
||||
except Exception as ex:
|
||||
if self.server.swap_client.debug is True:
|
||||
self.server.swap_client.log.error(traceback.format_exc())
|
||||
if swap_client.debug is True:
|
||||
swap_client.log.error(traceback.format_exc())
|
||||
return js_error(self, str(ex))
|
||||
|
||||
if len(url_split) > 1 and url_split[1] == 'static':
|
||||
try:
|
||||
static_path = os.path.join(os.path.dirname(__file__), 'static')
|
||||
|
||||
if len(url_split) > 3 and url_split[2] == 'sequence_diagrams':
|
||||
with open(os.path.join(static_path, 'sequence_diagrams', url_split[3]), 'rb') as fp:
|
||||
self.putHeaders(status_code, 'image/svg+xml')
|
||||
@ -639,13 +648,14 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
except FileNotFoundError:
|
||||
return self.page_404(url_split)
|
||||
except Exception as ex:
|
||||
if self.server.swap_client.debug is True:
|
||||
self.server.swap_client.log.error(traceback.format_exc())
|
||||
if swap_client.debug is True:
|
||||
swap_client.log.error(traceback.format_exc())
|
||||
return self.page_error(str(ex))
|
||||
|
||||
try:
|
||||
if len(url_split) > 1:
|
||||
page = url_split[1]
|
||||
|
||||
if page == 'active':
|
||||
return self.page_active(url_split, post_string)
|
||||
if page == 'wallets':
|
||||
@ -700,8 +710,8 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
return self.page_404(url_split)
|
||||
return self.page_index(url_split)
|
||||
except Exception as ex:
|
||||
if self.server.swap_client.debug is True:
|
||||
self.server.swap_client.log.error(traceback.format_exc())
|
||||
if swap_client.debug is True:
|
||||
swap_client.log.error(traceback.format_exc())
|
||||
return self.page_error(str(ex))
|
||||
|
||||
def do_GET(self):
|
||||
|
@ -262,7 +262,10 @@ class BTCInterface(CoinInterface):
|
||||
self.rpc_callback('sethdseed', [True, key_wif])
|
||||
|
||||
def getWalletInfo(self):
|
||||
return self.rpc_callback('getwalletinfo')
|
||||
rv = self.rpc_callback('getwalletinfo')
|
||||
rv['encrypted'] = 'unlocked_until' in rv
|
||||
rv['locked'] = rv.get('unlocked_until', 1) <= 0
|
||||
return rv
|
||||
|
||||
def walletRestoreHeight(self):
|
||||
return self._restore_height
|
||||
@ -1277,6 +1280,30 @@ class BTCInterface(CoinInterface):
|
||||
|
||||
return self.getUTXOBalance(address)
|
||||
|
||||
def isWalletEncrypted(self):
|
||||
wallet_info = self.rpc_callback('getwalletinfo')
|
||||
return 'unlocked_until' in wallet_info
|
||||
|
||||
def isWalletLocked(self):
|
||||
wallet_info = self.rpc_callback('getwalletinfo')
|
||||
if 'unlocked_until' in wallet_info and wallet_info['unlocked_until'] <= 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def changeWalletPassword(self, old_password, new_password):
|
||||
if old_password == '':
|
||||
return self.rpc_callback('encryptwallet', [new_password])
|
||||
self.rpc_callback('walletpassphrasechange', [old_password, new_password])
|
||||
|
||||
def unlockWallet(self, password):
|
||||
if password == '':
|
||||
return
|
||||
# Max timeout value, ~3 years
|
||||
self.rpc_callback('walletpassphrase', [password, 100000000])
|
||||
|
||||
def lockWallet(self):
|
||||
self.rpc_callback('walletlock')
|
||||
|
||||
|
||||
def testBTCInterface():
|
||||
print('TODO: testBTCInterface')
|
||||
|
@ -15,8 +15,11 @@ class DASHInterface(BTCInterface):
|
||||
def coin_type():
|
||||
return Coins.DASH
|
||||
|
||||
def seedToMnemonic(self, key):
|
||||
return Mnemonic('english').to_mnemonic(key)
|
||||
|
||||
def initialiseWallet(self, key):
|
||||
words = Mnemonic('english').to_mnemonic(key)
|
||||
words = self.seedToMnemonic(key)
|
||||
self.rpc_callback('upgradetohd', [words, ])
|
||||
|
||||
def checkExpectedSeed(self, key_hash):
|
||||
|
@ -74,6 +74,7 @@ class XMRInterface(CoinInterface):
|
||||
self.setFeePriority(coin_settings.get('fee_priority', 0))
|
||||
self._sc = swap_client
|
||||
self._log = self._sc.log if self._sc and self._sc.log else logging
|
||||
self._wallet_password = None
|
||||
|
||||
def setFeePriority(self, new_priority):
|
||||
ensure(new_priority >= 0 and new_priority < 4, 'Invalid fee_priority value')
|
||||
@ -82,10 +83,22 @@ class XMRInterface(CoinInterface):
|
||||
def setWalletFilename(self, wallet_filename):
|
||||
self._wallet_filename = wallet_filename
|
||||
|
||||
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)
|
||||
self._log.info('generate_from_keys %s', dumpj(rv))
|
||||
|
||||
def openWallet(self, filename):
|
||||
params = {'filename': filename}
|
||||
if self._wallet_password is not None:
|
||||
params['password'] = self._wallet_password
|
||||
self.rpc_wallet_cb('open_wallet', params)
|
||||
|
||||
def initialiseWallet(self, key_view, key_spend, restore_height=None):
|
||||
with self._mx_wallet:
|
||||
try:
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||
self.openWallet(self._wallet_filename)
|
||||
# TODO: Check address
|
||||
return # Wallet exists
|
||||
except Exception as e:
|
||||
@ -102,13 +115,12 @@ class XMRInterface(CoinInterface):
|
||||
'spendkey': b2h(key_spend[::-1]),
|
||||
'restore_height': self._restore_height,
|
||||
}
|
||||
rv = self.rpc_wallet_cb('generate_from_keys', params)
|
||||
self._log.info('generate_from_keys %s', dumpj(rv))
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||
self.createWallet(params)
|
||||
self.openWallet(self._wallet_filename)
|
||||
|
||||
def ensureWalletExists(self):
|
||||
with self._mx_wallet:
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||
self.openWallet(self._wallet_filename)
|
||||
|
||||
def testDaemonRPC(self, with_wallet=True):
|
||||
self.rpc_wallet_cb('get_languages')
|
||||
@ -149,12 +161,21 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
def getWalletInfo(self):
|
||||
with self._mx_wallet:
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||
try:
|
||||
self.openWallet(self._wallet_filename)
|
||||
except Exception as e:
|
||||
if 'Failed to open wallet' in str(e):
|
||||
rv = {'encrypted': True, 'locked': True, 'balance': 0, 'unconfirmed_balance': 0}
|
||||
return rv
|
||||
raise e
|
||||
|
||||
rv = {}
|
||||
self.rpc_wallet_cb('refresh')
|
||||
balance_info = self.rpc_wallet_cb('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
|
||||
rv['locked'] = False
|
||||
return rv
|
||||
|
||||
def walletRestoreHeight(self):
|
||||
@ -162,12 +183,12 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
def getMainWalletAddress(self):
|
||||
with self._mx_wallet:
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||
self.openWallet(self._wallet_filename)
|
||||
return self.rpc_wallet_cb('get_address')['address']
|
||||
|
||||
def getNewAddress(self, placeholder):
|
||||
with self._mx_wallet:
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||
self.openWallet(self._wallet_filename)
|
||||
return self.rpc_wallet_cb('create_address', {'account_index': 0})['address']
|
||||
|
||||
def get_fee_rate(self, conf_target=2):
|
||||
@ -230,7 +251,7 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
def publishBLockTx(self, Kbv, Kbs, output_amount, feerate, delay_for=10):
|
||||
with self._mx_wallet:
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||
self.openWallet(self._wallet_filename)
|
||||
|
||||
shared_addr = xmr_util.encode_address(Kbv, Kbs)
|
||||
|
||||
@ -275,10 +296,10 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
try:
|
||||
rv = self.rpc_wallet_cb('open_wallet', {'filename': address_b58})
|
||||
self.openWallet(address_b58)
|
||||
except Exception as e:
|
||||
rv = self.rpc_wallet_cb('generate_from_keys', params)
|
||||
self._log.info('generate_from_keys %s', dumpj(rv))
|
||||
rv = self.rpc_wallet_cb('open_wallet', {'filename': address_b58})
|
||||
self.createWallet(params)
|
||||
self.openWallet(address_b58)
|
||||
|
||||
self.rpc_wallet_cb('refresh', timeout=600)
|
||||
|
||||
@ -319,9 +340,8 @@ class XMRInterface(CoinInterface):
|
||||
'viewkey': b2h(kbv[::-1]),
|
||||
'restore_height': restore_height,
|
||||
}
|
||||
self.rpc_wallet_cb('generate_from_keys', params)
|
||||
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': address_b58})
|
||||
self.createWallet(params)
|
||||
self.openWallet(address_b58)
|
||||
# For a while after opening the wallet rpc cmds return empty data
|
||||
|
||||
num_tries = 40
|
||||
@ -367,7 +387,7 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
def findTxnByHash(self, txid):
|
||||
with self._mx_wallet:
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||
self.openWallet(self._wallet_filename)
|
||||
self.rpc_wallet_cb('refresh')
|
||||
|
||||
try:
|
||||
@ -409,11 +429,10 @@ class XMRInterface(CoinInterface):
|
||||
}
|
||||
|
||||
try:
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': wallet_filename})
|
||||
self.openWallet(wallet_filename)
|
||||
except Exception as e:
|
||||
rv = self.rpc_wallet_cb('generate_from_keys', params)
|
||||
self._log.info('generate_from_keys %s', dumpj(rv))
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': wallet_filename})
|
||||
self.createWallet(params)
|
||||
self.openWallet(wallet_filename)
|
||||
|
||||
self.rpc_wallet_cb('refresh')
|
||||
rv = self.rpc_wallet_cb('get_balance')
|
||||
@ -454,7 +473,7 @@ class XMRInterface(CoinInterface):
|
||||
with self._mx_wallet:
|
||||
value_sats = make_int(value, self.exp())
|
||||
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||
self.openWallet(self._wallet_filename)
|
||||
|
||||
if subfee:
|
||||
balance = self.rpc_wallet_cb('get_balance')
|
||||
@ -479,10 +498,10 @@ class XMRInterface(CoinInterface):
|
||||
address_b58 = xmr_util.encode_address(Kbv, Kbs)
|
||||
wallet_file = address_b58 + '_spend'
|
||||
try:
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': wallet_file})
|
||||
self.openWallet(wallet_file)
|
||||
except Exception:
|
||||
wallet_file = address_b58
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': wallet_file})
|
||||
self.openWallet(wallet_file)
|
||||
|
||||
self.rpc_wallet_cb('refresh')
|
||||
|
||||
@ -494,8 +513,25 @@ class XMRInterface(CoinInterface):
|
||||
|
||||
def getSpendableBalance(self):
|
||||
with self._mx_wallet:
|
||||
self.rpc_wallet_cb('open_wallet', {'filename': self._wallet_filename})
|
||||
self.openWallet(self._wallet_filename)
|
||||
|
||||
self.rpc_wallet_cb('refresh')
|
||||
balance_info = self.rpc_wallet_cb('get_balance')
|
||||
return balance_info['unlocked_balance']
|
||||
|
||||
def changeWalletPassword(self, old_password, new_password):
|
||||
orig_password = self._wallet_password
|
||||
if old_password != '':
|
||||
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})
|
||||
except Exception as e:
|
||||
self._wallet_password = orig_password
|
||||
raise e
|
||||
|
||||
def unlockWallet(self, password):
|
||||
self._wallet_password = password
|
||||
|
||||
def lockWallet(self):
|
||||
self._wallet_password = None
|
||||
|
@ -88,6 +88,7 @@ def js_coins(self, url_split, post_string, is_json):
|
||||
|
||||
def js_wallets(self, url_split, post_string, is_json):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
if len(url_split) > 3:
|
||||
ticker_str = url_split[3]
|
||||
coin_type = tickerToCoinId(ticker_str)
|
||||
@ -108,6 +109,7 @@ def js_wallets(self, url_split, post_string, is_json):
|
||||
|
||||
def js_offers(self, url_split, post_string, is_json, sent=False):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
offer_id = None
|
||||
if len(url_split) > 3:
|
||||
if url_split[3] == 'new':
|
||||
@ -186,6 +188,7 @@ def js_sentoffers(self, url_split, post_string, is_json):
|
||||
|
||||
def js_bids(self, url_split, post_string, is_json):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
if len(url_split) > 3:
|
||||
if url_split[3] == 'new':
|
||||
if post_string == '':
|
||||
@ -287,22 +290,29 @@ def js_bids(self, url_split, post_string, is_json):
|
||||
|
||||
|
||||
def js_sentbids(self, url_split, post_string, is_json):
|
||||
return bytes(json.dumps(self.server.swap_client.listBids(sent=True)), 'UTF-8')
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
return bytes(json.dumps(swap_client.listBids(sent=True)), 'UTF-8')
|
||||
|
||||
|
||||
def js_network(self, url_split, post_string, is_json):
|
||||
return bytes(json.dumps(self.server.swap_client.get_network_info()), 'UTF-8')
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
return bytes(json.dumps(swap_client.get_network_info()), 'UTF-8')
|
||||
|
||||
|
||||
def js_revokeoffer(self, url_split, post_string, is_json):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
offer_id = bytes.fromhex(url_split[3])
|
||||
assert (len(offer_id) == 28)
|
||||
self.server.swap_client.revokeOffer(offer_id)
|
||||
swap_client.revokeOffer(offer_id)
|
||||
return bytes(json.dumps({'revoked_offer': offer_id.hex()}), 'UTF-8')
|
||||
|
||||
|
||||
def js_smsgaddresses(self, url_split, post_string, is_json):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
if len(url_split) > 3:
|
||||
if post_string == '':
|
||||
raise ValueError('No post data')
|
||||
@ -394,7 +404,9 @@ def js_rate(self, url_split, post_string, is_json):
|
||||
|
||||
|
||||
def js_index(self, url_split, post_string, is_json):
|
||||
return bytes(json.dumps(self.server.swap_client.getSummary()), 'UTF-8')
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
return bytes(json.dumps(swap_client.getSummary()), 'UTF-8')
|
||||
|
||||
|
||||
def js_generatenotification(self, url_split, post_string, is_json):
|
||||
@ -418,6 +430,7 @@ def js_generatenotification(self, url_split, post_string, is_json):
|
||||
|
||||
def js_notifications(self, url_split, post_string, is_json):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
swap_client.getNotifications()
|
||||
|
||||
return bytes(json.dumps(swap_client.getNotifications()), 'UTF-8')
|
||||
@ -425,28 +438,140 @@ def js_notifications(self, url_split, post_string, is_json):
|
||||
|
||||
def js_vacuumdb(self, url_split, post_string, is_json):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
swap_client.vacuumDB()
|
||||
|
||||
return bytes(json.dumps({'completed': True}), 'UTF-8')
|
||||
|
||||
|
||||
def js_getcoinseed(self, url_split, post_string, is_json):
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
if post_string == '':
|
||||
raise ValueError('No post data')
|
||||
if is_json:
|
||||
post_data = json.loads(post_string)
|
||||
post_data['is_json'] = True
|
||||
else:
|
||||
post_data = urllib.parse.parse_qs(post_string)
|
||||
|
||||
coin = getCoinType(get_data_entry(post_data, 'coin'))
|
||||
if coin in (Coins.PART, Coins.PART_ANON, Coins.PART_BLIND):
|
||||
raise ValueError('Particl wallet seed is set from the Basicswap mnemonic.')
|
||||
|
||||
ci = swap_client.ci(coin)
|
||||
seed = swap_client.getWalletKey(coin, 1)
|
||||
if coin == Coins.DASH:
|
||||
return bytes(json.dumps({'coin': ci.ticker(), 'seed': seed.hex(), 'mnemonic': ci.seedToMnemonic(seed)}), 'UTF-8')
|
||||
return bytes(json.dumps({'coin': ci.ticker(), 'seed': seed.hex()}), 'UTF-8')
|
||||
|
||||
|
||||
def js_setpassword(self, url_split, post_string, is_json):
|
||||
# Set or change wallet passwords
|
||||
# Only works with currently enabled coins
|
||||
# Will fail if any coin does not unlock on the old password
|
||||
swap_client = self.server.swap_client
|
||||
if post_string == '':
|
||||
raise ValueError('No post data')
|
||||
if is_json:
|
||||
post_data = json.loads(post_string)
|
||||
post_data['is_json'] = True
|
||||
else:
|
||||
post_data = urllib.parse.parse_qs(post_string)
|
||||
|
||||
old_password = get_data_entry(post_data, 'oldpassword')
|
||||
new_password = get_data_entry(post_data, 'newpassword')
|
||||
|
||||
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):
|
||||
raise ValueError('Invalid coin.')
|
||||
swap_client.ci(coin).changeWalletPassword(old_password, new_password)
|
||||
return bytes(json.dumps({'success': True}), 'UTF-8')
|
||||
|
||||
# Set password for all coins
|
||||
swap_client.changeWalletPasswords(old_password, new_password)
|
||||
return bytes(json.dumps({'success': True}), 'UTF-8')
|
||||
|
||||
|
||||
def js_unlock(self, url_split, post_string, is_json):
|
||||
swap_client = self.server.swap_client
|
||||
if post_string == '':
|
||||
raise ValueError('No post data')
|
||||
if is_json:
|
||||
post_data = json.loads(post_string)
|
||||
post_data['is_json'] = True
|
||||
else:
|
||||
post_data = urllib.parse.parse_qs(post_string)
|
||||
|
||||
password = get_data_entry(post_data, 'password')
|
||||
|
||||
if have_data_entry(post_data, 'coin'):
|
||||
coin = getCoinType(str(get_data_entry(post_data, 'coin')))
|
||||
if coin in (Coins.PART_ANON, Coins.PART_BLIND):
|
||||
raise ValueError('Invalid coin.')
|
||||
swap_client.ci(coin).unlockWallet(password)
|
||||
return bytes(json.dumps({'success': True}), 'UTF-8')
|
||||
|
||||
swap_client.unlockWallets(password)
|
||||
return bytes(json.dumps({'success': True}), 'UTF-8')
|
||||
|
||||
|
||||
def js_lock(self, url_split, post_string, is_json):
|
||||
swap_client = self.server.swap_client
|
||||
if post_string == '':
|
||||
raise ValueError('No post data')
|
||||
if is_json:
|
||||
post_data = json.loads(post_string)
|
||||
post_data['is_json'] = True
|
||||
else:
|
||||
post_data = urllib.parse.parse_qs(post_string)
|
||||
|
||||
if have_data_entry(post_data, 'coin'):
|
||||
coin = getCoinType(get_data_entry(post_data, 'coin'))
|
||||
if coin in (Coins.PART_ANON, Coins.PART_BLIND):
|
||||
raise ValueError('Invalid coin.')
|
||||
swap_client.ci(coin).lockWallet()
|
||||
return bytes(json.dumps({'success': True}), 'UTF-8')
|
||||
|
||||
swap_client.lockWallets()
|
||||
return bytes(json.dumps({'success': True}), 'UTF-8')
|
||||
|
||||
|
||||
def js_help(self, url_split, post_string, is_json):
|
||||
# TODO: Add details and examples
|
||||
commands = []
|
||||
for k in pages:
|
||||
commands.append(k)
|
||||
return bytes(json.dumps({'commands': commands}), 'UTF-8')
|
||||
|
||||
|
||||
pages = {
|
||||
'coins': js_coins,
|
||||
'wallets': js_wallets,
|
||||
'offers': js_offers,
|
||||
'sentoffers': js_sentoffers,
|
||||
'bids': js_bids,
|
||||
'sentbids': js_sentbids,
|
||||
'network': js_network,
|
||||
'revokeoffer': js_revokeoffer,
|
||||
'smsgaddresses': js_smsgaddresses,
|
||||
'rate': js_rate,
|
||||
'rates': js_rates,
|
||||
'rateslist': js_rates_list,
|
||||
'generatenotification': js_generatenotification,
|
||||
'notifications': js_notifications,
|
||||
'vacuumdb': js_vacuumdb,
|
||||
'getcoinseed': js_getcoinseed,
|
||||
'setpassword': js_setpassword,
|
||||
'unlock': js_unlock,
|
||||
'lock': js_lock,
|
||||
'help': js_help,
|
||||
}
|
||||
|
||||
|
||||
def js_url_to_function(url_split):
|
||||
if len(url_split) > 2:
|
||||
return {
|
||||
'coins': js_coins,
|
||||
'wallets': js_wallets,
|
||||
'offers': js_offers,
|
||||
'sentoffers': js_sentoffers,
|
||||
'bids': js_bids,
|
||||
'sentbids': js_sentbids,
|
||||
'network': js_network,
|
||||
'revokeoffer': js_revokeoffer,
|
||||
'smsgaddresses': js_smsgaddresses,
|
||||
'rate': js_rate,
|
||||
'rates': js_rates,
|
||||
'rateslist': js_rates_list,
|
||||
'generatenotification': js_generatenotification,
|
||||
'notifications': js_notifications,
|
||||
'vacuumdb': js_vacuumdb,
|
||||
}.get(url_split[2], js_index)
|
||||
return pages.get(url_split[2], js_index)
|
||||
return js_index
|
||||
|
@ -130,13 +130,15 @@ def openrpc(rpc_port, auth, wallet=None, host='127.0.0.1'):
|
||||
raise ValueError('RPC error ' + str(ex))
|
||||
|
||||
|
||||
def callrpc_cli(bindir, datadir, chain, cmd, cli_bin='particl-cli'):
|
||||
def callrpc_cli(bindir, datadir, chain, cmd, cli_bin='particl-cli', wallet=None):
|
||||
cli_bin = os.path.join(bindir, cli_bin)
|
||||
|
||||
args = [cli_bin, ]
|
||||
if chain != 'mainnet':
|
||||
args.append('-' + chain)
|
||||
args.append('-datadir=' + datadir)
|
||||
if wallet is not None:
|
||||
args.append('-rpcwallet=' + wallet)
|
||||
args += shlex.split(cmd)
|
||||
|
||||
p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
@ -21,6 +21,7 @@ from basicswap.db import (
|
||||
def page_automation_strategies(self, url_split, post_string):
|
||||
server = self.server
|
||||
swap_client = server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
filters = {
|
||||
@ -61,6 +62,7 @@ def page_automation_strategies(self, url_split, post_string):
|
||||
def page_automation_strategy_new(self, url_split, post_string):
|
||||
server = self.server
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
messages = []
|
||||
@ -82,6 +84,7 @@ def page_automation_strategy(self, url_split, post_string):
|
||||
|
||||
server = self.server
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
messages = []
|
||||
|
@ -37,6 +37,7 @@ def page_bid(self, url_split, post_string):
|
||||
raise ValueError('Bad bid ID')
|
||||
server = self.server
|
||||
swap_client = server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
messages = []
|
||||
@ -121,6 +122,7 @@ def page_bid(self, url_split, post_string):
|
||||
def page_bids(self, url_split, post_string, sent=False, available=False, received=False):
|
||||
server = self.server
|
||||
swap_client = server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
filters = {
|
||||
|
@ -319,7 +319,8 @@ def offer_to_post_string(self, swap_client, offer_id):
|
||||
|
||||
def page_newoffer(self, url_split, post_string):
|
||||
server = self.server
|
||||
swap_client = server.swap_client
|
||||
swap_client = self.server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
messages = []
|
||||
@ -400,6 +401,7 @@ def page_offer(self, url_split, post_string):
|
||||
offer_id = decode_offer_id(url_split[2])
|
||||
server = self.server
|
||||
swap_client = server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
offer, xmr_offer = swap_client.getXmrOffer(offer_id)
|
||||
ensure(offer, 'Unknown offer ID')
|
||||
@ -564,6 +566,7 @@ def page_offer(self, url_split, post_string):
|
||||
def page_offers(self, url_split, post_string, sent=False):
|
||||
server = self.server
|
||||
swap_client = server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
filters = {
|
||||
|
@ -61,6 +61,7 @@ def format_wallet_data(ci, w):
|
||||
def page_wallets(self, url_split, post_string):
|
||||
server = self.server
|
||||
swap_client = server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
page_data = {}
|
||||
@ -165,6 +166,7 @@ def page_wallet(self, url_split, post_string):
|
||||
wallet_ticker = url_split[2]
|
||||
server = self.server
|
||||
swap_client = server.swap_client
|
||||
swap_client.checkSystemStatus()
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
coin_id = getCoinIdFromTicker(wallet_ticker)
|
||||
|
@ -33,6 +33,14 @@ class InactiveCoin(Exception):
|
||||
return str(self.coinid)
|
||||
|
||||
|
||||
class LockedCoinError(Exception):
|
||||
def __init__(self, coinid):
|
||||
self.coinid = coinid
|
||||
|
||||
def __str__(self):
|
||||
return 'Coin must be unlocked: ' + str(self.coinid)
|
||||
|
||||
|
||||
def ensure(v, err_string):
|
||||
if not v:
|
||||
raise ValueError(err_string)
|
||||
|
@ -217,13 +217,23 @@ def post_json_req(url, json_data):
|
||||
req.add_header('Content-Type', 'application/json; charset=utf-8')
|
||||
post_bytes = json.dumps(json_data).encode('utf-8')
|
||||
req.add_header('Content-Length', len(post_bytes))
|
||||
return urlopen(req, post_bytes).read()
|
||||
return urlopen(req, post_bytes, timeout=300).read()
|
||||
|
||||
|
||||
def read_json_api(port, path=None):
|
||||
def read_text_api(port, path=None):
|
||||
url = f'http://127.0.0.1:{port}/json'
|
||||
if path is not None:
|
||||
url += '/' + path
|
||||
return urlopen(url, timeout=300).read().decode('utf-8')
|
||||
|
||||
|
||||
def read_json_api(port, path=None, json_data=None):
|
||||
url = f'http://127.0.0.1:{port}/json'
|
||||
if path is not None:
|
||||
url += '/' + path
|
||||
|
||||
if json_data is not None:
|
||||
return json.loads(post_json_req(url, json_data))
|
||||
return json.loads(urlopen(url, timeout=300).read())
|
||||
|
||||
|
||||
|
@ -14,6 +14,7 @@ import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import random
|
||||
import shutil
|
||||
import signal
|
||||
import logging
|
||||
@ -204,8 +205,8 @@ def btcRpc(cmd):
|
||||
return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), 'regtest', cmd, cfg.BITCOIN_CLI)
|
||||
|
||||
|
||||
def dashRpc(cmd):
|
||||
return callrpc_cli(cfg.DASH_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(DASH_NODE)), 'regtest', cmd, cfg.DASH_CLI)
|
||||
def dashRpc(cmd, wallet=None):
|
||||
return callrpc_cli(cfg.DASH_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(DASH_NODE)), 'regtest', cmd, cfg.DASH_CLI, wallet=wallet)
|
||||
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
@ -533,18 +534,17 @@ class Test(unittest.TestCase):
|
||||
self.swap_clients[0].initialiseWallet(Coins.DASH, raise_errors=True)
|
||||
assert self.swap_clients[0].checkWalletSeed(Coins.DASH) is True
|
||||
|
||||
pivx_addr = dashRpc('getnewaddress \"hd test\"')
|
||||
assert pivx_addr == 'ybzWYJbZEhZai8kiKkTtPFKTuDNwhpiwac'
|
||||
addr = dashRpc('getnewaddress \"hd wallet test\"')
|
||||
assert addr == 'ybzWYJbZEhZai8kiKkTtPFKTuDNwhpiwac'
|
||||
|
||||
def pass_99_delay(self):
|
||||
global stop_test
|
||||
logging.info('Delay')
|
||||
for i in range(60 * 5):
|
||||
if stop_test:
|
||||
break
|
||||
time.sleep(1)
|
||||
print('delay', i)
|
||||
stop_test = True
|
||||
logging.info('Test that getcoinseed returns a mnemonic for Dash')
|
||||
mnemonic = read_json_api(1800, 'getcoinseed', {'coin': 'DASH'})['mnemonic']
|
||||
new_wallet_name = random.randbytes(10).hex()
|
||||
dashRpc(f'createwallet \"{new_wallet_name}\"')
|
||||
dashRpc(f'upgradetohd \"{mnemonic}\"', wallet=new_wallet_name)
|
||||
addr_test = dashRpc('getnewaddress', wallet=new_wallet_name)
|
||||
dashRpc('unloadwallet', wallet=new_wallet_name)
|
||||
assert (addr_test == addr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -108,6 +108,8 @@ class Test(BaseTest):
|
||||
firo_daemons = []
|
||||
firo_addr = None
|
||||
test_coin_from = Coins.FIRO
|
||||
start_ltc_nodes = False
|
||||
start_xmr_nodes = False
|
||||
|
||||
test_atomic = True
|
||||
test_xmr = False
|
||||
@ -119,12 +121,6 @@ class Test(BaseTest):
|
||||
'c5de2be44834e7e47ad7dc8e35c6b77c79f17c6bb40d5509a00fc3dff384a865',
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.start_ltc_nodes = False
|
||||
cls.start_xmr_nodes = False
|
||||
super(Test, cls).setUpClass()
|
||||
|
||||
@classmethod
|
||||
def prepareExtraDataDir(cls, i):
|
||||
if not cls.restore_instance:
|
||||
@ -135,7 +131,7 @@ class Test(BaseTest):
|
||||
callrpc_cli(cfg.FIRO_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'firo-wallet')
|
||||
|
||||
cls.firo_daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, 'firo_' + str(i)), cfg.FIRO_BINDIR, cfg.FIROD, opts=extra_opts))
|
||||
logging.info('Started %s %d', cfg.FIROD, cls.part_daemons[-1].pid)
|
||||
logging.info('Started %s %d', cfg.FIROD, cls.firo_daemons[-1].pid)
|
||||
|
||||
waitForRPC(make_rpc_func(i, base_rpc_port=FIRO_BASE_RPC_PORT))
|
||||
|
||||
|
@ -349,7 +349,7 @@ class Test(unittest.TestCase):
|
||||
num_blocks = 3
|
||||
logging.info('Waiting for Particl chain height %d', num_blocks)
|
||||
for i in range(60):
|
||||
particl_blocks = cls.swap_clients[0].callrpc('getblockchaininfo')['blocks']
|
||||
particl_blocks = cls.swap_clients[0].callrpc('getblockcount')
|
||||
print('particl_blocks', particl_blocks)
|
||||
if particl_blocks >= num_blocks:
|
||||
break
|
||||
|
@ -360,7 +360,7 @@ class Test(unittest.TestCase):
|
||||
num_blocks = 3
|
||||
logging.info('Waiting for Particl chain height %d', num_blocks)
|
||||
for i in range(60):
|
||||
particl_blocks = cls.swap_clients[0].callrpc('getblockchaininfo')['blocks']
|
||||
particl_blocks = cls.swap_clients[0].callrpc('getblockcount')
|
||||
print('particl_blocks', particl_blocks)
|
||||
if particl_blocks >= num_blocks:
|
||||
break
|
||||
@ -563,16 +563,6 @@ class Test(unittest.TestCase):
|
||||
break
|
||||
assert found
|
||||
|
||||
def pass_99_delay(self):
|
||||
global stop_test
|
||||
logging.info('Delay')
|
||||
for i in range(60 * 5):
|
||||
if stop_test:
|
||||
break
|
||||
time.sleep(1)
|
||||
print('delay', i)
|
||||
stop_test = True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -176,7 +176,7 @@ class Test(unittest.TestCase):
|
||||
for i in range(60):
|
||||
if self.delay_event.is_set():
|
||||
raise ValueError('Test stopped.')
|
||||
particl_blocks = callpartrpc(0, 'getblockchaininfo')['blocks']
|
||||
particl_blocks = callpartrpc(0, 'getblockcount')
|
||||
print('particl_blocks', particl_blocks)
|
||||
if particl_blocks >= num_blocks:
|
||||
break
|
||||
|
@ -425,6 +425,39 @@ class TestBTC(BasicSwapTest):
|
||||
start_ltc_nodes = False
|
||||
base_rpc_port = BTC_BASE_RPC_PORT
|
||||
|
||||
def test_009_wallet_encryption(self):
|
||||
|
||||
for coin in ('btc', 'part', 'xmr'):
|
||||
jsw = read_json_api(1800, f'wallets/{coin}')
|
||||
assert (jsw['encrypted'] is False)
|
||||
assert (jsw['locked'] is False)
|
||||
|
||||
rv = read_json_api(1800, 'setpassword', {'oldpassword': '', 'newpassword': 'notapassword123'})
|
||||
|
||||
# Entire system is locked with Particl wallet
|
||||
jsw = read_json_api(1800, 'wallets/btc')
|
||||
assert ('Coin must be unlocked' in jsw['error'])
|
||||
|
||||
read_json_api(1800, 'unlock', {'coin': 'part', 'password': 'notapassword123'})
|
||||
|
||||
for coin in ('btc', 'xmr'):
|
||||
jsw = read_json_api(1800, f'wallets/{coin}')
|
||||
assert (jsw['encrypted'] is True)
|
||||
assert (jsw['locked'] is True)
|
||||
|
||||
read_json_api(1800, 'lock', {'coin': 'part'})
|
||||
jsw = read_json_api(1800, 'wallets/part')
|
||||
assert ('Coin must be unlocked' in jsw['error'])
|
||||
|
||||
read_json_api(1800, 'setpassword', {'oldpassword': 'notapassword123', 'newpassword': 'notapassword456'})
|
||||
|
||||
read_json_api(1800, 'unlock', {'password': 'notapassword456'})
|
||||
|
||||
for coin in ('part', 'btc', 'xmr'):
|
||||
jsw = read_json_api(1800, f'wallets/{coin}')
|
||||
assert (jsw['encrypted'] is True)
|
||||
assert (jsw['locked'] is False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -14,7 +14,6 @@ $ pytest -v -s tests/basicswap/test_run.py::Test::test_04_ltc_btc
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import random
|
||||
import logging
|
||||
import unittest
|
||||
@ -43,7 +42,6 @@ from tests.basicswap.common import (
|
||||
wait_for_balance,
|
||||
wait_for_bid_tx_state,
|
||||
wait_for_in_progress,
|
||||
post_json_req,
|
||||
read_json_api,
|
||||
TEST_HTTP_PORT,
|
||||
LTC_BASE_RPC_PORT,
|
||||
@ -114,6 +112,21 @@ class Test(BaseTest):
|
||||
rv = read_json_api(1800, 'rateslist?from=PART&to=BTC')
|
||||
assert len(rv) == 2
|
||||
|
||||
def test_003_api(self):
|
||||
logging.info('---------- Test API')
|
||||
|
||||
help_output = read_json_api(1800, 'help')
|
||||
assert ('getcoinseed' in help_output['commands'])
|
||||
|
||||
rv = read_json_api(1800, 'getcoinseed')
|
||||
assert (rv['error'] == 'No post data')
|
||||
|
||||
rv = read_json_api(1800, 'getcoinseed', {'coin': 'PART'})
|
||||
assert ('seed is set from the Basicswap mnemonic' in rv['error'])
|
||||
|
||||
rv = read_json_api(1800, 'getcoinseed', {'coin': 'BTC'})
|
||||
assert (rv['seed'] == '8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b')
|
||||
|
||||
def test_01_verifyrawtransaction(self):
|
||||
txn = '0200000001eb6e5c4ebba4efa32f40c7314cad456a64008e91ee30b2dd0235ab9bb67fbdbb01000000ee47304402200956933242dde94f6cf8f195a470f8d02aef21ec5c9b66c5d3871594bdb74c9d02201d7e1b440de8f4da672d689f9e37e98815fb63dbc1706353290887eb6e8f7235012103dc1b24feb32841bc2f4375da91fa97834e5983668c2a39a6b7eadb60e7033f9d205a803b28fe2f86c17db91fa99d7ed2598f79b5677ffe869de2e478c0d1c02cc7514c606382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914225fbfa4cb725b75e511810ac4d6f74069bdded26703520140b27576a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666888acffffffff01e0167118020000001976a9140044e188928710cecba8311f1cf412135b98145c88ac00000000'
|
||||
prevout = {
|
||||
@ -412,7 +425,7 @@ class Test(BaseTest):
|
||||
'address': ltc_addr,
|
||||
'subfee': False,
|
||||
}
|
||||
json_rv = json.loads(post_json_req('http://127.0.0.1:{}/json/wallets/ltc/withdraw'.format(TEST_HTTP_PORT + 0), post_json))
|
||||
json_rv = read_json_api('json/wallets/ltc/withdraw', TEST_HTTP_PORT + 0, post_json)
|
||||
assert (len(json_rv['txid']) == 64)
|
||||
|
||||
def test_13_itx_refund(self):
|
||||
|
Loading…
Reference in New Issue
Block a user