ui: Connect new settings.

This commit is contained in:
tecnovert 2022-11-13 23:18:33 +02:00
parent bbe7556d18
commit 54e434e1c9
No known key found for this signature in database
GPG Key ID: 8ED6D8750C4E3F93
12 changed files with 411 additions and 152 deletions

View File

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

View File

@ -8,11 +8,13 @@ import os
import re
import sys
import zmq
import copy
import json
import time
import base64
import random
import shutil
import string
import struct
import urllib.request
import hashlib
@ -497,6 +499,20 @@ class BasicSwap(BaseApp):
raise ValueError('Failed to select a working XMR daemon url.')
def isCoinActive(self, coin):
use_coinid = coin
interface_ind = 'interface'
if coin == Coins.PART_ANON:
use_coinid = Coins.PART
interface_ind = 'interface_anon'
if coin == Coins.PART_BLIND:
use_coinid = Coins.PART
interface_ind = 'interface_blind'
if use_coinid not in self.coin_clients:
raise ValueError('Unknown coinid {}'.format(int(coin)))
return interface_ind in self.coin_clients[use_coinid]
def ci(self, coin): # Coin interface
use_coinid = coin
interface_ind = 'interface'
@ -5188,12 +5204,72 @@ class BasicSwap(BaseApp):
finally:
self.mxDB.release()
def editSettings(self, coin_name, data):
self.log.info('Updating settings %s', coin_name)
with self.mxDB:
settings_cc = self.settings['chainclients'][coin_name]
def editGeneralSettings(self, data):
self.log.info('Updating general settings')
settings_changed = False
suggest_reboot = False
settings_copy = copy.deepcopy(self.settings)
with self.mxDB:
if 'debug' in data:
new_value = data['debug']
ensure(type(new_value) == bool, 'New debug value not boolean')
if settings_copy.get('debug', False) != new_value:
self.debug = new_value
settings_copy['debug'] = new_value
settings_changed = True
if 'debug_ui' in data:
new_value = data['debug_ui']
ensure(type(new_value) == bool, 'New debug_ui value not boolean')
if settings_copy.get('debug_ui', False) != new_value:
self.debug_ui = new_value
settings_copy['debug_ui'] = new_value
settings_changed = True
if 'show_chart' in data:
new_value = data['show_chart']
ensure(type(new_value) == bool, 'New show_chart value not boolean')
if settings_copy.get('show_chart', True) != new_value:
settings_copy['show_chart'] = new_value
settings_changed = True
if 'chart_api_key' in data:
new_value = data['chart_api_key']
ensure(type(new_value) == str, 'New chart_api_key value not a string')
ensure(len(new_value) <= 128, 'New chart_api_key value too long')
if all(c in string.hexdigits for c in new_value):
if settings_copy.get('chart_api_key', '') != new_value:
settings_copy['chart_api_key'] = new_value
if 'chart_api_key_enc' in settings_copy:
settings_copy.pop('chart_api_key_enc')
settings_changed = True
else:
# Encode value as hex to avoid escaping
new_value = new_value.encode('utf-8').hex()
if settings_copy.get('chart_api_key_enc', '') != new_value:
settings_copy['chart_api_key_enc'] = new_value
if 'chart_api_key' in settings_copy:
settings_copy.pop('chart_api_key')
settings_changed = True
if settings_changed:
settings_path = os.path.join(self.data_dir, cfg.CONFIG_FILENAME)
settings_path_new = settings_path + '.new'
shutil.copyfile(settings_path, settings_path + '.last')
with open(settings_path_new, 'w') as fp:
json.dump(settings_copy, fp, indent=4)
shutil.move(settings_path_new, settings_path)
self.settings = settings_copy
return settings_changed, suggest_reboot
def editSettings(self, coin_name, data):
self.log.info(f'Updating settings {coin_name}')
settings_changed = False
suggest_reboot = False
settings_copy = copy.deepcopy(self.settings)
with self.mxDB:
settings_cc = settings_copy['chainclients'][coin_name]
if 'lookups' in data:
if settings_cc.get('chain_lookups', 'local') != data['lookups']:
settings_changed = True
@ -5233,6 +5309,7 @@ class BasicSwap(BaseApp):
for coin, cc in self.coin_clients.items():
if cc['name'] == coin_name:
cc['fee_priority'] = new_fee_priority
if self.isCoinActive(coin):
self.ci(coin).setFeePriority(new_fee_priority)
break
@ -5246,6 +5323,7 @@ class BasicSwap(BaseApp):
for coin, cc in self.coin_clients.items():
if cc['name'] == coin_name:
cc['conf_target'] = new_conf_target
if self.isCoinActive(coin):
self.ci(coin).setConfTarget(new_conf_target)
break
@ -5259,14 +5337,18 @@ class BasicSwap(BaseApp):
for coin, cc in self.coin_clients.items():
if cc['name'] == coin_name:
cc['anon_tx_ring_size'] = new_anon_tx_ring_size
if self.isCoinActive(coin):
self.ci(coin).setAnonTxRingSize(new_anon_tx_ring_size)
break
if settings_changed:
settings_path = os.path.join(self.data_dir, cfg.CONFIG_FILENAME)
settings_path_new = settings_path + '.new'
shutil.copyfile(settings_path, settings_path + '.last')
with open(settings_path, 'w') as fp:
json.dump(self.settings, fp, indent=4)
with open(settings_path_new, 'w') as fp:
json.dump(settings_copy, fp, indent=4)
shutil.move(settings_path_new, settings_path)
self.settings = settings_copy
return settings_changed, suggest_reboot
def enableCoin(self, coin_name):

