4 Commits

Author SHA1 Message Date
984e193ab7 feat: Try some more optimizations
All checks were successful
Build Docker / Build Image (push) Successful in 2m33s
2025-07-11 13:53:55 +10:00
70f0b2cf0e feat: Optimize some of the auction routes 2025-07-11 13:45:47 +10:00
33fc206c39 feat: Add red warning on auction page for potential outbids 2025-07-11 13:26:14 +10:00
4d4e0bf1e7 feat: Add api route for possible outbidded domains
All checks were successful
Build Docker / Build Image (push) Successful in 2m54s
2025-07-10 18:15:26 +10:00
5 changed files with 113 additions and 24 deletions

Binary file not shown.

View File

@@ -617,11 +617,24 @@ def getWalletStatus():
return "Error wallet ahead of node"
# Add a simple cache for bid data
_bid_cache = {}
_bid_cache_time = {}
_cache_duration = 60 # Cache duration in seconds
def getBids(account, domain="NONE"):
cache_key = f"{account}:{domain}"
current_time = time.time()
# Return cached data if available and fresh
if cache_key in _bid_cache and current_time - _bid_cache_time.get(cache_key, 0) < _cache_duration:
return _bid_cache[cache_key]
if domain == "NONE":
response = hsw.getWalletBids(account)
else:
response = hsw.getWalletBidsByName(domain, account)
# Add backup for bids with no value
bids = []
for bid in response:
@@ -632,30 +645,91 @@ def getBids(account, domain="NONE"):
if 'height' not in bid:
bid['height'] = 0
bids.append(bid)
# Cache the results
_bid_cache[cache_key] = bids
_bid_cache_time[cache_key] = current_time
return bids
def getPossibleOutbids(account):
# Get all bids
bids = getBids(account)
if 'error' in bids:
return []
# Get current height
current_height = getBlockHeight()
# Sort out bids older than 720 blocks
bids = [bid for bid in bids if (current_height - bid['height']) <= 720]
possible_outbids = []
processed_domains = set() # Track domains we've already processed
# Pre-fetch domain info for all domains in a single batch
domains_to_check = {bid['name'] for bid in bids}
domain_info_map = {}
for domain in domains_to_check:
domain_info = getDomain(domain)
if ('info' in domain_info and 'state' in domain_info['info'] and
domain_info['info']['state'] == "BIDDING"):
domain_info_map[domain] = domain_info
for bid in bids:
domain = bid['name']
# Skip if we've already processed this domain or it's not in bidding state
if domain in processed_domains or domain not in domain_info_map:
continue
processed_domains.add(domain)
# Get all bids for this domain in one call
domain_bids = getBids(account, domain)
# Find the highest bid we've made
current_highest_bid = bid['value']
for own_bid in domain_bids:
if own_bid["own"]:
current_highest_bid = max(current_highest_bid, own_bid['value'])
# Check if any unrevealed bids could outbid us
for domain_bid in domain_bids:
if domain_bid["own"] or domain_bid['value'] != -1000000:
continue # Skip our own bids or revealed bids
if current_highest_bid < domain_bid["lockup"]:
possible_outbids.append(domain)
break
return possible_outbids
def getReveals(account, domain):
return hsw.getWalletRevealsByName(domain, account)
def getPendingReveals(account):
bids = getBids(account)
domains = getDomains(account, False)
# Only get domains in REVEAL state to reduce API calls
domains = [d for d in getDomains(account, False) if d['state'] == "REVEAL"]
pending = []
for domain in domains:
if domain['state'] == "REVEAL":
reveals = getReveals(account, domain['name'])
for bid in bids:
if bid['name'] == domain['name']:
state_found = False
for reveal in reveals:
if reveal['own'] == True:
if bid['value'] == reveal['value']:
state_found = True
if not state_found:
# Process domains in REVEAL state
domain_names = {domain['name']: domain for domain in domains}
for bid in bids:
if bid['name'] in domain_names:
reveals = getReveals(account, bid['name'])
# Check if this bid has been revealed
bid_revealed = any(
reveal['own'] == True and bid['value'] == reveal['value']
for reveal in reveals
)
if not bid_revealed:
pending.append(bid)
return pending

