68 Commits

Author SHA1 Message Date
fb9cb50a90 Merge branch 'dev' 2025-01-28 21:57:26 +11:00
db5e672d7b feat: Update bootstrap and remove sidebar toggle 2025-01-28 21:56:05 +11:00
8ec23e3a32 feat: Add volume mount info for docker to readme 2025-01-28 17:38:02 +11:00
f84359a74b feat: Move plugin signatures to user data dir 2025-01-28 17:36:25 +11:00
92f05992ab fix: Add git to docker image 2025-01-28 17:33:14 +11:00
2ae618c68a feat: Add custom plugins 2025-01-28 17:26:59 +11:00
cfb814d006 feat: Add public info and troubleshooting modules 2025-01-28 16:46:06 +11:00
8c61a09e5b fix: Add more logging for batch errors 2025-01-28 16:30:30 +11:00
5c61bad9a2 fix: Update renewal plugin to get IP from env 2025-01-28 16:26:24 +11:00
35d3ccd0c0 feat: Sort bids by block to make it more intuitive 2025-01-28 16:16:46 +11:00
2b895a524a fix: Stop bids without known blind from causing crashes 2025-01-28 16:16:26 +11:00
f7968fc218 feat: Add change lookahead to plugin 2025-01-28 13:20:44 +11:00
d39f433738 fix: Add debugging to simple batches 2025-01-28 11:09:08 +11:00
2b6447fd12 fix: Add rounding to bid display and strip batch inputs 2025-01-28 10:56:24 +11:00
4b7b9f991b feat: Add batch renewals to batching plugin 2025-01-28 00:03:10 +11:00
f5fc0766a1 feat: Add batching plugin 2025-01-27 23:42:46 +11:00
209c3794fc Merge branch 'dev' 2025-01-14 15:55:55 +11:00
693bf13450 feat: Add wallet status 2025-01-14 15:54:25 +11:00
cff65b167a feat: Update settings page 2024-11-22 12:04:55 +11:00
d2ad6eaa58 feat: Update varo plugin to make it easier to setup and use 2024-11-22 11:56:08 +11:00
8099320673 Merge branch 'dev' 2024-11-22 09:48:07 +11:00
6c91ec88c7 fix: Create user_data dir if it doesn't exist 2024-11-22 09:47:37 +11:00
aa92220756 Merge branch 'dev' 2024-11-21 19:35:56 +11:00
3290240a25 fix: Cleanup plugin.py 2024-11-21 19:35:33 +11:00
40f520ba5e feat: Updated automations blacklist file to make it clearer 2024-11-21 19:33:10 +11:00
9f1f7fb18e feat: Add wallet blacklisting to automations plugin 2024-11-21 19:30:19 +11:00
3e78732333 fix: Check if .git dir exists before trying to read it 2024-11-21 16:30:44 +11:00
2595503dc0 Merge branch 'dev' 2024-11-21 16:22:07 +11:00
0be6b8b435 fix: Remove unused imports 2024-11-21 16:21:20 +11:00
00379aaa8f feat: Add new batch renewal plugin 2024-11-21 16:10:28 +11:00
da9354cb23 fix: Hide expired domains 2024-11-21 15:40:02 +11:00
d516e91592 Merge branch 'dev' 2024-11-21 15:21:38 +11:00
f695d53f8d feat: Ignore .venv 2024-11-21 15:21:08 +11:00
45fdaa2de4 feat: Add tx count plugin and fixed dns error 2024-04-08 11:44:50 +10:00
40b4c42492 feat: Fix lockup amount and auctions page 2024-03-15 15:07:27 +11:00
afd7ae2947 fix: Try to run automation every 5 mins 2024-03-15 14:59:07 +11:00
171e891555 feat: Added emoji display to domain list 2024-02-20 10:57:12 +11:00
5e21074b24 fix: Don't hide domains that have owner index 0 2024-02-20 10:45:58 +11:00
703f1ed5c1 fix: Version display 2024-02-17 12:55:14 +11:00
b24a3147dd Merge branch 'dev' 2024-02-17 12:53:32 +11:00
af4cd0c652 feat: Fixed some mobile UI issues 2024-02-17 12:27:20 +11:00
f8e03aca73 Merge branch 'dev' 2024-02-17 11:57:24 +11:00
b85d316491 feat: Download a csv for the report 2024-02-17 11:57:04 +11:00
43c5b5c3ba fix: Bids page title and remove report 2024-02-17 11:42:33 +11:00
5886ded19a feat: Add varo plugin 2024-02-13 13:42:02 +11:00
7085fbfa5c feat: Add template plugin 2024-02-13 13:41:56 +11:00
38f08c069c Merge branch 'dev' 2024-02-13 11:52:04 +11:00
fea42b1177 feat: Add version and links to settings page 2024-02-13 11:49:42 +11:00
4f74d51514 fix: Open report in new tab 2024-02-13 11:49:28 +11:00
472e9fb797 fix: Update navbar link to auctions page to 2024-02-13 11:24:03 +11:00
ecf6ac522a feat: Added auctions page 2024-02-13 11:18:16 +11:00
16ac6c7d2b Merge branch 'dev' 2024-02-13 10:01:21 +11:00
f525c0f1fd fix: Update readme to include windows instructions 2024-02-13 10:00:55 +11:00
c28874bb1c fix: Check that domains are closed before including their value 2024-02-13 09:56:46 +11:00
b0c7fcf779 Merge branch 'dev' 2024-02-12 22:08:02 +11:00
6e382b0e6e fix: Niami rating example fail on revealing domain 2024-02-12 22:07:18 +11:00
340898959d fix: Don't show output on plugins that aren't verified 2024-02-12 22:02:41 +11:00
4f163756de feat: Add automation plugin 2024-02-12 21:53:17 +11:00
360ca7bfe9 fix: Finally get around to having an accurate total HNS count 2024-02-12 21:18:05 +11:00
dc240bb1a7 fix: Hashing algorithm wasn't returning a consistent hash 2024-02-08 21:02:25 +11:00
0c0125b40c feat: Block new plugins from running until they have been verified 2024-02-08 14:33:27 +11:00
bfbac3a679 fix: Stop rendering of dashboard from breaking UI 2024-02-07 17:27:43 +11:00
a0989cccef feat: Add more error catching for plugins
This means that people could make completely broken plugins and still have a working wallet
2024-02-07 16:58:12 +11:00
a412573fab feat: Update themeing and add a light theme 2024-02-07 16:57:01 +11:00
97f7792612 feat: Fixed copy button for mobile 2024-02-07 16:12:31 +11:00
4c08d4e24e feat: Update plugins info page 2024-02-07 15:41:46 +11:00
6c61ecdd2c feat: Update UI for mobile view and fix a few small bugs 2024-02-07 15:35:38 +11:00
d62ced1375 Merge branch 'feat/plugins' into dev 2024-02-07 13:58:13 +11:00
60 changed files with 7254 additions and 235 deletions

9
.gitignore vendored
View File

@@ -4,3 +4,12 @@
__pycache__/
templates/assets/css/styles.min.css
ignore/
plugins/signatures.json
.venv/
user_data/
customPlugins/

View File

@@ -10,6 +10,7 @@ COPY . /app
# Add mount point for data volume
# VOLUME /data
RUN apk add git
ENTRYPOINT ["python3"]
CMD ["server.py"]

Binary file not shown.

View File

@@ -17,17 +17,23 @@ If you have HSD runnning on a separate computer also add the IP here
Make sure HSD is running then run the following commands:
On Linux:
```bash
python3 server.py
# Or for more verbose output
python3 main.py
```
On Windows:
```bash
python3 main.py
```
Then access the wallet at http://localhost:5000
Also available as a docker image:
To run using a HSD running directly on the host:
```bash
@@ -40,6 +46,8 @@ If you have HSD running on a different IP/container
sudo docker run -p 5000:5000 -e hsd_api=yourapikeyhere -e hsd_ip=hsdcontainer git.woodburn.au/nathanwoodburn/firewallet:latest
```
For Docker you can mount a volume to persist the user data (/app/user_data)
## Features
- Basic wallet functionality
- Create new wallet

View File

@@ -15,6 +15,9 @@ ip = os.getenv("hsd_ip")
if ip is None:
ip = "localhost"
show_expired = os.getenv("show_expired")
if show_expired is None:
show_expired = False
hsd = api.hsd(APIKEY,ip)
hsw = api.hsw(APIKEY,ip)
@@ -126,16 +129,26 @@ def getBalance(account: str):
total = info['confirmed']
available = total - info['lockedConfirmed']
locked = info['lockedConfirmed'] / 1000000
# Convert to HNS
total = total / 1000000
available = available / 1000000
domains = getDomains(account)
domainValue = 0
for domain in domains:
if domain['state'] == "CLOSED":
domainValue += domain['value']
total = total - (domainValue/1000000)
locked = locked - (domainValue/1000000)
# Only keep 2 decimal places
total = round(total, 2)
available = round(available, 2)
return {'available': available, 'total': total}
return {'available': available, 'total': total, 'locked': locked}
def getBlockHeight():
# Get the block height
@@ -163,17 +176,28 @@ def getPendingTX(account: str):
return pending
def getDomains(account):
# Get the domains
# info = hsw.getWalletNames(account)
# if 'error' in info:
# return []
# use requests to get the domains
def getDomains(account,own=True):
if own:
response = requests.get(f"http://x:{APIKEY}@{ip}:12039/wallet/{account}/name?own=true")
else:
response = requests.get(f"http://x:{APIKEY}@{ip}:12039/wallet/{account}/name")
info = response.json()
if show_expired:
return info
# Remove any expired domains
domains = []
for domain in info:
if 'stats' in domain:
if 'daysUntilExpire' in domain['stats']:
if domain['stats']['daysUntilExpire'] < 0:
continue
domains.append(domain)
return domains
def getTransactions(account):
# Get the transactions
info = hsw.getWalletTxHistory(account)
@@ -232,10 +256,6 @@ def check_hip2(domain: str):
def send(account,address,amount):
account_name = check_account(account)
password = ":".join(account.split(":")[1:])
response = hsw.rpc_selectWallet(account_name)
if response['error'] is not None:
return {
@@ -298,6 +318,12 @@ def getDNS(domain: str):
return {
"error": response['error']['message']
}
if 'result' not in response:
return {
"error": "No DNS records"
}
if 'records' not in response['result']:
return []
return response['result']['records']
@@ -317,7 +343,11 @@ def setDNS(account,domain,records):
TXTRecords = []
for record in records:
if record['type'] == 'TXT':
if 'txt' not in record:
TXTRecords.append(record['value'])
else:
for txt in record['txt']:
TXTRecords.append(txt)
elif record['type'] == 'NS':
newRecords.append({
'type': 'NS',
@@ -337,7 +367,6 @@ def setDNS(account,domain,records):
'type': 'TXT',
'txt': TXTRecords
})
data = '{"records":'+str(newRecords).replace("'","\"")+'}'
response = hsw.sendUPDATE(account_name,password,domain,data)
return response
@@ -352,10 +381,37 @@ def getNodeSync():
sync = round(sync, 2)
return sync
def getWalletStatus():
response = hsw.rpc_getWalletInfo()
if 'error' in response and response['error'] != None:
return "Error"
def getBids(account, domain):
# return response
walletHeight = response['result']['height']
# Get the current block height
nodeHeight = getBlockHeight()
if walletHeight < nodeHeight:
return f"Scanning {walletHeight/nodeHeight*100:.2f}%"
elif walletHeight == nodeHeight:
return "Ready"
else:
return "Error wallet ahead of node"
def getBids(account, domain="NONE"):
if domain == "NONE":
response = hsw.getWalletBids(account)
else:
response = hsw.getWalletBidsByName(domain,account)
return response
# Add backup for bids with no value
bids = []
for bid in response:
if 'value' not in bid:
bid['value'] = -1000000
bids.append(bid)
return bids
def getReveals(account,domain):
return hsw.getWalletRevealsByName(domain,account)
@@ -388,6 +444,35 @@ def revealAuction(account,domain):
"error": str(e)
}
def revealAll(account):
account_name = check_account(account)
password = ":".join(account.split(":")[1:])
if account_name == False:
return {
"error": {
"message": "Invalid account"
}
}
try:
# Try to select and login to the wallet
response = hsw.rpc_selectWallet(account_name)
if response['error'] is not None:
return
response = hsw.rpc_walletPassphrase(password,10)
if response['error'] is not None:
return
# Try to send the batch of all renew, reveal and redeem actions
return requests.post(f"http://x:{APIKEY}@{ip}:12039",json={"method": "sendbatch","params": [[["REVEAL"]]]}).json()
except Exception as e:
return {
"error": {
"message": str(e)
}
}
def rescan_auction(account,domain):
# Get height of the start of the auction
response = hsw.rpc_selectWallet(account)
@@ -579,6 +664,52 @@ def revoke(account,domain):
}
}
def sendBatch(account, batch):
account_name = check_account(account)
password = ":".join(account.split(":")[1:])
if account_name == False:
return {
"error": {
"message": "Invalid account"
}
}
try:
response = hsw.rpc_selectWallet(account_name)
if response['error'] is not None:
return {
"error": {
"message": response['error']['message']
}
}
response = hsw.rpc_walletPassphrase(password,10)
if response['error'] is not None:
return {
"error": {
"message": response['error']['message']
}
}
response = requests.post(f"http://x:{APIKEY}@{ip}:12039",json={
"method": "sendbatch",
"params": [batch]
}).json()
if response['error'] is not None:
return response
if 'result' not in response:
return {
"error": {
"message": "No result"
}
}
return response['result']
except Exception as e:
return {
"error": {
"message": str(e)
}
}
#region settingsAPIs
@@ -663,6 +794,42 @@ def getxPub(account):
}
def signMessage(account,domain,message):
account_name = check_account(account)
password = ":".join(account.split(":")[1:])
if account_name == False:
return {
"error": {
"message": "Invalid account"
}
}
try:
response = hsw.rpc_selectWallet(account_name)
if response['error'] is not None:
return {
"error": {
"message": response['error']['message']
}
}
response = hsw.rpc_walletPassphrase(password,10)
if response['error'] is not None:
return {
"error": {
"message": response['error']['message']
}
}
response = hsw.rpc_signMessageWithName(domain,message)
return response
except Exception as e:
return {
"error": {
"message": str(e)
}
}
#endregion
def generateReport(account,format="{name},{expiry},{value},{maxBid}"):

BIN
assets/plugin_page.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
assets/plugins.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -168,4 +168,10 @@ def emoji_to_punycode(emoji):
try:
return emoji.encode("idna").decode("ascii")
except Exception as e:
return ""
return emoji
def punycode_to_emoji(punycode):
try:
return punycode.encode("ascii").decode("idna")
except Exception as e:
return punycode

View File

@@ -1,3 +1,4 @@
hsd_api=123480615465636893475aCwyaae6s45
hsd_ip=localhost
theme=black
show_expired=false

342
main.py
View File

@@ -12,6 +12,8 @@ import domainLookup
import urllib.parse
import importlib
import plugin as plugins_module
import gitinfo
import datetime
dotenv.load_dotenv()
@@ -90,20 +92,20 @@ def index():
domain_count = len(domains)
domainsMobile = render.domains(domains,True)
domains = render.domains(domains)
plugins = ""
dashFunctions = plugins_module.getDashboardFunctions()
for function in dashFunctions:
functionOutput = plugins_module.runPluginFunction(function["plugin"],function["function"],{},account_module.check_account(request.cookies.get("account")))
functionOutput = plugins_module.runPluginFunction(function["plugin"],function["function"],{},request.cookies.get("account"))
plugins += render.plugin_output_dash(functionOutput,plugins_module.getPluginFunctionReturns(function["plugin"],function["function"]))
return render_template("index.html", account=account, available=available,
total=total, pending=pending, domains=domains, plugins=plugins,
total=total, pending=pending, domains=domains,
domainsMobile=domainsMobile, plugins=plugins,
domain_count=domain_count, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
sort_price=sort_price,sort_expiry=sort_expiry,
sort_domain=sort_domain,sort_price_next=sort_price_next,
sort_expiry_next=sort_expiry_next,sort_domain_next=sort_domain_next)
@@ -129,7 +131,7 @@ def transactions():
transactions = render.transactions(transactions)
return render_template("tx.html", account=account, sync=account_module.getNodeSync(),
tx=transactions)
wallet_status=account_module.getWalletStatus(),tx=transactions)
@app.route('/send')
@@ -157,6 +159,7 @@ def send_page():
return render_template("send.html", account=account,sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
max=max,message=message,address=address,amount=amount)
@app.route('/send', methods=["POST"])
@@ -205,7 +208,8 @@ def send():
return render_template("confirm.html", account=account_module.check_account(request.cookies.get("account")),
sync=account_module.getNodeSync(),action=action,
sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),action=action,
content=content,cancel=cancel,confirm=confirm)
@@ -235,6 +239,7 @@ def receive():
address = account_module.getAddress(account)
return render_template("receive.html", account=account,sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
address=address)
@app.route('/success')
@@ -249,7 +254,7 @@ def success():
tx = request.args.get("tx")
return render_template("success.html", account=account,sync=account_module.getNodeSync(),
tx=tx)
wallet_status=account_module.getWalletStatus(),tx=tx)
@app.route('/checkaddress')
def check_address():
@@ -261,6 +266,128 @@ def check_address():
#endregion
#region Domains
@app.route('/auctions')
def auctions():
# 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")
balance = account_module.getBalance(account)
locked = balance['locked']
# Round to 2 decimals
locked = round(locked, 2)
# Add commas to the numbers
locked = "{:,}".format(locked)
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
direction = request.args.get("direction")
if direction == None:
if sort == "time":
direction = ""
else:
direction = ""
if direction == "":
reverse = True
if sort == "price":
# Sort by price
bids = sorted(bids, key=lambda k: k['value'],reverse=reverse)
sort_price = direction
sort_price_next = reverseDirection(direction)
elif sort == "state":
sort_state = direction
sort_state_next = reverseDirection(direction)
domains = sorted(domains, key=lambda k: k['state'],reverse=reverse)
elif sort == "time":
sort_time = direction
sort_time_next = reverseDirection(direction)
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)
if sort == "state":
bidsHtml = render.bidDomains(bids,domains,True)
else:
bidsHtml = render.bidDomains(bids,domains)
pending_reveals = 0
for domain in domains:
if domain['state'] == "REVEAL":
for bid in bids:
if bid['name'] == domain['name']:
bid_found = False
reveals = account_module.getReveals(account,domain['name'])
for reveal in reveals:
if reveal['own'] == True:
if bid['value'] == reveal['value']:
bid_found = True
if not bid_found:
pending_reveals += 1
plugins = ""
message = ''
if 'message' in request.args:
message = request.args.get("message")
return render_template("auctions.html", account=account, locked=locked, domains=bidsHtml,
domainsMobile=bidsHtml, plugins=plugins,
domain_count=bidsHtml, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
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),reveal=pending_reveals,message=message,
sort_time=sort_time,sort_time_next=sort_time_next)
@app.route('/reveal')
def revealAllBids():
# 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")
response = account_module.revealAll(request.cookies.get("account"))
if 'error' in response:
print(response)
if response['error'] != None:
if response['error']['message'] == "Nothing to do.":
return redirect("/auctions?message=No reveals pending")
return redirect("/auctions?message=" + response['error']['message'])
return redirect("/success?tx=" + response['result']['hash'])
@app.route('/search')
def search():
# Check if the user is logged in
@@ -274,6 +401,9 @@ def search():
search_term = request.args.get("q")
search_term = search_term.lower().strip()
# Replace spaces with hyphens
search_term = search_term.replace(" ","-")
# Convert emoji to punycode
search_term = domainLookup.emoji_to_punycode(search_term)
if len(search_term) == 0:
@@ -281,14 +411,25 @@ def search():
domain = account_module.getDomain(search_term)
plugins = "<div class='container-fluid'>"
# Execute domain plugins
searchFunctions = plugins_module.getSearchFunctions()
for function in searchFunctions:
functionOutput = plugins_module.runPluginFunction(function["plugin"],function["function"],{"domain":search_term},account_module.check_account(request.cookies.get("account")))
plugins += render.plugin_output(functionOutput,plugins_module.getPluginFunctionReturns(function["plugin"],function["function"]))
plugins += "</div>"
if 'error' in domain:
return render_template("search.html", account=account,sync=account_module.getNodeSync(),
search_term=search_term, domain=domain['error'])
wallet_status=account_module.getWalletStatus(),
search_term=search_term, domain=domain['error'],plugins=plugins)
if domain['info'] is None:
return render_template("search.html", account=account, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
search_term=search_term,domain=search_term,
state="AVAILABLE", next="Available Now")
state="AVAILABLE", next="Available Now",plugins=plugins)
state = domain['info']['state']
if state == 'CLOSED':
@@ -329,16 +470,8 @@ def search():
dns = render.dns(dns)
txs = render.txs(txs)
plugins = "<div class='container-fluid'>"
# Execute domain plugins
searchFunctions = plugins_module.getSearchFunctions()
for function in searchFunctions:
functionOutput = plugins_module.runPluginFunction(function["plugin"],function["function"],{"domain":search_term},account_module.check_account(request.cookies.get("account")))
plugins += render.plugin_output(functionOutput,plugins_module.getPluginFunctionReturns(function["plugin"],function["function"]))
plugins += "</div>"
return render_template("search.html", account=account, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
search_term=search_term,domain=domain['info']['name'],
raw=domain,state=state, next=next, owner=owner,
dns=dns, txs=txs,plugins=plugins)
@@ -364,6 +497,7 @@ def manage(domain: str):
domain_info = account_module.getDomain(domain)
if 'error' in domain_info:
return render_template("manage.html", account=account, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
domain=domain, error=domain_info['error'])
expiry = domain_info['info']['stats']['daysUntilExpire']
@@ -400,6 +534,7 @@ def manage(domain: str):
return render_template("manage.html", account=account, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
error=errorMessage, address=address,
domain=domain,expiry=expiry, dns=dns,
raw_dns=urllib.parse.quote(raw_dns),
@@ -468,7 +603,8 @@ def revokeInit(domain: str):
return render_template("confirm-password.html", account=account_module.check_account(request.cookies.get("account")),
sync=account_module.getNodeSync(),action=action,
sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),action=action,
content=content,cancel=cancel,confirm=confirm,check=revokeCheck)
@app.route('/manage/<domain>/revoke/confirm', methods=["POST"])
@@ -575,6 +711,7 @@ def editPage(domain: str):
return render_template("edit.html", account=account, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
domain=domain, error=errorMessage,
dns=dns,raw_dns=urllib.parse.quote(raw_dns))
@@ -633,9 +770,52 @@ def transfer(domain):
return render_template("confirm.html", account=account_module.check_account(request.cookies.get("account")),
sync=account_module.getNodeSync(),action=action,
sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),action=action,
content=content,cancel=cancel,confirm=confirm)
@app.route('/manage/<domain>/sign')
def signMessage(domain):
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")
# Get the address and amount
message = request.args.get("message")
if message is None:
return redirect("/manage/" + domain + "?error=Invalid message")
content = "Message to sign:<br><code>" + message + "</code><br><br>"
signedMessage = account_module.signMessage(request.cookies.get("account"),domain,message)
if signedMessage["error"] != None:
return redirect("/manage/" + domain + "?error=" + signedMessage["error"])
content += "Signature:<br><code>" + signedMessage["result"] + "</code><br><br>"
data = {
"domain": domain,
"message": message,
"signature": signedMessage["result"]
}
content += "Full information:<br><code style='text-align:left;display: block;'>" + json.dumps(data,indent=4).replace('\n',"<br>") + "</code><br><br>"
content += "<textarea style='display: none;' id='data' rows='4' cols='50'>"+json.dumps(data)+"</textarea>"
copyScript = "<script>function copyToClipboard() {var copyText = document.getElementById('data');copyText.style.display = 'block';copyText.select();copyText.setSelectionRange(0, 99999);document.execCommand('copy');copyText.style.display = 'none';var copyButton = document.getElementById('copyButton');copyButton.innerHTML='Copied';}</script>"
content += "<button id='copyButton' onclick='copyToClipboard()' class='btn btn-secondary'>Copy to clipboard</button>" + copyScript
return render_template("message.html", account=account,sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
title="Sign Message",content=content)
@app.route('/manage/<domain>/transfer/confirm')
def transferConfirm(domain):
if request.cookies.get("account") is None:
@@ -674,11 +854,13 @@ def auction(domain):
if 'error' in domainInfo:
return render_template("auction.html", account=account,sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
search_term=search_term, domain=domainInfo['error'])
if domainInfo['info'] is None:
next_action = f'<a href="/auction/{domain}/open">Open Auction</a>'
return render_template("auction.html", account=account, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
search_term=search_term,domain=search_term,next_action=next_action,
state="AVAILABLE", next="Open Auction")
@@ -731,6 +913,7 @@ def auction(domain):
return render_template("auction.html", account=account, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
search_term=search_term,domain=domainInfo['info']['name'],
raw=domainInfo,state=state, next=next,
next_action=next_action, bids=bids,error=message)
@@ -770,18 +953,21 @@ def bid(domain):
if blind == "":
blind = 0
bid = float(bid)
blind = float(blind)
if bid+blind == 0:
return redirect("/auction/" + domain+ "?message=Invalid bid amount")
# Show confirm page
total = float(bid) + float(blind)
total = bid + 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:<br><br>"
content += f"Bid: {request.args.get('bid')} HNS<br>"
content += f"Blind: {request.args.get('blind')} HNS<br>"
content += f"Bid: {str(bid)} HNS<br>"
content += f"Blind: {str(blind)} HNS<br>"
content += f"Total: {total} HNS (excluding fees)<br><br>"
cancel = f"/auction/{domain}"
@@ -790,7 +976,8 @@ def bid(domain):
return render_template("confirm.html", account=account_module.check_account(request.cookies.get("account")),
sync=account_module.getNodeSync(),action=action,
sync=account_module.getNodeSync(),wallet_status=account_module.getWalletStatus(),
action=action,
domain=domain,content=content,cancel=cancel,confirm=confirm)
@app.route('/auction/<domain>/bid/confirm')
@@ -804,11 +991,22 @@ def bid_confirm(domain):
return redirect("/logout")
domain = domain.lower()
bid = request.args.get("bid")
blind = request.args.get("blind")
if bid == "":
bid = 0
if blind == "":
blind = 0
bid = float(bid)
blind = float(blind)
# Send the bid
response = account_module.bid(request.cookies.get("account"),domain,
float(request.args.get('bid')),
float(request.args.get('blind')))
float(bid),
float(blind))
print(response)
if 'error' in response:
return redirect("/auction/" + domain + "?message=" + response['error']['message'])
@@ -868,8 +1066,24 @@ def settings():
if success == None:
success = ""
if not os.path.exists(".git"):
return render_template("settings.html", account=account,sync=account_module.getNodeSync(),
error=error,success=success)
wallet_status=account_module.getWalletStatus(),
error=error,success=success,version="Error")
info = gitinfo.get_git_info()
branch = info['refs']
if branch != "main":
branch = f"({branch})"
else:
branch = ""
last_commit = info['author_date']
# import to time from format "2024-02-13 11:24:03"
last_commit = datetime.datetime.strptime(last_commit, "%Y-%m-%d %H:%M:%S")
version = f'{last_commit.strftime("%y-%m-%d")} {branch}'
return render_template("settings.html", account=account,sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
error=error,success=success,version=version)
@app.route('/settings/<action>')
def settings_action(action):
@@ -885,7 +1099,7 @@ def settings_action(action):
resp = account_module.rescan()
if 'error' in resp:
return redirect("/settings?error=" + str(resp['error']))
return redirect("/settings?success=Resent transactions")
return redirect("/settings?success=Rescan started")
elif action == "resend":
resp = account_module.resendTXs()
if 'error' in resp:
@@ -899,8 +1113,16 @@ def settings_action(action):
return redirect("/settings?error=" + str(resp['error']))
return redirect("/settings?success=Zapped transactions")
elif action == "xpub":
xpub = account_module.getxPub(request.cookies.get("account"))
content = "<br><br>"
content += "<textarea style='display: none;' id='data' rows='4' cols='50'>"+xpub+"</textarea>"
content += "<script>function copyToClipboard() {var copyText = document.getElementById('data');copyText.style.display = 'block';copyText.select();copyText.setSelectionRange(0, 99999);document.execCommand('copy');copyText.style.display = 'none';var copyButton = document.getElementById('copyButton');copyButton.innerHTML='Copied';}</script>"
content += "<button id='copyButton' onclick='copyToClipboard()' class='btn btn-secondary'>Copy to clipboard</button>"
return render_template("message.html", account=account,sync=account_module.getNodeSync(),
title="xPub Key",content=account_module.getxPub(request.cookies.get("account")))
wallet_status=account_module.getWalletStatus(),
title="xPub Key",
content="<code>"+xpub+"</code>" + content)
return redirect("/settings?error=Invalid action")
@@ -917,9 +1139,11 @@ def login():
if 'message' in request.args:
return render_template("login.html", sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
error=request.args.get("message"),wallets=wallets)
return render_template("login.html", sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
wallets=wallets)
@app.route('/login', methods=["POST"])
@@ -931,6 +1155,7 @@ def login_post():
# Check if the account is valid
if account.count(":") > 0:
return render_template("login.html", sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
error="Invalid account")
account = account + ":" + password
@@ -989,6 +1214,7 @@ def register():
# Set the cookie
response = make_response(render_template("message.html", sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
title="Account Created",
content="Your account has been created. Here is your seed phrase. Please write it down and keep it safe as it will not be shown again<br><br>" + response['seed']))
response.set_cookie("account", account+":"+password)
@@ -1046,8 +1272,14 @@ def report():
return redirect("/login")
account = account_module.check_account(request.cookies.get("account"))
csv = '\n'.join(account_module.generateReport(account))
# Create a download
response = make_response(csv)
response.headers["Content-Disposition"] = "attachment; filename=report.csv"
response.headers["Content-Type"] = "text/csv"
return response
return jsonify(account_module.generateReport(account))
#endregion
@@ -1065,10 +1297,11 @@ def plugins_index():
plugins = render.plugins(plugins_module.listPlugins())
return render_template("plugins.html", account=account, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
plugins=plugins)
@app.route('/plugin/<plugin>')
def plugin(plugin):
@app.route('/plugin/<ptype>/<path:plugin>')
def plugin(ptype,plugin):
# Check if the user is logged in
if request.cookies.get("account") is None:
return redirect("/login")
@@ -1077,7 +1310,10 @@ def plugin(plugin):
if not account:
return redirect("/logout")
plugin = f"{ptype}/{plugin}"
if not plugins_module.pluginExists(plugin):
print(f"Plugin {plugin} not found")
return redirect("/plugins")
data = plugins_module.getPluginData(plugin)
@@ -1085,17 +1321,22 @@ def plugin(plugin):
functions = plugins_module.getPluginFunctions(plugin)
functions = render.plugin_functions(functions,plugin)
if data['verified'] == False:
functions = "<div class='container-fluid'><div class='alert alert-warning' role='alert'>This plugin is not verified and is disabled for your protection. Please check the code before marking the plugin as verified <a href='/plugin/" + plugin + "/verify' class='btn btn-danger'>Verify</a></div></div>" + functions
error = request.args.get("error")
if error == None:
error = ""
return render_template("plugin.html", account=account, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
name=data['name'],description=data['description'],
author=data['author'],version=data['version'],
functions=functions,error=error)
source=data['source'],functions=functions,error=error)
@app.route('/plugin/<plugin>/<function>', methods=["POST"])
def plugin_function(plugin,function):
@app.route('/plugin/<ptype>/<path:plugin>/verify')
def plugin_verify(ptype,plugin):
# Check if the user is logged in
if request.cookies.get("account") is None:
return redirect("/login")
@@ -1104,6 +1345,30 @@ def plugin_function(plugin,function):
if not account:
return redirect("/logout")
plugin = f"{ptype}/{plugin}"
if not plugins_module.pluginExists(plugin):
return redirect("/plugins")
data = plugins_module.getPluginData(plugin)
if data['verified'] == False:
plugins_module.verifyPlugin(plugin)
return redirect("/plugin/" + plugin)
@app.route('/plugin/<ptype>/<path:plugin>/<function>', methods=["POST"])
def plugin_function(ptype,plugin,function):
# 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")
plugin = f"{ptype}/{plugin}"
if not plugins_module.pluginExists(plugin):
return redirect("/plugins")
@@ -1136,8 +1401,8 @@ def plugin_function(plugin,function):
return redirect("/plugin/" + plugin + "?error=" + response['error'])
response = render.plugin_output(response,plugins_module.getPluginFunctionReturns(plugin,function))
return render_template("plugin-output.html", account=account, sync=account_module.getNodeSync(),
wallet_status=account_module.getWalletStatus(),
name=data['name'],description=data['description'],output=response)
@@ -1155,7 +1420,8 @@ def qr(data):
# Theme
@app.route('/assets/css/styles.min.css')
def send_css():
print("Using theme: " + theme)
if theme == "live":
return send_from_directory('templates/assets/css', 'styles.min.css')
return send_from_directory('themes', f'{theme}.css')
@app.route('/assets/<path:path>')

164
plugin.py
View File

@@ -1,37 +1,155 @@
import os
import json
import importlib
import sys
import hashlib
import subprocess
def listPlugins():
plugins = []
customPlugins = []
for file in os.listdir("plugins"):
if file.endswith(".py"):
if file != "main.py":
plugin = importlib.import_module("plugins."+file[:-3])
if "info" not in dir(plugin):
continue
details = plugin.info
details["link"] = file[:-3]
details["source"] = "built-in"
details["link"] = f"plugins/{file[:-3]}"
plugins.append(details)
# Check for imported plugins
if not os.path.exists("user_data/plugins.json"):
with open("user_data/plugins.json", "w") as f:
json.dump([], f)
with open("user_data/plugins.json", "r") as f:
importurls = json.load(f)
for importurl in importurls:
# Get only repo name
importPath = importurl.split("/")[-1].removesuffix(".git")
# Git clone into customPlugins/<importPath>
if not os.path.exists(f"customPlugins/{importPath}"):
if os.system(f"git clone {importurl} customPlugins/{importPath}") != 0:
continue
else:
if os.system(f"cd customPlugins/{importPath} && git pull") != 0:
continue
# Import plugins from customPlugins/<importPath>
for file in os.listdir(f"customPlugins/{importPath}"):
if file.endswith(".py"):
if file != "main.py":
plugin = importlib.import_module(f"customPlugins.{importPath}."+file[:-3])
if "info" not in dir(plugin):
continue
details = plugin.info
details["source"] = importPath
details["link"] = f"customPlugins/{importPath}/{file[:-3]}"
plugins.append(details)
# Verify plugin signature
signatures = []
try:
with open("user_data/plugin_signatures.json", "r") as f:
signatures = json.load(f)
except:
# Write a new signatures file
with open("user_data/plugin_signatures.json", "w") as f:
json.dump(signatures, f)
for plugin in plugins:
# Hash the plugin file
pluginHash = hashPlugin(plugin["link"])
if pluginHash not in signatures:
plugin["verified"] = False
else:
plugin["verified"] = True
return plugins
def pluginExists(plugin: str):
for file in os.listdir("plugins"):
if file == plugin+".py":
return True
return False
return os.path.exists(plugin+".py")
def verifyPlugin(plugin: str):
signatures = []
try:
with open("user_data/plugin_signatures.json", "r") as f:
signatures = json.load(f)
except:
# Write a new signatures file
with open("user_data/plugin_signatures.json", "w") as f:
json.dump(signatures, f)
# Hash the plugin file
pluginHash = hashPlugin(plugin)
if pluginHash not in signatures:
signatures.append(pluginHash)
with open("user_data/plugin_signatures.json", "w") as f:
json.dump(signatures, f)
def hashPlugin(plugin: str):
BUF_SIZE = 65536
sha256 = hashlib.sha256()
with open(plugin+".py", 'rb') as f:
while True:
data = f.read(BUF_SIZE)
if not data:
break
sha256.update(data)
return sha256.hexdigest()
def getPluginData(pluginStr: str):
plugin = importlib.import_module(pluginStr.replace("/","."))
# Check if the plugin is verified
signatures = []
try:
with open("user_data/plugin_signatures.json", "r") as f:
signatures = json.load(f)
except:
# Write a new signatures file
with open("user_data/plugin_signatures.json", "w") as f:
json.dump(signatures, f)
info = plugin.info
info["source"] = "built-in"
# Check if the plugin is in customPlugins
if pluginStr.startswith("customPlugins"):
# Get git url for dir
print(f"cd customPlugins/{pluginStr.split('/')[-2]} && git remote get-url origin")
url = subprocess.check_output(f"cd customPlugins/{pluginStr.split('/')[-2]} && git remote get-url origin", shell=True).decode("utf-8").strip()
info["source"] = url
# Hash the plugin file
pluginHash = hashPlugin(pluginStr)
if pluginHash not in signatures:
info["verified"] = False
else:
info["verified"] = True
return info
def getPluginData(plugin: str):
plugin = importlib.import_module("plugins."+plugin)
return plugin.info
def getPluginFunctions(plugin: str):
plugin = importlib.import_module("plugins."+plugin)
plugin = importlib.import_module(plugin.replace("/","."))
return plugin.functions
def runPluginFunction(plugin: str, function: str, params: dict, authentication: str):
plugin_module = importlib.import_module("plugins."+plugin)
plugin_module = importlib.import_module(plugin.replace("/","."))
if function not in plugin_module.functions:
return {"error": "Function not found"}
@@ -41,6 +159,21 @@ def runPluginFunction(plugin: str, function: str, params: dict, authentication:
# Get the function object from the plugin module
plugin_function = getattr(plugin_module, function)
# Check if the function is in the signature list
signatures = []
try:
with open("user_data/plugin_signatures.json", "r") as f:
signatures = json.load(f)
except:
# Write a new signatures file
with open("user_data/plugin_signatures.json", "w") as f:
json.dump(signatures, f)
# Hash the plugin file
pluginHash = hashPlugin(plugin)
if pluginHash not in signatures:
return {"error": "Plugin not verified"}
# Call the function with provided parameters
try:
result = plugin_function(params, authentication)
@@ -50,14 +183,17 @@ def runPluginFunction(plugin: str, function: str, params: dict, authentication:
return {"error": str(e)}
# return plugin.runFunction(function, params, authentication)
def getPluginFunctionInputs(plugin: str, function: str):
plugin = importlib.import_module("plugins."+plugin)
plugin = importlib.import_module(plugin.replace("/","."))
return plugin.functions[function]["params"]
def getPluginFunctionReturns(plugin: str, function: str):
plugin = importlib.import_module("plugins."+plugin)
plugin = importlib.import_module(plugin.replace("/","."))
return plugin.functions[function]["returns"]
def getDomainFunctions():
plugins = listPlugins()
domainFunctions = []
@@ -72,6 +208,7 @@ def getDomainFunctions():
})
return domainFunctions
def getSearchFunctions():
plugins = listPlugins()
searchFunctions = []
@@ -86,6 +223,7 @@ def getSearchFunctions():
})
return searchFunctions
def getDashboardFunctions():
plugins = listPlugins()
dashboardFunctions = []