View File

@ -380,6 +380,8 @@ def describeEventEntry(event_type, event_msg):
def getVoutByAddress(txjs, p2sh):
for o in txjs['vout']:
try:
if 'address' in o['scriptPubKey'] and o['scriptPubKey']['address'] == p2sh:
return o['n']
if p2sh in o['scriptPubKey']['addresses']:
return o['n']
except Exception:

View File

@ -49,7 +49,7 @@ from .ui.page_bids import page_bids, page_bid
from .ui.page_offers import page_offers, page_offer, page_newoffer
from .ui.page_tor import page_tor, get_tor_established_state
from .ui.page_wallet import page_wallets, page_wallet
from .ui.page_settings import page_settings
env = Environment(loader=PackageLoader('basicswap', 'templates'))
env.filters['formatts'] = format_timestamp
@ -333,88 +333,6 @@ class HttpHandler(BaseHTTPRequestHandler):
'summary': summary,
})
def page_settings(self, url_split, post_string):
swap_client = self.server.swap_client
swap_client.checkSystemStatus()
summary = swap_client.getSummary()
messages = []
err_messages = []
form_data = self.checkForm(post_string, 'settings', err_messages)
if form_data:
for name, c in swap_client.settings['chainclients'].items():
if have_data_entry(form_data, 'apply_' + name):
data = {'lookups': get_data_entry(form_data, 'lookups_' + name)}
if name == 'monero':
data['fee_priority'] = int(get_data_entry(form_data, 'fee_priority_' + name))
data['manage_daemon'] = True if get_data_entry(form_data, 'managedaemon_' + name) == 'true' else False
data['rpchost'] = get_data_entry(form_data, 'rpchost_' + name)
data['rpcport'] = int(get_data_entry(form_data, 'rpcport_' + name))
data['remotedaemonurls'] = get_data_entry(form_data, 'remotedaemonurls_' + name)
data['automatically_select_daemon'] = True if get_data_entry(form_data, 'autosetdaemon_' + name) == 'true' else False
else:
data['conf_target'] = int(get_data_entry(form_data, 'conf_target_' + name))
if name == 'particl':
data['anon_tx_ring_size'] = int(get_data_entry(form_data, 'rct_ring_size_' + name))
settings_changed, suggest_reboot = swap_client.editSettings(name, data)
if settings_changed is True:
messages.append('Settings applied.')
if suggest_reboot is True:
messages.append('Please restart BasicSwap.')
elif have_data_entry(form_data, 'enable_' + name):
swap_client.enableCoin(name)
display_name = getCoinName(swap_client.getCoinIdFromName(name))
messages.append(display_name + ' enabled, shutting down.')
swap_client.stopRunning()
elif have_data_entry(form_data, 'disable_' + name):
swap_client.disableCoin(name)
display_name = getCoinName(swap_client.getCoinIdFromName(name))
messages.append(display_name + ' disabled, shutting down.')
swap_client.stopRunning()
chains_formatted = []
sorted_names = sorted(swap_client.settings['chainclients'].keys())
for name in sorted_names:
c = swap_client.settings['chainclients'][name]
try:
display_name = getCoinName(swap_client.getCoinIdFromName(name))
except Exception:
display_name = name
chains_formatted.append({
'name': name,
'display_name': display_name,
'lookups': c.get('chain_lookups', 'local'),
'manage_daemon': c.get('manage_daemon', 'Unknown'),
'connection_type': c.get('connection_type', 'Unknown'),
})
if name == 'monero':
chains_formatted[-1]['fee_priority'] = c.get('fee_priority', 0)
chains_formatted[-1]['manage_wallet_daemon'] = c.get('manage_wallet_daemon', 'Unknown')
chains_formatted[-1]['rpchost'] = c.get('rpchost', 'localhost')
chains_formatted[-1]['rpcport'] = int(c.get('rpcport', 18081))
chains_formatted[-1]['remotedaemonurls'] = '\n'.join(c.get('remote_daemon_urls', []))
chains_formatted[-1]['autosetdaemon'] = c.get('automatically_select_daemon', False)
else:
chains_formatted[-1]['conf_target'] = c.get('conf_target', 2)
if name == 'particl':
chains_formatted[-1]['anon_tx_ring_size'] = c.get('anon_tx_ring_size', 12)
else:
if c.get('connection_type', 'Unknown') == 'none':
if 'connection_type_prev' in c:
chains_formatted[-1]['can_reenable'] = True
else:
chains_formatted[-1]['can_disable'] = True
template = env.get_template('settings.html')
return self.render_template(template, {
'messages': messages,
'err_messages': err_messages,
'chains': chains_formatted,
'summary': summary,
})
def page_watched(self, url_split, post_string):
swap_client = self.server.swap_client
swap_client.checkSystemStatus()
@ -663,7 +581,7 @@ class HttpHandler(BaseHTTPRequestHandler):
if page == 'wallet':
return page_wallet(self, url_split, post_string)
if page == 'settings':
return self.page_settings(url_split, post_string)
return page_settings(self, url_split, post_string)
if page == 'error':
return self.page_error(url_split, post_string)
if page == 'info':