16
main.py
View File

@@ -306,7 +306,15 @@ def auctions():
sort_domain = direction
sort_domain_next = reverseDirection(direction)
bidsHtml = render.bidDomains(bids,domains,sortbyDomain)
# Check if outbids set to true
outbids = request.args.get("outbids")
if outbids is not None and outbids.lower() == "true":
# Get outbid domains
outbids = account_module.getPossibleOutbids(account)
else:
outbids = []
bidsHtml = render.bidDomains(bids,domains,sortbyDomain,outbids)
plugins = ""
message = ''
if 'message' in request.args:
@@ -1638,6 +1646,12 @@ def api_wallet(function):
return send_file('templates/assets/img/HNS.png')
if function == "possibleOutbids":
return jsonify({"result": account_module.getPossibleOutbids(account)})
return jsonify({"error": "Invalid function", "result": "Invalid function"}), 400
@app.route('/api/v1/wallet/<function>/mobile', methods=["GET"])

View File

@@ -306,9 +306,8 @@ def bids(bids,reveals):
return html
def bidDomains(bids,domains, sortbyDomains=False):
def bidDomains(bids,domains, sortbyDomains=False, outbids=[]):
html = ''
if not sortbyDomains:
for bid in bids:
for domain in domains:
@@ -323,12 +322,14 @@ def bidDomains(bids,domains, sortbyDomains=False):
else:
bidDisplay = f'<b>{bidValue:,.2f}</b> HNS'
html += "<tr>"
if domain['name'] in outbids:
html += f"<td style='background-color: red;'><a class='text-decoration-none' style='color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));' href='/auction/{domain['name']}'>{renderDomain(domain['name'])}</a></td>"
else:
html += f"<td><a class='text-decoration-none' style='color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));' href='/auction/{domain['name']}'>{renderDomain(domain['name'])}</a></td>"
html += f"<td>{domain['state']}</td>"
html += f"<td style='white-space: nowrap;'>{bidDisplay}</td>"
html += f"<td class='hide-mobile'>{domain['height']:,}</td>"
html += f"<td class='hide-mobile'>{bid['height']:,}</td>"
html += "</tr>"
else:
for domain in domains:
@@ -344,7 +345,7 @@ def bidDomains(bids,domains, sortbyDomains=False):
html += f"<td><a class='text-decoration-none' style='color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));' href='/auction/{domain['name']}'>{renderDomain(domain['name'])}</a></td>"
html += f"<td>{domain['state']}</td>"
html += f"<td>{bidDisplay}</td>"
html += f"<td class='hide-mobile'>{domain['height']:,}</td>"
html += f"<td class='hide-mobile'>{bid['height']:,}</td>"
html += "</tr>"
return html

View File