View File

@@ -1,5 +1,53 @@
# Plugins
Plugins can be created to add more functionality to FireWallet Browser
## Format
They are created in python and use the format:
```python
info = {
"name": "Plugin Name",
"description": "Plugin Description",
"version": "Version number",
"author": "Your Name",
}
functions = {
"internalName":{
"name": "Human readable name",
"type": "Type of plugin",
"description": "Function description",
"params": { # For plugins other than default use {} for no params
"paramName": {
"name":"Human readable paramiter name",
"type":"type of paramiter",
}
},
"returns": {
"returnName":
{
"name": "Human readable return name",
"type": "type of return"
}
}
}
}
def internalName(params, authentication): # This should always have the same inputs
paramName = params["paramName"]
wallet = authentication.split(":")[0]
# Do stuff
output = "Return value of stuff: " + paramName
return {"returnName": output}
```
## Types
### Default
Type: `default`
@@ -15,6 +63,7 @@ This type is used for domain plugins. It shows in the manage domain page or the
It gets the `domain` paramater as the only input (in addition to authentication)
### Dashboard
Type: `dashboard`
This type is used for dashboard plugins.
It shows in the dashboard page. It doesn't get any inputs other than the authentication

158
plugins/automations.py Normal file
View File

@@ -0,0 +1,158 @@
import json
import account
import requests
import threading
import os
import time
APIKEY = os.environ.get("hsd_api")
ip = os.getenv("hsd_ip")
if ip is None:
ip = "localhost"
if not os.path.exists("user_data"):
os.mkdir("user_data")
# Plugin Data
info = {
"name": "Automations",
"description": "This plugin will automatically renew domains, reveal and redeem bids.",
"version": "1.0",
"author": "Nathan.Woodburn/"
}
# Functions
functions = {
"automation":{
"name": "Function to automate",
"type": "dashboard",
"description": "This used type dashboard to trigger the function whenever you access the dashboard.",
"params": {},
"returns": {
"Status":
{
"name": "Status of the automation",
"type": "text"
}
}
},
"disable":{
"name": "Disable Automations",
"type": "default",
"description": "Disable Automations for this wallet",
"params": {},
"returns": {
"Status":
{
"name": "Status",
"type": "text"
}
}
},
"enable":{
"name": "Enable Automations",
"type": "default",
"description": "Enable Automations for this wallet",
"params": {},
"returns": {
"Status":
{
"name": "Status",
"type": "text"
}
}
},
"list":{
"name": "List Disabled Wallets",
"type": "default",
"description": "List wallets with automations disabled",
"params": {},
"returns": {
"wallets":
{
"name": "List of wallets",
"type": "list"
}
}
}
}
started = False
# Main entry point only lets the main function run every 5 mins
def automation(params, authentication):
global started
wallet = authentication.split(":")[0]
if os.path.exists(f"user_data/{wallet}.autoRenew"):
return {"Status": "Automations disabled"}
if started:
return {"Status": "Automations running"}
started = True
threading.Thread(target=automations_background, args=(authentication,)).start()
return {"Status": "Starting Automations..."}
def disable(params, authentication):
# Create walletname file in user_data
wallet = authentication.split(":")[0]
if not os.path.exists("user_data"):
os.mkdir("user_data")
with open(f"user_data/{wallet}.autoRenew", "w") as f:
f.write(f"This file is used to disable automations for '{wallet}' wallet.\nDelete this file to enable automations.")
return {"Status": "Disabled Automations"}
def enable(params, authentication):
# Delete walletname file in user_data
wallet = authentication.split(":")[0]
if os.path.exists(f"user_data/{wallet}.autoRenew"):
os.remove(f"user_data/{wallet}.autoRenew")
return {"Status": "Enabled Automations"}
def list(params, authentication):
wallets = []
for file in os.listdir("user_data"):
if file.endswith(".autoRenew"):
wallets.append(file[:-10])
return {"wallets": wallets}
# Background function to run the automations
def automations_background(authentication):
while True:
# Get account details
account_name = account.check_account(authentication)
password = ":".join(authentication.split(":")[1:])
if account_name == False:
return {
"error": {
"message": "Invalid account"
}
}
if os.path.exists(f"user_data/{account_name}.autoRenew"):
print("Skipping Automations")
time.sleep(300)
continue
print("Running automations")
try:
# Try to select and login to the wallet
response = account.hsw.rpc_selectWallet(account_name)
if response['error'] is not None:
return
response = account.hsw.rpc_walletPassphrase(password,30)
if response['error'] is not None:
return
# Try to send the batch of all renew, reveal and redeem actions
requests.post(f"http://x:{APIKEY}@{ip}:12039",json={"method": "sendbatch","params": [[["RENEW"]]]})
requests.post(f"http://x:{APIKEY}@{ip}:12039",json={"method": "sendbatch","params": [[["REVEAL"]]]})
requests.post(f"http://x:{APIKEY}@{ip}:12039",json={"method": "sendbatch","params": [[["REDEEM"]]]})
except Exception as e:
print(e)
# Sleep for 5 mins before running again
time.sleep(300)

518
plugins/batching.py Normal file
View File

