From 9e02fd77744bd49c1db18c299ad6cf776641052c Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Fri, 29 Dec 2023 12:42:07 +1100 Subject: [PATCH] feat: Add some basic auction functions --- account.py | 46 +++++++++++++ main.py | 149 ++++++++++++++++++++++++++++++++++++++++- render.py | 20 ++++++ templates/auction.html | 115 +++++++++++++++++++++++++++++++ templates/confirm.html | 84 +++++++++++++++++++++++ 5 files changed, 411 insertions(+), 3 deletions(-) create mode 100644 templates/auction.html create mode 100644 templates/confirm.html diff --git a/account.py b/account.py index b7f822b..1db55d4 100644 --- a/account.py +++ b/account.py @@ -204,3 +204,49 @@ def getDNS(domain: str): def getNodeSync(): response = hsd.getInfo() return response['chain']['progress']*100 + + +def getBids(account, domain): + response = hsw.getWalletBidsByName(domain,account) + return response + +def rescan_auction(account,domain): + # Get height of the start of the auction + response = hsw.rpc_selectWallet(account) + + + response = hsd.rpc_getNameInfo(domain) + if 'result' not in response: + return { + "error": "Invalid domain" + } + if 'bidPeriodStart' not in response['result']['info']['stats']: + return { + "error": "Not in auction" + } + height = response['result']['info']['stats']['bidPeriodStart'] + response = hsw.rpc_importName(domain,height) + + return response + + +def bid(account,domain,bid,blind): + account_name = check_account(account) + password = ":".join(account.split(":")[1:]) + + if account_name == False: + return { + "error": "Invalid account" + } + + bid = int(bid)*1000000 + lockup = int(blind)*1000000 + bid + + try: + response = hsw.sendBID(account_name,password,domain,bid,lockup) + return response + except Exception as e: + return { + "error": str(e) + } + \ No newline at end of file diff --git a/main.py b/main.py index 4e6e145..8f44b7a 100644 --- a/main.py +++ b/main.py @@ -195,7 +195,6 @@ def search(): search_term=search_term,domain=search_term, state="AVAILABLE", next="Available Now") - state = domain['info']['state'] if state == 'CLOSED': if not domain['info']['registered']: @@ -206,12 +205,10 @@ def search(): expires = domain['info']['stats']['daysUntilExpire'] next = f"Expires in ~{expires} days" elif state == 'OPENING': - print(domain['info']['stats']) next = "Bidding opens in ~" + str(domain['info']['stats']['blocksUntilBidding']) + " blocks" elif state == 'BIDDING': next = "Reveal in ~" + str(domain['info']['stats']['blocksUntilReveal']) + " blocks" elif state == 'REVEAL': - print(domain['info']['stats']) next = "Reveal ends in ~" + str(domain['info']['stats']['blocksUntilClose']) + " blocks" @@ -285,6 +282,152 @@ def renew(domain): response = account_module.renewDomain(request.cookies.get("account"),domain) return redirect("/success?tx=" + response['hash']) + + +@app.route('/auction/') +def auction(domain): + # Check if the user is logged in + if request.cookies.get("account") is None: + return redirect("/login") + + account = account_module.check_account(request.cookies.get("account")) + if not account: + return redirect("/logout") + + search_term = domain.lower().strip() + # Convert emoji to punycode + search_term = domainLookup.emoji_to_punycode(search_term) + if len(search_term) == 0: + return redirect("/") + + domainInfo = account_module.getDomain(search_term) + + if 'error' in domainInfo: + return render_template("auction.html", account=account,sync=account_module.getNodeSync(), + search_term=search_term, domain=domainInfo['error']) + + if domainInfo['info'] is None: + next_action = f'Open Auction' + return render_template("auction.html", account=account, sync=account_module.getNodeSync(), + search_term=search_term,domain=search_term,next_action=next_action, + state="AVAILABLE", next="Open Auction") + + 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: + bids = render.bids(bids) + + + if state == 'CLOSED': + if not domainInfo['info']['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" + + 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: + next_action = f'Manage' + elif state == 'OPENING': + next = "Bidding opens in ~" + str(domainInfo['info']['stats']['blocksUntilBidding']) + " blocks" + elif state == 'BIDDING': + #! Check if the user has scanned the auction + + next = "Reveal in ~" + str(domainInfo['info']['stats']['blocksUntilReveal']) + " blocks" + elif state == 'REVEAL': + next = "Reveal ends in ~" + str(domainInfo['info']['stats']['blocksUntilClose']) + " blocks" + next_action = f'Reveal All' + + message = '' + if 'message' in request.args: + message = request.args.get("message") + + + return render_template("auction.html", account=account, sync=account_module.getNodeSync(), + search_term=search_term,domain=domainInfo['info']['name'], + raw=domainInfo,state=state, next=next, + next_action=next_action, bids=bids,error=message) + + +@app.route('/auction//scan') +def rescan_auction(domain): + # Check if the user is logged in + if request.cookies.get("account") is None: + return redirect("/login") + + account = account_module.check_account(request.cookies.get("account")) + if not account: + return redirect("/logout") + + domain = domain.lower() + + response = account_module.rescan_auction(account,domain) + print(response) + return redirect("/auction/" + domain) + +@app.route('/auction//bid') +def bid(domain): + # Check if the user is logged in + if request.cookies.get("account") is None: + return redirect("/login") + + + if not account_module.check_account(request.cookies.get("account")): + return redirect("/logout") + + domain = domain.lower() + + # Show confirm page + total = float(request.args.get('bid')) + float(request.args.get('blind')) + + action = f"Bid on {domain}/" + content = f"Are you sure you want to bid on {domain}/?" + content = "You are about to bid with the following details:

" + content += f"Bid: {request.args.get('bid')} HNS
" + content += f"Blind: {request.args.get('blind')} HNS
" + content += f"Total: {total} HNS (excluding fees)

" + + cancel = f"/auction/{domain}" + confirm = f"/auction/{domain}/bid/confirm?bid={request.args.get('bid')}&blind={request.args.get('blind')}" + + + + return render_template("confirm.html", account=account_module.check_account(request.cookies.get("account")), + sync=account_module.getNodeSync(),action=action, + domain=domain,content=content,cancel=cancel,confirm=confirm) + +@app.route('/auction//bid/confirm') +def bid_confirm(domain): + # Check if the user is logged in + if request.cookies.get("account") is None: + return redirect("/login") + + + if not account_module.check_account(request.cookies.get("account")): + return redirect("/logout") + + domain = domain.lower() + + # Send the bid + response = account_module.bid(request.cookies.get("account"),domain, + float(request.args.get('bid')), + float(request.args.get('blind'))) + print(response) + if 'error' in response: + return redirect("/auction/" + domain + "?message=" + response['error']) + + return redirect("/success?tx=" + response['hash']) + #endregion diff --git a/render.py b/render.py index 7b1d292..2ca71c0 100644 --- a/render.py +++ b/render.py @@ -134,3 +134,23 @@ def timestamp_to_readable_time(timestamp): dt_object = datetime.datetime.fromtimestamp(timestamp) readable_time = dt_object.strftime("%H:%M:%S %d %b %Y") return readable_time + +def bids(data): + html = '' + for bid in data: + lockup = bid['lockup'] + lockup = lockup / 1000000 + lockup = round(lockup, 2) + html += "" + html += f"{lockup} HNS" + # TODO If revealed + html += f"Hidden until reveal" + html += f"Hidden until reveal" + if bid['own']: + html += "You" + else: + html += "Unknown" + + html += "" + + return html \ No newline at end of file diff --git a/templates/auction.html b/templates/auction.html new file mode 100644 index 0000000..5e4a404 --- /dev/null +++ b/templates/auction.html @@ -0,0 +1,115 @@ + + + + + + + Auction - FireWallet + + + + + + + + + + + + + +
+ +
+
+ +

{{error}}

+
+
+
+
{{next_action|safe}}
+

{{domain}}/

+
{{next}}
+
+
+
+
+
+
+

Bid

+
+
+
+
+
+
+
+
+
+

Bids

+ + + + + + + + + + + {{bids | safe}} + +
Bid+BlindBidBlindOwner
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + + \ No newline at end of file diff --git a/templates/confirm.html b/templates/confirm.html new file mode 100644 index 0000000..69d8c67 --- /dev/null +++ b/templates/confirm.html @@ -0,0 +1,84 @@ + + + + + + + Confirm - FireWallet + + + + + + + + + + + + + +
+ +
+
+ +
+

Are you sure you want to do this?

+
+
+

{{action}}

+
{{subtitle}}
+

{{content|safe}}

CancelConfirm +
+
+
+
+
+
+ +
+
+
+
+ + + + + \ No newline at end of file