Compare commits
12 Commits
feat/loggi
...
fix/balanc
| Author | SHA1 | Date | |
|---|---|---|---|
|
c4cd2bc443
|
|||
|
608933c228
|
|||
|
d9e847a995
|
|||
|
15d919ca97
|
|||
|
aa52911823
|
|||
|
2ee294cab8
|
|||
|
19771fe30d
|
|||
|
12d3958b9d
|
|||
|
d20fc1eb55
|
|||
|
148e5f325a
|
|||
|
6442aa4df6
|
|||
|
2e86e64dd0
|
BIN
FireWalletBrowser.bsdesign
LFS
BIN
FireWalletBrowser.bsdesign
LFS
Binary file not shown.
67
account.py
67
account.py
@@ -45,9 +45,7 @@ if HSD_INTERNAL_NODE:
|
|||||||
HSD_API = "firewallet-" + str(int(time.time()))
|
HSD_API = "firewallet-" + str(int(time.time()))
|
||||||
HSD_IP = "localhost"
|
HSD_IP = "localhost"
|
||||||
|
|
||||||
SHOW_EXPIRED = os.getenv("SHOW_EXPIRED")
|
SHOW_EXPIRED = os.getenv("SHOW_EXPIRED","false").lower() in ["1","true","yes"]
|
||||||
if SHOW_EXPIRED is None:
|
|
||||||
SHOW_EXPIRED = False
|
|
||||||
|
|
||||||
HSD_PROCESS = None
|
HSD_PROCESS = None
|
||||||
SPV_MODE = None
|
SPV_MODE = None
|
||||||
@@ -95,6 +93,7 @@ def hsdConnected():
|
|||||||
def hsdVersion(format=True):
|
def hsdVersion(format=True):
|
||||||
info = hsd.getInfo()
|
info = hsd.getInfo()
|
||||||
if 'error' in info:
|
if 'error' in info:
|
||||||
|
logger.error(f"HSD connection error: {info.get('error', 'Unknown error')}")
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
# Check if SPV mode is enabled
|
# Check if SPV mode is enabled
|
||||||
@@ -118,9 +117,12 @@ def check_account(cookie: str | None):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
account = cookie.split(":")[0]
|
account = cookie.split(":")[0]
|
||||||
|
if len(account) < 1:
|
||||||
|
return False
|
||||||
# Check if the account is valid
|
# Check if the account is valid
|
||||||
info = hsw.getAccountInfo(account, 'default')
|
info = hsw.getAccountInfo(account, 'default')
|
||||||
if 'error' in info:
|
if 'error' in info:
|
||||||
|
logger.error(f"HSW error checking account {account}: {info.get('error', 'Unknown error')}")
|
||||||
return False
|
return False
|
||||||
return account
|
return account
|
||||||
|
|
||||||
@@ -364,7 +366,7 @@ def getBalance(account: str):
|
|||||||
available = available / 1000000
|
available = available / 1000000
|
||||||
logger.debug(f"Initial balance for account {account}: total={total}, available={available}, locked={locked}")
|
logger.debug(f"Initial balance for account {account}: total={total}, available={available}, locked={locked}")
|
||||||
|
|
||||||
domains = getDomains(account)
|
domains = getDomains(account,True,True)
|
||||||
domainValue = 0
|
domainValue = 0
|
||||||
domains_to_update = [] # Track domains that need cache updates
|
domains_to_update = [] # Track domains that need cache updates
|
||||||
|
|
||||||
@@ -471,22 +473,27 @@ def getPendingTX(account: str):
|
|||||||
return pending
|
return pending
|
||||||
|
|
||||||
|
|
||||||
def getDomains(account, own=True):
|
def getDomains(account, own: bool = True, expired: bool = SHOW_EXPIRED):
|
||||||
if own:
|
if own:
|
||||||
response = requests.get(get_wallet_api_url(f"/wallet/{account}/name?own=true"))
|
response = requests.get(get_wallet_api_url(f"/wallet/{account}/name?own=true"))
|
||||||
else:
|
else:
|
||||||
response = requests.get(get_wallet_api_url(f"/wallet/{account}/name"))
|
response = requests.get(get_wallet_api_url(f"/wallet/{account}/name"))
|
||||||
info = response.json()
|
info = response.json()
|
||||||
|
|
||||||
if SHOW_EXPIRED:
|
if expired:
|
||||||
return info
|
return info
|
||||||
|
|
||||||
# Remove any expired domains
|
# Remove any expired domains
|
||||||
domains = []
|
domains = []
|
||||||
for domain in info:
|
for domain in info:
|
||||||
if 'stats' in domain:
|
if 'stats' in domain and domain['stats'] is not None:
|
||||||
if 'daysUntilExpire' in domain['stats']:
|
if 'daysUntilExpire' in domain['stats']:
|
||||||
if domain['stats']['daysUntilExpire'] < 0:
|
if domain['stats']['daysUntilExpire'] < 0:
|
||||||
|
logger.debug(f"Excluding expired domain: {domain['name']} due to daysUntilExpire")
|
||||||
|
continue
|
||||||
|
if 'blocksSinceExpired' in domain['stats']:
|
||||||
|
if domain['stats']['blocksSinceExpired'] > 0:
|
||||||
|
logger.debug(f"Excluding expired domain: {domain['name']} due to blocksSinceExpired")
|
||||||
continue
|
continue
|
||||||
domains.append(domain)
|
domains.append(domain)
|
||||||
|
|
||||||
@@ -583,6 +590,7 @@ def getTransactions(account, page=1, limit=100):
|
|||||||
return []
|
return []
|
||||||
info = hsw.getWalletTxHistory(account)
|
info = hsw.getWalletTxHistory(account)
|
||||||
if 'error' in info:
|
if 'error' in info:
|
||||||
|
logger.error(f"Error getting transactions for account {account}: {info['error']}")
|
||||||
return []
|
return []
|
||||||
return info[::-1]
|
return info[::-1]
|
||||||
|
|
||||||
@@ -916,6 +924,7 @@ def register(account, domain):
|
|||||||
def getNodeSync():
|
def getNodeSync():
|
||||||
response = hsd.getInfo()
|
response = hsd.getInfo()
|
||||||
if 'error' in response:
|
if 'error' in response:
|
||||||
|
logger.error(f"Error getting node sync status: {response['error']}")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
sync = response['chain']['progress']*100
|
sync = response['chain']['progress']*100
|
||||||
@@ -923,11 +932,14 @@ def getNodeSync():
|
|||||||
return sync
|
return sync
|
||||||
|
|
||||||
|
|
||||||
def getWalletStatus():
|
def getWalletStatus(verbose: bool = False):
|
||||||
response = hsw.rpc_getWalletInfo()
|
response = hsw.rpc_getWalletInfo()
|
||||||
|
|
||||||
if 'error' in response and response['error'] is not None:
|
if 'error' in response and response['error'] is not None:
|
||||||
return "Error"
|
return "Error"
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
return response.get('result', {})
|
||||||
# return response
|
# return response
|
||||||
walletHeight = response['result']['height']
|
walletHeight = response['result']['height']
|
||||||
# Get the current block height
|
# Get the current block height
|
||||||
@@ -1564,9 +1576,15 @@ def getMempoolBids():
|
|||||||
|
|
||||||
|
|
||||||
# region settingsAPIs
|
# region settingsAPIs
|
||||||
def rescan():
|
def rescan(height:int = 0):
|
||||||
try:
|
try:
|
||||||
response = hsw.walletRescan(0)
|
response = hsw.walletRescan(height)
|
||||||
|
if 'success' in response and response['success'] is False:
|
||||||
|
return {
|
||||||
|
"error": {
|
||||||
|
"message": "Rescan already in progress"
|
||||||
|
}
|
||||||
|
}
|
||||||
return response
|
return response
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {
|
return {
|
||||||
@@ -1941,13 +1959,17 @@ def hsdStart():
|
|||||||
cmd.append(flag)
|
cmd.append(flag)
|
||||||
|
|
||||||
# Launch process
|
# Launch process
|
||||||
HSD_PROCESS = subprocess.Popen(
|
try:
|
||||||
cmd,
|
HSD_PROCESS = subprocess.Popen(
|
||||||
cwd=os.getcwd(),
|
cmd,
|
||||||
text=True
|
cwd=os.getcwd(),
|
||||||
)
|
text=True
|
||||||
|
)
|
||||||
|
|
||||||
logger.info(f"HSD started with PID {HSD_PROCESS.pid}")
|
logger.info(f"HSD started with PID {HSD_PROCESS.pid}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to start HSD: {str(e)}", exc_info=True)
|
||||||
|
return
|
||||||
|
|
||||||
atexit.register(hsdStop)
|
atexit.register(hsdStop)
|
||||||
|
|
||||||
@@ -1959,6 +1981,19 @@ def hsdStart():
|
|||||||
logger.error(f"Failed to set signal handlers: {str(e)}", exc_info=True)
|
logger.error(f"Failed to set signal handlers: {str(e)}", exc_info=True)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def hsdRunning() -> bool:
|
||||||
|
global HSD_PROCESS
|
||||||
|
if not HSD_INTERNAL_NODE:
|
||||||
|
return False
|
||||||
|
if HSD_PROCESS is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Check if process has terminated
|
||||||
|
poll_result = HSD_PROCESS.poll()
|
||||||
|
if poll_result is not None:
|
||||||
|
logger.error(f"HSD process has terminated with exit code: {poll_result}")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def hsdStop():
|
def hsdStop():
|
||||||
global HSD_PROCESS
|
global HSD_PROCESS
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ SHOW_EXPIRED=false
|
|||||||
EXPLORER_TX=https://shakeshift.com/transaction/
|
EXPLORER_TX=https://shakeshift.com/transaction/
|
||||||
DISABLE_WALLETDNS=false
|
DISABLE_WALLETDNS=false
|
||||||
INTERNAL_HSD=false
|
INTERNAL_HSD=false
|
||||||
|
LOG_LEVEL=WARNING
|
||||||
201
main.py
201
main.py
@@ -7,13 +7,9 @@ from flask import Flask, make_response, redirect, request, jsonify, render_templ
|
|||||||
import os
|
import os
|
||||||
import dotenv
|
import dotenv
|
||||||
import requests
|
import requests
|
||||||
import account as account_module
|
|
||||||
import render
|
|
||||||
import re
|
import re
|
||||||
from flask_qrcode import QRcode
|
from flask_qrcode import QRcode
|
||||||
import domainLookup
|
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import plugin as plugins_module
|
|
||||||
import gitinfo
|
import gitinfo
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
@@ -22,18 +18,6 @@ from logging.handlers import RotatingFileHandler
|
|||||||
|
|
||||||
dotenv.load_dotenv()
|
dotenv.load_dotenv()
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
qrcode = QRcode(app)
|
|
||||||
|
|
||||||
|
|
||||||
# Change this if network fees change
|
|
||||||
fees = 0.02
|
|
||||||
revokeCheck = random.randint(100000,999999)
|
|
||||||
|
|
||||||
|
|
||||||
THEME = os.getenv("THEME", "black")
|
|
||||||
|
|
||||||
|
|
||||||
# Setup logging
|
# Setup logging
|
||||||
if not os.path.exists('logs'):
|
if not os.path.exists('logs'):
|
||||||
os.makedirs('logs')
|
os.makedirs('logs')
|
||||||
@@ -42,15 +26,33 @@ handler = RotatingFileHandler(log_file, maxBytes=1024*1024, backupCount=3)
|
|||||||
formatter = logging.Formatter('[%(asctime)s] %(levelname)s in %(module)s: %(message)s')
|
formatter = logging.Formatter('[%(asctime)s] %(levelname)s in %(module)s: %(message)s')
|
||||||
handler.setFormatter(formatter)
|
handler.setFormatter(formatter)
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
logger.setLevel(logging.WARNING)
|
|
||||||
|
log_level = os.getenv("LOG_LEVEL", "WARNING").upper()
|
||||||
|
if log_level in ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]:
|
||||||
|
logger.setLevel(getattr(logging, log_level))
|
||||||
|
else:
|
||||||
|
logger.setLevel(logging.WARNING)
|
||||||
|
|
||||||
# Disable werkzeug logging
|
# Disable werkzeug logging
|
||||||
logging.getLogger('werkzeug').setLevel(logging.INFO)
|
logging.getLogger('werkzeug').setLevel(logging.INFO)
|
||||||
logging.getLogger("urllib3").setLevel(logging.ERROR)
|
logging.getLogger("urllib3").setLevel(logging.ERROR)
|
||||||
logging.getLogger("requests").setLevel(logging.ERROR)
|
logging.getLogger("requests").setLevel(logging.ERROR)
|
||||||
|
|
||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
|
|
||||||
|
# Import after logger setup to capture logs from these modules
|
||||||
|
import render # noqa: E402
|
||||||
|
import domainLookup # noqa: E402
|
||||||
|
import account as account_module # noqa: E402
|
||||||
|
import plugin as plugins_module # noqa: E402
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
qrcode = QRcode(app)
|
||||||
|
|
||||||
|
# Change this if network fees change
|
||||||
|
fees = 0.02
|
||||||
|
revokeCheck = random.randint(100000,999999)
|
||||||
|
THEME = os.getenv("THEME", "black")
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
# Check if the user is logged in
|
# Check if the user is logged in
|
||||||
@@ -315,11 +317,12 @@ def auctions():
|
|||||||
sort_time_next = reverseDirection(direction)
|
sort_time_next = reverseDirection(direction)
|
||||||
|
|
||||||
# If older HSD version sort by domain height
|
# If older HSD version sort by domain height
|
||||||
if bids[0]['height'] == 0:
|
if len(bids) > 0:
|
||||||
domains = sorted(domains, key=lambda k: k['height'],reverse=reverse)
|
if bids[0]['height'] == 0:
|
||||||
sortbyDomain = True
|
domains = sorted(domains, key=lambda k: k['height'],reverse=reverse)
|
||||||
else:
|
sortbyDomain = True
|
||||||
bids = sorted(bids, key=lambda k: k['height'],reverse=reverse)
|
else:
|
||||||
|
bids = sorted(bids, key=lambda k: k['height'],reverse=reverse)
|
||||||
else:
|
else:
|
||||||
# Sort by domain
|
# Sort by domain
|
||||||
bids = sorted(bids, key=lambda k: k['name'],reverse=reverse)
|
bids = sorted(bids, key=lambda k: k['name'],reverse=reverse)
|
||||||
@@ -1235,12 +1238,18 @@ def settings_action(action):
|
|||||||
|
|
||||||
if action == "logs":
|
if action == "logs":
|
||||||
if not os.path.exists(log_file):
|
if not os.path.exists(log_file):
|
||||||
return jsonify({"error": "Log file not found"}), 404
|
return redirect("/settings?error=No log file found")
|
||||||
|
# Check if log file is empty
|
||||||
|
if os.path.getsize(log_file) == 0:
|
||||||
|
return redirect("/settings?error=Log file is empty")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(log_file, 'rb') as f:
|
with open(log_file, 'rb') as f:
|
||||||
response = requests.put(f"https://upload.woodburn.au/{os.path.basename(log_file)}", data=f)
|
response = requests.put(f"https://upload.woodburn.au/{os.path.basename(log_file)}", data=f,
|
||||||
|
headers={"Max-Days": "5"})
|
||||||
if response.status_code == 200 or response.status_code == 201:
|
if response.status_code == 200 or response.status_code == 201:
|
||||||
url = response.text.strip().split('\n')[-1]
|
token = response.text.strip().split('\n')[-1].split('/')[-2:]
|
||||||
|
url = f"https://upload.woodburn.au/inline/{token[0]}/{token[1]}"
|
||||||
logger.info(f"Log upload successful: {url}")
|
logger.info(f"Log upload successful: {url}")
|
||||||
return redirect(url)
|
return redirect(url)
|
||||||
else:
|
else:
|
||||||
@@ -1598,13 +1607,6 @@ def plugin_function(ptype,plugin,function):
|
|||||||
#region API Routes
|
#region API Routes
|
||||||
@app.route('/api/v1/hsd/<function>', methods=["GET"])
|
@app.route('/api/v1/hsd/<function>', methods=["GET"])
|
||||||
def api_hsd(function):
|
def api_hsd(function):
|
||||||
# Check if the user is logged in
|
|
||||||
if request.cookies.get("account") is None:
|
|
||||||
return jsonify({"error": "Not logged in"})
|
|
||||||
|
|
||||||
account = account_module.check_account(request.cookies.get("account"))
|
|
||||||
if not account:
|
|
||||||
return jsonify({"error": "Invalid account"})
|
|
||||||
|
|
||||||
if function == "sync":
|
if function == "sync":
|
||||||
return jsonify({"result": account_module.getNodeSync()})
|
return jsonify({"result": account_module.getNodeSync()})
|
||||||
@@ -1614,8 +1616,22 @@ def api_hsd(function):
|
|||||||
return jsonify({"result": account_module.getBlockHeight()})
|
return jsonify({"result": account_module.getBlockHeight()})
|
||||||
if function == "mempool":
|
if function == "mempool":
|
||||||
return jsonify({"result": account_module.getMempoolTxs()})
|
return jsonify({"result": account_module.getMempoolTxs()})
|
||||||
if function == "mempoolBids":
|
|
||||||
|
# Check if the user is logged in for all other functions
|
||||||
|
account = None
|
||||||
|
if request.cookies.get("account") is not None:
|
||||||
|
account = account_module.check_account(request.cookies.get("account"))
|
||||||
|
|
||||||
|
# Allow login using http basic auth
|
||||||
|
if account is None and request.authorization is not None:
|
||||||
|
account = account_module.check_account(f"{request.authorization.username}:{request.authorization.password}")
|
||||||
|
|
||||||
|
if not account:
|
||||||
|
return jsonify({"error": "Not logged in"})
|
||||||
|
|
||||||
|
if function == "mempoolBids": # This is a heavy function so only allow for logged in users
|
||||||
return jsonify({"result": account_module.getMempoolBids()})
|
return jsonify({"result": account_module.getMempoolBids()})
|
||||||
|
|
||||||
if function == "nextAuctionState":
|
if function == "nextAuctionState":
|
||||||
# Get the domain from the query parameters
|
# Get the domain from the query parameters
|
||||||
domain = request.args.get('domain')
|
domain = request.args.get('domain')
|
||||||
@@ -1699,20 +1715,29 @@ def api_hsd_mobile(function):
|
|||||||
|
|
||||||
@app.route('/api/v1/wallet/<function>', methods=["GET"])
|
@app.route('/api/v1/wallet/<function>', methods=["GET"])
|
||||||
def api_wallet(function):
|
def api_wallet(function):
|
||||||
# Check if the user is logged in
|
|
||||||
if request.cookies.get("account") is None:
|
|
||||||
return jsonify({"error": "Not logged in"})
|
|
||||||
|
|
||||||
account = account_module.check_account(request.cookies.get("account"))
|
|
||||||
if not account:
|
|
||||||
return jsonify({"error": "Invalid account"})
|
|
||||||
|
|
||||||
password = request.cookies.get("account","").split(":")[1]
|
|
||||||
if not account:
|
|
||||||
return jsonify({"error": "Invalid account"})
|
|
||||||
|
|
||||||
if function == "sync":
|
if function == "sync":
|
||||||
return jsonify({"result": account_module.getWalletStatus()})
|
# Check if arg verbose is set
|
||||||
|
verbose = request.args.get('verbose', 'false').lower() == 'true'
|
||||||
|
return jsonify({"result": account_module.getWalletStatus(verbose)})
|
||||||
|
|
||||||
|
# Check if the user is logged in for all other functions
|
||||||
|
account = None
|
||||||
|
password = None
|
||||||
|
if request.cookies.get("account") is not None:
|
||||||
|
account = account_module.check_account(request.cookies.get("account"))
|
||||||
|
password = request.cookies.get("account","").split(":")[1]
|
||||||
|
|
||||||
|
# Allow login using http basic auth
|
||||||
|
if account is None and request.authorization is not None:
|
||||||
|
account = account_module.check_account(f"{request.authorization.username}:{request.authorization.password}")
|
||||||
|
password = request.authorization.password
|
||||||
|
|
||||||
|
if not account:
|
||||||
|
return jsonify({"error": "Not logged in"})
|
||||||
|
|
||||||
|
if function == "balance":
|
||||||
|
return jsonify({"result": account_module.getBalance(account)})
|
||||||
|
|
||||||
if function == "available":
|
if function == "available":
|
||||||
return jsonify({"result": account_module.getBalance(account)['available']})
|
return jsonify({"result": account_module.getBalance(account)['available']})
|
||||||
@@ -1859,9 +1884,43 @@ def api_icon(account):
|
|||||||
def api_status():
|
def api_status():
|
||||||
# This doesn't require a login
|
# This doesn't require a login
|
||||||
# Check if the node is connected
|
# Check if the node is connected
|
||||||
if not account_module.hsdConnected():
|
node_status = {
|
||||||
return jsonify({"status":503,"error": "Node not connected"}), 503
|
"connected": account_module.hsdConnected(),
|
||||||
return jsonify({"status": 200,"result": "FireWallet is running"})
|
"internal": account_module.HSD_INTERNAL_NODE,
|
||||||
|
"internal_running": False,
|
||||||
|
"version": "N/A"
|
||||||
|
}
|
||||||
|
status = 200
|
||||||
|
error = None
|
||||||
|
node_status['version'] = account_module.hsdVersion(False)
|
||||||
|
|
||||||
|
|
||||||
|
if node_status['internal']:
|
||||||
|
node_status['internal_running'] = account_module.hsdRunning()
|
||||||
|
|
||||||
|
# If the node is not connected, return an error
|
||||||
|
if not node_status['connected']:
|
||||||
|
error = "Node not connected"
|
||||||
|
status = 503
|
||||||
|
if node_status['version'] == -1:
|
||||||
|
error = "Error connecting to HSD"
|
||||||
|
status = 503
|
||||||
|
if node_status['internal'] and not node_status['internal_running']:
|
||||||
|
error = "Internal node not running"
|
||||||
|
status = 503
|
||||||
|
|
||||||
|
commit = currentCurrentCommit()
|
||||||
|
return jsonify({
|
||||||
|
"node": node_status,
|
||||||
|
"version": {
|
||||||
|
"commit": commit,
|
||||||
|
"branch": currentCurrentBranch(),
|
||||||
|
"latest": runningLatestVersion(),
|
||||||
|
"url": f"https://git.woodburn.au/nathanwoodburn/firewalletbrowser/commit/{commit}" if commit != "Error" else None
|
||||||
|
},
|
||||||
|
"error": error,
|
||||||
|
"status": status
|
||||||
|
}), status
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -1906,6 +1965,45 @@ def renderDomain(name: str) -> str:
|
|||||||
except Exception:
|
except Exception:
|
||||||
return f"{name}/"
|
return f"{name}/"
|
||||||
|
|
||||||
|
def currentCurrentCommit() -> str:
|
||||||
|
"""
|
||||||
|
Get the current commit of the application.
|
||||||
|
"""
|
||||||
|
if not os.path.exists(".git"):
|
||||||
|
return "Error"
|
||||||
|
info = gitinfo.get_git_info()
|
||||||
|
if info is None:
|
||||||
|
return "Error"
|
||||||
|
commit = info['commit']
|
||||||
|
return commit
|
||||||
|
|
||||||
|
def currentCurrentBranch() -> str:
|
||||||
|
"""
|
||||||
|
Get the current branch of the application.
|
||||||
|
"""
|
||||||
|
if not os.path.exists(".git"):
|
||||||
|
return "Error"
|
||||||
|
info = gitinfo.get_git_info()
|
||||||
|
if info is None:
|
||||||
|
return "Error"
|
||||||
|
branch = info['refs']
|
||||||
|
return branch
|
||||||
|
|
||||||
|
def runningLatestVersion() -> bool:
|
||||||
|
"""
|
||||||
|
Check if the current version is the latest version.
|
||||||
|
"""
|
||||||
|
if not os.path.exists(".git"):
|
||||||
|
return False
|
||||||
|
info = gitinfo.get_git_info()
|
||||||
|
if info is None:
|
||||||
|
return False
|
||||||
|
branch = info['refs']
|
||||||
|
commit = info['commit']
|
||||||
|
if commit != latestVersion(branch):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def get_alerts(account:str) -> list:
|
def get_alerts(account:str) -> list:
|
||||||
"""
|
"""
|
||||||
Get alerts to show on the dashboard.
|
Get alerts to show on the dashboard.
|
||||||
@@ -1939,8 +2037,8 @@ def get_alerts(account:str) -> list:
|
|||||||
wallet_status = account_module.getWalletStatus()
|
wallet_status = account_module.getWalletStatus()
|
||||||
if wallet_status != "Ready":
|
if wallet_status != "Ready":
|
||||||
alerts.append({
|
alerts.append({
|
||||||
"name": "Wallet",
|
"name": "Wallet Not Synced",
|
||||||
"output": f"The wallet is not synced ({wallet_status}). Please wait for it to sync."
|
"output": "Please wait for it to sync."
|
||||||
})
|
})
|
||||||
# Try to read from notifications sqlite database
|
# Try to read from notifications sqlite database
|
||||||
if os.path.exists("user_data/notifications.db"):
|
if os.path.exists("user_data/notifications.db"):
|
||||||
@@ -2091,7 +2189,6 @@ if __name__ == '__main__':
|
|||||||
logger.setLevel(logging.DEBUG)
|
logger.setLevel(logging.DEBUG)
|
||||||
app.run(debug=True, host=host, port=port)
|
app.run(debug=True, host=host, port=port)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
app.run(host=host, port=port)
|
app.run(host=host, port=port)
|
||||||
|
|
||||||
def tests():
|
def tests():
|
||||||
|
|||||||
@@ -133,7 +133,7 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h4 class="card-title">About</h4>
|
<h4 class="card-title">About</h4>
|
||||||
<h6 class="text-muted mb-2 card-subtitle">FireWallet is a UI to allow easy connection with HSD created by <a href="https://nathan.woodburn.au" target="_blank">Nathan.Woodburn/</a> and freely available. Please contact him <a href="https://l.woodburn.au/contact" target="_blank">here</a> if you would like to request any features or report any bugs.<br>FireWallet version: <code>{{version}}</code></h6>
|
<h6 class="text-muted mb-2 card-subtitle">FireWallet is a UI to allow easy connection with HSD created by <a href="https://nathan.woodburn.au" target="_blank">Nathan.Woodburn/</a> and freely available. Please contact him <a href="https://l.woodburn.au/contact" target="_blank">here</a> if you would like to request any features or report any bugs.<br>FireWallet version: <code>{{version}}</code></h6>
|
||||||
<div class="text-center"><a href="https://github.com/nathanwoodburn/firewalletbrowser" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration:none;" target="_blank"><i class="icon ion-social-github" style="color: var(--bs-emphasis-color);"></i> Github</a><a href="https://firewallet.au" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration:none;" target="_blank"><i class="icon ion-ios-information" style="color: var(--bs-emphasis-color);"></i> Website</a><a href="https://l.woodburn.au/donate" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration:none;" target="_blank"><i class="icon ion-social-usd" style="color: var(--bs-emphasis-color);"></i> Donate to support development</a><a href="/settings/logs" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration:none;" target="_blank"><i class="icon ion-help" style="color: var(--bs-emphasis-color);"></i> Upload logs for debugging</a></div>
|
<div class="text-center"><a href="https://github.com/nathanwoodburn/firewalletbrowser" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration: none;display: inline-block;" target="_blank"><i class="icon ion-social-github" style="color: var(--bs-emphasis-color);"></i> Github</a><a href="https://firewallet.au" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration: none;display: inline-block;" target="_blank"><i class="icon ion-ios-information" style="color: var(--bs-emphasis-color);"></i> Website</a><a href="https://l.woodburn.au/donate" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration: none;display: inline-block;" target="_blank"><i class="icon ion-social-usd" style="color: var(--bs-emphasis-color);"></i> Donate to support development</a><a href="/settings/logs" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration: none;display: inline-block;" target="_blank"><i class="icon ion-help" style="color: var(--bs-emphasis-color);"></i> Upload logs for debugging</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user