GUI: Dynamic balances (WS) + Better Notifications (Toasts) + various fixes. (#332)

* GUI: Dynamic balances (WS) + various fixes.

* BLACK + FLAKE8

* Clean-up.

* Fix refresh intervals + Fix pending balance.

* Fix amounts scientific notation (1e-8)

* Better Notifications (Toasts)

* Removed duplicated code + Balance skip if the chain is still syncing.

* Fix MWEB doesnt show as pending + Various fixes.

* Fix: USD values are off with part blind.

* Fix: Percentage change buttons on wallet page.

* Cleanup debug on wallet page.

* Use ZMQ for part balances.

* Fix ZMQ config.

* Fix PART price in chart.
This commit is contained in:
Gerlof van Ek
2025-07-22 23:45:45 +02:00
committed by GitHub
parent d6ef4f2edb
commit a5cc83157d
24 changed files with 3199 additions and 302 deletions

View File

@@ -14,7 +14,7 @@ import traceback
import sys
from urllib import parse
from urllib.request import Request, urlopen
from .util import listAvailableCoins
from .util import listAvailableCoinsWithBalances
DEFAULT_AMM_CONFIG_FILE = "createoffers.json"
DEFAULT_AMM_STATE_FILE = "createoffers_state.json"
@@ -1286,7 +1286,7 @@ def page_amm(self, _, post_string):
except Exception as e:
err_messages.append(f"Failed to read state file: {str(e)}")
coins = listAvailableCoins(swap_client)
coins = listAvailableCoinsWithBalances(swap_client)
template = server.env.get_template("amm.html")
return self.render_template(

View File

@@ -16,6 +16,7 @@ from .util import (
have_data_entry,
inputAmount,
listAvailableCoins,
listAvailableCoinsWithBalances,
PAGE_LIMIT,
setCoinFilter,
set_pagination_filters,
@@ -526,7 +527,7 @@ def page_newoffer(self, url_split, post_string):
if swap_client.debug_ui:
messages.append("Debug mode active.")
coins_from, coins_to = listAvailableCoins(swap_client, split_from=True)
coins_from, coins_to = listAvailableCoinsWithBalances(swap_client, split_from=True)
addrs_from_raw = swap_client.listSMSGAddresses("offer_send_from")
addrs_to_raw = swap_client.listSMSGAddresses("offer_send_to")

View File

@@ -60,6 +60,38 @@ def page_settings(self, url_split, post_string):
),
}
swap_client.editGeneralSettings(data)
elif have_data_entry(form_data, "apply_notifications"):
active_tab = "notifications"
data = {
"notifications_new_offers": toBool(
get_data_entry_or(
form_data, "notifications_new_offers", "false"
)
),
"notifications_new_bids": toBool(
get_data_entry_or(form_data, "notifications_new_bids", "false")
),
"notifications_bid_accepted": toBool(
get_data_entry_or(
form_data, "notifications_bid_accepted", "false"
)
),
"notifications_balance_changes": toBool(
get_data_entry_or(
form_data, "notifications_balance_changes", "false"
)
),
"notifications_outgoing_transactions": toBool(
get_data_entry_or(
form_data, "notifications_outgoing_transactions", "false"
)
),
"notifications_duration": int(
get_data_entry_or(form_data, "notifications_duration", "20")
),
}
swap_client.editGeneralSettings(data)
messages.append("Notification settings applied.")
elif have_data_entry(form_data, "apply_tor"):
active_tab = "tor"
# TODO: Detect if running in docker
@@ -186,6 +218,27 @@ def page_settings(self, url_split, post_string):
"enabled_chart_coins": swap_client.settings.get("enabled_chart_coins", ""),
}
notification_settings = {
"notifications_new_offers": swap_client.settings.get(
"notifications_new_offers", False
),
"notifications_new_bids": swap_client.settings.get(
"notifications_new_bids", True
),
"notifications_bid_accepted": swap_client.settings.get(
"notifications_bid_accepted", True
),
"notifications_balance_changes": swap_client.settings.get(
"notifications_balance_changes", True
),
"notifications_outgoing_transactions": swap_client.settings.get(
"notifications_outgoing_transactions", True
),
"notifications_duration": swap_client.settings.get(
"notifications_duration", 20
),
}
tor_control_password = (
""
if swap_client.tor_control_password is None
@@ -209,6 +262,7 @@ def page_settings(self, url_split, post_string):
"chains": chains_formatted,
"general_settings": general_settings,
"chart_settings": chart_settings,
"notification_settings": notification_settings,
"tor_settings": tor_settings,
"active_tab": active_tab,
},

View File

@@ -659,6 +659,76 @@ def listAvailableCoins(swap_client, with_variants=True, split_from=False):
return coins
def listAvailableCoinsWithBalances(swap_client, with_variants=True, split_from=False):
swap_client.updateWalletsInfo()
wallets = swap_client.getCachedWalletsInfo()
coins_from = []
coins = []
for k, v in swap_client.coin_clients.items():
if k not in chainparams:
continue
if v["connection_type"] == "rpc":
balance = "0.0"
if k in wallets:
w = wallets[k]
if "balance" in w and "error" not in w and "no_data" not in w:
balance = w["balance"]
coin_entry = (int(k), getCoinName(k), balance)
coins.append(coin_entry)
if split_from:
coins_from.append(coin_entry)
if with_variants and k == Coins.PART:
for variant in (Coins.PART_ANON, Coins.PART_BLIND):
variant_balance = "0.0"
if k in wallets:
w = wallets[k]
if "error" not in w and "no_data" not in w:
if variant == Coins.PART_ANON and "anon_balance" in w:
variant_balance = w["anon_balance"]
elif variant == Coins.PART_BLIND and "blind_balance" in w:
variant_balance = w["blind_balance"]
variant_entry = (
int(variant),
getCoinName(variant),
variant_balance,
)
coins.append(variant_entry)
if split_from:
coins_from.append(variant_entry)
if with_variants and k == Coins.LTC:
for variant in (Coins.LTC_MWEB,):
variant_balance = "0.0"
if k in wallets:
w = wallets[k]
if (
"error" not in w
and "no_data" not in w
and "mweb_balance" in w
):
variant_balance = w["mweb_balance"]
variant_entry = (
int(variant),
getCoinName(variant),
variant_balance,
)
pass
if split_from:
return coins_from, coins
return coins
def checkAddressesOwned(swap_client, ci, wallet_info):
if "stealth_address" in wallet_info: