api: Add wallet lock/unlock commands and getcoinseed.

This commit is contained in:
tecnovert
2022-11-12 01:51:30 +02:00
parent 020a65db8a
commit fc31615a97
21 changed files with 412 additions and 121 deletions

View File

@@ -1,3 +1,3 @@
name = "basicswap"
__version__ = "0.11.45"
__version__ = "0.11.46"

View File

@@ -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

View File

@@ -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):

View File

@@ -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')

View File

@@ -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):

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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 = []

View File

@@ -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 = {

View File

@@ -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 = {

View File

@@ -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)

View File

@@ -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)