diff --git a/FireWalletBrowser.bsdesign b/FireWalletBrowser.bsdesign
index 2c9d800..e4d7098 100644
Binary files a/FireWalletBrowser.bsdesign and b/FireWalletBrowser.bsdesign differ
diff --git a/account.py b/account.py
index f98db89..4427a61 100644
--- a/account.py
+++ b/account.py
@@ -109,8 +109,7 @@ def createWallet(account: str, password: str):
}
# Create the account
# Python wrapper doesn't support this yet
- response = requests.put(
- f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}/wallet/{account}")
+ response = requests.put(get_wallet_api_url(f"wallet/{account}"))
if response.status_code != 200:
return {
"error": {
@@ -123,7 +122,7 @@ def createWallet(account: str, password: str):
seed = seed['mnemonic']['phrase']
# Encrypt the wallet (python wrapper doesn't support this yet)
- response = requests.post(f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}/wallet/{account}/passphrase",
+ response = requests.post(get_wallet_api_url(f"/wallet/{account}/passphrase"),
json={"passphrase": password})
return {
@@ -147,8 +146,7 @@ def importWallet(account: str, password: str, seed: str):
"mnemonic": seed,
}
- response = requests.put(
- f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}/wallet/{account}", json=data)
+ response = requests.put(get_wallet_api_url(f"/wallet/{account}"), json=data)
if response.status_code != 200:
return {
"error": {
@@ -186,7 +184,6 @@ def selectWallet(account: str):
}
}
-
def getBalance(account: str):
# Get the total balance
info = hsw.getBalance('default', account)
@@ -251,11 +248,9 @@ def getPendingTX(account: str):
def getDomains(account, own=True):
if own:
- response = requests.get(
- f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}/wallet/{account}/name?own=true")
+ response = requests.get(get_wallet_api_url(f"/wallet/{account}/name?own=true"))
else:
- response = requests.get(
- f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}/wallet/{account}/name")
+ response = requests.get(get_wallet_api_url(f"/wallet/{account}/name"))
info = response.json()
if SHOW_EXPIRED:
@@ -339,11 +334,9 @@ def getTransactions(account, page=1, limit=100):
lastTX = getTXFromPage(account, page-1, limit)
if lastTX:
- response = requests.get(
- f'http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}/wallet/{account}/tx/history?reverse=true&limit={limit}&after={lastTX}')
+ response = requests.get(get_wallet_api_url(f"/wallet/{account}/tx/history?reverse=true&limit={limit}&after={lastTX}"))
elif page == 1:
- response = requests.get(
- f'http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}/wallet/{account}/tx/history?reverse=true&limit={limit}')
+ response = requests.get(get_wallet_api_url(f"/wallet/{account}/tx/history?reverse=true&limit={limit}"))
else:
return []
@@ -383,7 +376,7 @@ def check_address(address: str, allow_name: bool = True, return_address: bool =
return check_hip2(address[1:])
# Check if the address is a valid HNS address
- response = requests.post(f"http://x:{HSD_API}@{HSD_IP}:{HSD_NODE_PORT}", json={
+ response = requests.post(get_node_api_url(), json={
"method": "validateaddress",
"params": [address]
}).json()
@@ -431,8 +424,6 @@ def send(account, address, amount):
response = hsw.rpc_walletPassphrase(password, 10)
# Unlock the account
- # response = requests.post(f"http://x:{APIKEY}@{ip}:{HSD_WALLET_PORT}/wallet/{account_name}/unlock",
- # json={"passphrase": password,"timeout": 10})
if response['error'] is not None:
if response['error']['message'] != "Wallet is not encrypted.":
return {
@@ -454,10 +445,19 @@ def send(account, address, amount):
def isOwnDomain(account, name: str):
- domains = getDomains(account)
- for domain in domains:
- if domain['name'] == name:
- return True
+ # Get domain
+ domain_info = getDomain(name)
+ owner = getAddressFromCoin(domain_info['info']['owner']['hash'],domain_info['info']['owner']['index'])
+ # Select the account
+ hsw.rpc_selectWallet(account)
+ account = hsw.rpc_getAccount(owner)
+
+ 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
@@ -474,20 +474,14 @@ def getDomain(domain: str):
def getAddressFromCoin(coinhash: str, coinindex = 0):
# Get the address from the hash
- response = requests.get(f"http://x:{HSD_API}@{HSD_IP}:{HSD_NODE_PORT}/coin/{coinhash}/{coinindex}")
+ response = requests.get(get_node_api_url(f"coin/{coinhash}/{coinindex}"))
if response.status_code != 200:
- return {
- "error": {
- "message": "Error getting address from coin"
- }
- }
+ print(f"Error getting address from coin: {response.text}")
+ return "No Owner"
data = response.json()
if 'address' not in data:
- return {
- "error": {
- "message": "Error getting address from coin"
- }
- }
+ print(json.dumps(data, indent=4))
+ return "No Owner"
return data['address']
@@ -783,7 +777,7 @@ def revealAll(account):
}
}
- return requests.post(f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}", json={"method": "sendbatch", "params": [[["REVEAL"]]]}).json()
+ return requests.post(get_wallet_api_url(), json={"method": "sendbatch", "params": [[["REVEAL"]]]}).json()
except Exception as e:
return {
"error": {
@@ -817,7 +811,7 @@ def redeemAll(account):
}
}
- return requests.post(f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}", json={"method": "sendbatch", "params": [[["REDEEM"]]]}).json()
+ return requests.post(get_wallet_api_url(), json={"method": "sendbatch", "params": [[["REDEEM"]]]}).json()
except Exception as e:
return {
"error": {
@@ -1089,7 +1083,7 @@ def sendBatch(account, batch):
"message": response['error']['message']
}
}
- response = requests.post(f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}", json={
+ response = requests.post(get_wallet_api_url(), json={
"method": "sendbatch",
"params": [batch]
}).json()
@@ -1138,7 +1132,7 @@ def createBatch(account, batch):
"message": response['error']['message']
}
}
- response = requests.post(f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}", json={
+ response = requests.post(get_wallet_api_url(), json={
"method": "createbatch",
"params": [batch]
}).json()
@@ -1198,7 +1192,7 @@ def zapTXs(account):
}
try:
- response = requests.post(f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}/wallet/{account_name}/zap",
+ response = requests.post(get_wallet_api_url(f"/wallet/{account_name}/zap"),
json={"age": age,
"account": "default"
})
@@ -1327,3 +1321,25 @@ def generateReport(account, format="{name},{expiry},{value},{maxBid}"):
def convertHNS(value: int):
return value/1000000
+ return value/1000000
+
+
+def get_node_api_url(path=''):
+ """Construct a URL for the HSD node API."""
+ base_url = f"http://x:{HSD_API}@{HSD_IP}:{HSD_NODE_PORT}"
+ if path:
+ # Ensure path starts with a slash if it's not empty
+ if not path.startswith('/'):
+ path = f'/{path}'
+ return f"{base_url}{path}"
+ return base_url
+
+def get_wallet_api_url(path=''):
+ """Construct a URL for the HSD wallet API."""
+ base_url = f"http://x:{HSD_API}@{HSD_IP}:{HSD_WALLET_PORT}"
+ if path:
+ # Ensure path starts with a slash if it's not empty
+ if not path.startswith('/'):
+ path = f'/{path}'
+ return f"{base_url}{path}"
+ return base_url
diff --git a/main.py b/main.py
index a3fab1d..e263000 100644
--- a/main.py
+++ b/main.py
@@ -32,6 +32,30 @@ revokeCheck = random.randint(100000,999999)
THEME = os.getenv("THEME")
+
+def blocks_to_time(blocks: int) -> str:
+ """
+ Convert blocks to time in a human-readable format.
+ Blocks are mined approximately every 10 minutes.
+ """
+ if blocks < 0:
+ return "Invalid time"
+
+ if blocks < 6:
+ return f"{blocks * 10} mins"
+ elif blocks < 144:
+ hours = blocks // 6
+ minutes = (blocks % 6) * 10
+ return f"{hours} hrs {minutes} mins"
+ else:
+ days = blocks // 144
+ hours = (blocks % 144) // 6
+ return f"{days} days {hours} hrs"
+
+
+
+
+
@app.route('/')
def index():
# Check if the user is logged in
@@ -445,10 +469,11 @@ def search():
state="AVAILABLE", next="Available Now",plugins=plugins)
state = domain['info']['state']
+ stats = domain['info']['stats']
if state == 'CLOSED':
if domain['info']['registered']:
state = 'REGISTERED'
- expires = domain['info']['stats']['daysUntilExpire']
+ expires = stats['daysUntilExpire']
next = f"Expires in ~{expires} days"
else:
state = 'AVAILABLE'
@@ -456,11 +481,11 @@ def search():
elif state == "REVOKED":
next = "Available Now"
elif state == 'OPENING':
- next = "Bidding opens in ~" + str(domain['info']['stats']['blocksUntilBidding']) + " blocks"
+ next = f"Bidding opens in {str(stats['blocksUntilBidding'])} blocks (~{blocks_to_time(stats['blocksUntilBidding'])})"
elif state == 'BIDDING':
- next = "Reveal in ~" + str(domain['info']['stats']['blocksUntilReveal']) + " blocks"
+ next = f"Reveal in {str(stats['blocksUntilReveal'])} blocks (~{blocks_to_time(stats['blocksUntilReveal'])})"
elif state == 'REVEAL':
- next = "Reveal ends in ~" + str(domain['info']['stats']['blocksUntilClose']) + " blocks"
+ next = f"Reveal ends in {str(stats['blocksUntilClose'])} blocks (~{blocks_to_time(stats['blocksUntilClose'])})"
@@ -501,11 +526,8 @@ def manage(domain: str):
return redirect("/logout")
domain = domain.lower()
-
- 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 domain not in own_domains:
+
+ if not account_module.isOwnDomain(account, domain):
return redirect("/search?q=" + domain)
domain_info = account_module.getDomain(domain)
@@ -514,7 +536,10 @@ def manage(domain: str):
rendered=renderDomain(domain),
domain=domain, error=domain_info['error'])
- expiry = domain_info['info']['stats']['daysUntilExpire']
+ if domain_info['info'] is not None and 'stats' in domain_info['info'] and 'daysUntilExpire' in domain_info['info']['stats']:
+ expiry = domain_info['info']['stats']['daysUntilExpire']
+ else:
+ expiry = "Unknown"
dns = account_module.getDNS(domain)
raw_dns = str(dns).replace("'",'"')
dns = render.dns(dns)
@@ -900,7 +925,7 @@ def auction(domain):
reveal['bid'] = revealInfo
bids = render.bids(bids,reveals)
-
+ stats = domainInfo['info']['stats'] if 'stats' in domainInfo['info'] else {}
if state == 'CLOSED':
if not domainInfo['info']['registered']:
if account_module.isOwnDomain(account,domain):
@@ -928,11 +953,21 @@ def auction(domain):
next = "Available Now"
next_action = f'Open Auction'
elif state == 'OPENING':
- next = "Bidding opens in ~" + str(domainInfo['info']['stats']['blocksUntilBidding']) + " blocks"
+ next = f"Bidding opens in {str(stats['blocksUntilBidding'])} blocks (~{blocks_to_time(stats['blocksUntilBidding'])})"
elif state == 'BIDDING':
- next = "Reveal in ~" + str(domainInfo['info']['stats']['blocksUntilReveal']) + " blocks"
+ 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 = "Reveal ends in ~" + str(domainInfo['info']['stats']['blocksUntilClose']) + " blocks"
+ next = f"Reveal ends in {str(stats['blocksUntilClose'])} blocks (~{blocks_to_time(stats['blocksUntilClose'])})"
next_action = f'Reveal All'
message = ''
@@ -1070,7 +1105,7 @@ def reveal_auction(domain):
return redirect("/logout")
domain = domain.lower()
- response = account_module(request.cookies.get("account"),domain)
+ response = account_module.revealAuction(request.cookies.get("account"),domain)
if 'error' in response:
return redirect("/auction/" + domain + "?message=" + response['error']['message'])
return redirect("/success?tx=" + response['hash'])
diff --git a/render.py b/render.py
index c3cdd39..ff79dd9 100644
--- a/render.py
+++ b/render.py
@@ -210,7 +210,6 @@ def dns(data, edit=False):
html_output = ""
index = 0
for entry in data:
- print(entry, flush=True)
html_output += f"