@@ -0,0 +1,518 @@
import json
import account
import requests
import os
# Plugin Data
info = {
"name": "Batching Functions",
"description": "This is a plugin that provides multiple functions to batch transactions",
"version": "1.0",
"author": "Nathan.Woodburn/"
}
# https://hsd-dev.org/api-docs/?shell--cli#sendbatch
# Functions
functions = {
"transfer":{
"name": "Batch transfer",
"type": "default",
"description": "Transfer a ton of domains",
"params": {
"domains": {
"name":"List of domains to transfer (one per line)",
"type":"longText"
},
"address": {
"name":"Address to transfer to",
"type":"address"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"finalize":{
"name": "Batch finalize a transfer",
"type": "default",
"description": "Finalize transferring a ton of domains",
"params": {
"domains": {
"name":"List of domains to finalize (one per line)",
"type":"longText"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"cancel":{
"name": "Batch cancel a transfer",
"type": "default",
"description": "Cancel transferring a ton of domains",
"params": {
"domains": {
"name":"List of domains to cancel (one per line)",
"type":"longText"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"open":{
"name": "Batch open auctions",
"type": "default",
"description": "Open auctions for a ton of domains",
"params": {
"domains": {
"name":"List of domains to open (one per line)",
"type":"longText"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"bid":{
"name": "Batch bid on auctions",
"type": "default",
"description": "Bid on auctions for a ton of domains",
"params": {
"domains": {
"name":"List of domains to bid on (one per line)",
"type":"longText"
},
"bid": {
"name":"Bid amount",
"type":"text"
},
"blind": {
"name":"Blind amount",
"type":"text"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"reveal":{
"name": "Batch reveal bids",
"type": "default",
"description": "Reveal bids for tons of auctions",
"params": {
"domains": {
"name":"List of domains to reveal (one per line)",
"type":"longText"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"redeem":{
"name": "Batch redeem bids",
"type": "default",
"description": "Redeem lost bids to get funds back",
"params": {
"domains": {
"name":"List of domains to redeem (one per line)",
"type":"longText"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"register":{
"name": "Batch register domains",
"type": "default",
"description": "Register domains won in auction",
"params": {
"domains": {
"name":"List of domains to redeem (one per line)",
"type":"longText"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"renew":{
"name": "Batch renew domains",
"type": "default",
"description": "Renew a ton of domain",
"params": {
"domains": {
"name": "Domains to renew (one per line)",
"type": "longText"
}
},
"returns": {
"status": {
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"advancedBid":{
"name": "Bid on domains with csv",
"type": "default",
"description": "Bid on domains using a csv format",
"params": {
"bids": {
"name":"List of bids in format `domain,bid,blind` (one per line)",
"type":"longText"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"advancedBatch":{
"name": "Batch transactions with csv",
"type": "default",
"description": "Batch transactions using a csv format",
"params": {
"transactions": {
"name":"List of transactions in format `type,domain,param1,param2` (one per line) Eg.<br>TRANSFER,woodburn1,hs1q4rkfe5df7ss6wzhnw388hv27we0hp7ha2np0hk<br>OPEN,woodburn2",
"type":"longText"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
},
"transaction":
{
"name": "Hash of the transaction",
"type": "tx"
}
}
},
"advancedChangeLookahead":{
"name": "Change wallet lookahead",
"type": "default",
"description": "Change the lookahead of the wallet",
"params": {
"lookahead": {
"name":"Lookahead (default 200)",
"type":"number"
}
},
"returns": {
"status":
{
"name": "Status",
"type": "text"
}
}
}
}
def sendBatch(batch, authentication):
response = account.sendBatch(authentication, batch)
return response
def transfer(params, authentication):
domains = params["domains"]
address = params["address"]
domains = domains.splitlines()
domains = [x.strip() for x in domains]
domains = [x for x in domains if x != ""]
wallet = authentication.split(":")[0]
owned = account.getDomains(wallet)
# Only keep owned domains ["name"]
ownedNames = [domain["name"] for domain in owned]
for domain in domains:
if domain not in ownedNames:
return {
"status":f"Domain {domain} not owned",
"transaction":None
}
batch = []
for domain in domains:
batch.append(['TRANSFER', domain, address])
response = sendBatch(batch, authentication)
if 'error' in response:
return {
"status":response['error']['message'],
"transaction":None
}
return {
"status":"Sent batch successfully",
"transaction":response['hash']
}
def simple(batchType,params, authentication):
domains = params["domains"]
domains = domains.splitlines()
domains = [x.strip() for x in domains]
domains = [x for x in domains if x != ""]
batch = []
for domain in domains:
batch.append([batchType, domain])
print(batch)
response = sendBatch(batch, authentication)
if 'error' in response:
print(response)
return {
"status":response['error']['message'],
"transaction":None
}
return {
"status":"Sent batch successfully",
"transaction":response['hash']
}
def finalize(params, authentication):
return simple("FINALIZE",params,authentication)
def cancel(params, authentication):
return simple("CANCEL",params,authentication)
def open(params, authentication):
return simple("OPEN",params,authentication)
def bid(params, authentication):
domains = params["domains"]
domains = domains.splitlines()
domains = [x.strip() for x in domains]
domains = [x for x in domains if x != ""]
try:
bid = float(params["bid"])
blind = float(params["blind"])
blind+=bid
except:
return {
"status":"Invalid bid amount",
"transaction":None
}
batch = []
for domain in domains:
batch.append(['BID', domain, bid, blind])
print(batch)
response = sendBatch(batch, authentication)
if 'error' in response:
return {
"status":response['error']['message'],
"transaction":None
}
return {
"status":"Sent batch successfully",
"transaction":response['hash']
}
def reveal(params, authentication):
return simple("REVEAL",params,authentication)
def redeem(params, authentication):
return simple("REDEEM",params,authentication)
def register(params, authentication):
domains = params["domains"]
domains = domains.splitlines()
domains = [x.strip() for x in domains]
domains = [x for x in domains if x != ""]
batch = []
for domain in domains:
batch.append(['UPDATE', domain,{"records": []}])
print(batch)
response = sendBatch(batch, authentication)
if 'error' in response:
return {
"status":response['error']['message'],
"transaction":None
}
return {
"status":"Sent batch successfully",
"transaction":response['hash']
}
def renew(params, authentication):
return simple("RENEW", params, authentication)
def advancedBid(params, authentication):
bids = params["bids"]
bids = bids.splitlines()
bids = [x.strip() for x in bids]
bids = [x for x in bids if x != ""]
batch = []
for bid in bids:
# Split the bid
line = bid.split(",")
domain = line[0]
bid = float(line[1])
blind = float(line[2])
blind+=bid
batch.append(['BID', domain, bid, blind])
print(batch)
response = sendBatch(batch, authentication)
if 'error' in response:
return {
"status":response['error']['message'],
"transaction":None
}
return {
"status":"Sent batch successfully",
"transaction":response['hash']
}
def advancedBatch(params, authentication):
transactions = params["transactions"]
transactions = transactions.splitlines()
transactions = [x.strip() for x in transactions]
transactions = [x for x in transactions if x != ""]
batch = []
for transaction in transactions:
# Split the bid
line = transaction.split(",")
line[0] = line[0].upper()
batch.append(line)
print(batch)
response = sendBatch(batch, authentication)
if 'error' in response:
return {
"status":response['error']['message'],
"transaction":None
}
return {
"status":"Sent batch successfully",
"transaction":response['hash']
}
def advancedChangeLookahead(params, authentication):
lookahead = params["lookahead"]
lookahead = int(lookahead)
wallet = authentication.split(":")[0]
password = ":".join(authentication.split(":")[1:])
APIKEY = os.getenv("hsd_api")
ip = os.getenv("hsd_ip")
if ip is None:
ip = "localhost"
# Unlock wallet
response = requests.post(f"http://x:{APIKEY}@{ip}:12039/wallet/{wallet}/unlock",
json={"passphrase": password, "timeout": 10})
response = requests.patch(f"http://x:{APIKEY}@{ip}:12039/wallet/{wallet}/account/default",
json={"lookahead": lookahead})
return {
"status":f"Status: {'Success' if response.status_code == 200 else 'Error'}"
}

114
plugins/customPlugins.py Normal file
View File

@@ -0,0 +1,114 @@
import json
import account
import requests
import os
# Plugin Data
info = {
"name": "Custom Plugin Manager",
"description": "Import custom plugins from git repositories",
"version": "1.0",
"author": "Nathan.Woodburn/"
}
# Functions
functions = {
"add":{
"name": "Add Plugin repo",
"type": "default",
"description": "Add a plugin repo",
"params": {
"url": {
"name":"URL",
"type":"text"
}
},
"returns": {
"status":
{
"name": "Status of the function",
"type": "text"
}
}
},
"remove":{
"name": "Remove Plugins",
"type": "default",
"description": "Remove a plugin repo from the list",
"params": {
"url": {
"name":"URL",
"type":"text"
}
},
"returns": {
"status":
{
"name": "Status of the function",
"type": "text"
}
}
},
"list":{
"name": "List Plugins",
"type": "default",
"description": "List all imported plugins",
"params": {},
"returns": {
"plugins":
{
"name": "List of plugins",
"type": "list"
}
}
}
}
def add(params, authentication):
url = params["url"]
if not os.path.exists("user_data/plugins.json"):
with open("user_data/plugins.json", "w") as f:
json.dump([], f)
with open("user_data/plugins.json", "r") as f:
importurls = json.load(f)
# Check if the plugin is already imported
if url in importurls:
return {"status": "Plugin already imported"}
importurls.append(url)
with open("user_data/plugins.json", "w") as f:
json.dump(importurls, f)
return {"status": "Imported"}
def remove(params, authentication):
url = params["url"]
if not os.path.exists("user_data/plugins.json"):
with open("user_data/plugins.json", "w") as f:
json.dump([], f)
with open("user_data/plugins.json", "r") as f:
importurls = json.load(f)
# Check if the plugin is already imported
if url not in importurls:
return {"status": "Plugin not imported"}
importurls.remove(url)
with open("user_data/plugins.json", "w") as f:
json.dump(importurls, f)
return {"status": "Removed"}
def list(params, authentication):
if not os.path.exists("user_data/plugins.json"):
with open("user_data/plugins.json", "w") as f:
json.dump([], f)
with open("user_data/plugins.json", "r") as f:
importurls = json.load(f)
return {"plugins": importurls}

View File

@@ -138,7 +138,7 @@ def check(params, authentication):
return {"domains": domains}
def search(params, authentication):
search = params["search"]
search = params["search"].lower()
wallet = authentication.split(":")[0]
owned = account.getDomains(wallet)
# Only keep owned domains ["name"]
@@ -159,10 +159,10 @@ def dns(params,authentication):
def niami(params, authentication):
domain = params["domain"]
print(domain)
response = requests.get(f"https://api.handshake.niami.io/domain/{domain}")
print(response.text)
data = response.json()["data"]
if 'rating' not in data:
return {"rating":"No rating found."}
rating = str(data["rating"]["score"]) + " (" + data["rating"]["rarity"] + ")"
return {"rating":rating}

98
plugins/renewal.py Normal file
View File

@@ -0,0 +1,98 @@
import json
import account
import requests
import os
# Plugin Data
info = {
"name": "Batch Renew Domains",
"description": "Renew the next 100 domains",
"version": "1.0",
"author": "Nathan.Woodburn/"
}
# Functions
functions = {
"main":{
"name": "Renew",
"type": "default",
"description": "Renew the next 100 domains in one transaction. Please wait for at least 1 block confirmation before renewing the next 100 domains",
"params": {},
"returns": {
"status":
{
"name": "Status of the function",
"type": "text"
},
"transaction":
{
"name": "Transaction ID",
"type": "tx"
}
}
}
}
def main(params, authentication):
password = authentication.split(":")[1]
wallet = authentication.split(":")[0]
domains = account.getDomains(wallet)
domains = sorted(domains, key=lambda k: k['renewal'])
names = []
for domain in domains:
name = domain["name"]
names.append(name)
# Split names into batches of 100
batches = []
for i in range(0, len(names), 100):
batches.append(names[i:i+100])
# Unlock wallet
api_key = os.getenv("hsd_api")
ip = os.getenv("hsd_ip")
if api_key is None:
print("API key not set")
return {"status": "API key not set", "transaction": "None"}
response = requests.post(f'http://x:{api_key}@{ip}:12039/wallet/{wallet}/unlock',
json={'passphrase': password, 'timeout': 600})
if response.status_code != 200:
print("Failed to unlock wallet")
print(f'Status code: {response.status_code}')
print(f'Response: {response.text}')
return {"status": "Failed unlocking wallet", "transaction": "None"}
tx = "None"
for batch in batches:
batch = []
for domain in names:
batch.append(f'["RENEW", "{domain}"]')
batchTX = "[" + ", ".join(batch) + "]"
responseContent = f'{{"method": "sendbatch","params":[ {batchTX} ]}}'
response = requests.post(f'http://x:{api_key}@{ip}:12039', data=responseContent)
if response.status_code != 200:
print("Failed to create batch",flush=True)
print(f'Status code: {response.status_code}',flush=True)
print(f'Response: {response.text}',flush=True)
return {"status": "Failed", "transaction": "None"}
batch = response.json()
# Verify the batch
print("Verifying tx...")
if batch["error"]:
if batch["error"] != "":
print("Failed to verify batch",flush=True)
print(batch["error"]["message"],flush=True)
return {"status": f"Failed: {batch['error']['message']}", "transaction": "None"}
if 'result' in batch:
if batch['result'] != None:
tx = batch['result']['hash']
return {"status": "Success", "transaction": tx}
# Note only one batch can be sent at a time

32
plugins/template.py Normal file
View File

@@ -0,0 +1,32 @@
import json
import account
import requests
# Plugin Data
info = {
"name": "Plugin Template",
"description": "Plugin Description",
"version": "1.0",
"author": "Nathan.Woodburn/"
}
# Functions
functions = {
"main":{
"name": "Function name",
"type": "dashboard",
"description": "Description",
"params": {},
"returns": {
"status":
{
"name": "Status of the function",
"type": "text"
}
}
}
}
def main(params, authentication):
return {"status": "Success"}

35
plugins/txcount.py Normal file
View File

@@ -0,0 +1,35 @@
import json
import account
import requests
# Plugin Data
info = {
"name": "TX Count",
"description": "Plugin for checking how many txs are in a wallet",
"version": "1.0",
"author": "Nathan.Woodburn/"
}
# Functions
functions = {
"main":{
"name": "List TXs",
"type": "default",
"description": "Get TXs",
"params": {},
"returns": {
"txs":
{
"name": "Transactions",
"type": "text"
}
}
}
}
def main(params, authentication):
wallet = authentication.split(":")[0]
txs = account.getTransactions(wallet)
return {"txs": f'Total TXs: {len(txs)}'}

195
plugins/varo.py Normal file
View File

@@ -0,0 +1,195 @@
import json
import account
import requests
import os
if not os.path.exists("user_data"):
os.mkdir("user_data")
# Plugin Data
info = {
"name": "Varo Functions",
"description": "Integration with Varo.",
"version": "1.0",
"author": "Nathan.Woodburn/"
}
# Functions
functions = {
"status":{
"name": "Check connection",
"type": "dashboard",
"description": "You need to login to the varo instance before you can use this function.",
"params": {},
"returns": {
"status":
{
"name": "Status of varo connection",
"type": "text"
}
}
},
"login":{
"name": "Login to Varo",
"type": "default",
"description": "Login to Varo<br>Use the domain of the varo instance (eg. <a target='_blank' href='https://domains.hns.au'>domains.hns.au</a>) and API key from the dashboard.",
"params": {
"instance": {
"name":"Varo instance",
"type":"text"
},
"api": {
"name":"API key",
"type":"text"
}
},
"returns": {
"status":
{
"name": "Status of the function",
"type": "text"
}
}
},
"addDomain":{
"name": "Add domain",
"type": "default",
"description": "Add a domain to Varo",
"params": {
"domain": {
"name":"Domain",
"type":"text"
}
},
"returns": {
"status":
{
"name": "Status of the function",
"type": "text"
}
}
}
}
def status(params, authentication):
# Try to connect to Varo
if not os.path.exists("user_data/varo.json"):
return {"status": "Missing Varo API or instance"}
with open("user_data/varo.json", "r") as f:
auth = json.load(f)
if not auth:
return {"status": "Missing Varo API or instance"}
if 'api' not in auth or 'instance' not in auth:
return {"status": "Missing Varo API or instance"}
api = auth["api"]
instance = auth["instance"]
headers = {"Authorization": f"Bearer {api}"}
data = {
"action": "getInfo"
}
response = requests.post(f"https://{instance}/api", json=data, headers=headers)
if response.status_code != 200:
return {"status": "Error connecting to Varo"}
if response.json()["success"] != True:
return {"status": "Error connecting to Varo"}
return {"status": f"Connected to {instance}"}
def login(params, authentication):
# Verify the user has entered the correct details
instance = params["instance"]
api = params["api"]
# Strip the https:// from the instance
instance = instance.replace("https://", "")
instance = instance.replace("http://", "")
response = requests.post(f"https://{instance}/api", json={"action": "getInfo"}, headers={"Authorization": f"Bearer {api}"})
if response.status_code != 200:
return {"status": "Error connecting to Varo"}
if response.json()["success"] != True:
return {"status": "Error connecting to Varo"}
auth = {
"instance": instance,
"api": api
}
# Save the API key to the varo.json file
with open("user_data/varo.json", "w") as f:
json.dump(auth, f)
return {"status": "Success"}
def addDomain(params, authentication):
# Add a domain to Varo
domain = params["domain"]
if not os.path.exists("user_data/varo.json"):
return {"status": "Missing Varo API or instance"}
with open("user_data/varo.json", "r") as f:
auth = json.load(f)
if not auth:
return {"status": "Missing Varo API or instance"}
if 'api' not in auth or 'instance' not in auth:
return {"status": "Missing Varo API or instance"}
api = auth["api"]
instance = auth["instance"]
headers = {"Authorization": f"Bearer {api}"}
data = {
"action": "getZones"
}
zones = requests.post(f"https://{instance}/api", json=data, headers=headers)
if zones.status_code != 200:
return {"status": "Error connecting to Varo"}
if zones.json()["success"] != True:
return {"status": "Error connecting to Varo"}
zones = zones.json()["data"]
for zone in zones:
if zone["name"] == domain:
return {"status": "Domain already exists"}
# Check domain is owned by user
wallet = authentication.split(":")[0]
owned = account.getDomains(wallet)
# Only keep owned domains ["name"]
ownedNames = [domain["name"] for domain in owned]
if domain not in ownedNames:
return {"status": "Domain not owned by user"}
data = {
"action": "createZone",
"domain": domain
}
response = requests.post(f"https://{instance}/api", json=data, headers=headers)
if response.status_code != 200:
return {"status": "Error connecting to Varo"}
if response.json()["success"] != True:
return {"status": "Error connecting to Varo"}
zoneID = response.json()["data"]["zone"]
data = {
"action": "showZone",
"zone": zoneID
}
response = requests.post(f"https://{instance}/api", json=data, headers=headers)
if response.status_code != 200:
return {"status": "Error connecting to Varo"}
if response.json()["success"] != True:
return {"status": "Error connecting to Varo"}
zone = response.json()["data"]
dns = []
for ns in zone['NS']:
dns.append({'type': 'NS', 'value': ns})
ds = zone['DS']
ds = ds.split(' ')
dns.append({'type': 'DS', 'keyTag': int(ds[0]), 'algorithm': int(ds[1]), 'digestType': int(ds[2]), 'digest': ds[3]})
dns = json.dumps(dns)
response = account.setDNS(authentication,domain,dns)
return {"status": "Success"}

View File

@@ -2,23 +2,29 @@ import datetime
import json
import urllib.parse
from flask import render_template
from domainLookup import punycode_to_emoji
def domains(domains):
def domains(domains, mobile=False):
html = ''
for domain in domains:
owner = domain['owner']
if 'index' in owner:
if owner['index'] == 0:
continue
expires = domain['stats']
if 'daysUntilExpire' in expires:
expires = expires['daysUntilExpire']
else:
expires = "No expiration date"
paid = domain['value']
paid = paid / 1000000
# Handle punycodes
name = domain['name']
emoji = punycode_to_emoji(name)
if emoji != name:
name = f'{emoji} ({name})'
html += f'<tr><td>{domain["name"]}</td><td>{expires} days</td><td>{paid} HNS</td><td><a href="/manage/{domain["name"]}">Manage</a></td></tr>'
if not mobile:
html += f'<tr><td>{name}</td><td>{expires} days</td><td>{paid} HNS</td><td><a href="/manage/{domain["name"]}">Manage</a></td></tr>'
else:
html += f'<tr><td><a href="/manage/{domain["name"]}">{name}</a></td><td>{expires} days</td></tr>'
return html
@@ -64,11 +70,6 @@ def transactions(txs):
html += f'<tr><td>{action}</td><td>{address}</td><td>{hash}</td>{confirmations}<td>{amount} HNS</td></tr>'
return html
@@ -175,6 +176,53 @@ def bids(bids,reveals):
return html
def bidDomains(bids,domains, sortState=False):
html = ''
if not sortState:
for bid in bids:
for domain in domains:
if bid['name'] == domain['name']:
lockup = bid['lockup']
lockup = lockup / 1000000
lockup = round(lockup, 2)
bidValue = bid['value'] / 1000000
bidValue = round(bidValue, 2)
blind = lockup - bidValue
bidValue = "{:,}".format(bidValue)
blind = round(blind, 2)
blind = "{:,}".format(blind)
bidDisplay = f'<b>{bidValue} HNS</b> + {blind} HNS blind'
html += "<tr>"
html += f"<td>{domain['name']}</td>"
html += f"<td>{domain['state']}</td>"
html += f"<td>{bidDisplay}</td>"
html += f"<td>{bid['height']}</td>"
html += "</tr>"
else:
for domain in domains:
for bid in bids:
if bid['name'] == domain['name']:
lockup = bid['lockup']
lockup = lockup / 1000000
lockup = round(lockup, 2)
bidValue = bid['value'] / 1000000
bidValue = round(bidValue, 2)
blind = lockup - bidValue
bidValue = "{:,}".format(bidValue)
blind = "{:,}".format(blind)
bidDisplay = f'<b>{bidValue} HNS</b> + {blind} HNS blind'
html += "<tr>"
html += f"<td>{domain['name']}</td>"
html += f"<td>{domain['state']}</td>"
html += f"<td>{bidDisplay}</td>"
html += "</tr>"
return html
def wallets(wallets):
html = ''
for wallet in wallets:
@@ -187,7 +235,10 @@ def plugins(plugins):
name = plugin['name']
link = plugin['link']
html += f'<li class="list-group-item"><a class="btn btn-primary" style="width:100%;height:100%;margin:0px;font-size: x-large;" role="button" href="/plugin/{link}">{name}</a></li>'
if plugin['verified']:
html += f'<li class="list-group-item"><a class="btn btn-secondary" style="width:100%;height:100%;margin:0px;font-size: x-large;" role="button" href="/plugin/{link}">{name}</a></li>'
else:
html += f'<li class="list-group-item"><a class="btn btn-danger" style="width:100%;height:100%;margin:0px;font-size: x-large;" role="button" href="/plugin/{link}">{name} (Not verified)</a></li>'
return html
def plugin_functions(functions, pluginName):
@@ -265,11 +316,12 @@ def plugin_output(outputs, returns):
html = ''
for returnOutput in returns:
if returnOutput not in outputs:
continue
html += f'<div class="card" style="margin-top: 50px; margin-bottom: 50px;">'
html += f'<div class="card-body">'
html += f'<h4 class="card-title">{returns[returnOutput]["name"]}</h4>'
# Get the output
output = outputs[returnOutput]
if returns[returnOutput]["type"] == "list":
html += f'<ul>'
@@ -294,9 +346,7 @@ def plugin_output_dash(outputs, returns):
html = ''
for returnOutput in returns:
if returnOutput not in outputs:
continue
html += render_template('components/dashboard-plugin.html', name=returns[returnOutput]["name"], output=outputs[returnOutput])
html += f'</div>'
html += f'</div>'
return html

View File

@@ -8,3 +8,4 @@ cryptography
requests-doh
Flask-QRcode
PySocks
python-git-info

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
.fab.fa-bitcoin:before{content:"\f379"}.far.fa-calendar:before,.fas.fa-calendar:before{content:"\f133"}.far.fa-clipboard:before,.fas.fa-clipboard:before{content:"\f328"}.fab.fa-facebook-f:before{content:"\f39e"}.fab.fa-google-plus:before{content:"\f2b3"}.fas.fa-hotel:before{content:"\f594"}.fab.fa-linkedin:before{content:"\f08c"}.fas.fa-reply:before{content:"\f3e5"}.fas.fa-thermometer:before{content:"\f491"}.fab.fa-vimeo:before{content:"\f40a"}.far.fa-window-close:before,.fas.fa-window-close:before{content:"\f410"}.fab.fa-youtube-square:before{content:"\f431"}

Binary file not shown.

11
templates/assets/fonts/ionicons.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
function copyAddress(){var e=document.getElementById("copyLink").getAttribute("address"),t=document.createElement("input");t.value=e,document.body.appendChild(t),t.select(),t.setSelectionRange(0,99999),navigator.clipboard.writeText(t.value),document.body.removeChild(t),document.getElementById("copyLink").innerHTML="Copied!"}
function copyToClipboard(){var e=document.getElementById("data");e.style.display="block",e.select(),e.setSelectionRange(0,99999),document.execCommand("copy"),e.style.display="none",document.getElementById("copyButton").innerHTML="Copied"}

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>

176
templates/auctions.html Normal file
View File

@@ -0,0 +1,176 @@
<!DOCTYPE html>
<html data-bs-theme="dark" lang="en-au">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Auctions - FireWallet</title>
<link rel="icon" type="image/png" sizes="900x768" href="/assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="900x768" href="/assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="900x768" href="/assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="900x768" href="/assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="900x768" href="/assets/img/favicon.png">
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
</a>
<hr class="sidebar-divider my-0">
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
<div id="content">
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>
</ul>
</div>
</nav>
<div class="container-fluid">
<div class="d-sm-flex justify-content-between align-items-center mb-4">
<h3 class="text-dark mb-0">Bids</h3>
</div>
<h1 class="text-center">{{message}}</h1>
<div class="row">
<div class="col-md-6 col-xl-3 mb-4">
<div class="card shadow border-start-primary py-2">
<div class="card-body">
<div class="row align-items-center no-gutters">
<div class="col me-2">
<div class="text-uppercase text-primary fw-bold text-xs mb-1"><span style="color: var(--bs-dark);">HNS Locked</span></div>
<div class="text-dark fw-bold h5 mb-0"><span><img src="/assets/img/HNS.png" width="20px">&nbsp;{{locked}}</span></div>
</div>
<div class="col-auto"><i class="fas fa-dollar-sign fa-2x text-gray-300"></i></div>
</div>
</div>
</div>
</div>
<div class="col-md-6 col-xl-3 mb-4">
<div class="card shadow border-start-success py-2">
<div class="card-body">
<div class="row align-items-center no-gutters">
<div class="col me-2">
<div class="text-uppercase text-success fw-bold text-xs mb-1"><span>Total Bids</span></div>
<div class="text-dark fw-bold h5 mb-0"><span>{{bids}}</span></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6 col-xl-3 mb-4">
<div class="card shadow border-start-info py-2">
<div class="card-body">
<div class="row align-items-center no-gutters">
<div class="col me-2">
<div class="text-uppercase text-info fw-bold text-xs mb-1"><span>Pending Reveal</span></div>
<div class="row g-0 align-items-center">
<div class="col-auto">
<div class="text-dark fw-bold h5 mb-0 me-3"><span>{{reveal}}</span></div>
</div>
<div class="col"><a class="btn btn-primary" role="button" href="/reveal">Reveal All</a></div>
</div>
</div>
</div>
</div>
</div>
</div>{{plugins|safe}}
</div>
<div class="row d-none d-sm-none d-md-block">
<div class="col">
<div class="card shadow mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<h6 class="text-primary fw-bold m-0">Domains</h6>
</div>
<div class="card-body"><div class="table-responsive">
<table class="table">
<thead>
<tr>
<th><a href="/auctions?direction={{sort_domain_next}}">Domain{{sort_domain}}</a></th>
<th><a href="/auctions?sort=state&direction={{sort_state_next}}">State{{sort_state}}</a></th>
<th><a href="/auctions?sort=price&direction={{sort_price_next}}">Bid{{sort_price}}</a></th>
<th><a href="/auctions?sort=time&direction={{sort_time_next}}">Block{{sort_time}}</a></th>
<th></th>
</tr>
</thead>
<tbody>
{{domains | safe}}
</tbody>
</table>
</div></div>
</div>
</div>
</div>
<div class="row d-block d-sm-block d-md-none">
<div class="col">
<div class="card shadow mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<h6 class="text-primary fw-bold m-0">Domains</h6>
</div>
<div class="card-body"><div class="table-responsive">
<table class="table">
<thead>
<tr>
<th><a href="/auctions?direction={{sort_domain_next}}">Domain{{sort_domain}}</a></th>
<th><a href="/auctions?sort=state&direction={{sort_state_next}}">State{{sort_state}}</a></th>
<th><a href="/auctions?sort=price&direction={{sort_price_next}}">Bid{{sort_price}}</a></th>
<th></th>
</tr>
</thead>
<tbody>
{{domains | safe}}
</tbody>
</table>
</div></div>
</div>
</div>
</div>
</div>
</div>
<footer class="sticky-footer" style="background: var(--bs-primary-text-emphasis);">
<div class="container my-auto">
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2024</span></div>
</div>
</footer>
</div><a class="border rounded d-inline scroll-to-top" href="#page-top"><i class="fas fa-angle-up"></i></a>
</div>
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
<script src="/assets/js/script.min.js"></script>
</body>
</html>

View File

@@ -2,7 +2,7 @@
<div class="card shadow border-start-warning py-2">
<div class="card-body">
<div class="text-uppercase fw-bold text-xs mb-1"><span style="color: var(--bs-dark);">{{name}}</span></div>
<div class="text-dark fw-bold h5 mb-0"><span>{{output}}</span></div>
<div class="text-dark fw-bold h5 mb-0"><span>{{output | safe}}</span></div>
</div>
</div>
</div>

View File

@@ -2,3 +2,4 @@
<span style="display: block;">Check your transaction on a block explorer</span>
<a class="card-link" href="https://niami.io/tx/{{tx}}" target="_blank">Niami</a>
<a class="card-link" href="https://3xpl.com/handshake/transaction/{{tx}}" target="_blank">3xpl</a>
<a class="card-link" href="https://hns.cymon.de/tx/{{tx}}" target="_blank">Cymon.de</a>

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,10 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link active" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>
@@ -62,7 +64,7 @@
</nav>
<div class="container-fluid">
<div class="d-sm-flex justify-content-between align-items-center mb-4">
<h3 class="text-dark mb-0">Dashboard</h3><a class="btn btn-primary btn-sm d-none d-sm-inline-block" role="button" href="/report"><i class="fas fa-download fa-sm text-white-50"></i>&nbsp;Generate Report</a>
<h3 class="text-dark mb-0">Dashboard</h3><a class="btn btn-primary btn-sm d-none d-sm-inline-block" role="button" href="/report" target="_blank"><i class="fas fa-download fa-sm text-white-50"></i>&nbsp;Generate Report</a>
</div>
<div class="row">
<div class="col-md-6 col-xl-3 mb-4">
@@ -70,7 +72,7 @@
<div class="card-body">
<div class="row align-items-center no-gutters">
<div class="col me-2">
<div class="text-uppercase text-primary fw-bold text-xs mb-1"><span>HNS Available</span></div>
<div class="text-uppercase text-primary fw-bold text-xs mb-1"><span style="color: var(--bs-dark);">HNS Available</span></div>
<div class="text-dark fw-bold h5 mb-0"><span><img src="/assets/img/HNS.png" width="20px">&nbsp;{{available}}</span></div>
</div>
<div class="col-auto"><i class="fas fa-dollar-sign fa-2x text-gray-300"></i></div>
@@ -128,7 +130,7 @@
</div>
</div>{{plugins|safe}}
</div>
<div class="row">
<div class="row d-none d-sm-none d-md-block">
<div class="col">
<div class="card shadow mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
@@ -148,6 +150,28 @@
{{domains | safe}}
</tbody>
</table>
</div></div>
</div>
</div>
</div>
<div class="row d-block d-sm-block d-md-none">
<div class="col">
<div class="card shadow mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<h6 class="text-primary fw-bold m-0">Domains</h6>
</div>
<div class="card-body"><div class="table-responsive">
<table class="table">
<thead>
<tr>
<th><a href="/?direction={{sort_domain_next}}">Domain{{sort_domain}}</a></th>
<th><a href="/?sort=expiry&direction={{sort_expiry_next}}">Expires{{sort_expiry}}</a></th>
</tr>
</thead>
<tbody>
{{domainsMobile | safe}}
</tbody>
</table>
</div></div>
</div>
</div>

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,32 +30,32 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
<div id="content">
<div id="content" style="padding-bottom: 25px;">
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>
@@ -136,6 +138,16 @@ function checkAddress(inputValue) {
</div>
</div>
</div>
<div class="container-fluid" style="margin-top: 50px;">
<div class="card">
<div class="card-body">
<h4 class="card-title" style="display: inline-block;">Sign Message</h4>
<form action="/manage/{{domain}}/sign" style="display: {% if finalize_time=='' %} block {% else %} none {% endif %};">
<div style="margin-top: 25px;"><label class="form-label">Message</label><input class="form-control" type="text" placeholder="Message to sign" name="message" value="{{message}}"></div><input class="btn btn-primary" type="submit" value="Sign" style="margin-top: 16px;">
</form>
</div>
</div>
</div>
</div>
<footer class="sticky-footer" style="background: var(--bs-primary-text-emphasis);">
<div class="container my-auto">

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>
@@ -64,7 +66,7 @@
<div class="container-fluid" style="margin-bottom: 20px;">
<h3 class="text-dark mb-1">{{name}}</h3>
<h4 class="text-dark mb-1">{{description}}</h4>
<h6 class="text-dark mb-1">Author: {{author}}<br>Version: {{version}}</h6>{{functions|safe}}
<h6 class="text-dark mb-1">Author: {{author}}<br>Version: {{version}}<br>Source: {{source}}</h6>{{functions|safe}}
</div>
</div>
<footer class="sticky-footer" style="background: var(--bs-primary-text-emphasis);">

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>
@@ -66,7 +68,7 @@
<div class="card" style="margin: auto;max-width: 500px;margin-top: 50px;">
<div class="card-body text-center">
<h4 class="card-title">{{address}}</h4><img src="/qr/{{address}}">
<p class="card-text">Use this address to receive HNS or Handshake domains from other people or wallets.</p><a class="card-link" id="copyLink" href="javascript:;" address="{{address}}" onclick="copyAddress()">Copy</a>
<p class="card-text">Use this address to receive HNS or Handshake domains from other people or wallets.</p><textarea id="data" style="display: none;">{{address}}</textarea><button class="btn btn-primary" id="copyButton" type="button" onclick="copyToClipboard()">Copy</button>
</div>
</div>
</div>

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>
@@ -63,8 +65,9 @@
<div class="container-fluid">
<div class="card">
<div class="card-body">
<h4 class="card-title">{{domain}}/<span class="stick-right">{{next}}</span></h4>
<h6 class="text-muted card-subtitle mb-2">{{state}}</h6>
<h4 class="d-none d-sm-none d-md-none d-lg-inline-block d-xl-inline-block card-title">{{domain}}/<span class="stick-right">{{next}}</span></h4>
<h4 class="d-print-none d-sm-inline-block d-md-inline-block d-lg-none d-xl-none d-xxl-none card-title">{{domain}}/<br><br><span class="stick-right">{{next}}</span></h4>
<h6 class="text-muted card-subtitle mb-2"><br>{{state}}</h6>
<h6 class="text-muted card-subtitle mb-2">Owner: {{owner}}</h6><a class="btn btn-primary" role="button" style="margin-right: 25px;" href="/manage/{{domain}}">Manage</a><a class="btn btn-primary" role="button" href="/auction/{{domain}}">Auction</a>
</div>
</div>

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>
@@ -99,7 +101,7 @@ function checkAddress(inputValue) {
var inputField = document.getElementById('address');
inputField.addEventListener('blur', handleBlur);
</script></div>
<div style="margin-top: 25px;"><label class="form-label">Amount</label><input class="form-control" type="text" id="amount" placeholder="0.00000" name="amount" style="margin-bottom: 10px;" value="{{amount}}"><span>Available to send: {{max}} HNS</span><button class="btn btn-primary btn-sm" id="maxButton" type="button" style="margin-left: 25px;background: var(--bs-primary-bg-subtle);">Send Max</button><script>
<div style="margin-top: 25px;"><label class="form-label">Amount</label><input class="form-control" type="text" id="amount" placeholder="0.00000" name="amount" style="margin-bottom: 10px;" value="{{amount}}"><span>Available to send: {{max}} HNS</span><button class="btn btn-secondary btn-sm" id="maxButton" type="button" style="margin-left: 25px;">Send Max</button><script>
// Function to fill in the form input
function fillInput() {
// Get the input field and set its value
@@ -111,7 +113,7 @@ function checkAddress(inputValue) {
var fillButton = document.getElementById('maxButton');
fillButton.addEventListener('click', fillInput);
</script></div>
<div class="text-center" style="margin-top: 25px;"><input class="btn btn-primary" type="submit" value="Send" style="background: var(--bs-primary-bg-subtle);"></div>
<div class="text-center" style="margin-top: 25px;"><input class="btn btn-secondary" type="submit" value="Send"></div>
</form>
</div>
<footer class="sticky-footer" style="background: var(--bs-primary-text-emphasis);">

View File

@@ -13,13 +13,16 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/ionicons.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +31,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +43,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>
@@ -102,6 +105,15 @@
</div>
</div>
</div>
<div class="container-fluid" style="margin-top: 50px;">
<div class="card">
<div class="card-body">
<h4 class="card-title">About</h4>
<h6 class="text-muted card-subtitle mb-2">FireWallet is a UI to allow easy connection with HSD created by <a href="https://nathan.woodburn.au" target="_blank">Nathan.Woodburn/</a> and freely available. Please contact him <a href="https://l.woodburn.au/contact" target="_blank">here</a> if you would like to request any features or report any bugs.<br>FireWallet version: <code>{{version}}</code></h6>
<div class="text-center"><a href="https://github.com/nathanwoodburn/firewalletbrowser" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration:none;" target="_blank"><i class="icon ion-social-github" style="color: var(--bs-emphasis-color);"></i>&nbsp;Github</a><a href="https://firewallet.au" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration:none;" target="_blank"><i class="icon ion-ios-information" style="color: var(--bs-emphasis-color);"></i>&nbsp;Website</a><a href="https://l.woodburn.au/donate" style="margin: 15px;color: var(--bs-emphasis-color);text-decoration:none;" target="_blank"><i class="icon ion-social-usd" style="color: var(--bs-emphasis-color);"></i>&nbsp;Donate to support development</a></div>
</div>
</div>
</div>
</div>
<footer class="sticky-footer" style="background: var(--bs-primary-text-emphasis);">
<div class="container my-auto">

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>

View File

@@ -13,13 +13,15 @@
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css">
<link rel="stylesheet" href="/assets/fonts/font-awesome.min.css">
<link rel="stylesheet" href="/assets/fonts/material-icons.min.css">
<link rel="stylesheet" href="/assets/fonts/fontawesome5-overrides.min.css">
<link rel="stylesheet" href="/assets/css/styles.min.css">
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="background: var(--bs-primary-border-subtle);">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark toggled" style="background: var(--bs-primary-border-subtle);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="/">
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
@@ -28,11 +30,11 @@
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
<li class="nav-item"><a class="nav-link" href="/auctions"><i class="fa fa-gavel"></i><span>Bids</span></a></li>
<li class="nav-item"><a class="nav-link" href="/send"><i class="material-icons">send</i><span>Send HNS</span></a></li>
<li class="nav-item"><a class="nav-link" href="/receive"><i class="material-icons">call_received</i><span>Receive</span></a></li>
<li class="nav-item"><a class="nav-link" href="/plugins"><i class="material-icons">code</i><span>Plugins</span></a><a class="nav-link" href="/settings"><i class="material-icons">settings</i><span>Settings</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper" style="background: var(--bs-primary);">
@@ -40,20 +42,20 @@
<nav class="navbar navbar-expand shadow mb-4 topbar static-top navbar-light" style="background: var(--bs-primary-text-emphasis);">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span>Sync: {{sync}}%</span>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for domain" name="q" value="{{search_term}}" style="color: var(--bs-dark-text-emphasis);background: var(--bs-light);"><button class="btn btn-primary py-0" type="submit"><i class="fas fa-search"></i></button></div>
</form><span style="color: var(--bs-dark);">Sync: {{sync}}%</span><span style="color: var(--bs-dark);margin-left: 10px;">Wallet: {{wallet_status}}</span>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<form class="me-auto navbar-search w-100" action="/search" method="get">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..." name="q" value="{{search_term}}">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 small" style="color: var(--bs-dark);">{{account}}</span><img class="border rounded-circle img-profile" src="/assets/img/HNS.png"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a></div>
</div>
</li>

View File

@@ -1 +1 @@
[data-bs-theme=dark]{--bs-primary:#000000;--bs-primary-rgb:0,0,0;--bs-primary-text-emphasis:#666666;--bs-primary-bg-subtle:#000000;--bs-primary-border-subtle:#000000;--bs-light:#404040;--bs-light-rgb:64,64,64;--bs-light-text-emphasis:#8C8C8C;--bs-light-bg-subtle:#0D0D0D;--bs-light-border-subtle:#262626;--bs-dark:#ffffff;--bs-dark-rgb:255,255,255;--bs-dark-text-emphasis:#FFFFFF;--bs-dark-bg-subtle:#333333;--bs-dark-border-subtle:#999999}.btn-primary[data-bs-theme=dark],[data-bs-theme=dark] .btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#000000;--bs-btn-border-color:#000000;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#000000;--bs-btn-hover-border-color:#000000;--bs-btn-focus-shadow-rgb:217,217,217;--bs-btn-active-color:#fff;--bs-btn-active-bg:#000000;--bs-btn-active-border-color:#000000;--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#000000;--bs-btn-disabled-border-color:#000000}.btn-outline-primary[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-primary{--bs-btn-color:#000000;--bs-btn-border-color:#000000;--bs-btn-focus-shadow-rgb:0,0,0;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#000000;--bs-btn-hover-border-color:#000000;--bs-btn-active-color:#fff;--bs-btn-active-bg:#000000;--bs-btn-active-border-color:#000000;--bs-btn-disabled-color:#000000;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#000000}.btn-light[data-bs-theme=dark],[data-bs-theme=dark] .btn-light{--bs-btn-color:#fff;--bs-btn-bg:#404040;--bs-btn-border-color:#404040;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#363636;--bs-btn-hover-border-color:#333333;--bs-btn-focus-shadow-rgb:226,226,226;--bs-btn-active-color:#fff;--bs-btn-active-bg:#333333;--bs-btn-active-border-color:#303030;--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#404040;--bs-btn-disabled-border-color:#404040}.btn-outline-light[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-light{--bs-btn-color:#404040;--bs-btn-border-color:#404040;--bs-btn-focus-shadow-rgb:64,64,64;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#404040;--bs-btn-hover-border-color:#404040;--bs-btn-active-color:#fff;--bs-btn-active-bg:#404040;--bs-btn-active-border-color:#404040;--bs-btn-disabled-color:#404040;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#404040}.btn-dark[data-bs-theme=dark],[data-bs-theme=dark] .btn-dark{--bs-btn-color:#000000;--bs-btn-bg:#ffffff;--bs-btn-border-color:#ffffff;--bs-btn-hover-color:#000000;--bs-btn-hover-bg:#FFFFFF;--bs-btn-hover-border-color:#FFFFFF;--bs-btn-focus-shadow-rgb:38,38,38;--bs-btn-active-color:#000000;--bs-btn-active-bg:#FFFFFF;--bs-btn-active-border-color:#FFFFFF;--bs-btn-disabled-color:#000000;--bs-btn-disabled-bg:#ffffff;--bs-btn-disabled-border-color:#ffffff}.btn-outline-dark[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-dark{--bs-btn-color:#ffffff;--bs-btn-border-color:#ffffff;--bs-btn-focus-shadow-rgb:255,255,255;--bs-btn-hover-color:#000000;--bs-btn-hover-bg:#ffffff;--bs-btn-hover-border-color:#ffffff;--bs-btn-active-color:#000000;--bs-btn-active-bg:#ffffff;--bs-btn-active-border-color:#ffffff;--bs-btn-disabled-color:#ffffff;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ffffff}.stick-right{position:absolute;right:25px}.error:after{content:attr(data-text);position:absolute;left:2px;text-shadow:-1px 0 #e74a3b;top:0;color:#5a5c69;background:var(--bs-primary);overflow:hidden;clip:rect(0,900px,0,0);animation:2s linear infinite alternate-reverse noise-anim}.error:before{content:attr(data-text);position:absolute;left:-2px;text-shadow:1px 0 #4e73df;top:0;color:#5a5c69;background:var(--bs-primary);overflow:hidden;clip:rect(0,900px,0,0);animation:3s linear infinite alternate-reverse noise-anim-2}
[data-bs-theme=dark]{--bs-primary:#000000;--bs-primary-rgb:0,0,0;--bs-primary-text-emphasis:#666666;--bs-primary-bg-subtle:#000000;--bs-primary-border-subtle:#000000;--bs-light:#404040;--bs-light-rgb:64,64,64;--bs-light-text-emphasis:#8C8C8C;--bs-light-bg-subtle:#0D0D0D;--bs-light-border-subtle:#262626;--bs-dark:#ffffff;--bs-dark-rgb:255,255,255;--bs-dark-text-emphasis:#FFFFFF;--bs-dark-bg-subtle:#333333;--bs-dark-border-subtle:#999999}.btn-primary[data-bs-theme=dark],[data-bs-theme=dark] .btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#000000;--bs-btn-border-color:#000000;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#000000;--bs-btn-hover-border-color:#000000;--bs-btn-focus-shadow-rgb:217,217,217;--bs-btn-active-color:#fff;--bs-btn-active-bg:#000000;--bs-btn-active-border-color:#000000;--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#000000;--bs-btn-disabled-border-color:#000000}.btn-outline-primary[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-primary{--bs-btn-color:#000000;--bs-btn-border-color:#000000;--bs-btn-focus-shadow-rgb:0,0,0;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#000000;--bs-btn-hover-border-color:#000000;--bs-btn-active-color:#fff;--bs-btn-active-bg:#000000;--bs-btn-active-border-color:#000000;--bs-btn-disabled-color:#000000;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#000000}.btn-light[data-bs-theme=dark],[data-bs-theme=dark] .btn-light{--bs-btn-color:#fff;--bs-btn-bg:#404040;--bs-btn-border-color:#404040;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#363636;--bs-btn-hover-border-color:#333333;--bs-btn-focus-shadow-rgb:226,226,226;--bs-btn-active-color:#fff;--bs-btn-active-bg:#333333;--bs-btn-active-border-color:#303030;--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#404040;--bs-btn-disabled-border-color:#404040}.btn-outline-light[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-light{--bs-btn-color:#404040;--bs-btn-border-color:#404040;--bs-btn-focus-shadow-rgb:64,64,64;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#404040;--bs-btn-hover-border-color:#404040;--bs-btn-active-color:#fff;--bs-btn-active-bg:#404040;--bs-btn-active-border-color:#404040;--bs-btn-disabled-color:#404040;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#404040}.btn-dark[data-bs-theme=dark],[data-bs-theme=dark] .btn-dark{--bs-btn-color:#000000;--bs-btn-bg:#ffffff;--bs-btn-border-color:#ffffff;--bs-btn-hover-color:#000000;--bs-btn-hover-bg:#FFFFFF;--bs-btn-hover-border-color:#FFFFFF;--bs-btn-focus-shadow-rgb:38,38,38;--bs-btn-active-color:#000000;--bs-btn-active-bg:#FFFFFF;--bs-btn-active-border-color:#FFFFFF;--bs-btn-disabled-color:#000000;--bs-btn-disabled-bg:#ffffff;--bs-btn-disabled-border-color:#ffffff}.btn-outline-dark[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-dark{--bs-btn-color:#ffffff;--bs-btn-border-color:#ffffff;--bs-btn-focus-shadow-rgb:255,255,255;--bs-btn-hover-color:#000000;--bs-btn-hover-bg:#ffffff;--bs-btn-hover-border-color:#ffffff;--bs-btn-active-color:#000000;--bs-btn-active-bg:#ffffff;--bs-btn-active-border-color:#ffffff;--bs-btn-disabled-color:#ffffff;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ffffff}::-webkit-resizer{display:none}.stick-right{position:absolute;right:25px}.error:after{content:attr(data-text);position:absolute;left:2px;text-shadow:-1px 0 #e74a3b;top:0;color:#5a5c69;background:var(--bs-primary);overflow:hidden;clip:rect(0,900px,0,0);animation:2s linear infinite alternate-reverse noise-anim}.error:before{content:attr(data-text);position:absolute;left:-2px;text-shadow:1px 0 #4e73df;top:0;color:#5a5c69;background:var(--bs-primary);overflow:hidden;clip:rect(0,900px,0,0);animation:3s linear infinite alternate-reverse noise-anim-2}

1
themes/light.css Normal file
View File

@@ -0,0 +1 @@
[data-bs-theme=dark]{--bs-light:#ffffff;--bs-light-rgb:255,255,255;--bs-light-text-emphasis:#FFFFFF;--bs-light-bg-subtle:#333333;--bs-light-border-subtle:#999999;--bs-dark:#000000;--bs-dark-rgb:0,0,0;--bs-dark-text-emphasis:#666666;--bs-dark-bg-subtle:#000000;--bs-dark-border-subtle:#000000}.btn-light[data-bs-theme=dark],[data-bs-theme=dark] .btn-light{--bs-btn-color:#000000;--bs-btn-bg:#ffffff;--bs-btn-border-color:#ffffff;--bs-btn-hover-color:#000000;--bs-btn-hover-bg:#D9D9D9;--bs-btn-hover-border-color:#CCCCCC;--bs-btn-focus-shadow-rgb:38,38,38;--bs-btn-active-color:#000000;--bs-btn-active-bg:#CCCCCC;--bs-btn-active-border-color:#BFBFBF;--bs-btn-disabled-color:#000000;--bs-btn-disabled-bg:#ffffff;--bs-btn-disabled-border-color:#ffffff}.btn-outline-light[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-light{--bs-btn-color:#ffffff;--bs-btn-border-color:#ffffff;--bs-btn-focus-shadow-rgb:255,255,255;--bs-btn-hover-color:#000000;--bs-btn-hover-bg:#ffffff;--bs-btn-hover-border-color:#ffffff;--bs-btn-active-color:#000000;--bs-btn-active-bg:#ffffff;--bs-btn-active-border-color:#ffffff;--bs-btn-disabled-color:#ffffff;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ffffff}.btn-dark[data-bs-theme=dark],[data-bs-theme=dark] .btn-dark{--bs-btn-color:#fff;--bs-btn-bg:#000000;--bs-btn-border-color:#000000;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#000000;--bs-btn-hover-border-color:#000000;--bs-btn-focus-shadow-rgb:217,217,217;--bs-btn-active-color:#fff;--bs-btn-active-bg:#000000;--bs-btn-active-border-color:#000000;--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#000000;--bs-btn-disabled-border-color:#000000}.btn-outline-dark[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-dark{--bs-btn-color:#000000;--bs-btn-border-color:#000000;--bs-btn-focus-shadow-rgb:0,0,0;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#000000;--bs-btn-hover-border-color:#000000;--bs-btn-active-color:#fff;--bs-btn-active-bg:#000000;--bs-btn-active-border-color:#000000;--bs-btn-disabled-color:#000000;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#000000}::-webkit-resizer{display:none}.stick-right{position:absolute;right:25px}.error:after{content:attr(data-text);position:absolute;left:2px;text-shadow:-1px 0 #e74a3b;top:0;color:#5a5c69;background:var(--bs-primary);overflow:hidden;clip:rect(0,900px,0,0);animation:2s linear infinite alternate-reverse noise-anim}.error:before{content:attr(data-text);position:absolute;left:-2px;text-shadow:1px 0 #4e73df;top:0;color:#5a5c69;background:var(--bs-primary);overflow:hidden;clip:rect(0,900px,0,0);animation:3s linear infinite alternate-reverse noise-anim-2}