@@ -1 +1 @@
function createCard(e,n,t){if(document.getElementById(t)&&document.getElementById(t).remove(),n<=0)return;const a=document.createElement("div");a.classList.add("col-md-6","col-xl-3","mb-4"),a.id=t,html=`\n <div class="card shadow border-start-warning py-2">\n <div class="card-body">\n <div class="row align-items-center no-gutters">\n <div class="col me-2">\n <div class="text-uppercase text-warning fw-bold text-xs mb-1"><span>${e}</span></div>\n <div class="text-dark fw-bold h5 mb-0"><span id="${e}">${n}</span></div>\n </div>\n <div class="col"><a class="btn btn-primary" role="button" href="/all/${t.toLowerCase()}">${t} All</a></div>\n <div class="col-auto"><svg class="fa-2x text-gray-300" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="1em" viewBox="0 0 24 24" width="1em" fill="currentColor">\n <g>\n <rect fill="none" height="24" width="24"></rect>\n </g>\n <g>\n <path d="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M7,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C8.5,12.83,7.83,13.5,7,13.5z M12,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C13.5,12.83,12.83,13.5,12,13.5z M17,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C18.5,12.83,17.83,13.5,17,13.5z"></path>\n </g>\n </svg></div>\n </div>\n </div>`,a.innerHTML=html,document.getElementById("actions-row").appendChild(a)}async function updateActions(){const e={Finalize:"Pending Finalizes",Register:"Pending Register",Redeem:"Pending Redeem",Reveal:"Pending Reveal"};for(const n in e){const t=await request(`wallet/pending${n}`);"Error"!=t&&createCard(e[n],t.length,n)}}window.addEventListener("load",(async()=>{updateActions()})),setInterval((async function(){updateActions()}),2e4);
function createCard(e,n,t){if(document.getElementById(t)&&document.getElementById(t).remove(),n<=0)return;const s=document.createElement("div");s.classList.add("col-md-6","col-xl-3","mb-4"),s.id=t,html=`\n <div class="card shadow border-start-warning py-2">\n <div class="card-body">\n <div class="row align-items-center no-gutters">\n <div class="col me-2">\n <div class="text-uppercase text-warning fw-bold text-xs mb-1"><span>${e}</span></div>\n <div class="text-dark fw-bold h5 mb-0"><span id="${e}">${n}</span></div>\n </div>\n <div class="col"><a class="btn btn-primary" role="button" href="/all/${t.toLowerCase()}">${t} All</a></div>\n <div class="col-auto"><svg class="fa-2x text-gray-300" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="1em" viewBox="0 0 24 24" width="1em" fill="currentColor">\n <g>\n <rect fill="none" height="24" width="24"></rect>\n </g>\n <g>\n <path d="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M7,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C8.5,12.83,7.83,13.5,7,13.5z M12,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C13.5,12.83,12.83,13.5,12,13.5z M17,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C18.5,12.83,17.83,13.5,17,13.5z"></path>\n </g>\n </svg></div>\n </div>\n </div>`,s.innerHTML=html,document.getElementById("actions-row").appendChild(s)}async function updateActions(){const e={Finalize:"Pending Finalizes",Register:"Pending Register",Redeem:"Pending Redeem",Reveal:"Pending Reveal"},n=Object.keys(e).map((e=>request(`wallet/pending${e}`).then((n=>({id:e,result:n}))))),t=await Promise.all(n);for(const{id:n,result:s}of t)"Error"!==s&&createCard(e[n],s.length,n);const s=await request("wallet/possibleOutbids");if("Error"===s)return;const d=document.getElementById("outbids");if(d&&d.remove(),s.length<=0)return;const i=document.createElement("div");i.classList.add("col-md-6","col-xl-3","mb-4"),i.id="outbids",i.innerHTML=`\n <div class="card shadow border-start-warning py-2">\n <div class="card-body">\n <div class="row align-items-center no-gutters">\n <div class="col me-2">\n <div class="text-uppercase text-warning fw-bold text-xs mb-1"><span>Names with possible outbids</span></div>\n <div class="text-dark fw-bold h5 mb-0"><span id="outbids-count">${s.length}</span></div>\n </div>\n <div class="col"><a class="btn btn-primary" role="button" href="/auctions?outbids=true">Show All</a></div>\n <div class="col-auto">\n <svg class="fa-2x text-gray-300" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="1em" viewBox="0 0 24 24" width="1em" fill="currentColor">\n <g><rect fill="none" height="24" width="24"></rect></g>\n <g>\n <path d="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M7,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C8.5,12.83,7.83,13.5,7,13.5z M12,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C13.5,12.83,12.83,13.5,12,13.5z M17,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C18.5,12.83,17.83,13.5,17,13.5z"></path>\n </g>\n </svg>\n </div>\n </div>\n </div>\n </div>\n `,document.getElementById("actions-row").appendChild(i)}window.addEventListener("load",(async()=>{updateActions()})),setInterval((async function(){updateActions()}),2e4);