diff --git a/FireWalletBrowser.bsdesign b/FireWalletBrowser.bsdesign index e4d7098..3e627ef 100644 Binary files a/FireWalletBrowser.bsdesign and b/FireWalletBrowser.bsdesign differ diff --git a/account.py b/account.py index 83a3de1..76892af 100644 --- a/account.py +++ b/account.py @@ -460,6 +460,23 @@ def isOwnDomain(account, name: str): return True return False +def isOwnPrevout(account, prevout: dict): + if 'hash' not in prevout or 'index' not in prevout: + return False + # Get the address from the prevout + address = getAddressFromCoin(prevout['hash'], prevout['index']) + # Select the account + hsw.rpc_selectWallet(account) + account = hsw.rpc_getAccount(address) + + if 'error' in account and account['error'] is not None: + return False + if 'result' not in account: + return False + if account['result'] == 'default': + return True + return False + def getDomain(domain: str): # Get the domain @@ -1155,6 +1172,80 @@ def createBatch(account, batch): } } +# region Mempool +def getMempoolTxs(): + # hsd-cli rpc getrawmempool + response = hsd.rpc_getRawMemPool() + if 'error' in response and response['error'] is not None: + return [] + + return response['result'] if 'result' in response else [] + + +def getMempoolBids(): + mempoolTxs = getMempoolTxs() + bids = {} + for txid in mempoolTxs: + tx = hsd.getTxByHash(txid) + if 'error' in tx and tx['error'] is not None: + print(f"Error getting tx {txid}: {tx['error']}") + continue + if 'outputs' not in tx: + print(f"Error getting outputs for tx {txid}") + continue + for output in tx['outputs']: + if output['covenant']['action'] not in ["BID", "REVEAL"]: + continue + if output['covenant']['action'] == "REVEAL": + # Try to find bid tx from inputs + namehash = output['covenant']['items'][0] + for txInput in tx['inputs']: + if txInput['coin']['covenant']['action'] != "BID": + continue + if txInput['coin']['covenant']['items'][0] != namehash: + continue + name = txInput['coin']['covenant']['items'][2] + # Convert name from hex to ascii + name = bytes.fromhex(name).decode('ascii') + + bid = { + 'txid': txid, + 'lockup': txInput['coin']['value'], + 'revealed': True, + 'height': -1, + 'value': output['value'], + 'sort_value': txInput['coin']['value'], + 'owner': "Unknown" + } + if name not in bids: + bids[name] = [] + bids[name].append(bid) + continue + + name = output['covenant']['items'][2] + # Convert name from hex to ascii + name = bytes.fromhex(name).decode('ascii') + if name not in bids: + bids[name] = [] + bid = { + 'txid': txid, + 'value': -1000000, # Default value if not found + 'lockup': output['value'], + 'revealed': False, + 'height': -1, + 'sort_value': output['value'], + 'owner': "Unknown" + } + bids[name].append(bid) + return bids + + + + +# endregion + + + # region settingsAPIs def rescan(): diff --git a/main.py b/main.py index e263000..01f5241 100644 --- a/main.py +++ b/main.py @@ -46,10 +46,15 @@ def blocks_to_time(blocks: int) -> str: elif blocks < 144: hours = blocks // 6 minutes = (blocks % 6) * 10 + if minutes == 0: + return f"{hours} hrs" + return f"{hours} hrs {minutes} mins" else: days = blocks // 144 hours = (blocks % 144) // 6 + if hours == 0: + return f"{days} days" return f"{days} days {hours} hrs" @@ -913,17 +918,18 @@ def auction(domain): state = domainInfo['info']['state'] next_action = '' - bids = account_module.getBids(account,search_term) - if bids == []: - bids = "No bids found" - next_action = f'Rescan Auction' - else: - reveals = account_module.getReveals(account,search_term) - for reveal in reveals: - # Get TX - revealInfo = account_module.getRevealTX(reveal) - reveal['bid'] = revealInfo - bids = render.bids(bids,reveals) + # bids = account_module.getBids(account,search_term) + bids = [] + # if bids == []: + # bids = "No bids found" + # next_action = f'Rescan Auction' + # else: + # reveals = account_module.getReveals(account,search_term) + # for reveal in reveals: + # # Get TX + # revealInfo = account_module.getRevealTX(reveal) + # reveal['bid'] = revealInfo + # bids = render.bids(bids,reveals) stats = domainInfo['info']['stats'] if 'stats' in domainInfo['info'] else {} if state == 'CLOSED': @@ -944,10 +950,7 @@ def auction(domain): expires = domainInfo['info']['stats']['daysUntilExpire'] next = f"Expires in ~{expires} days" - own_domains = account_module.getDomains(account) - own_domains = [x['name'] for x in own_domains] - own_domains = [x.lower() for x in own_domains] - if search_term in own_domains: + if account_module.isOwnDomain(account,domain): next_action = f'Manage' elif state == "REVOKED": next = "Available Now" @@ -1542,7 +1545,66 @@ def api_hsd(function): return jsonify({"result": account_module.hsdVersion(False)}) if function == "height": return jsonify({"result": account_module.getBlockHeight()}) - + if function == "mempool": + return jsonify({"result": account_module.getMempoolTxs()}) + if function == "mempoolBids": + return jsonify({"result": account_module.getMempoolBids()}) + if function == "nextAuctionState": + # Get the domain from the query parameters + domain = request.args.get('domain') + if not domain: + return jsonify({"error": "No domain specified"}), 400 + domainInfo = account_module.getDomain(domain) + if 'error' in domainInfo and domainInfo['error'] != None: + return jsonify({"error": domainInfo['error']}), 400 + stats = domainInfo['info']['stats'] if 'stats' in domainInfo['info'] else {} + state = domainInfo['info']['state'] + next_action = "" + if state == 'CLOSED': + if not domainInfo['info']['registered']: + if account_module.isOwnDomain(account,domain): + print("Waiting to be registered") + state = 'PENDING REGISTER' + next = "Pending Register" + next_action = f'Register Domain' + + else: + print("Not registered") + state = 'AVAILABLE' + next = "Available Now" + next_action = f'Open Auction' + else: + state = 'REGISTERED' + expires = domainInfo['info']['stats']['daysUntilExpire'] + next = f"Expires in ~{expires} days" + elif state == "REVOKED": + next = "Available Now" + next_action = f'Open Auction' + elif state == 'OPENING': + next = f"Bidding opens in {str(stats['blocksUntilBidding'])} blocks (~{blocks_to_time(stats['blocksUntilBidding'])})" + elif state == 'BIDDING': + next = f"Reveal in {stats['blocksUntilReveal']} blocks (~{blocks_to_time(stats['blocksUntilReveal'])})" + if stats['blocksUntilReveal'] == 1: + next += "
Bidding no longer possible" + elif stats['blocksUntilReveal'] == 2: + next += "
LAST CHANCE TO BID" + elif stats['blocksUntilReveal'] == 3: + next += f"
Next block is last chance to bid" + elif stats['blocksUntilReveal'] < 6: + next += f"
Last chance to bid in {stats['blocksUntilReveal']-2} blocks" + + + elif state == 'REVEAL': + next = f"Reveal ends in {str(stats['blocksUntilClose'])} blocks (~{blocks_to_time(stats['blocksUntilClose'])})" + next_action = f'Reveal All' + + return jsonify({ + "state": state, + "next": next, + "next_action": next_action + }) + + return jsonify({"error": "Invalid function", "result": "Invalid function"}), 400 @@ -1661,6 +1723,21 @@ def api_wallet(function): "page": page }) + if function == "domainBids": + domain = request.args.get('domain') + if not domain: + return jsonify({"error": "No domain specified"}), 400 + bids = account_module.getBids(account,domain) + if bids == []: + return jsonify({"result": [], "error": "No bids found"}), 404 + else: + reveals = account_module.getReveals(account,domain) + for reveal in reveals: + # Get TX + revealInfo = account_module.getRevealTX(reveal) + reveal['bid'] = revealInfo + bids = render.bids(bids,reveals) + return jsonify({"result": bids}) if function == "icon": # Check if there is an icon diff --git a/render.py b/render.py index 680982b..3740cad 100644 --- a/render.py +++ b/render.py @@ -320,7 +320,6 @@ def bids(bids,reveals): 'value': value, 'sort_value': value if revealed else lockup # Use value for sorting if revealed, otherwise lockup }) - # Sort by the sort_value in descending order (highest first) bid_data.sort(key=lambda x: x['sort_value'], reverse=True) diff --git a/templates/auction.html b/templates/auction.html index cd5b559..967a9ce 100644 --- a/templates/auction.html +++ b/templates/auction.html @@ -66,9 +66,9 @@
-
{{next_action|safe}}
+
{{next_action|safe}}

{{rendered}}

-
{{next | safe}}
+
{{next | safe}}
@@ -96,11 +96,89 @@ - - {{bids | safe}} + + + +
+ Loading... +
+ Loading bids... + + + +