View File

@ -43,14 +43,16 @@
<div class="pb-6 border-coolGray-100">
<div class="flex flex-wrap items-center justify-between -m-2">
<div class="w-full pt-2">
<!-- Chart-->
<div class="mb-10 mt-8 {{ chart }}">
{% if show_chart %}
<div class="mb-10 mt-8">
<div id="price-chart"></div>
<script src="/static/js/chart.js"></script>
<script>
CryptoCharts.roiComparison({
chart_id: "price-chart",
cryptocompare_api_key: "cd7600e7b5fdd99c6f900673ff0ee8f64d6d4219a4bb87191ad4a2e3fc65d7f4", // Todo @ in settings/general user can set api_key
cryptocompare_api_key: "{{chart_api_key}}",
cryptocompare_tickers: ["BTC", "PART", "DASH", "PIVX", "XMR", "LTC", "FIRO"],
last_days: 30,
axes: true,
@ -210,6 +212,7 @@
</script>
</div>
<!-- Chart -->
{% endif %}
<form method="post">
<div class="flex justify-between items-center pb-4 bg-white">
<div class="bg-white bg-opacity-60 rounded-b-md">

View File

@ -42,9 +42,9 @@
<div class="w-full pt-2">
<div class="mb-10 border-b border-gray-200">
<ul class="flex flex-wrap -mb-px text-sm font-medium text-center" id="myTab" data-tabs-toggle="#settingstab" role="tablist">
<li class="mr-2" role="presentation"> <a class="cursor-pointer inline-block p-4 rounded-t-lg border-b-2" id="profile-tab" data-tabs-target="#coins" role="tab" aria-controls="coins" aria-selected="false">Coins</a> </li>
<li class="mr-2" role="presentation"> <a class="cursor-pointer inline-block p-4 rounded-t-lg border-b-2 border-transparent hover:text-gray-600 hover:border-gray-300" id="general-tab" data-tabs-target="#general" role="tab" aria-controls="general" aria-selected="false">General</a> </li>
<li class="mr-2" role="presentation"> <a class="cursor-pointer inline-block p-4 rounded-t-lg border-b-2 border-transparent hover:text-gray-600 hover:border-gray-300" id="tor-tab" data-tabs-target="#tor" role="tab" aria-controls="tor" aria-selected="false">Tor</a> </li>
<li class="mr-2" role="presentation"> <a class="cursor-pointer inline-block p-4 rounded-t-lg border-b-2" id="profile-tab" data-tabs-target="#coins" role="tab" aria-controls="coins" aria-selected={% if active_tab == 'default' %}"true"{% else %}"false"{% endif %}>Coins</a> </li>
<li class="mr-2" role="presentation"> <a class="cursor-pointer inline-block p-4 rounded-t-lg border-b-2 border-transparent hover:text-gray-600 hover:border-gray-300" id="general-tab" data-tabs-target="#general" role="tab" aria-controls="general" aria-selected={% if active_tab == 'general' %}"true"{% else %}"false"{% endif %}>General</a> </li>
<li class="mr-2" role="presentation"> <a class="cursor-pointer inline-block p-4 rounded-t-lg border-b-2 border-transparent hover:text-gray-600 hover:border-gray-300" id="tor-tab" data-tabs-target="#tor" role="tab" aria-controls="tor" aria-selected={% if active_tab == 'tor' %}"true"{% else %}"false"{% endif %}>Tor</a> </li>
</ul>
</div>
<div id="settingstab">
@ -207,9 +207,6 @@
</div>
{% endif %}
</div>
</div>
@ -229,7 +226,7 @@
<h4 class="font-semibold text-black text-2xl align-middle">
<span class="mr-2 inline-block align-middle items-center justify-center w-8 h-7 bg-white-50 rounded">
<svg class="text-gray-500 w-7 h-7" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round" class="nc-icon-wrapper"><circle cx="12" cy="12" r="3" stroke="#3b82f6"></circle> <path d="M20,12a8.049,8.049,0,0,0-.188-1.713l2.714-2.055-2-3.464L17.383,6.094a7.987,7.987,0,0,0-2.961-1.719L14,1H10L9.578,4.375A7.987,7.987,0,0,0,6.617,6.094L3.474,4.768l-2,3.464,2.714,2.055a7.9,7.9,0,0,0,0,3.426L1.474,15.768l2,3.464,3.143-1.326a7.987,7.987,0,0,0,2.961,1.719L10,23h4l.422-3.375a7.987,7.987,0,0,0,2.961-1.719l3.143,1.326,2-3.464-2.714-2.055A8.049,8.049,0,0,0,20,12Z"></path></g></svg>
</span>General (todo)
</span>General
</h4> </div>
</div>
</section>
@ -250,9 +247,9 @@
<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="appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option value="true">True</option>
<option value="false">False</option>
<select name="debugmode" class="appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option {% if general_settings.debug %}selected{% endif %} value="true">True</option>
<option {% if not general_settings.debug %}selected{% endif %} value="false">False</option>
</select>
</div>
</div>
@ -266,9 +263,9 @@
<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="appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option value="true">True</option>
<option value="false">False</option>
<select name="debugui" class="appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option {% if general_settings.debug_ui %}selected{% endif %} value="true">True</option>
<option {% if not general_settings.debug_ui %}selected{% endif %} value="false">False</option>
</select>
</div>
</div>
@ -281,7 +278,7 @@
<div class="w-full md:w-0/12">
<div class="flex flex-wrap justify-end -m-1.5">
<div class="w-full md:w-auto p-1.5 ml-2">
<button name="" value="Apply" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 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"><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 stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" ><polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline> <circle cx="12" cy="12" r="11"></circle></g></svg> Apply</button>
<button name="apply_general" value="Apply" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 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"><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 stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" ><polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline> <circle cx="12" cy="12" r="11"></circle></g></svg> Apply</button>
</div>
</div>
</div>
@ -292,7 +289,7 @@
<h4 class="font-semibold text-black text-2xl align-middle">
<span class="mr-2 inline-block align-middle items-center justify-center w-9 h-8 bg-white-50 rounded">
<svg class="text-gray-500 w-7 h-7" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><g stroke-linecap="round" stroke-width="2" fill="none" stroke="#3b82f6" stroke-linejoin="round" class="nc-icon-wrapper"><rect x="10" y="14" width="4" height="9"></rect> <rect x="1" y="18" width="4" height="5"></rect> <rect x="19" y="10" width="4" height="13"></rect> <polyline data-cap="butt" points="3,10 8,5 12,9 20,1 " stroke="#3b82f6"></polyline> <polyline points=" 15,1 20,1 20,6 " stroke="#3b82f6"></polyline></g></svg>
</span>Chart (todo)
</span>Chart
</h4> </div>
</div>
</section>
@ -313,18 +310,18 @@
<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="appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option value="true">True</option>
<option value="false">False</option>
<select name="showchart" class="appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option {% if chart_settings.show_chart %}selected{% endif %} value="true">True</option>
<option {% if not chart_settings.show_chart %}selected{% endif %} value="false">False</option>
</select>
</div>
</div>
</td>
</tr>
<tr class="bg-white border-t hover:bg-gray-50">
<td class="py-4 px-6 bold">Chart API Key (URL)</td>
<td class="py-4 px-6 bold">Chart API Key</td>
<td class="py-4 pr-5">
<input type="text" class="w-52 appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block p-2.5" name="" min="3" max="32" value=""> </td>
<input name="chartapikey" type="text" class="w-52 appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block p-2.5" name="" min="3" max="32" value="{{chart_settings.chart_api_key}}"> </td>
</tr>
</table>
</div>
@ -333,7 +330,7 @@
<div class="w-full md:w-0/12">
<div class="flex flex-wrap justify-end -m-1.5">
<div class="w-full md:w-auto p-1.5 ml-2">
<button name="" value="Apply" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 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"><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 stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" ><polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline> <circle cx="12" cy="12" r="11"></circle></g></svg> Apply</button>
<button name="apply_chart" value="Apply" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 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"><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 stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" ><polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline> <circle cx="12" cy="12" r="11"></circle></g></svg> Apply</button>
</div>
</div>
</div>
@ -361,7 +358,7 @@
<path d="M14,2.256V1H10V2.256A3.949,3.949,0,0,1,7.658,5.891,8.979,8.979,0,0,0,2,14c0,4.971,4.477,9,10,9s10-4.029,10-9a8.978,8.978,0,0,0-5.658-8.109A3.95,3.95,0,0,1,14,2.256Z"></path>
</g>
</svg>
</span>Tor (todo)
</span>Tor
</h4> </div>
</div>
</section>
@ -374,22 +371,6 @@
<th scope="col">Value</th>
</tr>
</thead>
<tr>
<td class="py-4 px-6 bold w-96 bold">Use Tor</td>
<td class="py-4 pr-5">
<div class="w-1/5 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="appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option value="true">True</option>
<option value="false">False</option>
</select>
</div>
</div>
</td>
</tr>
<tr class="bg-white border-t hover:bg-gray-50">
<td class="py-4 px-6 bold w-96">Use Tor Proxy</td>
<td class="py-4 pr-5">
@ -398,9 +379,9 @@
<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="appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option value="true">True</option>
<option value="false">False</option>
<select name="usetorproxy" class="appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option {% if tor_settings.use_tor %}selected{% endif %} value="true">True</option>
<option {% if not tor_settings.use_tor %}selected{% endif %} value="false">False</option>
</select>
</div>
</div>
@ -409,17 +390,22 @@
<tr class="bg-white border-t hover:bg-gray-50">
<td class="py-4 px-6 bold w-96">Tor Proxy Host</td>
<td class="py-4 pr-5">
<input type="text" class="w-1/5 appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block p-2.5" name="" min="3" max="32" value=""> </td>
<input name="proxyhost" type="text" class="w-1/5 appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block p-2.5" name="" min="3" max="32" value="{{tor_settings.proxy_host}}"> </td>
</tr>
<tr class="bg-white border-t hover:bg-gray-50">
<td class="py-4 px-6 bold w-96">Tor Proxy Port</td>
<td class="py-4 pr-5">
<input type="text" class="w-1/5 appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block p-2.5" name="" min="3" max="32" value=""> </td>
<input name="proxyport" type="text" class="w-1/5 appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block p-2.5" name="" min="3" max="32" value="{{tor_settings.proxy_port}}"> </td>
</tr>
<tr class="bg-white border-t hover:bg-gray-50">
<td class="py-4 px-6 bold w-96">Tor Control Port</td>
<td class="py-4 pr-5">
<input type="text" class="w-1/5 appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block p-2.5" name="" min="3" max="32" value=""> </td>
<input name="controlport" type="text" class="w-1/5 appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block p-2.5" name="" min="3" max="32" value="{{tor_settings.control_port}}"> </td>
</tr>
<tr class="bg-white border-t hover:bg-gray-50">
<td class="py-4 px-6 bold w-96">Tor Control Password</td>
<td class="py-4 pr-5">
<input name="controlpwd" type="text" class="w-1/5 appearance-none bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block p-2.5" name="" min="3" max="32" value="{{tor_settings.control_password}}"> </td>
</tr>
</table>
</div>
@ -428,7 +414,7 @@
<div class="w-full md:w-0/12">
<div class="flex flex-wrap justify-end -m-1.5">
<div class="w-full md:w-auto p-1.5 ml-2">
<button name="" value="Apply" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 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"><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 stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" ><polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline> <circle cx="12" cy="12" r="11"></circle></g></svg> Apply</button>
<button name="apply_tor" value="Apply" type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 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"><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 stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round" ><polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline> <circle cx="12" cy="12" r="11"></circle></g></svg> Apply</button>
</div>
</div>
</div>

View File

@ -83,12 +83,12 @@ def page_automation_strategy(self, url_split, post_string):
raise ValueError('Bad strategy ID')
server = self.server
swap_client = self.server.swap_client
swap_client = server.swap_client
swap_client.checkSystemStatus()
summary = swap_client.getSummary()
messages = []
err_messages = []
strategy = swap_client.getAutomationStrategy(strategy_id)
formatted_strategy = {
@ -103,6 +103,7 @@ def page_automation_strategy(self, url_split, post_string):
template = server.env.get_template('automation_strategy.html')
return self.render_template(template, {
'messages': messages,
'err_messages': err_messages,
'strategy': formatted_strategy,
'summary': summary,
})

View File

@ -629,12 +629,18 @@ def page_offers(self, url_split, post_string, sent=False):
coins_from, coins_to = listAvailableCoins(swap_client, split_from=True)
chart_api_key = swap_client.settings.get('chart_api_key', '')
if chart_api_key == '':
chart_api_key_enc = swap_client.settings.get('chart_api_key_enc', '')
chart_api_key = 'cd7600e7b5fdd99c6f900673ff0ee8f64d6d4219a4bb87191ad4a2e3fc65d7f4' if chart_api_key_enc == '' else bytes.fromhex(chart_api_key_enc).decode('utf-8')
template = server.env.get_template('offers.html')
return self.render_template(template, {
'page_type': 'Your Offers' if sent else 'Network Order Book',
'page_type_description': '' if sent else '',
'messages': messages,
'chart': 'hidden' if sent else '',
'show_chart': False if sent else swap_client.settings.get('show_chart', True),
'chart_api_key': chart_api_key,
'coins_from': coins_from,
'coins': coins_to,
'messages': messages,

View File

@ -0,0 +1,156 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import html
from .util import (
getCoinName,
get_data_entry,
have_data_entry,
get_data_entry_or,
)
from basicswap.util import (
toBool,
InactiveCoin,
)
from basicswap.chainparams import (
Coins,
)
def page_settings(self, url_split, post_string):
server = self.server
swap_client = server.swap_client
swap_client.checkSystemStatus()
messages = []
err_messages = []
active_tab = 'default'
form_data = self.checkForm(post_string, 'settings', err_messages)
if form_data:
try:
if have_data_entry(form_data, 'apply_general'):
active_tab = 'general'
data = {
'debug': toBool(get_data_entry(form_data, 'debugmode')),
'debug_ui': toBool(get_data_entry(form_data, 'debugui')),
}
swap_client.editGeneralSettings(data)
if have_data_entry(form_data, 'apply_chart'):
active_tab = 'general'
data = {
'show_chart': toBool(get_data_entry(form_data, 'showchart')),
'chart_api_key': html.unescape(get_data_entry_or(form_data, 'chartapikey', '')),
}
swap_client.editGeneralSettings(data)
if have_data_entry(form_data, 'apply_tor'):
active_tab = 'tor'
# TODO: Detect if running in docker
raise ValueError('TODO: If running in docker see doc/tor.md to enable/disable tor.')
for name, c in swap_client.settings['chainclients'].items():
if have_data_entry(form_data, 'apply_' + name):
data = {'lookups': get_data_entry(form_data, 'lookups_' + name)}
if name == 'monero':
data['fee_priority'] = int(get_data_entry(form_data, 'fee_priority_' + name))
data['manage_daemon'] = True if get_data_entry(form_data, 'managedaemon_' + name) == 'true' else False
data['rpchost'] = get_data_entry(form_data, 'rpchost_' + name)
data['rpcport'] = int(get_data_entry(form_data, 'rpcport_' + name))
data['remotedaemonurls'] = get_data_entry(form_data, 'remotedaemonurls_' + name)
data['automatically_select_daemon'] = True if get_data_entry(form_data, 'autosetdaemon_' + name) == 'true' else False
else:
data['conf_target'] = int(get_data_entry(form_data, 'conf_target_' + name))
if name == 'particl':
data['anon_tx_ring_size'] = int(get_data_entry(form_data, 'rct_ring_size_' + name))
settings_changed, suggest_reboot = swap_client.editSettings(name, data)
if settings_changed is True:
messages.append('Settings applied.')
if suggest_reboot is True:
messages.append('Please restart BasicSwap.')
elif have_data_entry(form_data, 'enable_' + name):
swap_client.enableCoin(name)
display_name = getCoinName(swap_client.getCoinIdFromName(name))
messages.append(display_name + ' enabled, shutting down.')
swap_client.stopRunning()
elif have_data_entry(form_data, 'disable_' + name):
swap_client.disableCoin(name)
display_name = getCoinName(swap_client.getCoinIdFromName(name))
messages.append(display_name + ' disabled, shutting down.')
swap_client.stopRunning()
except InactiveCoin as ex:
err_messages.append('InactiveCoin {}'.format(Coins(ex.coinid).name))
except Exception as e:
err_messages.append(str(e))
chains_formatted = []
sorted_names = sorted(swap_client.settings['chainclients'].keys())
for name in sorted_names:
c = swap_client.settings['chainclients'][name]
try:
display_name = getCoinName(swap_client.getCoinIdFromName(name))
except Exception:
display_name = name
chains_formatted.append({
'name': name,
'display_name': display_name,
'lookups': c.get('chain_lookups', 'local'),
'manage_daemon': c.get('manage_daemon', 'Unknown'),
'connection_type': c.get('connection_type', 'Unknown'),
})
if name == 'monero':
chains_formatted[-1]['fee_priority'] = c.get('fee_priority', 0)
chains_formatted[-1]['manage_wallet_daemon'] = c.get('manage_wallet_daemon', 'Unknown')
chains_formatted[-1]['rpchost'] = c.get('rpchost', 'localhost')
chains_formatted[-1]['rpcport'] = int(c.get('rpcport', 18081))
chains_formatted[-1]['remotedaemonurls'] = '\n'.join(c.get('remote_daemon_urls', []))
chains_formatted[-1]['autosetdaemon'] = c.get('automatically_select_daemon', False)
else:
chains_formatted[-1]['conf_target'] = c.get('conf_target', 2)
if name == 'particl':
chains_formatted[-1]['anon_tx_ring_size'] = c.get('anon_tx_ring_size', 12)
else:
if c.get('connection_type', 'Unknown') == 'none':
if 'connection_type_prev' in c:
chains_formatted[-1]['can_reenable'] = True
else:
chains_formatted[-1]['can_disable'] = True
general_settings = {
'debug': swap_client.debug,
'debug_ui': swap_client.debug_ui,
}
if 'chart_api_key_enc' in swap_client.settings:
chart_api_key = html.escape(bytes.fromhex(swap_client.settings.get('chart_api_key_enc', '')).decode('utf-8'))
else:
chart_api_key = swap_client.settings.get('chart_api_key', '')
chart_settings = {
'show_chart': swap_client.settings.get('show_chart', True),
'chart_api_key': chart_api_key,
}
tor_control_password = '' if swap_client.tor_control_password is None else swap_client.tor_control_password
tor_settings = {
'use_tor': swap_client.use_tor_proxy,
'proxy_host': swap_client.tor_proxy_host,
'proxy_port': swap_client.tor_proxy_port,
'control_password': html.escape(tor_control_password),
'control_port': swap_client.tor_control_port,
}
template = server.env.get_template('settings.html')
return self.render_template(template, {
'messages': messages,
'err_messages': err_messages,
'summary': swap_client.getSummary(),
'chains': chains_formatted,
'general_settings': general_settings,
'chart_settings': chart_settings,
'tor_settings': tor_settings,
'active_tab': active_tab,
})

View File

@ -0,0 +1,105 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2022 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import json
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.select import Select
from selenium.webdriver.support import expected_conditions as EC
def test_html():
base_url = 'http://localhost:12701'
node2_url = 'http://localhost:12702'
driver = webdriver.Chrome(service=Service('/opt/chromedriver96'))
url = base_url + '/settings'
driver.get(url)
driver.find_element(By.ID, 'general-tab').click()
wait = WebDriverWait(driver, 10)
btn_apply_general = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_general')))
el = driver.find_element(By.NAME, 'debugmode')
selected_option = Select(el).first_selected_option
assert (selected_option.text == 'True')
for option in el.find_elements(By.TAG_NAME, 'option'):
if option.text == 'False':
option.click()
break
el = driver.find_element(By.NAME, 'debugui')
selected_option = Select(el).first_selected_option
assert (selected_option.text == 'False')
for option in el.find_elements(By.TAG_NAME, 'option'):
if option.text == 'True':
option.click()
break
btn_apply_general.click()
time.sleep(1)
settings_path = '/tmp/test_persistent/client0/basicswap.json'
with open(settings_path) as fs:
settings = json.load(fs)
assert (settings['debug'] is False)
assert (settings['debug_ui'] is True)
el = driver.find_element(By.NAME, 'showchart')
selected_option = Select(el).first_selected_option
assert (selected_option.text == 'True')
for option in el.find_elements(By.TAG_NAME, 'option'):
if option.text == 'False':
option.click()
break
difficult_text = '`~!@#$%^&*()-_=+[{}]\\|;:\'",<>./? '
el = driver.find_element(By.NAME, 'chartapikey')
el.send_keys(difficult_text)
btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_chart')))
btn_apply_chart.click()
time.sleep(1)
settings_path = '/tmp/test_persistent/client0/basicswap.json'
with open(settings_path) as fs:
settings = json.load(fs)
assert (settings['show_chart'] is False)
chart_api_key = bytes.fromhex(settings.get('chart_api_key_enc', '')).decode('utf-8')
assert (chart_api_key == difficult_text)
hex_text = 'cd7600e7b5fdd99c6f900673ff0ee8f64d6d4219a4bb87191ad4a2e3fc65d7f4'
el = driver.find_element(By.NAME, 'chartapikey')
el.clear()
el.send_keys(hex_text)
btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_chart')))
btn_apply_chart.click()
time.sleep(1)
el = driver.find_element(By.NAME, 'chartapikey')
assert el.get_property('value') == hex_text
settings_path = '/tmp/test_persistent/client0/basicswap.json'
with open(settings_path) as fs:
settings = json.load(fs)
assert (settings.get('chart_api_key') == hex_text)
driver.close()
print('Done.')
if __name__ == '__main__':
test_html()

View File

@ -7,7 +7,7 @@
"""
cd /tmp
wget -4 https://chromedriver.storage.googleapis.com/105.0.5195.52/chromedriver_linux64.zip
wget -4 https://chromedriver.storage.googleapis.com/107.0.5304.62/chromedriver_linux64.zip
7z x chromedriver_linux64.zip
sudo mv chromedriver /opt/chromedriver96

View File

@ -425,7 +425,7 @@ class Test(BaseTest):
'address': ltc_addr,
'subfee': False,
}
json_rv = read_json_api('json/wallets/ltc/withdraw', TEST_HTTP_PORT + 0, post_json)
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json)
assert (len(json_rv['txid']) == 64)
def test_13_itx_refund(self):