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