diff --git a/FireWalletBrowser.bsdesign b/FireWalletBrowser.bsdesign index eb14d1f..f64aeaa 100644 Binary files a/FireWalletBrowser.bsdesign and b/FireWalletBrowser.bsdesign differ diff --git a/account.py b/account.py index 53c46b3..4eb045c 100644 --- a/account.py +++ b/account.py @@ -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,6 +645,11 @@ 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): @@ -646,28 +664,41 @@ def getPossibleOutbids(account): # 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'] - - # Check to make sure that bidding is still happening - domain_info = getDomain(domain) - if 'info' not in domain_info or 'state' not in domain_info['info']: - print(f"Domain {domain} not found or no info available",flush=True) + + # 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 - if domain_info['info']['state'] != "BIDDING": - continue - - - current_highest_bid = bid['value'] + + 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"]: - current_highest_bid = max(current_highest_bid, domain_bid['value']) - continue - if domain_bid['value'] != -1000000: - print("Revealed bid") - continue + 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 @@ -677,24 +708,28 @@ def getPossibleOutbids(account): 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: - pending.append(bid) + + # 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 diff --git a/main.py b/main.py index f719f93..b46d052 100644 --- a/main.py +++ b/main.py @@ -249,84 +249,74 @@ def auctions(): if not account: return redirect("/logout") - - bids = account_module.getBids(account) - domains = account_module.getDomains(account,False) - - # Sort - sort = request.args.get("sort") - if sort == None: - sort = "time" - sort = sort.lower() - sort_price = "" - sort_price_next = "⬇" - sort_state = "" - sort_state_next = "⬇" - sort_domain = "" - sort_domain_next = "⬇" - sort_time = "" - sort_time_next = "⬇" - reverse = False - + # Get sort parameters with defaults + sort = request.args.get("sort", "time").lower() direction = request.args.get("direction") - if direction == None: - if sort == "time": - direction = "⬆" - else: - direction = "⬇" - - if direction == "⬆": - reverse = True - + if direction is None: + direction = "⬆" if sort == "time" else "⬇" + + reverse = (direction == "⬆") + + # Initialize sort indicators with a more efficient approach + sort_indicators = { + "price": ["", "⬇"], + "state": ["", "⬇"], + "domain": ["", "⬇"], + "time": ["", "⬇"] + } + # Set the current sort column's indicators + sort_indicators[sort][0] = direction + sort_indicators[sort][1] = reverseDirection(direction) + + # Efficiently retrieve data + bids = account_module.getBids(account) + domains = account_module.getDomains(account, False) + + # Determine if sorting by domains and apply appropriate sort sortbyDomain = False - + if sort == "price": - # Sort by price - bids = sorted(bids, key=lambda k: k['value'],reverse=reverse) - sort_price = direction - sort_price_next = reverseDirection(direction) + bids = sorted(bids, key=lambda k: k['value'], reverse=reverse) elif sort == "state": - sort_state = direction - sort_state_next = reverseDirection(direction) - domains = sorted(domains, key=lambda k: k['state'],reverse=reverse) + domains = sorted(domains, key=lambda k: k['state'], reverse=reverse) sortbyDomain = True elif sort == "time": - sort_time = direction - sort_time_next = reverseDirection(direction) - - # If older HSD version sort by domain height - if bids[0]['height'] == 0: - domains = sorted(domains, key=lambda k: k['height'],reverse=reverse) + # Handle older HSD versions that don't have height in bids + if bids and bids[0]['height'] == 0: + domains = sorted(domains, key=lambda k: k['height'], reverse=reverse) sortbyDomain = True else: - bids = sorted(bids, key=lambda k: k['height'],reverse=reverse) - else: - # Sort by domain - bids = sorted(bids, key=lambda k: k['name'],reverse=reverse) - sort_domain = direction - sort_domain_next = reverseDirection(direction) + bids = sorted(bids, key=lambda k: k['height'], reverse=reverse) + else: # Default to domain name sorting + bids = sorted(bids, key=lambda k: k['name'], reverse=reverse) - # Check if outbids set to true - outbids = request.args.get("outbids") - if outbids is not None and outbids.lower() == "true": - # Get outbid domains + # Get outbids only if explicitly requested + outbids = [] + if request.args.get("outbids", "").lower() == "true": outbids = account_module.getPossibleOutbids(account) - - - bidsHtml = render.bidDomains(bids,domains,sortbyDomain,outbids) - plugins = "" - message = '' - if 'message' in request.args: - message = request.args.get("message") - return render_template("auctions.html", account=account, domains=bidsHtml, - domainsMobile=bidsHtml, plugins=plugins, - domain_count=bidsHtml,sort_price=sort_price, - sort_state=sort_state,sort_domain=sort_domain, - sort_price_next=sort_price_next, - sort_state_next=sort_state_next,sort_domain_next=sort_domain_next, - bids=len(bids),message=message, - sort_time=sort_time,sort_time_next=sort_time_next) - + + # Generate HTML just once + bidsHtml = render.bidDomains(bids, domains, sortbyDomain, outbids) + + # Get message if present + message = request.args.get("message", "") + + return render_template("auctions.html", account=account, + domains=bidsHtml, + domainsMobile=bidsHtml, + plugins="", + domain_count=bidsHtml, + sort_price=sort_indicators["price"][0], + sort_state=sort_indicators["state"][0], + sort_domain=sort_indicators["domain"][0], + sort_time=sort_indicators["time"][0], + sort_price_next=sort_indicators["price"][1], + sort_state_next=sort_indicators["state"][1], + sort_domain_next=sort_indicators["domain"][1], + sort_time_next=sort_indicators["time"][1], + bids=len(bids), + message=message) +#endregion #region All Auctions @app.route('/reveal') diff --git a/render.py b/render.py index 9a85245..29d2705 100644 --- a/render.py +++ b/render.py @@ -306,47 +306,77 @@ def bids(bids,reveals): return html -def bidDomains(bids,domains, sortbyDomains=False, outbids=[]): +def bidDomains(bids, domains, sortbyDomains=False, outbids=[]): html = '' + + # Create lookup dictionaries for O(1) lookups instead of O(n) searches + domain_lookup = {d['name']: d for d in domains} + bid_lookup = {} + for bid in bids: + if bid['name'] not in bid_lookup or bid['value'] > bid_lookup[bid['name']]['value']: + bid_lookup[bid['name']] = bid + if not sortbyDomains: + # Process by bids first for bid in bids: - for domain in domains: - if bid['name'] == domain['name']: - lockup = bid['lockup'] - lockup = lockup / 1000000 - bidValue = bid['value'] / 1000000 - blind = lockup - bidValue + domain_name = bid['name'] + if domain_name not in domain_lookup: + continue + + domain = domain_lookup[domain_name] + + lockup = bid['lockup'] + lockup = lockup / 1000000 + bidValue = bid['value'] / 1000000 + blind = lockup - bidValue - if blind > 0: - bidDisplay = f'{bidValue:,.2f} (+{blind:,.2f}) HNS' - else: - bidDisplay = f'{bidValue:,.2f} HNS' - - html += "" - if domain['name'] in outbids: - html += f"{renderDomain(domain['name'])}" - else: - html += f"{renderDomain(domain['name'])}" - html += f"{domain['state']}" - html += f"{bidDisplay}" - html += f"{bid['height']:,}" - html += "" + if blind > 0: + bidDisplay = f'{bidValue:,.2f} (+{blind:,.2f}) HNS' + else: + bidDisplay = f'{bidValue:,.2f} HNS' + + html += "" + + # Efficiently check if domain is in outbids list + is_outbid = domain_name in outbids + td_style = " style='background-color: red;'" if is_outbid else "" + + html += f"{renderDomain(domain_name)}" + html += f"{domain['state']}" + html += f"{bidDisplay}" + html += f"{bid['height']:,}" + html += "" else: + # Process by domains first (for state sorting) for domain in domains: - for bid in bids: - if bid['name'] == domain['name']: - lockup = bid['lockup'] - lockup = lockup / 1000000 - bidValue = bid['value'] / 1000000 - blind = lockup - bidValue + domain_name = domain['name'] + if domain_name not in bid_lookup: + continue + + bid = bid_lookup[domain_name] + + lockup = bid['lockup'] + lockup = lockup / 1000000 + bidValue = bid['value'] / 1000000 + blind = lockup - bidValue - bidDisplay = f'{bidValue:,.2f} HNS + {blind:,.2f} HNS blind' - html += "" - html += f"{renderDomain(domain['name'])}" - html += f"{domain['state']}" - html += f"{bidDisplay}" - html += f"{bid['height']:,}" - html += "" + if blind > 0: + bidDisplay = f'{bidValue:,.2f} (+{blind:,.2f}) HNS' + else: + bidDisplay = f'{bidValue:,.2f} HNS' + + html += "" + + # Efficiently check if domain is in outbids list + is_outbid = domain_name in outbids + td_style = " style='background-color: red;'" if is_outbid else "" + + html += f"{renderDomain(domain_name)}" + html += f"{domain['state']}" + html += f"{bidDisplay}" + html += f"{bid['height']:,}" + html += "" + return html