Compare commits
181 Commits
feat/plugi
...
feat/WALLE
| Author | SHA1 | Date | |
|---|---|---|---|
|
792688064e
|
|||
|
599c0df00c
|
|||
|
a619d78efd
|
|||
|
f090b7b71a
|
|||
|
545a0b9475
|
|||
|
501091eeae
|
|||
|
6911e3663c
|
|||
|
eda690544d
|
|||
|
e67c178ea7
|
|||
|
631d558377
|
|||
|
1d5ed059b3
|
|||
|
747ac575fa
|
|||
|
e574933302
|
|||
|
c0f0dc5010
|
|||
|
060132bfec
|
|||
|
7bc1fad280
|
|||
|
63e0b1c2f2
|
|||
|
2fab7b3bc0
|
|||
|
3fa57cc617
|
|||
|
4c3a738e43
|
|||
|
988d03b48c
|
|||
|
21043fc124
|
|||
|
67e5276a13
|
|||
|
0164a9c3f2
|
|||
|
075e432900
|
|||
|
e5fcf4500a
|
|||
|
01c6b4ffba
|
|||
|
0e7a72a136
|
|||
|
df09a32280
|
|||
|
eead0d03cc
|
|||
|
84a48a8580
|
|||
|
7494b77f32
|
|||
|
a3560c2615
|
|||
|
520a47bcc1
|
|||
|
1d26c8cda1
|
|||
|
85cf5306b5
|
|||
|
a8c7dbe716
|
|||
|
fe960c0c2b
|
|||
|
1e06605feb
|
|||
|
0082c0e9ec
|
|||
|
5d79a534bf
|
|||
|
47b76cf159
|
|||
|
f966b421e2
|
|||
|
e5397e1fe0
|
|||
|
fdffa5bd31
|
|||
|
9a8472c5cb
|
|||
|
43efac30a8
|
|||
|
a67034de27
|
|||
|
11699834cf
|
|||
|
17ad73ad8b
|
|||
|
8ce0e94e67
|
|||
|
d42dae3263
|
|||
|
d92cb7c743
|
|||
|
fd1ba1d059
|
|||
|
6bbc294116
|
|||
|
80e380b183
|
|||
|
30f61f1505
|
|||
|
3bee713b9a
|
|||
|
7bd59a0fd6
|
|||
|
56016b1f6f
|
|||
|
3aff724b81
|
|||
|
afc227b5b4
|
|||
|
ab7749ef93
|
|||
|
a568abeb49
|
|||
|
4652af3a2d
|
|||
|
65eedff61c
|
|||
|
9aa061691d
|
|||
|
ce8c773db3
|
|||
|
461e2cdbe9
|
|||
|
12884fe696
|
|||
|
563363fd0c
|
|||
|
1d1aee898f
|
|||
|
fc2ad1682c
|
|||
|
57530fc904
|
|||
|
520a6625f9
|
|||
|
35c3130e29
|
|||
|
0c11ccfb01
|
|||
|
82b9241c00
|
|||
|
a56ffef656
|
|||
|
f1828d39a7
|
|||
|
2e743528d4
|
|||
|
3db0ba46d0
|
|||
|
80a4628d77
|
|||
|
47f210e51b
|
|||
|
2d574c0d46
|
|||
|
01d820368a
|
|||
|
71e59a9a95
|
|||
|
7a4300066f
|
|||
|
b5c3075fba
|
|||
|
3844acdaf8
|
|||
|
a1d1a6337e
|
|||
|
9507bc17a8
|
|||
|
c236cb964d
|
|||
|
08e6d5834d
|
|||
|
c568668b39
|
|||
|
a877b5bf9e
|
|||
|
22d301581b
|
|||
|
a888a3bd55
|
|||
|
c247aef2d5
|
|||
|
0118200098
|
|||
|
7e861534a6
|
|||
|
50164e9d5d
|
|||
|
7c943c137c
|
|||
|
8622400427
|
|||
|
26633c1c61
|
|||
|
86c93da5a2
|
|||
|
42e8f642b4
|
|||
|
1962c9345e
|
|||
|
4b15a1aa0c
|
|||
|
76dd5a429b
|
|||
|
83d676c372
|
|||
|
ca32bf7780
|
|||
|
9c32ec788e
|
|||
|
fb9cb50a90
|
|||
|
db5e672d7b
|
|||
|
8ec23e3a32
|
|||
|
f84359a74b
|
|||
|
92f05992ab
|
|||
|
2ae618c68a
|
|||
|
cfb814d006
|
|||
|
8c61a09e5b
|
|||
|
5c61bad9a2
|
|||
|
35d3ccd0c0
|
|||
|
2b895a524a
|
|||
|
f7968fc218
|
|||
|
d39f433738
|
|||
|
2b6447fd12
|
|||
|
4b7b9f991b
|
|||
|
f5fc0766a1
|
|||
|
209c3794fc
|
|||
|
693bf13450
|
|||
|
cff65b167a
|
|||
|
d2ad6eaa58
|
|||
|
8099320673
|
|||
|
6c91ec88c7
|
|||
|
aa92220756
|
|||
|
3290240a25
|
|||
|
40f520ba5e
|
|||
|
9f1f7fb18e
|
|||
|
3e78732333
|
|||
|
2595503dc0
|
|||
|
0be6b8b435
|
|||
|
00379aaa8f
|
|||
|
da9354cb23
|
|||
|
d516e91592
|
|||
|
f695d53f8d
|
|||
|
45fdaa2de4
|
|||
|
40b4c42492
|
|||
|
afd7ae2947
|
|||
|
171e891555
|
|||
|
5e21074b24
|
|||
|
703f1ed5c1
|
|||
|
b24a3147dd
|
|||
|
af4cd0c652
|
|||
|
f8e03aca73
|
|||
|
b85d316491
|
|||
|
43c5b5c3ba
|
|||
|
5886ded19a
|
|||
|
7085fbfa5c
|
|||
|
38f08c069c
|
|||
|
fea42b1177
|
|||
|
4f74d51514
|
|||
|
472e9fb797
|
|||
|
ecf6ac522a
|
|||
|
16ac6c7d2b
|
|||
|
f525c0f1fd
|
|||
|
c28874bb1c
|
|||
|
b0c7fcf779
|
|||
|
6e382b0e6e
|
|||
|
340898959d
|
|||
|
4f163756de
|
|||
|
360ca7bfe9
|
|||
|
dc240bb1a7
|
|||
|
0c0125b40c
|
|||
|
bfbac3a679
|
|||
|
a0989cccef
|
|||
|
a412573fab
|
|||
|
97f7792612
|
|||
|
4c08d4e24e
|
|||
|
6c61ecdd2c
|
|||
|
d62ced1375
|
14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,6 +1,18 @@
|
||||
|
||||
.env
|
||||
|
||||
.env*
|
||||
__pycache__/
|
||||
|
||||
templates/assets/css/styles.min.css
|
||||
|
||||
ignore/
|
||||
|
||||
plugins/signatures.json
|
||||
|
||||
.venv/
|
||||
|
||||
user_data/
|
||||
customPlugins/
|
||||
cache/
|
||||
build/
|
||||
dist/
|
||||
|
||||
@@ -10,8 +10,9 @@ COPY . /app
|
||||
|
||||
# Add mount point for data volume
|
||||
# VOLUME /data
|
||||
RUN apk add git openssl curl
|
||||
|
||||
ENTRYPOINT ["python3"]
|
||||
CMD ["server.py"]
|
||||
|
||||
FROM builder as dev-envs
|
||||
FROM builder as dev-envs
|
||||
|
||||
Binary file not shown.
42
README.md
42
README.md
@@ -1,8 +1,8 @@
|
||||
# FireWalletBrowser
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
See [here](https://firewallet.au/setup) for instructions on how to setup a FireWallet
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Nathanwoodburn/firewalletbrowser.git
|
||||
cd firewalletbrowser
|
||||
@@ -17,29 +17,37 @@ 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
|
||||
sudo docker run --network=host -e hsd_api=yourapikeyhere git.woodburn.au/nathanwoodburn/firewallet:latest
|
||||
sudo docker run --network=host -e HSD_API=yourapikeyhere git.woodburn.au/nathanwoodburn/firewallet:latest
|
||||
```
|
||||
|
||||
If you have HSD running on a different IP/container
|
||||
|
||||
```bash
|
||||
sudo docker run -p 5000:5000 -e hsd_api=yourapikeyhere -e hsd_ip=hsdcontainer git.woodburn.au/nathanwoodburn/firewallet:latest
|
||||
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
|
||||
@@ -64,7 +72,7 @@ sudo docker run -p 5000:5000 -e hsd_api=yourapikeyhere -e hsd_ip=hsdcontainer gi
|
||||
- Rescan
|
||||
- Zap pending transactions
|
||||
- View xPub
|
||||
- Custom plugin support
|
||||
- Custom plugin support (find some [here](https://git.woodburn.au/nathanwoodburn?tab=repositories&q=plugin&sort=recentupdate))
|
||||
|
||||
## Themes
|
||||
Set a theme in the .env file
|
||||
@@ -104,4 +112,24 @@ DNS Editor page
|
||||

|
||||
|
||||
Auction page
|
||||

|
||||

|
||||
|
||||
## Environment variables
|
||||
|
||||
```yaml
|
||||
HSD_API: HSD API key
|
||||
HSD_IP: HSD IP address
|
||||
THEME: Theme to use (dark-purple, black)
|
||||
SHOW_EXPIRED: Show expired domains (true/false)
|
||||
EXCLUDE: Comma separated list of wallets to exclude from the wallet list (default primary)
|
||||
EXPLORER_TX: URL for exploring transactions (default https://shakeshift.com/transaction/)
|
||||
HSD_NETWORK: Network to connect to (main, regtest, simnet)
|
||||
```
|
||||
|
||||
|
||||
## Warnings
|
||||
|
||||
- This is a work in progress and is not guaranteed to work
|
||||
- This is not a wallet by itself but rather a frontend for HSD
|
||||
- I am not responsible for any loss of funds from using this wallet (including loss of funds from auctions)
|
||||
- I am not responsible if you expose this frontend to the internet (please don't do this unless you know what you are doing)
|
||||
1096
account.py
1096
account.py
File diff suppressed because it is too large
Load Diff
BIN
assets/plugin_page.png
Normal file
BIN
assets/plugin_page.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
BIN
assets/plugins.png
Normal file
BIN
assets/plugins.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
@@ -6,9 +6,16 @@ import subprocess
|
||||
import binascii
|
||||
import datetime
|
||||
import dns.asyncresolver
|
||||
import dns.message
|
||||
import dns.query
|
||||
import dns.rdatatype
|
||||
import httpx
|
||||
from requests_doh import DNSOverHTTPSSession, add_dns_provider
|
||||
import requests
|
||||
import urllib3
|
||||
from cryptography.x509.oid import ExtensionOID
|
||||
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # Disable insecure request warnings (since we are manually verifying the certificate)
|
||||
|
||||
def hip2(domain: str):
|
||||
domain_check = False
|
||||
@@ -53,7 +60,7 @@ def hip2(domain: str):
|
||||
|
||||
domains = []
|
||||
for ext in cert_obj.extensions:
|
||||
if ext.oid == x509.ExtensionOID.SUBJECT_ALTERNATIVE_NAME:
|
||||
if ext.oid == ExtensionOID.SUBJECT_ALTERNATIVE_NAME:
|
||||
san_list = ext.value.get_values_for_type(x509.DNSName)
|
||||
domains.extend(san_list)
|
||||
|
||||
@@ -75,9 +82,9 @@ def hip2(domain: str):
|
||||
break
|
||||
|
||||
|
||||
expiry_date = cert_obj.not_valid_after
|
||||
expiry_date = cert_obj.not_valid_after_utc
|
||||
# Check if expiry date is past
|
||||
if expiry_date < datetime.datetime.now():
|
||||
if expiry_date < datetime.datetime.now(datetime.timezone.utc):
|
||||
return "Hip2: Certificate is expired"
|
||||
|
||||
|
||||
@@ -114,15 +121,42 @@ def hip2(domain: str):
|
||||
|
||||
# Catch all exceptions
|
||||
except Exception as e:
|
||||
print(f"Hip2: Lookup failed with error: {e}",flush=True)
|
||||
return "Hip2: Lookup failed."
|
||||
|
||||
def wallet_txt(domain: str, doh_url="https://hnsdoh.com/dns-query"):
|
||||
with httpx.Client() as client:
|
||||
q = dns.message.make_query(domain, dns.rdatatype.from_text("TYPE262"))
|
||||
r = dns.query.https(q, doh_url, session=client)
|
||||
|
||||
if not r.answer:
|
||||
return "No wallet address found for this domain"
|
||||
|
||||
wallet_record = "No WALLET record found"
|
||||
for ans in r.answer:
|
||||
raw = ans[0].to_wire() # type: ignore
|
||||
try:
|
||||
data = raw[1:].decode("utf-8", errors="ignore")
|
||||
except UnicodeDecodeError:
|
||||
return f"Unknown WALLET record format: {raw.hex()}"
|
||||
|
||||
if data.startswith("HNS:"):
|
||||
wallet_record = data[4:]
|
||||
break
|
||||
elif data.startswith("HNS "):
|
||||
wallet_record = data[4:]
|
||||
break
|
||||
elif data.startswith('"HNS" '):
|
||||
wallet_record = data[6:].strip('"')
|
||||
break
|
||||
return wallet_record
|
||||
|
||||
def resolve_with_doh(query_name, doh_url="https://hnsdoh.com/dns-query"):
|
||||
with httpx.Client() as client:
|
||||
q = dns.message.make_query(query_name, dns.rdatatype.A)
|
||||
r = dns.query.https(q, doh_url, session=client)
|
||||
|
||||
ip = r.answer[0][0].address
|
||||
ip = r.answer[0][0].address # type: ignore
|
||||
return ip
|
||||
|
||||
def resolve_TLSA_with_doh(query_name, doh_url="https://hnsdoh.com/dns-query"):
|
||||
@@ -134,38 +168,15 @@ def resolve_TLSA_with_doh(query_name, doh_url="https://hnsdoh.com/dns-query"):
|
||||
tlsa = r.answer[0][0]
|
||||
return tlsa
|
||||
|
||||
|
||||
def niami_info(domain: str):
|
||||
response = requests.get(f"https://api.niami.io/hsd/{domain}")
|
||||
if response.status_code != 200:
|
||||
return False
|
||||
|
||||
response = response.json()
|
||||
if response["data"]["owner_tx_data"] is not None:
|
||||
output = {
|
||||
"owner": response["data"]["owner_tx_data"]["address"]
|
||||
}
|
||||
else:
|
||||
output = {
|
||||
"owner": None
|
||||
}
|
||||
|
||||
if 'dnsData' in response["data"]:
|
||||
output["dns"] = response["data"]["dnsData"]
|
||||
else:
|
||||
output["dns"] = []
|
||||
|
||||
transactions = requests.get(f"https://api.niami.io/txs/{domain}")
|
||||
if transactions.status_code != 200:
|
||||
return False
|
||||
|
||||
transactions = transactions.json()
|
||||
output["txs"] = transactions["txs"]
|
||||
return output
|
||||
|
||||
|
||||
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
|
||||
@@ -1,3 +1,5 @@
|
||||
hsd_api=123480615465636893475aCwyaae6s45
|
||||
hsd_ip=localhost
|
||||
theme=black
|
||||
HSD_API=123480615465636893475aCwyaae6s45
|
||||
HSD_IP=localhost
|
||||
THEME=black
|
||||
SHOW_EXPIRED=false
|
||||
EXPLORER_TX=https://shakeshift.com/transaction/
|
||||
185
plugin.py
185
plugin.py
@@ -1,46 +1,186 @@
|
||||
import os
|
||||
import json
|
||||
import importlib
|
||||
import sys
|
||||
import hashlib
|
||||
import subprocess
|
||||
|
||||
|
||||
def import_module(module_name):
|
||||
if module_name in sys.modules:
|
||||
return importlib.reload(sys.modules[module_name])
|
||||
else:
|
||||
return importlib.import_module(module_name)
|
||||
|
||||
def listPlugins():
|
||||
|
||||
def listPlugins(update=False):
|
||||
plugins = []
|
||||
for file in os.listdir("plugins"):
|
||||
if file.endswith(".py"):
|
||||
if file != "main.py":
|
||||
plugin = importlib.import_module("plugins."+file[:-3])
|
||||
plugin = 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
|
||||
elif update:
|
||||
os.system(f"cd customPlugins/{importPath} && git pull")
|
||||
|
||||
# Import plugins from customPlugins/<importPath>
|
||||
for file in os.listdir(f"customPlugins/{importPath}"):
|
||||
if file.endswith(".py"):
|
||||
if file != "main.py":
|
||||
plugin = 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 = 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
|
||||
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)
|
||||
return plugin.functions
|
||||
imported_plugin = import_module(plugin.replace("/","."))
|
||||
return imported_plugin.functions
|
||||
|
||||
def runPluginFunction(plugin: str, function: str, params: dict, authentication: str):
|
||||
plugin_module = importlib.import_module("plugins."+plugin)
|
||||
|
||||
def runPluginFunction(plugin: str, function: str, params: dict, authentication: (str|None)):
|
||||
if not authentication:
|
||||
return {"error": "Authentication required"}
|
||||
|
||||
plugin_module = import_module(plugin.replace("/","."))
|
||||
if function not in plugin_module.functions:
|
||||
return {"error": "Function not found"}
|
||||
|
||||
|
||||
if not hasattr(plugin_module, function):
|
||||
return {"error": "Function not found"}
|
||||
|
||||
# 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,13 +190,16 @@ 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)
|
||||
return plugin.functions[function]["params"]
|
||||
imported_plugin = import_module(plugin.replace("/","."))
|
||||
return imported_plugin.functions[function]["params"]
|
||||
|
||||
|
||||
def getPluginFunctionReturns(plugin: str, function: str):
|
||||
plugin = importlib.import_module("plugins."+plugin)
|
||||
return plugin.functions[function]["returns"]
|
||||
imported_plugin = import_module(plugin.replace("/","."))
|
||||
return imported_plugin.functions[function]["returns"]
|
||||
|
||||
|
||||
def getDomainFunctions():
|
||||
plugins = listPlugins()
|
||||
@@ -72,6 +215,7 @@ def getDomainFunctions():
|
||||
})
|
||||
return domainFunctions
|
||||
|
||||
|
||||
def getSearchFunctions():
|
||||
plugins = listPlugins()
|
||||
searchFunctions = []
|
||||
@@ -86,6 +230,7 @@ def getSearchFunctions():
|
||||
})
|
||||
return searchFunctions
|
||||
|
||||
|
||||
def getDashboardFunctions():
|
||||
plugins = listPlugins()
|
||||
dashboardFunctions = []
|
||||
@@ -98,4 +243,4 @@ def getDashboardFunctions():
|
||||
"function": function,
|
||||
"description": functions[function]["description"]
|
||||
})
|
||||
return dashboardFunctions
|
||||
return dashboardFunctions
|
||||
|
||||
49
plugins.md
49
plugins.md
@@ -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
158
plugins/automations.py
Normal file
@@ -0,0 +1,158 @@
|
||||
import json
|
||||
import account
|
||||
import requests
|
||||
import threading
|
||||
import os
|
||||
import time
|
||||
|
||||
KEY = account.HSD_API
|
||||
IP = account.HSD_IP
|
||||
PORT = account.HSD_WALLET_PORT
|
||||
|
||||
|
||||
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:{KEY}@{IP}:{PORT}",json={"method": "sendbatch","params": [[["RENEW"]]]})
|
||||
requests.post(f"http://x:{KEY}@{IP}:{PORT}",json={"method": "sendbatch","params": [[["REVEAL"]]]})
|
||||
requests.post(f"http://x:{KEY}@{IP}:{PORT}",json={"method": "sendbatch","params": [[["REDEEM"]]]})
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
# Sleep for 5 mins before running again
|
||||
time.sleep(300)
|
||||
516
plugins/batching.py
Normal file
516
plugins/batching.py
Normal file
@@ -0,0 +1,516 @@
|
||||
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.1",
|
||||
"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])
|
||||
|
||||
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:])
|
||||
KEY = account.HSD_API
|
||||
IP = account.HSD_IP
|
||||
PORT = account.HSD_WALLET_PORT
|
||||
|
||||
# Unlock wallet
|
||||
response = requests.post(f"http://x:{KEY}@{IP}:{PORT}/wallet/{wallet}/unlock",
|
||||
json={"passphrase": password, "timeout": 10})
|
||||
|
||||
response = requests.patch(f"http://x:{KEY}@{IP}:{PORT}/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
114
plugins/customPlugins.py
Normal 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<br>Find some plugins <a href=https://git.woodburn.au/nathanwoodburn?tab=repositories&q=plugin&sort=recentupdate target=_blank>here</a>",
|
||||
"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}
|
||||
@@ -1,175 +0,0 @@
|
||||
import json
|
||||
import account
|
||||
import requests
|
||||
|
||||
|
||||
# Plugin Data
|
||||
info = {
|
||||
"name": "Example Plugin",
|
||||
"description": "This is a plugin to be used as an example",
|
||||
"version": "1.0",
|
||||
"author": "Nathan.Woodburn/"
|
||||
}
|
||||
|
||||
|
||||
# Functions
|
||||
functions = {
|
||||
"search":{
|
||||
"name": "Search Owned",
|
||||
"type": "default",
|
||||
"description": "Search for owned domains containing a string",
|
||||
"params": {
|
||||
"search": {
|
||||
"name":"Search string",
|
||||
"type":"text"
|
||||
}
|
||||
},
|
||||
"returns": {
|
||||
"domains":
|
||||
{
|
||||
"name": "List of owned domains",
|
||||
"type": "list"
|
||||
}
|
||||
}
|
||||
},
|
||||
"transfer":{
|
||||
"name": "Bulk Transfer Domains",
|
||||
"type": "default",
|
||||
"description": "Transfer domains to another wallet",
|
||||
"params": {
|
||||
"address": {
|
||||
"name":"Address to transfer to",
|
||||
"type":"address"
|
||||
},
|
||||
"domains": {
|
||||
"name":"List of domains to transfer",
|
||||
"type":"longText"
|
||||
}
|
||||
},
|
||||
"returns": {
|
||||
"hash": {
|
||||
"name": "Hash of the transaction",
|
||||
"type": "tx"
|
||||
},
|
||||
"address":{
|
||||
"name": "Address of the new owner",
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dns":{
|
||||
"name": "Set DNS for Domains",
|
||||
"type": "default",
|
||||
"description": "Set DNS for domains",
|
||||
"params": {
|
||||
"domains": {
|
||||
"name":"List of domains to set DNS for",
|
||||
"type":"longText"
|
||||
},
|
||||
"dns": {
|
||||
"name":"DNS",
|
||||
"type":"dns"
|
||||
}
|
||||
},
|
||||
"returns": {
|
||||
"hash": {
|
||||
"name": "Hash of the transaction",
|
||||
"type": "tx"
|
||||
},
|
||||
"dns":{
|
||||
"name": "DNS",
|
||||
"type": "dns"
|
||||
}
|
||||
}
|
||||
},
|
||||
"niami": {
|
||||
"name": "Niami info",
|
||||
"type": "domain",
|
||||
"description": "Check the domains niami rating",
|
||||
"params": {},
|
||||
"returns": {
|
||||
"rating":
|
||||
{
|
||||
"name": "Niami Rating",
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"niamiSearch": {
|
||||
"name": "Niami info",
|
||||
"type": "search",
|
||||
"description": "Check the domains niami rating",
|
||||
"params": {},
|
||||
"returns": {
|
||||
"rating":
|
||||
{
|
||||
"name": "Niami Rating",
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"connections":{
|
||||
"name": "HSD Connections",
|
||||
"type": "dashboard",
|
||||
"description": "Show the number of connections the HSD node is connected to",
|
||||
"params": {},
|
||||
"returns": {
|
||||
"connections":
|
||||
{
|
||||
"name": "HSD Connections",
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def check(params, authentication):
|
||||
domains = params["domains"]
|
||||
domains = domains.splitlines()
|
||||
|
||||
wallet = authentication.split(":")[0]
|
||||
owned = account.getDomains(wallet)
|
||||
# Only keep owned domains ["name"]
|
||||
ownedNames = [domain["name"] for domain in owned]
|
||||
|
||||
domains = [domain for domain in domains if domain in ownedNames]
|
||||
|
||||
|
||||
return {"domains": domains}
|
||||
|
||||
def search(params, authentication):
|
||||
search = params["search"]
|
||||
wallet = authentication.split(":")[0]
|
||||
owned = account.getDomains(wallet)
|
||||
# Only keep owned domains ["name"]
|
||||
ownedNames = [domain["name"] for domain in owned]
|
||||
|
||||
domains = [domain for domain in ownedNames if search in domain]
|
||||
|
||||
return {"domains": domains}
|
||||
|
||||
|
||||
def transfer(params, authentication):
|
||||
address = params["address"]
|
||||
return {"hash":"f921ffe1bb01884bf515a8079073ee9381cb93a56b486694eda2cce0719f27c0","address":address}
|
||||
|
||||
def dns(params,authentication):
|
||||
dns = params["dns"]
|
||||
return {"hash":"f921ffe1bb01884bf515a8079073ee9381cb93a56b486694eda2cce0719f27c0","dns":dns}
|
||||
|
||||
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"]
|
||||
rating = str(data["rating"]["score"]) + " (" + data["rating"]["rarity"] + ")"
|
||||
return {"rating":rating}
|
||||
|
||||
def niamiSearch(params, authentication):
|
||||
return niami(params, authentication)
|
||||
|
||||
|
||||
def connections(params,authentication):
|
||||
outbound = account.hsd.getInfo()['pool']['outbound']
|
||||
return {"connections": outbound}
|
||||
97
plugins/renewal.py
Normal file
97
plugins/renewal.py
Normal file
@@ -0,0 +1,97 @@
|
||||
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
|
||||
KEY = account.HSD_API
|
||||
IP = account.HSD_IP
|
||||
PORT = account.HSD_WALLET_PORT
|
||||
|
||||
response = requests.post(f'http://x:{KEY}@{IP}:{PORT}/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:{KEY}@{IP}:{PORT}', 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
|
||||
|
||||
195
plugins/varo.py
Normal file
195
plugins/varo.py
Normal 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"}
|
||||
439
render.py
439
render.py
@@ -2,73 +2,225 @@ import datetime
|
||||
import json
|
||||
import urllib.parse
|
||||
from flask import render_template
|
||||
from domainLookup import punycode_to_emoji
|
||||
import os
|
||||
from handywrapper import api
|
||||
import threading
|
||||
|
||||
def domains(domains):
|
||||
HSD_API = os.getenv("HSD_API","")
|
||||
HSD_IP = os.getenv("HSD_IP","localhost")
|
||||
|
||||
HSD_NETWORK = os.getenv("HSD_NETWORK")
|
||||
HSD_WALLET_PORT = 12039
|
||||
HSD_NODE_PORT = 12037
|
||||
|
||||
if not HSD_NETWORK:
|
||||
HSD_NETWORK = "main"
|
||||
else:
|
||||
HSD_NETWORK = HSD_NETWORK.lower()
|
||||
|
||||
if HSD_NETWORK == "simnet":
|
||||
HSD_WALLET_PORT = 15039
|
||||
HSD_NODE_PORT = 15037
|
||||
elif HSD_NETWORK == "testnet":
|
||||
HSD_WALLET_PORT = 13039
|
||||
HSD_NODE_PORT = 13037
|
||||
elif HSD_NETWORK == "regtest":
|
||||
HSD_WALLET_PORT = 14039
|
||||
HSD_NODE_PORT = 14037
|
||||
|
||||
hsd = api.hsd(HSD_API, HSD_IP, HSD_NODE_PORT)
|
||||
|
||||
# Get Explorer URL
|
||||
TX_EXPLORER_URL = os.getenv("EXPLORER_TX")
|
||||
if TX_EXPLORER_URL is None:
|
||||
TX_EXPLORER_URL = "https://shakeshift.com/transaction/"
|
||||
|
||||
|
||||
NAMEHASH_CACHE = 'user_data/namehash_cache.json'
|
||||
# Validate cache version
|
||||
if os.path.exists(NAMEHASH_CACHE):
|
||||
with open(NAMEHASH_CACHE, 'r') as f:
|
||||
cache = json.load(f)
|
||||
if not isinstance(cache, dict):
|
||||
print("Invalid namehash cache format. Resetting cache.")
|
||||
with open(NAMEHASH_CACHE, 'w') as f:
|
||||
json.dump({}, f)
|
||||
# Check if cache entries are valid
|
||||
for key in cache:
|
||||
if not cache[key].startswith("<a href='/manage/"):
|
||||
print(f"Invalid cache entry for {key}. Resetting cache.")
|
||||
with open(NAMEHASH_CACHE, 'w') as f:
|
||||
json.dump({}, f)
|
||||
break
|
||||
|
||||
|
||||
|
||||
CACHE_LOCK = threading.Lock()
|
||||
|
||||
|
||||
HNS_ICON = '<img src="/assets/img/HNS.png" width="20px" style="filter: invert(1);" />'
|
||||
|
||||
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 = renderDomain(domain['name'])
|
||||
|
||||
|
||||
link = f'/manage/{domain["name"]}'
|
||||
link_action = "Manage"
|
||||
if domain['registered'] == False:
|
||||
link_action = "Register"
|
||||
link = f'/auction/{domain["name"]}/register'
|
||||
|
||||
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:,.2f} HNS</td><td><a href="{link}">{link_action}</a></td></tr>'
|
||||
else:
|
||||
html += f'<tr><td><a href="{link}">{name}</a></td><td>{expires} days</td></tr>'
|
||||
|
||||
return html
|
||||
|
||||
|
||||
actionMap = {
|
||||
"UPDATE": "Updated ",
|
||||
"REGISTER": "Registered ",
|
||||
"RENEW": "Renewed ",
|
||||
"OPEN": "Opened ",
|
||||
"BID": "Bid on ",
|
||||
"REVEAL": "Revealed bid for ",
|
||||
"REDEEM": "Redeemed bid for ",
|
||||
"TRANSFER": "Started transfer for ",
|
||||
"NONE": "Multiple actions"
|
||||
}
|
||||
|
||||
actionMapPlural = {
|
||||
"UPDATE": "Updated multiple domains' records",
|
||||
"REGISTER": "Registered multiple domains",
|
||||
"RENEW": "Renewed multiple domains",
|
||||
"OPEN": "Opened multiple domains",
|
||||
"BID": "Bid on multiple domains",
|
||||
"REVEAL": "Revealed multiple bids",
|
||||
"REDEEM": "Redeemed multiple bids",
|
||||
"TRANSFER": "Started multiple domain transfers",
|
||||
"NONE": "Multiple actions"
|
||||
}
|
||||
|
||||
def transactions(txs):
|
||||
|
||||
if len(txs) == 0:
|
||||
return '<tr><td colspan="5">No transactions found</td></tr>'
|
||||
html = ''
|
||||
|
||||
# Reverse the list
|
||||
txs = txs[::-1]
|
||||
|
||||
for tx in txs:
|
||||
action = "HNS Transfer"
|
||||
address = tx["outputs"][0]["address"]
|
||||
hash = tx["hash"]
|
||||
txhash = tx["hash"]
|
||||
confirmations=tx["confirmations"]
|
||||
mined_date = "Pending"
|
||||
if confirmations >= 1:
|
||||
mined_date = tx["mdate"]
|
||||
if mined_date is None:
|
||||
mined_date = "Pending"
|
||||
else:
|
||||
# Format 2025-06-27T01:49:14Z
|
||||
mined_date = datetime.datetime.strptime(mined_date, "%Y-%m-%dT%H:%M:%SZ").strftime("%d %b %Y")
|
||||
incomming = True
|
||||
amount = 0
|
||||
incomming = False
|
||||
if not tx["inputs"][0]["path"]:
|
||||
incomming = True
|
||||
bid_value = 0
|
||||
isMulti = 0
|
||||
nameHashes = []
|
||||
|
||||
for txInput in tx["inputs"]:
|
||||
if txInput["path"]:
|
||||
incomming = False
|
||||
amount -= txInput["value"]
|
||||
|
||||
for output in tx["outputs"]:
|
||||
if output["covenant"]["action"] != "NONE":
|
||||
if action == "HNS Transfer":
|
||||
action = output["covenant"]["action"]
|
||||
elif action == output["covenant"]["action"]:
|
||||
continue
|
||||
isMulti += 1
|
||||
else:
|
||||
action = "Multiple Actions"
|
||||
|
||||
|
||||
if output["covenant"]["items"] and len(output["covenant"]["items"]) > 0:
|
||||
nameHashes.append(output["covenant"]["items"][0])
|
||||
|
||||
if not incomming:
|
||||
if output["path"]:
|
||||
amount += output["value"]
|
||||
else:
|
||||
if output["path"] and output["covenant"]["action"] == "NONE":
|
||||
amount += output["value"]
|
||||
|
||||
# Check if this is a bid
|
||||
if output["covenant"]["action"] == "BID":
|
||||
bid_value += output["value"]
|
||||
amount -= output["value"]
|
||||
|
||||
if not incomming:
|
||||
# Subtract fee to make it easier to read
|
||||
amount += tx["fee"]
|
||||
|
||||
if not output["path"] and not incomming:
|
||||
amount += output["value"]
|
||||
elif output["path"] and incomming:
|
||||
amount += output["value"]
|
||||
|
||||
amount = amount / 1000000
|
||||
amount = round(amount, 2)
|
||||
amount = "{:,}".format(amount)
|
||||
bid_value = bid_value / 1000000
|
||||
humanAction = action
|
||||
|
||||
hash = "<a target='_blank' href='https://niami.io/tx/" + hash + "'>" + hash[:8] + "...</a>"
|
||||
if confirmations < 5:
|
||||
confirmations = "<td style='background-color: red;'>" + str(confirmations) + "</td>"
|
||||
if action == "HNS Transfer":
|
||||
if amount >= 0:
|
||||
humanAction = f"Received {amount:,.2f} {HNS_ICON}"
|
||||
else:
|
||||
humanAction = f"Sent {(amount*-1):,.2f} {HNS_ICON}"
|
||||
elif action == "FINALIZE":
|
||||
if incomming and not isMulti:
|
||||
humanAction = f"Received {renderFromNameHash(nameHashes[0])}"
|
||||
elif incomming and isMulti:
|
||||
humanAction = f"Received {isMulti + 1} domains"
|
||||
elif not isMulti:
|
||||
humanAction = f"Finalized {renderFromNameHash(nameHashes[0])}"
|
||||
else:
|
||||
humanAction = f"Finalized {isMulti + 1} domain transfers"
|
||||
elif action == "BID" and not isMulti:
|
||||
humanAction = f"Bid {bid_value:,.2f} {HNS_ICON} on {renderFromNameHash(nameHashes[0])}"
|
||||
elif isMulti:
|
||||
humanAction = actionMapPlural.get(action, "Unknown Action")
|
||||
humanAction = humanAction.replace("multiple", f'{isMulti + 1}')
|
||||
else:
|
||||
confirmations = "<td>" + str(confirmations) + "</td>"
|
||||
humanAction = actionMap.get(action, "Unknown Action")
|
||||
humanAction += renderFromNameHash(nameHashes[0])
|
||||
|
||||
|
||||
html += f'<tr><td>{action}</td><td>{address}</td><td>{hash}</td>{confirmations}<td>{amount} HNS</td></tr>'
|
||||
|
||||
|
||||
|
||||
if amount < 0:
|
||||
amount = f"<span style='color: red;'>{amount:,.2f}</span>"
|
||||
elif amount > 0:
|
||||
amount = f"<span style='color: green;'>+{amount:,.2f}</span>"
|
||||
else:
|
||||
amount = f"<span style='color: gray;'>0.00</span>"
|
||||
|
||||
|
||||
# hash = f"<a target='_blank' href='{TX_EXPLORER_URL}{hash}'>{hash[:8]}...</a>"
|
||||
txdate = ""
|
||||
if confirmations < 5:
|
||||
txdate = f"<span style='color: red;'>{mined_date}</span>"
|
||||
else:
|
||||
txdate = f"<span>{mined_date}</span>"
|
||||
# confirmations = f"<td class='hide-mobile'>{confirmations:,}</td>"
|
||||
html += f'''
|
||||
<tr>
|
||||
<td style='white-space: nowrap;'>{txdate}</td>
|
||||
<td><a style="color:var(--bs-body-color); text-decoration:none;" target="_blank" href="{TX_EXPLORER_URL}{txhash}">{humanAction}</a></td>
|
||||
</tr>
|
||||
'''
|
||||
return html
|
||||
|
||||
|
||||
@@ -82,28 +234,28 @@ def dns(data, edit=False):
|
||||
for key, value in entry.items():
|
||||
if key != 'type':
|
||||
if isinstance(value, list):
|
||||
html_output += "<td>\n"
|
||||
for val in value:
|
||||
html_output += f"{val}<br>\n"
|
||||
|
||||
html_output += "</td>\n"
|
||||
if len(value) > 1:
|
||||
html_output += '<td style="white-space: pre-wrap; font-family: monospace;">\n'
|
||||
for val in value:
|
||||
html_output += f"{val}<br>\n"
|
||||
html_output += "</td>\n"
|
||||
else:
|
||||
html_output += f'<td style="white-space: pre-wrap; font-family: monospace;">{value[0]}</td>\n'
|
||||
else:
|
||||
html_output += f"<td>{value}</td>\n"
|
||||
|
||||
html_output += f'<td style="white-space: pre-wrap; font-family: monospace;">{value}</td>\n'
|
||||
|
||||
elif entry['type'] == 'DS':
|
||||
ds = str(entry['keyTag']) + " " + str(entry['algorithm']) + " " + str(entry['digestType']) + " " + entry['digest']
|
||||
html_output += f"<td>{ds}</td>\n"
|
||||
ds = f"{entry['keyTag']} {entry['algorithm']} {entry['digestType']} {entry['digest']}"
|
||||
html_output += f'<td style="white-space: pre-wrap; font-family: monospace;">{ds}</td>\n'
|
||||
|
||||
else:
|
||||
value = ""
|
||||
for key, val in entry.items():
|
||||
if key != 'type':
|
||||
value += str(val) + " "
|
||||
html_output += f"<td>{value}</td>\n"
|
||||
value += f'{val} '
|
||||
html_output += f'<td style="white-space: pre-wrap; font-family: monospace;">{value.strip()}</td>\n'
|
||||
|
||||
if edit:
|
||||
# Remove the current entry from the list
|
||||
keptRecords = str(data[:index] + data[index+1:]).replace("'", '"')
|
||||
keptRecords = urllib.parse.quote(keptRecords)
|
||||
html_output += f"<td><a href='edit?dns={keptRecords}'>Remove</a></td>\n"
|
||||
@@ -112,6 +264,7 @@ def dns(data, edit=False):
|
||||
index += 1
|
||||
return html_output
|
||||
|
||||
|
||||
def txs(data):
|
||||
data = data[::-1]
|
||||
|
||||
@@ -119,18 +272,16 @@ def txs(data):
|
||||
|
||||
for entry in data:
|
||||
html_output += f"<tr><td>{entry['action']}</td>\n"
|
||||
html_output += f"<td><a target='_blank' href='https://niami.io/tx/{entry['txid']}'>{entry['txid'][:8]}...</a></td>\n"
|
||||
html_output += f"<td><a target='_blank' href='{TX_EXPLORER_URL}{entry['txid']}'>{entry['txid'][:8]}...</a></td>\n"
|
||||
amount = entry['amount']
|
||||
amount = amount / 1000000
|
||||
amount = round(amount, 2)
|
||||
|
||||
if entry['blind'] == None:
|
||||
html_output += f"<td>{amount} HNS</td>\n"
|
||||
html_output += f"<td>{amount:,.2f} HNS</td>\n"
|
||||
else:
|
||||
blind = entry['blind']
|
||||
blind = blind / 1000000
|
||||
blind = round(blind, 2)
|
||||
html_output += f"<td>{amount} + {blind} HNS</td>\n"
|
||||
html_output += f"<td>{amount:,.2f} + {blind:,.2f} HNS</td>\n"
|
||||
|
||||
html_output += f"<td>{timestamp_to_readable_time(entry['time'])}</td>\n"
|
||||
html_output += f"</tr>\n"
|
||||
@@ -145,33 +296,103 @@ def timestamp_to_readable_time(timestamp):
|
||||
return readable_time
|
||||
|
||||
def bids(bids,reveals):
|
||||
html = ''
|
||||
# Create a list to hold bid data for sorting
|
||||
bid_data = []
|
||||
|
||||
# Prepare data for sorting
|
||||
for bid in bids:
|
||||
lockup = bid['lockup']
|
||||
lockup = lockup / 1000000
|
||||
lockup = round(lockup, 2)
|
||||
html += "<tr>"
|
||||
html += f"<td>{lockup} HNS</td>"
|
||||
lockup = bid['lockup'] / 1000000
|
||||
revealed = False
|
||||
value = 0
|
||||
|
||||
# Check if this bid has been revealed
|
||||
for reveal in reveals:
|
||||
if reveal['bid'] == bid['prevout']['hash']:
|
||||
revealed = True
|
||||
value = reveal['value']
|
||||
value = value / 1000000
|
||||
value = round(value, 2)
|
||||
html += f"<td>{value} HNS</td>"
|
||||
bidValue = lockup - value
|
||||
bidValue = round(bidValue, 2)
|
||||
html += f"<td>{bidValue} HNS</td>"
|
||||
value = reveal['value'] / 1000000
|
||||
break
|
||||
if not revealed:
|
||||
|
||||
# Store all relevant information for sorting and display
|
||||
bid_data.append({
|
||||
'bid': bid,
|
||||
'lockup': lockup,
|
||||
'revealed': revealed,
|
||||
'value': value,
|
||||
'sort_value': value if revealed else lockup # Use value for sorting if revealed, otherwise lockup
|
||||
})
|
||||
# Sort by the sort_value in descending order (highest first)
|
||||
bid_data.sort(key=lambda x: x['sort_value'], reverse=True)
|
||||
|
||||
# Generate HTML from sorted data
|
||||
html = ''
|
||||
for data in bid_data:
|
||||
bid = data['bid']
|
||||
lockup = data['lockup']
|
||||
revealed = data['revealed']
|
||||
value = data['value']
|
||||
|
||||
html += "<tr>"
|
||||
html += f"<td>{lockup:,.2f} HNS</td>"
|
||||
|
||||
if revealed:
|
||||
bidValue = lockup - value
|
||||
html += f"<td>{value:,.2f} HNS</td>"
|
||||
html += f"<td>{bidValue:,.2f} HNS</td>"
|
||||
else:
|
||||
html += f"<td>Hidden until reveal</td>"
|
||||
html += f"<td>Hidden until reveal</td>"
|
||||
|
||||
if bid['own']:
|
||||
html += "<td>You</td>"
|
||||
else:
|
||||
html += "<td>Unknown</td>"
|
||||
html += f"<td>Unknown</td>"
|
||||
|
||||
html += f"<td><a class='text-decoration-none' style='color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));' target='_blank' href='{TX_EXPLORER_URL}{bid['prevout']['hash']}'>Bid TX 🔗</a></td>"
|
||||
html += "</tr>"
|
||||
|
||||
return html
|
||||
|
||||
|
||||
def bidDomains(bids,domains, sortbyDomains=False):
|
||||
html = ''
|
||||
|
||||
if not sortbyDomains:
|
||||
for bid in bids:
|
||||
for domain in domains:
|
||||
if bid['name'] == domain['name']:
|
||||
lockup = bid['lockup']
|
||||
lockup = lockup / 1000000
|
||||
bidValue = bid['value'] / 1000000
|
||||
blind = lockup - bidValue
|
||||
|
||||
if blind > 0:
|
||||
bidDisplay = f'<b>{bidValue:,.2f}</b> (+{blind:,.2f}) HNS'
|
||||
else:
|
||||
bidDisplay = f'<b>{bidValue:,.2f}</b> HNS'
|
||||
|
||||
|
||||
html += "<tr>"
|
||||
html += f"<td><a class='text-decoration-none' style='color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));' href='/auction/{domain['name']}'>{renderDomain(domain['name'])}</a></td>"
|
||||
html += f"<td>{domain['state']}</td>"
|
||||
html += f"<td style='white-space: nowrap;'>{bidDisplay}</td>"
|
||||
html += f"<td class='hide-mobile'>{domain['height']:,}</td>"
|
||||
html += "</tr>"
|
||||
else:
|
||||
for domain in domains:
|
||||
for bid in bids:
|
||||
if bid['name'] == domain['name']:
|
||||
lockup = bid['lockup']
|
||||
lockup = lockup / 1000000
|
||||
bidValue = bid['value'] / 1000000
|
||||
blind = lockup - bidValue
|
||||
|
||||
bidDisplay = f'<b>{bidValue:,.2f} HNS</b> + {blind:,.2f} HNS blind'
|
||||
html += "<tr>"
|
||||
html += f"<td><a class='text-decoration-none' style='color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));' href='/auction/{domain['name']}'>{renderDomain(domain['name'])}</a></td>"
|
||||
html += f"<td>{domain['state']}</td>"
|
||||
html += f"<td>{bidDisplay}</td>"
|
||||
html += f"<td class='hide-mobile'>{domain['height']:,}</td>"
|
||||
html += "</tr>"
|
||||
return html
|
||||
|
||||
|
||||
@@ -187,7 +408,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 +489,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 +519,87 @@ def plugin_output_dash(outputs, returns):
|
||||
html = ''
|
||||
|
||||
for returnOutput in returns:
|
||||
html += render_template('components/dashboard-plugin.html', name=returns[returnOutput]["name"], output=outputs[returnOutput])
|
||||
if returnOutput not in outputs:
|
||||
continue
|
||||
if outputs[returnOutput] == None:
|
||||
continue
|
||||
html += render_template('components/dashboard-plugin.html', name=returns[returnOutput]["name"], output=outputs[returnOutput])
|
||||
return html
|
||||
|
||||
|
||||
html += f'</div>'
|
||||
html += f'</div>'
|
||||
return html
|
||||
|
||||
def renderDomain(name: str) -> str:
|
||||
"""
|
||||
Render a domain name with emojis and other special characters.
|
||||
"""
|
||||
# Convert emoji to punycode
|
||||
try:
|
||||
rendered = name.encode("ascii").decode("idna")
|
||||
if rendered == name:
|
||||
return f"{name}/"
|
||||
return f"{rendered}/ ({name})"
|
||||
|
||||
|
||||
except Exception as e:
|
||||
return f"{name}/"
|
||||
|
||||
def renderDomainAsync(namehash: str) -> None:
|
||||
"""
|
||||
Get the domain name from HSD using its name hash and store it in the cache.
|
||||
This function is meant to be run in the background.
|
||||
"""
|
||||
try:
|
||||
with CACHE_LOCK:
|
||||
if not os.path.exists(NAMEHASH_CACHE):
|
||||
with open(NAMEHASH_CACHE, 'w') as f:
|
||||
json.dump({}, f)
|
||||
with open(NAMEHASH_CACHE, 'r') as f:
|
||||
cache = json.load(f)
|
||||
|
||||
if namehash in cache:
|
||||
return
|
||||
# Fetch the name outside the lock (network call)
|
||||
name = hsd.rpc_getNameByHash(namehash)
|
||||
if name["error"] is None:
|
||||
name = name["result"]
|
||||
rendered = renderDomain(name)
|
||||
rendered = f"<a href='/manage/{name}' target='_blank' style='color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));'>{rendered}</a>"
|
||||
|
||||
|
||||
with CACHE_LOCK:
|
||||
with open(NAMEHASH_CACHE, 'r') as f:
|
||||
cache = json.load(f)
|
||||
cache[namehash] = rendered
|
||||
with open(NAMEHASH_CACHE, 'w') as f:
|
||||
json.dump(cache, f)
|
||||
|
||||
return
|
||||
else:
|
||||
print(f"Error fetching name for hash {namehash}: {name['error']}", flush=True)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Exception fetching name for hash {namehash}: {e}", flush=True)
|
||||
|
||||
|
||||
def renderFromNameHash(nameHash: str) -> str:
|
||||
"""
|
||||
Render a domain name from its name hash.
|
||||
Try to retrieve the name from the cache. If not, create a background task to fetch it.
|
||||
"""
|
||||
try:
|
||||
with CACHE_LOCK:
|
||||
if not os.path.exists(NAMEHASH_CACHE):
|
||||
with open(NAMEHASH_CACHE, 'w') as f:
|
||||
json.dump({}, f)
|
||||
with open(NAMEHASH_CACHE, 'r') as f:
|
||||
cache = json.load(f)
|
||||
|
||||
if nameHash in cache:
|
||||
return cache[nameHash]
|
||||
thread = threading.Thread(target=renderDomainAsync, args=(nameHash,))
|
||||
thread.start()
|
||||
return "domain"
|
||||
|
||||
except Exception as e:
|
||||
print(f"Exception in renderFromNameHash: {e}", flush=True)
|
||||
return "domain"
|
||||
@@ -7,4 +7,6 @@ dnspython
|
||||
cryptography
|
||||
requests-doh
|
||||
Flask-QRcode
|
||||
PySocks
|
||||
PySocks
|
||||
python-git-info
|
||||
waitress
|
||||
58
server.py
58
server.py
@@ -1,38 +1,44 @@
|
||||
from flask import Flask
|
||||
from main import app
|
||||
import main
|
||||
from gunicorn.app.base import BaseApplication
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
from main import app
|
||||
from waitress import serve
|
||||
|
||||
|
||||
class GunicornApp(BaseApplication):
|
||||
def __init__(self, app, options=None):
|
||||
self.options = options or {}
|
||||
self.application = app
|
||||
super().__init__()
|
||||
threads = 4
|
||||
|
||||
def load_config(self):
|
||||
for key, value in self.options.items():
|
||||
if key in self.cfg.settings and value is not None:
|
||||
self.cfg.set(key.lower(), value)
|
||||
def gunicornServer():
|
||||
from gunicorn.app.base import BaseApplication
|
||||
class GunicornApp(BaseApplication):
|
||||
def __init__(self, app, options=None):
|
||||
self.options = options or {}
|
||||
self.application = app
|
||||
super().__init__()
|
||||
|
||||
def load(self):
|
||||
return self.application
|
||||
def load_config(self):
|
||||
for key, value in self.options.items():
|
||||
if key in self.cfg.settings and value is not None: # type: ignore
|
||||
self.cfg.set(key.lower(), value) # type: ignore
|
||||
|
||||
if __name__ == '__main__':
|
||||
workers = 1
|
||||
threads = 2
|
||||
if workers is None:
|
||||
workers = 1
|
||||
if threads is None:
|
||||
threads = 2
|
||||
workers = int(workers)
|
||||
threads = int(threads)
|
||||
def load(self):
|
||||
return self.application
|
||||
options = {
|
||||
'bind': '0.0.0.0:5000',
|
||||
'workers': workers,
|
||||
'workers': 2,
|
||||
'threads': threads,
|
||||
}
|
||||
gunicorn_app = GunicornApp(app, options)
|
||||
print('Starting server with ' + str(workers) + ' workers and ' + str(threads) + ' threads', flush=True)
|
||||
print(f'Starting server with Gunicorn on {platform.system()} with {threads} threads...', flush=True)
|
||||
gunicorn_app.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Check if --gunicorn is in the command line arguments
|
||||
if "--gunicorn" in sys.argv:
|
||||
gunicornServer()
|
||||
sys.exit()
|
||||
|
||||
print(f'Starting server with Waitress on {platform.system()} with {threads} threads...', flush=True)
|
||||
print(f'Press Ctrl+C to stop the server', flush=True)
|
||||
print(f'Serving on http://0.0.0.0:5000/', flush=True)
|
||||
serve(app, host="0.0.0.0", port=5000, threads=threads)
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -62,7 +64,7 @@
|
||||
</nav>
|
||||
<div class="container-fluid">
|
||||
<div class="text-center mt-5">
|
||||
<div class="error mx-auto" data-text="404">
|
||||
<div class="mx-auto error" data-text="404">
|
||||
<p class="m-0">404</p>
|
||||
</div>
|
||||
<p class="text-dark mb-5 lead">Page Not Found</p>
|
||||
@@ -72,7 +74,7 @@
|
||||
</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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
templates/assets/fonts/FontAwesome.otf
Normal file
BIN
templates/assets/fonts/FontAwesome.otf
Normal file
Binary file not shown.
4
templates/assets/fonts/font-awesome.min.css
vendored
Normal file
4
templates/assets/fonts/font-awesome.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
templates/assets/fonts/fontawesome-webfont.eot
Normal file
BIN
templates/assets/fonts/fontawesome-webfont.eot
Normal file
Binary file not shown.
2671
templates/assets/fonts/fontawesome-webfont.svg
Normal file
2671
templates/assets/fonts/fontawesome-webfont.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 434 KiB |
BIN
templates/assets/fonts/fontawesome-webfont.ttf
Normal file
BIN
templates/assets/fonts/fontawesome-webfont.ttf
Normal file
Binary file not shown.
BIN
templates/assets/fonts/fontawesome-webfont.woff
Normal file
BIN
templates/assets/fonts/fontawesome-webfont.woff
Normal file
Binary file not shown.
BIN
templates/assets/fonts/fontawesome-webfont.woff2
Normal file
BIN
templates/assets/fonts/fontawesome-webfont.woff2
Normal file
Binary file not shown.
1
templates/assets/fonts/fontawesome5-overrides.min.css
vendored
Normal file
1
templates/assets/fonts/fontawesome5-overrides.min.css
vendored
Normal 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"}
|
||||
BIN
templates/assets/fonts/ionicons.eot
Normal file
BIN
templates/assets/fonts/ionicons.eot
Normal file
Binary file not shown.
11
templates/assets/fonts/ionicons.min.css
vendored
Normal file
11
templates/assets/fonts/ionicons.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
2230
templates/assets/fonts/ionicons.svg
Normal file
2230
templates/assets/fonts/ionicons.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 326 KiB |
BIN
templates/assets/fonts/ionicons.ttf
Normal file
BIN
templates/assets/fonts/ionicons.ttf
Normal file
Binary file not shown.
BIN
templates/assets/fonts/ionicons.woff
Normal file
BIN
templates/assets/fonts/ionicons.woff
Normal file
Binary file not shown.
1
templates/assets/js/dashboard.min.js
vendored
Normal file
1
templates/assets/js/dashboard.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
function createCard(e,n,t){if(document.getElementById(t)&&document.getElementById(t).remove(),n<=0)return;const a=document.createElement("div");a.classList.add("col-md-6","col-xl-3","mb-4"),a.id=t,html=`\n <div class="card shadow border-start-warning py-2">\n <div class="card-body">\n <div class="row align-items-center no-gutters">\n <div class="col me-2">\n <div class="text-uppercase text-warning fw-bold text-xs mb-1"><span>${e}</span></div>\n <div class="text-dark fw-bold h5 mb-0"><span id="${e}">${n}</span></div>\n </div>\n <div class="col"><a class="btn btn-primary" role="button" href="/all/${t.toLowerCase()}">${t} All</a></div>\n <div class="col-auto"><svg class="fa-2x text-gray-300" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="1em" viewBox="0 0 24 24" width="1em" fill="currentColor">\n <g>\n <rect fill="none" height="24" width="24"></rect>\n </g>\n <g>\n <path d="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M7,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C8.5,12.83,7.83,13.5,7,13.5z M12,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C13.5,12.83,12.83,13.5,12,13.5z M17,13.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C18.5,12.83,17.83,13.5,17,13.5z"></path>\n </g>\n </svg></div>\n </div>\n </div>`,a.innerHTML=html,document.getElementById("actions-row").appendChild(a)}async function updateActions(){const e={Finalize:"Pending Finalizes",Register:"Pending Register",Redeem:"Pending Redeem",Reveal:"Pending Reveal"};for(const n in e){const t=await request(`wallet/pending${n}`);"Error"!=t&&createCard(e[n],t.length,n)}}window.addEventListener("load",(async()=>{updateActions()})),setInterval((async function(){updateActions()}),2e4);
|
||||
2
templates/assets/js/receive.min.js
vendored
2
templates/assets/js/receive.min.js
vendored
@@ -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"}
|
||||
2
templates/assets/js/script.min.js
vendored
2
templates/assets/js/script.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -64,9 +66,9 @@
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="stick-right">{{next_action|safe}}</div>
|
||||
<h4 class="card-title">{{domain}}/</h4>
|
||||
<h6 class="text-muted card-subtitle mb-2">{{next}}</h6>
|
||||
<div id="next-action" class="stick-right">{{next_action|safe}}</div>
|
||||
<h4 class="card-title">{{rendered}}</h4>
|
||||
<h6 class="text-muted mb-2 card-subtitle" id="next">{{next | safe}}</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -91,20 +93,99 @@
|
||||
<th>Bid</th>
|
||||
<th>Blind</th>
|
||||
<th>Owner</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{bids | safe}}
|
||||
<tbody id="bids-tbody">
|
||||
<tr id="loading-row">
|
||||
<td colspan="5" class="text-center">
|
||||
<div class="spinner-border spinner-border-sm me-2" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
Loading bids...
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
async function loadBids(initial = false) {
|
||||
const tbody = document.getElementById('bids-tbody');
|
||||
|
||||
try {
|
||||
// Fetch all required data
|
||||
const response = await fetch(`/api/v1/wallet/domainBids?domain={{search_term}}`);
|
||||
const data = await response.json();
|
||||
if (initial) {
|
||||
if (response.ok && data.result) {
|
||||
tbody.innerHTML = data.result;
|
||||
} else {
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="text-center text-muted">No bids found. <a href="/auction/{{search_term}}/scan">Rescan Auction</a></td></tr>';
|
||||
}
|
||||
}
|
||||
const mempoolResponse = await fetch('/api/v1/hsd/mempoolBids');
|
||||
const nextStateResponse = await fetch(`/api/v1/hsd/nextAuctionState?domain={{search_term}}`);
|
||||
|
||||
if (!initial) {
|
||||
if (response.ok && data.result) {
|
||||
tbody.innerHTML = data.result;
|
||||
} else {
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="text-center text-muted">No bids found. <a href="/auction/{{search_term}}/scan">Rescan Auction</a></td></tr>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const nextStateData = await nextStateResponse.json();
|
||||
|
||||
if (nextStateResponse.ok && nextStateData.state) {
|
||||
document.getElementById('next').innerHTML = nextStateData.next;
|
||||
document.getElementById('next-action').innerHTML = nextStateData.next_action;
|
||||
} else {
|
||||
document.getElementById('next').innerHTML = 'Unknown';
|
||||
document.getElementById('next-action').innerHTML = '';
|
||||
}
|
||||
|
||||
const mempoolData = await mempoolResponse.json();
|
||||
if (mempoolResponse.ok && mempoolData.result) {
|
||||
const domainBids = mempoolData.result['{{search_term}}'];
|
||||
if (domainBids && domainBids.length > 0) {
|
||||
let mempoolRows = '';
|
||||
domainBids.forEach(bid => {
|
||||
const bidValue = bid.revealed ? `${(bid.value / 1000000).toFixed(2)} HNS` : 'Hidden until reveal';
|
||||
const lockupValue = (bid.lockup / 1000000).toFixed(2);
|
||||
const blindValue = bid.revealed ? `${((bid.lockup - bid.value) / 1000000).toFixed(2)} HNS` : 'Hidden until reveal';
|
||||
const type = bid.revealed ? 'Reveal' : 'Bid';
|
||||
mempoolRows += `<tr class="table-warning">
|
||||
<td>${lockupValue} HNS</td>
|
||||
<td>${bidValue}</td>
|
||||
<td>${blindValue}</td>
|
||||
<td>${bid.owner}</td>
|
||||
<td><a class='text-decoration-none' style='color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));' target='_blank' href='https://shakeshift.com/transaction/${bid.txid}'>Mempool ${type} 🔗</a></td>
|
||||
</tr>`;
|
||||
});
|
||||
tbody.innerHTML += mempoolRows;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading bids:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Load bids when page loads
|
||||
document.addEventListener('DOMContentLoaded', () => loadBids(true));
|
||||
|
||||
// Auto-refresh bids every 20 seconds
|
||||
setInterval(() => loadBids(false), 20000);
|
||||
</script>
|
||||
</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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
210
templates/auctions.html
Normal file
210
templates/auctions.html
Normal file
@@ -0,0 +1,210 @@
|
||||
<!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&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 p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" href="/">
|
||||
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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 me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> 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">Auctions</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 py-2 border-start-primary">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center no-gutters">
|
||||
<div class="col me-2">
|
||||
<div class="text-uppercase text-primary mb-1 fw-bold text-xs"><span style="color: var(--bs-dark);">HNS Locked</span></div>
|
||||
<div class="text-dark mb-0 fw-bold h5"><span><img src="/assets/img/HNS.png" width="20px"> <span id="wallet-locked">0.00</span></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 py-2 border-start-success">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center no-gutters">
|
||||
<div class="col me-2">
|
||||
<div class="text-uppercase text-success mb-1 fw-bold text-xs"><span>Total Bids</span></div>
|
||||
<div class="text-dark mb-0 fw-bold h5"><span id="wallet-bidCount">0</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-xl-3 mb-4">
|
||||
<div class="card shadow py-2 border-start-info">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center no-gutters">
|
||||
<div class="col me-2">
|
||||
<div class="text-uppercase text-info mb-1 fw-bold text-xs"><span>Pending Reveal</span></div>
|
||||
<div class="row g-0 align-items-center">
|
||||
<div class="col-auto">
|
||||
<div class="text-dark me-3 mb-0 fw-bold h5"><span id="wallet-pendingReveal">0</span></div>
|
||||
</div>
|
||||
<div class="col"><a class="btn btn-primary" role="button" href="/all/reveal">Reveal All</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-xl-3 mb-4">
|
||||
<div class="card shadow py-2 border-start-info">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center no-gutters">
|
||||
<div class="col me-2">
|
||||
<div class="text-uppercase text-info mb-1 fw-bold text-xs"><span>Pending Redeem</span></div>
|
||||
<div class="row g-0 align-items-center">
|
||||
<div class="col-auto">
|
||||
<div class="text-dark me-3 mb-0 fw-bold h5"><span id="wallet-pendingRedeem">0</span></div>
|
||||
</div>
|
||||
<div class="col"><a class="btn btn-primary" role="button" href="/all/redeem">Redeem All</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-xl-3 mb-4">
|
||||
<div class="card shadow py-2 border-start-info">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center no-gutters">
|
||||
<div class="col me-2">
|
||||
<div class="text-uppercase text-info mb-1 fw-bold text-xs"><span>Pending Register</span></div>
|
||||
<div class="row g-0 align-items-center">
|
||||
<div class="col-auto">
|
||||
<div class="text-dark me-3 mb-0 fw-bold h5"><span id="wallet-pendingRegister">0</span></div>
|
||||
</div>
|
||||
<div class="col"><a class="btn btn-primary" role="button" href="/all/register">Register All</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>{{plugins|safe}}
|
||||
</div>
|
||||
<div class="row d-none d-print-block d-sm-none d-md-none d-lg-block d-xl-block d-xxl-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 m-0 fw-bold">Domains</h6>
|
||||
</div>
|
||||
<div class="card-body"><div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><a href="/auctions?sort=domain&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-print-none d-sm-block d-md-block d-lg-none d-xl-none d-xxl-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 m-0 fw-bold">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 2025</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>
|
||||
8
templates/components/dashboard-alert.html
Normal file
8
templates/components/dashboard-alert.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<div class="col-md-6 col-xl-3 mb-4">
|
||||
<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 | safe}}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -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>
|
||||
@@ -1,4 +1,4 @@
|
||||
<span style="display: block;font-size: 12px;">TX: {{tx}}</span>
|
||||
<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://shakeshift.com/transaction/{{tx}}" target="_blank">ShakeShift</a>
|
||||
<a class="card-link" href="https://3xpl.com/handshake/transaction/{{tx}}" target="_blank">3xpl</a>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -65,7 +67,7 @@
|
||||
<div class="card" style="margin-top: 50px;">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">{{action}}</h4>
|
||||
<h6 class="text-muted card-subtitle mb-2">{{subtitle}}</h6>
|
||||
<h6 class="text-muted mb-2 card-subtitle">{{subtitle}}</h6>
|
||||
<p class="card-text">{{content|safe}}</p>
|
||||
<form method="post" action="{{confirm}}"><input class="form-control" type="password" name="password" placeholder="Password"><input class="btn btn-primary" type="submit" style="display: block;margin-top: 16px;margin-bottom: 16px;"><input class="form-control" type="hidden" name="check" value="{{check}}"></form><a class="card-link" href="{{cancel}}">Cancel</a>
|
||||
</div>
|
||||
@@ -74,7 +76,7 @@
|
||||
</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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -65,7 +67,7 @@
|
||||
<div class="card" style="margin-top: 50px;">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">{{action}}</h4>
|
||||
<h6 class="text-muted card-subtitle mb-2">{{subtitle}}</h6>
|
||||
<h6 class="text-muted mb-2 card-subtitle">{{subtitle}}</h6>
|
||||
<p class="card-text">{{content|safe}}</p><a class="card-link" href="{{cancel}}">Cancel</a><a class="card-link" href="{{confirm}}">Confirm</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -73,7 +75,7 @@
|
||||
</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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,38 +13,41 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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);">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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>
|
||||
<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="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search">
|
||||
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
|
||||
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
|
||||
</div>
|
||||
@@ -53,7 +56,7 @@
|
||||
</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="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> Logout</a></div>
|
||||
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="/logout"><i class="fas fa-sign-out-alt me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -63,7 +66,7 @@
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">{{domain}}/</h4>
|
||||
<h4 class="card-title">{{rendered}}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -120,7 +123,7 @@
|
||||
</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 2023</span></div>
|
||||
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<body class="bg-gradient-primary">
|
||||
<div class="container">
|
||||
<div class="card shadow-lg o-hidden border-0 my-5">
|
||||
<div class="card shadow-lg my-5 o-hidden border-0">
|
||||
<div class="card-body p-0">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 d-none d-lg-flex">
|
||||
@@ -30,12 +30,12 @@
|
||||
<h4 class="text-dark mb-4">Import a wallet!</h4>
|
||||
</div>
|
||||
<form class="user" method="post">
|
||||
<div class="row mb-3" style="padding-right: 16px;padding-left: 16px;"><input class="form-control form-control-user" type="text" id="exampleLastName" placeholder="Wallet name" name="name" value="{{name}}"></div>
|
||||
<div class="row mb-3">
|
||||
<div class="mb-3 row" style="padding-right: 16px;padding-left: 16px;"><input class="form-control form-control-user" type="text" id="exampleLastName" placeholder="Wallet name" name="name" value="{{name}}"></div>
|
||||
<div class="mb-3 row">
|
||||
<div class="col-sm-6 mb-3 mb-sm-0"><input class="form-control form-control-user" type="password" id="examplePasswordInput" placeholder="Password" name="password" required="" value="{{password}}"></div>
|
||||
<div class="col-sm-6"><input class="form-control form-control-user" type="password" id="exampleRepeatPasswordInput" placeholder="Repeat Password" name="password_repeat" required="" value="{{password_repeat}}"></div>
|
||||
</div>
|
||||
<div style="margin-bottom: 16px;"><textarea class="form-control form-control-lg" placeholder="Seed Phrase" name="seed" rows="1" style="height: 7em;">{{seed}}</textarea></div><button class="btn btn-primary d-block btn-user w-100" type="submit">Import Wallet</button>
|
||||
<div style="margin-bottom: 16px;"><textarea class="form-control form-control-lg" placeholder="Seed Phrase" name="seed" rows="1" style="height: 7em;">{{seed}}</textarea></div><button class="btn btn-primary d-block w-100 btn-user" type="submit">Import Wallet</button>
|
||||
<hr>
|
||||
</form>
|
||||
<div class="text-center"><a class="small" href="/login">Didn't mean to create a new wallet? Login!</a></div>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -62,16 +64,16 @@
|
||||
</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> 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> Generate Report</a>
|
||||
</div>
|
||||
<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 shadow py-2 border-start-primary">
|
||||
<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-dark fw-bold h5 mb-0"><span><img src="/assets/img/HNS.png" width="20px"> {{available}}</span></div>
|
||||
<div class="text-uppercase text-primary mb-1 fw-bold text-xs"><span style="color: var(--bs-dark);">HNS Available</span></div>
|
||||
<div class="text-dark mb-0 fw-bold h5"><span><img src="/assets/img/HNS.png" width="20px"> <span id="wallet-available">0.00</span></span></div>
|
||||
</div>
|
||||
<div class="col-auto"><i class="fas fa-dollar-sign fa-2x text-gray-300"></i></div>
|
||||
</div>
|
||||
@@ -79,12 +81,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-xl-3 mb-4">
|
||||
<div class="card shadow border-start-success py-2">
|
||||
<div class="card shadow py-2 border-start-success">
|
||||
<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>HNS Total</span></div>
|
||||
<div class="text-dark fw-bold h5 mb-0"><span><img src="/assets/img/HNS.png" width="20px"> {{total}}</span></div>
|
||||
<div class="text-uppercase text-success mb-1 fw-bold text-xs"><span>HNS Total</span></div>
|
||||
<div class="text-dark mb-0 fw-bold h5"><span><img src="/assets/img/HNS.png" width="20px"> <span id="wallet-total">0.00</span></span></div>
|
||||
</div>
|
||||
<div class="col-auto"><i class="fas fa-dollar-sign fa-2x text-gray-300"></i></div>
|
||||
</div>
|
||||
@@ -92,14 +94,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-xl-3 mb-4">
|
||||
<div class="card shadow border-start-info py-2">
|
||||
<div class="card shadow py-2 border-start-info">
|
||||
<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>Domains</span></div>
|
||||
<div class="text-uppercase text-info mb-1 fw-bold text-xs"><span>Domains</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>{{domain_count}}</span></div>
|
||||
<div class="text-dark me-3 mb-0 fw-bold h5"><span id="wallet-domainCount">0</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -108,12 +110,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-xl-3 mb-4">
|
||||
<div class="card shadow border-start-warning py-2">
|
||||
<div class="card shadow py-2 border-start-warning">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center no-gutters">
|
||||
<div class="col me-2">
|
||||
<div class="text-uppercase text-warning fw-bold text-xs mb-1"><span>Pending Transactions</span></div>
|
||||
<div class="text-dark fw-bold h5 mb-0"><span>{{pending}}</span></div>
|
||||
<div class="text-uppercase text-warning mb-1 fw-bold text-xs"><span>Pending Transactions</span></div>
|
||||
<div class="text-dark mb-0 fw-bold h5"><span id="wallet-pending">0</span></div>
|
||||
</div>
|
||||
<div class="col-auto"><svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="1em" viewBox="0 0 24 24" width="1em" fill="currentColor" class="fa-2x text-gray-300">
|
||||
<g>
|
||||
@@ -126,15 +128,32 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>{{plugins|safe}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="actions-row">{{plugins|safe}}</div>
|
||||
<div class="row">
|
||||
<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>
|
||||
<h6 class="text-primary m-0 fw-bold">Domains</h6>
|
||||
</div>
|
||||
<div class="card-body"><div class="table-responsive">
|
||||
<table class="table" id="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th onclick="sortTable(0)">Domain <span class="sort-indicator"></span></th>
|
||||
<th onclick="sortTable(1)" class="hide-mobile">Expires <span class="sort-indicator"></span></th>
|
||||
<th onclick="sortTable(2)" class="hide-mobile">Price Paid <span class="sort-indicator"></span></th>
|
||||
<!-- <th><span class="sort-indicator"></span></th> -->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- <div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -148,7 +167,7 @@
|
||||
{{domains | safe}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div></div>
|
||||
</div> --></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -156,13 +175,14 @@
|
||||
</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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
<script src="/assets/js/dashboard.min.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -19,7 +19,8 @@
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-9 col-lg-12 col-xl-10">
|
||||
<div class="card shadow-lg o-hidden border-0 my-5">
|
||||
<h1 class="text-center" style="color: var(--bs-danger);background: var(--bs-primary);">{{error}}</h1>
|
||||
<div class="card shadow-lg my-5 o-hidden border-0">
|
||||
<div class="card-body p-0">
|
||||
<div class="row">
|
||||
<div class="col-lg-6 d-none d-lg-flex">
|
||||
@@ -31,10 +32,22 @@
|
||||
<h4 class="text-dark mb-4">Welcome Back!</h4>
|
||||
</div>
|
||||
<form class="user" method="post">
|
||||
<div class="mb-3"><select class="form-control form-select form-select-lg form-control-user" name="account" value="default">
|
||||
<div class="mb-3"><img class="border rounded-circle img-profile" id="accountIcon" src="/api/v1/icon/primary" width="50px" height="50px" style="width: 50px;height: 50px;display: inline;"><select id="accountSelect" class="form-control form-select form-select-lg form-control-user" name="account" style="display: inline;width:calc(100% - 60px);margin-left:10px;" onchange="updateIcon()">
|
||||
{{wallets|safe}}
|
||||
</select></div>
|
||||
<div class="mb-3"><input class="form-control form-control-user" type="password" id="exampleInputPassword" placeholder="Password" name="password"></div><button class="btn btn-primary d-block btn-user w-100" type="submit">Login</button>
|
||||
</select>
|
||||
<script>
|
||||
function updateIcon() {
|
||||
var select = document.getElementById("accountSelect");
|
||||
var selectedValue = select.value;
|
||||
document.getElementById("accountIcon").src = "/api/v1/icon/" + selectedValue;
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
updateIcon();
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<div class="mb-3"><input class="form-control form-control-user" type="password" id="exampleInputPassword" placeholder="Password" name="password"></div><button class="btn btn-primary d-block w-100 btn-user" type="submit">Login</button>
|
||||
<hr>
|
||||
</form>
|
||||
<div class="text-center"><a class="small" href="register">Create a wallet</a></div>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -64,15 +66,16 @@
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">{{domain}}/<a class="btn btn-primary stick-right" role="button" href="/manage/{{domain}}/renew">Renew</a></h4>
|
||||
<h6 class="text-muted card-subtitle mb-2">Expires in {{expiry}} days</h6>
|
||||
<h4 class="card-title">{{rendered}}<a class="btn btn-primary stick-right" role="button" href="/manage/{{domain}}/renew">Renew</a></h4>
|
||||
<h6 class="text-muted mb-2 card-subtitle">Expires in {{expiry}} days</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>{{plugins|safe}}
|
||||
<div class="container-fluid" style="margin-top: 50px;">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title" style="display: inline-block;">DNS</h4><a class="btn btn-primary" role="button" style="position: absolute; right:16px;" href="/manage/{{domain}}/edit?dns={{raw_dns}}">Edit</a><div class="table-responsive">
|
||||
<h4 class="card-title" style="display: inline-block;">DNS</h4>
|
||||
<div style="width: fit-content;position: absolute;right: 0px;top: 16px;"><a class="btn btn-primary" role="button" href="https://tools.c.woodburn.au/?domain={{domain}}&url=https://{{domain}}" style="margin: 0px 16px;" target="_blank">Debug</a><a class="btn btn-primary" role="button" href="/manage/{{domain}}/edit?dns={{raw_dns}}" style="margin: 0px 16px;">Edit</a></div><div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -136,10 +139,20 @@ 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">
|
||||
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2024</span></div>
|
||||
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -67,7 +69,7 @@
|
||||
</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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -62,12 +64,12 @@
|
||||
</nav>
|
||||
<div class="container-fluid" style="margin-bottom: 20px;">
|
||||
<h3 class="text-dark mb-1">{{name}}</h3>
|
||||
<h4 class="text-dark mb-1">{{description}}</h4>{{output|safe}}
|
||||
<h4 class="text-dark mb-1">{{description|safe}}</h4>{{output|safe}}
|
||||
</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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -63,13 +65,13 @@
|
||||
<h1 class="text-center" style="color: rgb(255,0,0);">{{error}}</h1>
|
||||
<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}}
|
||||
<h4 class="text-dark mb-1">{{description|safe}}</h4>
|
||||
<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);">
|
||||
<div class="container my-auto">
|
||||
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2024</span></div>
|
||||
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -68,7 +70,7 @@
|
||||
</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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -66,13 +68,13 @@
|
||||
<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>
|
||||
<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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<body class="bg-gradient-primary">
|
||||
<div class="container">
|
||||
<div class="card shadow-lg o-hidden border-0 my-5">
|
||||
<div class="card shadow-lg my-5 o-hidden border-0">
|
||||
<div class="card-body p-0">
|
||||
<div class="row">
|
||||
<div class="col-lg-5 d-none d-lg-flex">
|
||||
@@ -30,11 +30,11 @@
|
||||
<h4 class="text-dark mb-4">Create a new wallet!</h4>
|
||||
</div>
|
||||
<form class="user" method="post">
|
||||
<div class="row mb-3" style="padding-right: 16px;padding-left: 16px;"><input class="form-control form-control-user" type="text" id="exampleLastName" placeholder="Wallet name" name="name" value="{{name}}"></div>
|
||||
<div class="row mb-3">
|
||||
<div class="mb-3 row" style="padding-right: 16px;padding-left: 16px;"><input class="form-control form-control-user" type="text" id="exampleLastName" placeholder="Wallet name" name="name" value="{{name}}"></div>
|
||||
<div class="mb-3 row">
|
||||
<div class="col-sm-6 mb-3 mb-sm-0"><input class="form-control form-control-user" type="password" id="examplePasswordInput" placeholder="Password" name="password" required="" value="{{password}}"></div>
|
||||
<div class="col-sm-6"><input class="form-control form-control-user" type="password" id="exampleRepeatPasswordInput" placeholder="Repeat Password" name="password_repeat" required="" value="{{password_repeat}}"></div>
|
||||
</div><button class="btn btn-primary d-block btn-user w-100" type="submit">Create Wallet</button>
|
||||
</div><button class="btn btn-primary d-block w-100 btn-user" type="submit">Create Wallet</button>
|
||||
<hr>
|
||||
</form>
|
||||
<div class="text-center"><a class="small" href="/login">Didn't mean to create a new wallet? Login!</a></div>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -63,9 +65,10 @@
|
||||
<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>
|
||||
<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>
|
||||
<h4 class="d-none d-sm-none d-md-none d-lg-inline-block d-xl-inline-block card-title">{{rendered}}<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 mb-2 card-subtitle"><br>{{state}}</h6>
|
||||
<h6 class="text-muted mb-2 card-subtitle">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>
|
||||
</div>{{plugins|safe}}
|
||||
@@ -84,27 +87,6 @@
|
||||
{{dns | safe}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid" style="margin-top: 50px;">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">History</h4><div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Action</th>
|
||||
<th>TX</th>
|
||||
<th>Amount</th>
|
||||
<th>Time</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{txs | safe}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -112,7 +94,7 @@
|
||||
</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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -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,12 +113,12 @@ 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);">
|
||||
<div class="container my-auto">
|
||||
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2024</span></div>
|
||||
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,48 +13,51 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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" id="wallet-icon" src="/api/v1/wallet/icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -65,8 +68,8 @@
|
||||
<h3 class="mb-1" style="text-align: center;color: rgb(0,255,0);">{{success}}</h3>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Node Settings</h4>
|
||||
<h6 class="text-muted card-subtitle mb-2">Settings that affect all wallets</h6>
|
||||
<h4 class="card-title">Node Settings</h4><small>HSD Version: v{{hsd_version}}</small>
|
||||
<h6 class="text-muted mb-2 card-subtitle">Settings that affect all wallets</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<div><a class="btn btn-primary stick-right" role="button" href="/settings/rescan">Rescan</a>
|
||||
@@ -91,21 +94,41 @@
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Wallet Settings</h4>
|
||||
<h6 class="text-muted card-subtitle mb-2">Settings that affect only current wallets</h6>
|
||||
<h6 class="text-muted mb-2 card-subtitle">Settings that affect only current wallets</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<div><a class="btn btn-primary stick-right" role="button" href="/settings/xpub">xPub</a>
|
||||
<h3>xPub Key</h3><span>Get your xPub key</span>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<form id="uploadForm" action="/settings/upload" method="post" enctype="multipart/form-data">
|
||||
<div>
|
||||
<h3>Account Icon</h3><span>Customise your account</span><script>
|
||||
function autoSubmit() {
|
||||
document.getElementById('uploadForm').submit();
|
||||
}
|
||||
</script><input class="form-control" type="file" name="image" onchange="autoSubmit()">
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid" style="margin-top: 50px;margin-bottom: 50px;">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">About</h4>
|
||||
<h6 class="text-muted mb-2 card-subtitle">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> 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> 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> 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">
|
||||
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2024</span></div>
|
||||
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -65,13 +67,13 @@
|
||||
</div>
|
||||
<div class="card" style="max-width: 500px;margin: auto;margin-top: 50px;">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Your transaction has been sent and will be mined soon.</h4><span style="display: block;font-size: 12px;">TX: {{tx}}</span><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>
|
||||
<h4 class="card-title">Your transaction has been sent and will be mined soon.</h4><span style="display: block;font-size: 12px;">TX: {{tx}}</span><span style="display: block;">Check your transaction on a block explorer</span><a class="card-link" href="https://shakeshift.com/transaction/{{tx}}" target="_blank">ShakeShift</a><a class="card-link" href="https://3xpl.com/handshake/transaction/{{tx}}" target="_blank">3xpl</a>
|
||||
</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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -13,48 +13,50 @@
|
||||
<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&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);">
|
||||
<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="/">
|
||||
<nav class="navbar align-items-start p-0 sidebar sidebar-dark accordion bg-gradient-primary 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 m-0 sidebar-brand" 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>
|
||||
<div class="mx-3 sidebar-brand-text"><span>FireWallet</span></div>
|
||||
</a>
|
||||
<hr class="sidebar-divider my-0">
|
||||
<hr class="my-0 sidebar-divider">
|
||||
<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>Auctions</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">
|
||||
<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="container-fluid"><button class="btn btn-link d-md-none me-3 rounded-circle" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
|
||||
<form class="d-none d-sm-inline-block mw-100 ms-md-3 me-auto my-2 my-md-0 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 class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);"><span id="hsd-sync-mobile">{{sync}}</span></span><span class="d-inline d-print-none d-sm-inline d-md-inline d-lg-none d-xl-none d-xxl-none" style="color: var(--bs-dark);margin-left: 10px;"><span id="wallet-sync-mobile">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);">Sync: <span id="hsd-sync">{{sync}}</span>%</span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Wallet: <span id="wallet-sync">{{wallet_status}}</span></span><span class="d-none d-print-inline d-sm-none d-md-none d-lg-inline d-xl-inline d-xxl-inline" style="color: var(--bs-dark);margin-left: 10px;">Height: <span id="hsd-height">{{height}}</span></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 ...">
|
||||
<div class="dropdown-menu p-3 dropdown-menu-end animated--grow-in" aria-labelledby="searchDropdown">
|
||||
<form class="w-100 me-auto navbar-search" 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="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> Logout</a></div>
|
||||
<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="/api/v1/wallet/icon" id="wallet-icon"></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 me-2 fa-sm fa-fw text-gray-400"></i> Logout</a></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -63,40 +65,97 @@
|
||||
<div class="container-fluid">
|
||||
<h3 class="text-dark mb-4">Transactions</h3>
|
||||
<div class="card shadow">
|
||||
<div class="card-header py-3">
|
||||
<p class="text-primary m-0 fw-bold">Transactions</p>
|
||||
<div class="card-header py-3" style="padding: 16px;">
|
||||
<div style="height: 38px;">
|
||||
<p class="text-primary m-0 fw-bold" style="display: inline-block;">Transactions</p><div class="btn-group" role="group" style="right: 16px;top: 16px;position: absolute;height: 38px;">
|
||||
{% if page != 1 %}
|
||||
<a class="btn btn-primary" role="button" href="/tx?page={{page-1}}">Prev</a>
|
||||
{% endif %}
|
||||
<!-- {% if txCount == 100 %} -->
|
||||
<!-- {% endif %} -->
|
||||
<a class="btn btn-primary" role="button" href="/tx?page={{page+1}}">Next</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body"><div id="dataTable" class="table-responsive table mt-2" role="grid" aria-describedby="dataTable_info">
|
||||
<table id="dataTable" class="table my-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Action</th>
|
||||
<th>Address</th>
|
||||
<th>Tx</th>
|
||||
<th>Confirmations</th>
|
||||
<th>Amount</th>
|
||||
<th>Date</th>
|
||||
<th>Transaction</th>
|
||||
<!-- <th class="hide-mobile">Address</th> -->
|
||||
<!-- <th class="amount-column">Amount</th> -->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{tx|safe}}
|
||||
<tbody id="transactions-tbody">
|
||||
<tr id="loading-row">
|
||||
<td colspan="5" class="text-center">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
<div class="mt-2">Loading transactions...</div>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- <tbody>
|
||||
{{tx|safe}} -->
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td><strong>Action</strong></td>
|
||||
<td><strong>Address</strong></td>
|
||||
<td><strong>Tx</strong></td>
|
||||
<td><strong>Confirmations</strong></td>
|
||||
<td><strong>Amount</strong></td>
|
||||
<td><strong>Date</strong></td>
|
||||
<td><strong>Transaction</strong></td>
|
||||
<!-- <td class="hide-mobile"><strong>Address</strong></td> -->
|
||||
<!-- <td class="amount-column"><strong>Amount</strong></td> -->
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div></div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const page = {{ page }};
|
||||
const tbody = document.getElementById('transactions-tbody');
|
||||
const loadingRow = document.getElementById('loading-row');
|
||||
|
||||
// Fetch transactions
|
||||
fetch(`/api/v1/wallet/transactions?page=${page}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
tbody.innerHTML = `<tr><td colspan="5" class="text-center text-danger">Error: ${data.error}</td></tr>`;
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace loading with actual transactions
|
||||
tbody.innerHTML = data.html;
|
||||
|
||||
// Update pagination buttons if needed
|
||||
updatePagination(data.txCount, page);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching transactions:', error);
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="text-center text-danger">Failed to load transactions</td></tr>';
|
||||
});
|
||||
});
|
||||
|
||||
function updatePagination(txCount, currentPage) {
|
||||
// Update pagination buttons based on transaction count
|
||||
const prevBtn = document.querySelector('a[href*="page=' + (currentPage - 1) + '"]');
|
||||
const nextBtn = document.querySelector('a[href*="page=' + (currentPage + 1) + '"]');
|
||||
|
||||
if (currentPage <= 1 && prevBtn) {
|
||||
prevBtn.style.display = 'none';
|
||||
}
|
||||
if (txCount < 100 && nextBtn) {
|
||||
nextBtn.style.display = 'none';
|
||||
}
|
||||
}
|
||||
</script></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 class="text-center my-auto copyright"><span>Copyright © FireWallet 2025</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>
|
||||
|
||||
@@ -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}.no-display{text-decoration:none}.amount-column{text-align:right;padding-right:10px;white-space:nowrap}.domain-name{text-decoration:none;color:var(--bs-body-color)}@media (max-width:768px){.hide-mobile{display:none!important}
|
||||
|
||||
@@ -1 +1 @@
|
||||
[data-bs-theme=dark]{--bs-primary:#6e0e9c;--bs-primary-rgb:110,14,156;--bs-primary-text-emphasis:#A86EC4;--bs-primary-bg-subtle:#16031F;--bs-primary-border-subtle:#42085E;--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:#6e0e9c;--bs-btn-border-color:#6e0e9c;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#5E0C85;--bs-btn-hover-border-color:#580B7D;--bs-btn-focus-shadow-rgb:233,219,240;--bs-btn-active-color:#fff;--bs-btn-active-bg:#580B7D;--bs-btn-active-border-color:#530B75;--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#6e0e9c;--bs-btn-disabled-border-color:#6e0e9c}.btn-outline-primary[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-primary{--bs-btn-color:#6e0e9c;--bs-btn-border-color:#6e0e9c;--bs-btn-focus-shadow-rgb:110,14,156;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#6e0e9c;--bs-btn-hover-border-color:#6e0e9c;--bs-btn-active-color:#fff;--bs-btn-active-bg:#6e0e9c;--bs-btn-active-border-color:#6e0e9c;--bs-btn-disabled-color:#6e0e9c;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#6e0e9c}.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:#6e0e9c;--bs-primary-rgb:110,14,156;--bs-primary-text-emphasis:#A86EC4;--bs-primary-bg-subtle:#16031F;--bs-primary-border-subtle:#42085E;--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:#6e0e9c;--bs-btn-border-color:#6e0e9c;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#5E0C85;--bs-btn-hover-border-color:#580B7D;--bs-btn-focus-shadow-rgb:233,219,240;--bs-btn-active-color:#fff;--bs-btn-active-bg:#580B7D;--bs-btn-active-border-color:#530B75;--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#6e0e9c;--bs-btn-disabled-border-color:#6e0e9c}.btn-outline-primary[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-primary{--bs-btn-color:#6e0e9c;--bs-btn-border-color:#6e0e9c;--bs-btn-focus-shadow-rgb:110,14,156;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#6e0e9c;--bs-btn-hover-border-color:#6e0e9c;--bs-btn-active-color:#fff;--bs-btn-active-bg:#6e0e9c;--bs-btn-active-border-color:#6e0e9c;--bs-btn-disabled-color:#6e0e9c;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#6e0e9c}.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}.no-display{text-decoration:none}.amount-column{text-align:right;padding-right:10px;white-space:nowrap}.domain-name{text-decoration:none;color:var(--bs-body-color)}@media (max-width:768px){.hide-mobile{display:none!important}
|
||||
|
||||
@@ -1 +1 @@
|
||||
[data-bs-theme=dark]{--bs-primary:#1a0023;--bs-primary-rgb:26,0,35;--bs-primary-text-emphasis:#76667B;--bs-primary-bg-subtle:#050007;--bs-primary-border-subtle:#100015;--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:#1a0023;--bs-btn-border-color:#1a0023;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#16001E;--bs-btn-hover-border-color:#15001C;--bs-btn-focus-shadow-rgb:221,217,222;--bs-btn-active-color:#fff;--bs-btn-active-bg:#15001C;--bs-btn-active-border-color:#14001A;--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#1a0023;--bs-btn-disabled-border-color:#1a0023}.btn-outline-primary[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-primary{--bs-btn-color:#1a0023;--bs-btn-border-color:#1a0023;--bs-btn-focus-shadow-rgb:26,0,35;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#1a0023;--bs-btn-hover-border-color:#1a0023;--bs-btn-active-color:#fff;--bs-btn-active-bg:#1a0023;--bs-btn-active-border-color:#1a0023;--bs-btn-disabled-color:#1a0023;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#1a0023}.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:#1a0023;--bs-primary-rgb:26,0,35;--bs-primary-text-emphasis:#76667B;--bs-primary-bg-subtle:#050007;--bs-primary-border-subtle:#100015;--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:#1a0023;--bs-btn-border-color:#1a0023;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#16001E;--bs-btn-hover-border-color:#15001C;--bs-btn-focus-shadow-rgb:221,217,222;--bs-btn-active-color:#fff;--bs-btn-active-bg:#15001C;--bs-btn-active-border-color:#14001A;--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#1a0023;--bs-btn-disabled-border-color:#1a0023}.btn-outline-primary[data-bs-theme=dark],[data-bs-theme=dark] .btn-outline-primary{--bs-btn-color:#1a0023;--bs-btn-border-color:#1a0023;--bs-btn-focus-shadow-rgb:26,0,35;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#1a0023;--bs-btn-hover-border-color:#1a0023;--bs-btn-active-color:#fff;--bs-btn-active-bg:#1a0023;--bs-btn-active-border-color:#1a0023;--bs-btn-disabled-color:#1a0023;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#1a0023}.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}.no-display{text-decoration:none}.amount-column{text-align:right;padding-right:10px;white-space:nowrap}.domain-name{text-decoration:none;color:var(--bs-body-color)}@media (max-width:768px){.hide-mobile{display:none!important}
|
||||
|
||||
1
themes/light.css
Normal file
1
themes/light.css
Normal 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}.no-display{text-decoration:none}.amount-column{text-align:right;padding-right:10px;white-space:nowrap}.domain-name{text-decoration:none;color:var(--bs-body-color)}@media (max-width:768px){.hide-mobile{display:none!important}
|
||||
Reference in New Issue
Block a user