Merge branch 'feat/plugins' into dev
All checks were successful
Build Docker / Build Image (push) Successful in 26s
All checks were successful
Build Docker / Build Image (push) Successful in 26s
This commit is contained in:
commit
d62ced1375
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,3 +2,5 @@
|
|||||||
.env
|
.env
|
||||||
|
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
|
||||||
|
templates/assets/css/styles.min.css
|
||||||
|
BIN
FireWalletBrowser.bsdesign
Normal file
BIN
FireWalletBrowser.bsdesign
Normal file
Binary file not shown.
26
README.md
26
README.md
@ -40,6 +40,32 @@ If you have HSD running on a different IP/container
|
|||||||
sudo docker run -p 5000:5000 -e hsd_api=yourapikeyhere -e hsd_ip=hsdcontainer git.woodburn.au/nathanwoodburn/firewallet:latest
|
sudo docker run -p 5000:5000 -e hsd_api=yourapikeyhere -e hsd_ip=hsdcontainer git.woodburn.au/nathanwoodburn/firewallet:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- Basic wallet functionality
|
||||||
|
- Create new wallet
|
||||||
|
- Import wallet from seed
|
||||||
|
- Send HNS
|
||||||
|
- Receive HNS
|
||||||
|
- Have multiple wallets
|
||||||
|
- View transactions
|
||||||
|
- View balance
|
||||||
|
- View wallet domains
|
||||||
|
- Domain management
|
||||||
|
- Transfer domains
|
||||||
|
- DNS Editor
|
||||||
|
- Renew domains
|
||||||
|
- Auctions
|
||||||
|
- Send open
|
||||||
|
- Send bid
|
||||||
|
- Send reveal
|
||||||
|
- Send redeem
|
||||||
|
- Download a list of all domains
|
||||||
|
- Resend all pending transactions
|
||||||
|
- Rescan
|
||||||
|
- Zap pending transactions
|
||||||
|
- View xPub
|
||||||
|
- Custom plugin support
|
||||||
|
|
||||||
## Themes
|
## Themes
|
||||||
Set a theme in the .env file
|
Set a theme in the .env file
|
||||||
**Available themes**
|
**Available themes**
|
||||||
|
49
account.py
49
account.py
@ -84,6 +84,31 @@ def createWallet(account: str, password: str):
|
|||||||
"password": password
|
"password": password
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def importWallet(account: str, password: str,seed: str):
|
||||||
|
# Import the wallet
|
||||||
|
data = {
|
||||||
|
"passphrase": password,
|
||||||
|
"mnemonic": seed,
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.put(f"http://x:{APIKEY}@{ip}:12039/wallet/{account}",json=data)
|
||||||
|
print(response)
|
||||||
|
print(response.json())
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
return {
|
||||||
|
"error": {
|
||||||
|
"message": "Error creating account"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"seed": seed,
|
||||||
|
"account": account,
|
||||||
|
"password": password
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def listWallets():
|
def listWallets():
|
||||||
# List the wallets
|
# List the wallets
|
||||||
response = hsw.listWallets()
|
response = hsw.listWallets()
|
||||||
@ -461,7 +486,21 @@ def finalize(account,domain):
|
|||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = hsw.sendFINALIZE(account_name,password,domain)
|
response = hsw.rpc_selectWallet(account_name)
|
||||||
|
if response['error'] is not None:
|
||||||
|
return {
|
||||||
|
"error": {
|
||||||
|
"message": response['error']['message']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response = hsw.rpc_walletPassphrase(password,10)
|
||||||
|
if response['error'] is not None:
|
||||||
|
return {
|
||||||
|
"error": {
|
||||||
|
"message": response['error']['message']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response = hsw.rpc_sendFINALIZE(domain)
|
||||||
return response
|
return response
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {
|
return {
|
||||||
@ -626,9 +665,8 @@ def getxPub(account):
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
def generateReport(account):
|
def generateReport(account,format="{name},{expiry},{value},{maxBid}"):
|
||||||
domains = getDomains(account)
|
domains = getDomains(account)
|
||||||
format = str('{name},{expiry},{value},{maxBid}')
|
|
||||||
|
|
||||||
lines = [format.replace("{","").replace("}","")]
|
lines = [format.replace("{","").replace("}","")]
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
@ -650,4 +688,7 @@ def generateReport(account):
|
|||||||
line = line.replace("{openHeight}",str(domain['height']))
|
line = line.replace("{openHeight}",str(domain['height']))
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
def convertHNS(value: int):
|
||||||
|
return value/1000000
|
184
main.py
184
main.py
@ -10,6 +10,8 @@ import re
|
|||||||
from flask_qrcode import QRcode
|
from flask_qrcode import QRcode
|
||||||
import domainLookup
|
import domainLookup
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
import importlib
|
||||||
|
import plugin as plugins_module
|
||||||
|
|
||||||
dotenv.load_dotenv()
|
dotenv.load_dotenv()
|
||||||
|
|
||||||
@ -90,10 +92,17 @@ def index():
|
|||||||
domain_count = len(domains)
|
domain_count = len(domains)
|
||||||
domains = render.domains(domains)
|
domains = render.domains(domains)
|
||||||
|
|
||||||
|
plugins = ""
|
||||||
|
dashFunctions = plugins_module.getDashboardFunctions()
|
||||||
|
for function in dashFunctions:
|
||||||
|
functionOutput = plugins_module.runPluginFunction(function["plugin"],function["function"],{},account_module.check_account(request.cookies.get("account")))
|
||||||
|
plugins += render.plugin_output_dash(functionOutput,plugins_module.getPluginFunctionReturns(function["plugin"],function["function"]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return render_template("index.html", account=account, available=available,
|
return render_template("index.html", account=account, available=available,
|
||||||
total=total, pending=pending, domains=domains,
|
total=total, pending=pending, domains=domains, plugins=plugins,
|
||||||
domain_count=domain_count, sync=account_module.getNodeSync(),
|
domain_count=domain_count, sync=account_module.getNodeSync(),
|
||||||
sort_price=sort_price,sort_expiry=sort_expiry,
|
sort_price=sort_price,sort_expiry=sort_expiry,
|
||||||
sort_domain=sort_domain,sort_price_next=sort_price_next,
|
sort_domain=sort_domain,sort_price_next=sort_price_next,
|
||||||
@ -319,10 +328,20 @@ def search():
|
|||||||
|
|
||||||
dns = render.dns(dns)
|
dns = render.dns(dns)
|
||||||
txs = render.txs(txs)
|
txs = render.txs(txs)
|
||||||
|
|
||||||
|
plugins = "<div class='container-fluid'>"
|
||||||
|
# Execute domain plugins
|
||||||
|
searchFunctions = plugins_module.getSearchFunctions()
|
||||||
|
for function in searchFunctions:
|
||||||
|
functionOutput = plugins_module.runPluginFunction(function["plugin"],function["function"],{"domain":search_term},account_module.check_account(request.cookies.get("account")))
|
||||||
|
plugins += render.plugin_output(functionOutput,plugins_module.getPluginFunctionReturns(function["plugin"],function["function"]))
|
||||||
|
|
||||||
|
plugins += "</div>"
|
||||||
|
|
||||||
return render_template("search.html", account=account, sync=account_module.getNodeSync(),
|
return render_template("search.html", account=account, sync=account_module.getNodeSync(),
|
||||||
search_term=search_term,domain=domain['info']['name'],
|
search_term=search_term,domain=domain['info']['name'],
|
||||||
raw=domain,state=state, next=next, owner=owner,
|
raw=domain,state=state, next=next, owner=owner,
|
||||||
dns=dns, txs=txs)
|
dns=dns, txs=txs,plugins=plugins)
|
||||||
|
|
||||||
@app.route('/manage/<domain>')
|
@app.route('/manage/<domain>')
|
||||||
def manage(domain: str):
|
def manage(domain: str):
|
||||||
@ -370,11 +389,21 @@ def manage(domain: str):
|
|||||||
else:
|
else:
|
||||||
finalize_time = "now"
|
finalize_time = "now"
|
||||||
|
|
||||||
|
plugins = "<div class='container-fluid'>"
|
||||||
|
# Execute domain plugins
|
||||||
|
domainFunctions = plugins_module.getDomainFunctions()
|
||||||
|
for function in domainFunctions:
|
||||||
|
functionOutput = plugins_module.runPluginFunction(function["plugin"],function["function"],{"domain":domain},account_module.check_account(request.cookies.get("account")))
|
||||||
|
plugins += render.plugin_output(functionOutput,plugins_module.getPluginFunctionReturns(function["plugin"],function["function"]))
|
||||||
|
|
||||||
|
plugins += "</div>"
|
||||||
|
|
||||||
|
|
||||||
return render_template("manage.html", account=account, sync=account_module.getNodeSync(),
|
return render_template("manage.html", account=account, sync=account_module.getNodeSync(),
|
||||||
error=errorMessage, address=address,
|
error=errorMessage, address=address,
|
||||||
domain=domain,expiry=expiry, dns=dns,
|
domain=domain,expiry=expiry, dns=dns,
|
||||||
raw_dns=urllib.parse.quote(raw_dns),
|
raw_dns=urllib.parse.quote(raw_dns),
|
||||||
finalize_time=finalize_time)
|
finalize_time=finalize_time,plugins=plugins)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/manage/<domain>/finalize')
|
@app.route('/manage/<domain>/finalize')
|
||||||
@ -390,11 +419,11 @@ def finalize(domain: str):
|
|||||||
domain = domain.lower()
|
domain = domain.lower()
|
||||||
print(domain)
|
print(domain)
|
||||||
response = account_module.finalize(request.cookies.get("account"),domain)
|
response = account_module.finalize(request.cookies.get("account"),domain)
|
||||||
if 'error' in response:
|
if response['error'] != None:
|
||||||
print(response)
|
print(response)
|
||||||
return redirect("/manage/" + domain + "?error=" + response['error']['message'])
|
return redirect("/manage/" + domain + "?error=" + response['error']['message'])
|
||||||
|
|
||||||
return redirect("/success?tx=" + response['hash'])
|
return redirect("/success?tx=" + response['result']['hash'])
|
||||||
|
|
||||||
@app.route('/manage/<domain>/cancel')
|
@app.route('/manage/<domain>/cancel')
|
||||||
def cancelTransfer(domain: str):
|
def cancelTransfer(domain: str):
|
||||||
@ -820,8 +849,8 @@ def reveal_auction(domain):
|
|||||||
return redirect("/auction/" + domain + "?message=" + response['error']['message'])
|
return redirect("/auction/" + domain + "?message=" + response['error']['message'])
|
||||||
return redirect("/success?tx=" + response['hash'])
|
return redirect("/success?tx=" + response['hash'])
|
||||||
|
|
||||||
|
#endregion
|
||||||
#region settings
|
#region Settings
|
||||||
@app.route('/settings')
|
@app.route('/settings')
|
||||||
def settings():
|
def settings():
|
||||||
# Check if the user is logged in
|
# Check if the user is logged in
|
||||||
@ -877,7 +906,6 @@ def settings_action(action):
|
|||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Account
|
#region Account
|
||||||
@ -966,6 +994,50 @@ def register():
|
|||||||
response.set_cookie("account", account+":"+password)
|
response.set_cookie("account", account+":"+password)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@app.route('/import-wallet', methods=["POST"])
|
||||||
|
def import_wallet():
|
||||||
|
# Get the account and password
|
||||||
|
account = request.form.get("name")
|
||||||
|
password = request.form.get("password")
|
||||||
|
repeatPassword = request.form.get("password_repeat")
|
||||||
|
seed = request.form.get("seed")
|
||||||
|
|
||||||
|
# Check if the passwords match
|
||||||
|
if password != repeatPassword:
|
||||||
|
return render_template("import-wallet.html",
|
||||||
|
error="Passwords do not match",
|
||||||
|
name=account,password=password,password_repeat=repeatPassword,
|
||||||
|
seed=seed)
|
||||||
|
|
||||||
|
# Check if the account is valid
|
||||||
|
if account.count(":") > 0:
|
||||||
|
return render_template("import-wallet.html",
|
||||||
|
error="Invalid account",
|
||||||
|
name=account,password=password,password_repeat=repeatPassword,
|
||||||
|
seed=seed)
|
||||||
|
|
||||||
|
# List wallets
|
||||||
|
wallets = account_module.listWallets()
|
||||||
|
if account in wallets:
|
||||||
|
return render_template("import-wallet.html",
|
||||||
|
error="Account already exists",
|
||||||
|
name=account,password=password,password_repeat=repeatPassword,
|
||||||
|
seed=seed)
|
||||||
|
|
||||||
|
# Create the account
|
||||||
|
response = account_module.importWallet(account,password,seed)
|
||||||
|
|
||||||
|
if 'error' in response:
|
||||||
|
return render_template("import-wallet.html",
|
||||||
|
error=response['error'],
|
||||||
|
name=account,password=password,password_repeat=repeatPassword,
|
||||||
|
seed=seed)
|
||||||
|
|
||||||
|
|
||||||
|
# Set the cookie
|
||||||
|
response = make_response(redirect("/"))
|
||||||
|
response.set_cookie("account", account+":"+password)
|
||||||
|
return response
|
||||||
|
|
||||||
@app.route('/report')
|
@app.route('/report')
|
||||||
def report():
|
def report():
|
||||||
@ -979,6 +1051,102 @@ def report():
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Plugins
|
||||||
|
@app.route('/plugins')
|
||||||
|
def plugins_index():
|
||||||
|
# Check if the user is logged in
|
||||||
|
if request.cookies.get("account") is None:
|
||||||
|
return redirect("/login")
|
||||||
|
|
||||||
|
account = account_module.check_account(request.cookies.get("account"))
|
||||||
|
if not account:
|
||||||
|
return redirect("/logout")
|
||||||
|
|
||||||
|
plugins = render.plugins(plugins_module.listPlugins())
|
||||||
|
|
||||||
|
return render_template("plugins.html", account=account, sync=account_module.getNodeSync(),
|
||||||
|
plugins=plugins)
|
||||||
|
|
||||||
|
@app.route('/plugin/<plugin>')
|
||||||
|
def plugin(plugin):
|
||||||
|
# Check if the user is logged in
|
||||||
|
if request.cookies.get("account") is None:
|
||||||
|
return redirect("/login")
|
||||||
|
|
||||||
|
account = account_module.check_account(request.cookies.get("account"))
|
||||||
|
if not account:
|
||||||
|
return redirect("/logout")
|
||||||
|
|
||||||
|
if not plugins_module.pluginExists(plugin):
|
||||||
|
return redirect("/plugins")
|
||||||
|
|
||||||
|
data = plugins_module.getPluginData(plugin)
|
||||||
|
|
||||||
|
functions = plugins_module.getPluginFunctions(plugin)
|
||||||
|
functions = render.plugin_functions(functions,plugin)
|
||||||
|
|
||||||
|
error = request.args.get("error")
|
||||||
|
if error == None:
|
||||||
|
error = ""
|
||||||
|
|
||||||
|
return render_template("plugin.html", account=account, sync=account_module.getNodeSync(),
|
||||||
|
name=data['name'],description=data['description'],
|
||||||
|
author=data['author'],version=data['version'],
|
||||||
|
functions=functions,error=error)
|
||||||
|
|
||||||
|
@app.route('/plugin/<plugin>/<function>', methods=["POST"])
|
||||||
|
def plugin_function(plugin,function):
|
||||||
|
# Check if the user is logged in
|
||||||
|
if request.cookies.get("account") is None:
|
||||||
|
return redirect("/login")
|
||||||
|
|
||||||
|
account = account_module.check_account(request.cookies.get("account"))
|
||||||
|
if not account:
|
||||||
|
return redirect("/logout")
|
||||||
|
|
||||||
|
if not plugins_module.pluginExists(plugin):
|
||||||
|
return redirect("/plugins")
|
||||||
|
|
||||||
|
data = plugins_module.getPluginData(plugin)
|
||||||
|
|
||||||
|
# Get plugin/main.py listfunctions()
|
||||||
|
if function in plugins_module.getPluginFunctions(plugin):
|
||||||
|
inputs = plugins_module.getPluginFunctionInputs(plugin,function)
|
||||||
|
request_data = {}
|
||||||
|
for input in inputs:
|
||||||
|
request_data[input] = request.form.get(input)
|
||||||
|
|
||||||
|
if inputs[input]['type'] == "address":
|
||||||
|
# Handle hip2
|
||||||
|
address_check = account_module.check_address(request_data[input],True,True)
|
||||||
|
if not address_check:
|
||||||
|
return redirect("/plugin/" + plugin + "?error=Invalid address")
|
||||||
|
request_data[input] = address_check
|
||||||
|
elif inputs[input]['type'] == "dns":
|
||||||
|
# Handle URL encoding of DNS
|
||||||
|
request_data[input] = urllib.parse.unquote(request_data[input])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
response = plugins_module.runPluginFunction(plugin,function,request_data,request.cookies.get("account"))
|
||||||
|
if not response:
|
||||||
|
return redirect("/plugin/" + plugin + "?error=An error occurred")
|
||||||
|
if 'error' in response:
|
||||||
|
return redirect("/plugin/" + plugin + "?error=" + response['error'])
|
||||||
|
|
||||||
|
response = render.plugin_output(response,plugins_module.getPluginFunctionReturns(plugin,function))
|
||||||
|
|
||||||
|
return render_template("plugin-output.html", account=account, sync=account_module.getNodeSync(),
|
||||||
|
name=data['name'],description=data['description'],output=response)
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
return jsonify({"error": "Function not found"})
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Assets and default pages
|
#region Assets and default pages
|
||||||
@app.route('/qr/<data>')
|
@app.route('/qr/<data>')
|
||||||
def qr(data):
|
def qr(data):
|
||||||
|
101
plugin.py
Normal file
101
plugin.py
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
import importlib
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def listPlugins():
|
||||||
|
plugins = []
|
||||||
|
for file in os.listdir("plugins"):
|
||||||
|
if file.endswith(".py"):
|
||||||
|
if file != "main.py":
|
||||||
|
plugin = importlib.import_module("plugins."+file[:-3])
|
||||||
|
details = plugin.info
|
||||||
|
details["link"] = file[:-3]
|
||||||
|
plugins.append(details)
|
||||||
|
return plugins
|
||||||
|
|
||||||
|
|
||||||
|
def pluginExists(plugin: str):
|
||||||
|
for file in os.listdir("plugins"):
|
||||||
|
if file == plugin+".py":
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def runPluginFunction(plugin: str, function: str, params: dict, authentication: str):
|
||||||
|
plugin_module = importlib.import_module("plugins."+plugin)
|
||||||
|
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)
|
||||||
|
|
||||||
|
# Call the function with provided parameters
|
||||||
|
try:
|
||||||
|
result = plugin_function(params, authentication)
|
||||||
|
return result
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error running plugin: {e}")
|
||||||
|
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"]
|
||||||
|
|
||||||
|
def getPluginFunctionReturns(plugin: str, function: str):
|
||||||
|
plugin = importlib.import_module("plugins."+plugin)
|
||||||
|
return plugin.functions[function]["returns"]
|
||||||
|
|
||||||
|
def getDomainFunctions():
|
||||||
|
plugins = listPlugins()
|
||||||
|
domainFunctions = []
|
||||||
|
for plugin in plugins:
|
||||||
|
functions = getPluginFunctions(plugin["link"])
|
||||||
|
for function in functions:
|
||||||
|
if functions[function]["type"] == "domain":
|
||||||
|
domainFunctions.append({
|
||||||
|
"plugin": plugin["link"],
|
||||||
|
"function": function,
|
||||||
|
"description": functions[function]["description"]
|
||||||
|
})
|
||||||
|
return domainFunctions
|
||||||
|
|
||||||
|
def getSearchFunctions():
|
||||||
|
plugins = listPlugins()
|
||||||
|
searchFunctions = []
|
||||||
|
for plugin in plugins:
|
||||||
|
functions = getPluginFunctions(plugin["link"])
|
||||||
|
for function in functions:
|
||||||
|
if functions[function]["type"] == "search":
|
||||||
|
searchFunctions.append({
|
||||||
|
"plugin": plugin["link"],
|
||||||
|
"function": function,
|
||||||
|
"description": functions[function]["description"]
|
||||||
|
})
|
||||||
|
return searchFunctions
|
||||||
|
|
||||||
|
def getDashboardFunctions():
|
||||||
|
plugins = listPlugins()
|
||||||
|
dashboardFunctions = []
|
||||||
|
for plugin in plugins:
|
||||||
|
functions = getPluginFunctions(plugin["link"])
|
||||||
|
for function in functions:
|
||||||
|
if functions[function]["type"] == "dashboard":
|
||||||
|
dashboardFunctions.append({
|
||||||
|
"plugin": plugin["link"],
|
||||||
|
"function": function,
|
||||||
|
"description": functions[function]["description"]
|
||||||
|
})
|
||||||
|
return dashboardFunctions
|
62
plugins.md
Normal file
62
plugins.md
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# Plugins
|
||||||
|
|
||||||
|
## Types
|
||||||
|
### Default
|
||||||
|
Type: `default`
|
||||||
|
This is the default type and is used when no type is specified.
|
||||||
|
This type is displayed in the plugin page only.
|
||||||
|
This is the onlu type of plugin that takes user input
|
||||||
|
|
||||||
|
### Manage & Search
|
||||||
|
For manage page use type: `domain`
|
||||||
|
For search page use type: `search`
|
||||||
|
|
||||||
|
This type is used for domain plugins. It shows in the manage domain page or the search page.
|
||||||
|
It gets the `domain` paramater as the only input (in addition to authentication)
|
||||||
|
|
||||||
|
### Dashboard
|
||||||
|
This type is used for dashboard plugins.
|
||||||
|
It shows in the dashboard page. It doesn't get any inputs other than the authentication
|
||||||
|
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
### Plain Text
|
||||||
|
Type: `text`
|
||||||
|
|
||||||
|
### Long Text
|
||||||
|
Type: `longText`
|
||||||
|
|
||||||
|
### Number
|
||||||
|
Type: `number`
|
||||||
|
|
||||||
|
|
||||||
|
### Checkbox
|
||||||
|
Type: `checkbox`
|
||||||
|
|
||||||
|
### Address
|
||||||
|
Type: `address`
|
||||||
|
This will handle hip2 resolution for you so the function will always receive a valid address
|
||||||
|
|
||||||
|
### DNS
|
||||||
|
Type: `dns`
|
||||||
|
This isn't done yet but use it over text as it includes parsing
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Outputs
|
||||||
|
### Plain Text
|
||||||
|
Type: `text`
|
||||||
|
|
||||||
|
|
||||||
|
### List
|
||||||
|
Type: `list`
|
||||||
|
This is a list if text items (or HTML items)
|
||||||
|
|
||||||
|
### Transaction hash
|
||||||
|
Type: `tx`
|
||||||
|
This will display the hash and links to explorers
|
||||||
|
|
||||||
|
### DNS records
|
||||||
|
Type: `dns`
|
||||||
|
This will display DNS in a table format
|
175
plugins/example.py
Normal file
175
plugins/example.py
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
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}
|
121
render.py
121
render.py
@ -1,6 +1,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
from flask import render_template
|
||||||
|
|
||||||
def domains(domains):
|
def domains(domains):
|
||||||
html = ''
|
html = ''
|
||||||
@ -178,4 +179,124 @@ def wallets(wallets):
|
|||||||
html = ''
|
html = ''
|
||||||
for wallet in wallets:
|
for wallet in wallets:
|
||||||
html += f'<option value="{wallet}">{wallet}</option>'
|
html += f'<option value="{wallet}">{wallet}</option>'
|
||||||
|
return html
|
||||||
|
|
||||||
|
def plugins(plugins):
|
||||||
|
html = ''
|
||||||
|
for plugin in 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>'
|
||||||
|
return html
|
||||||
|
|
||||||
|
def plugin_functions(functions, pluginName):
|
||||||
|
html = ''
|
||||||
|
for function in functions:
|
||||||
|
name = functions[function]['name']
|
||||||
|
description = functions[function]['description']
|
||||||
|
params = functions[function]['params']
|
||||||
|
returnsRaw = functions[function]['returns']
|
||||||
|
|
||||||
|
returns = ""
|
||||||
|
for output in returnsRaw:
|
||||||
|
returns += f"{returnsRaw[output]['name']}, "
|
||||||
|
|
||||||
|
returns = returns.removesuffix(', ')
|
||||||
|
|
||||||
|
functionType = "default"
|
||||||
|
if "type" in functions[function]:
|
||||||
|
functionType = functions[function]["type"]
|
||||||
|
|
||||||
|
|
||||||
|
html += f'<div class="card" style="margin-top: 50px;">'
|
||||||
|
html += f'<div class="card-body">'
|
||||||
|
html += f'<h4 class="card-title">{name}</h4>'
|
||||||
|
html += f'<h6 class="text-muted card-subtitle mb-2">{description}</h6>'
|
||||||
|
html += f'<h6 class="text-muted card-subtitle mb-2">Function type: {functionType.capitalize()}</h6>'
|
||||||
|
|
||||||
|
if functionType != "default":
|
||||||
|
html += f'<p class="card-text">Returns: {returns}</p>'
|
||||||
|
html += f'</div>'
|
||||||
|
html += f'</div>'
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Form
|
||||||
|
html += f'<form method="post" style="padding: 20px;" action="/plugin/{pluginName}/{function}">'
|
||||||
|
for param in params:
|
||||||
|
html += f'<div style="margin-bottom: 20px;">'
|
||||||
|
paramName = params[param]["name"]
|
||||||
|
paramType = params[param]["type"]
|
||||||
|
if paramType == "text":
|
||||||
|
html += f'<label for="{param}">{paramName}</label>'
|
||||||
|
html += f'<input class="form-control" type="text" name="{param}" />'
|
||||||
|
elif paramType == "longText":
|
||||||
|
html += f'<label for="{param}">{paramName}</label>'
|
||||||
|
html += f'<textarea class="form-control" name="{param}" rows="4" cols="50"></textarea>'
|
||||||
|
elif paramType == "number":
|
||||||
|
html += f'<label for="{param}">{paramName}</label>'
|
||||||
|
html += f'<input class="form-control" type="number" name="{param}" />'
|
||||||
|
elif paramType == "checkbox":
|
||||||
|
html += f'<div class="form-check"><input id="{param}" class="form-check-input" type="checkbox" name="{param}" /><label class="form-check-label" for="{param}">{paramName}</label></div>'
|
||||||
|
elif paramType == "address":
|
||||||
|
# render components/address.html
|
||||||
|
address = render_template('components/address.html', paramName=paramName, param=param)
|
||||||
|
html += address
|
||||||
|
elif paramType == "dns":
|
||||||
|
html += render_template('components/dns-input.html', paramName=paramName, param=param)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
html += f'</div>'
|
||||||
|
|
||||||
|
html += f'<button type="submit" class="btn btn-primary">Submit</button>'
|
||||||
|
html += f'</form>'
|
||||||
|
# For debugging
|
||||||
|
html += f'<p class="card-text">Returns: {returns}</p>'
|
||||||
|
html += f'</div>'
|
||||||
|
html += f'</div>'
|
||||||
|
|
||||||
|
|
||||||
|
return html
|
||||||
|
|
||||||
|
def plugin_output(outputs, returns):
|
||||||
|
|
||||||
|
html = ''
|
||||||
|
|
||||||
|
for returnOutput in returns:
|
||||||
|
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>'
|
||||||
|
for item in output:
|
||||||
|
html += f'<li>{item}</li>'
|
||||||
|
html += f'</ul>'
|
||||||
|
elif returns[returnOutput]["type"] == "text":
|
||||||
|
html += f'<p>{output}</p>'
|
||||||
|
elif returns[returnOutput]["type"] == "tx":
|
||||||
|
html += render_template('components/tx.html', tx=output)
|
||||||
|
elif returns[returnOutput]["type"] == "dns":
|
||||||
|
output = json.loads(output)
|
||||||
|
html += render_template('components/dns-output.html', dns=dns(output))
|
||||||
|
|
||||||
|
|
||||||
|
html += f'</div>'
|
||||||
|
html += f'</div>'
|
||||||
|
return html
|
||||||
|
|
||||||
|
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])
|
||||||
|
|
||||||
|
|
||||||
|
html += f'</div>'
|
||||||
|
html += f'</div>'
|
||||||
return html
|
return html
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
|
40
templates/components/address.html
Normal file
40
templates/components/address.html
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<div style="margin-top: 25px;">
|
||||||
|
<label class="form-label">{{paramName}}</label>
|
||||||
|
<input id="{{param}}" class="form-control" type="text" placeholder="Address or @domain" name="{{param}}" value="{{address}}" />
|
||||||
|
<span id="addressValid"></span>
|
||||||
|
<script>
|
||||||
|
function checkAddress(inputValue) {
|
||||||
|
// Make API request to "/checkaddress"
|
||||||
|
var apiUrl = '/checkaddress?address=' + encodeURIComponent(inputValue);
|
||||||
|
|
||||||
|
fetch(apiUrl)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
// Update the content of the span with the response data
|
||||||
|
var addressCheckSpan = document.getElementById('addressValid');
|
||||||
|
addressCheckSpan.textContent = data.result; // You can replace 'addressInfo' with the actual property you receive from the API
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error fetching data:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to handle input field blur event
|
||||||
|
function handleBlur() {
|
||||||
|
var inputField = document.getElementById('{{param}}');
|
||||||
|
var inputValue = inputField.value;
|
||||||
|
|
||||||
|
// Check if the input value is not empty
|
||||||
|
if (inputValue.trim() !== '') {
|
||||||
|
checkAddress(inputValue);
|
||||||
|
} else {
|
||||||
|
var addressCheckSpan = document.getElementById('addressValid');
|
||||||
|
addressCheckSpan.textContent = 'Invalid address';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a blur event listener to the input field
|
||||||
|
var inputField = document.getElementById('{{param}}');
|
||||||
|
inputField.addEventListener('blur', handleBlur);
|
||||||
|
</script>
|
||||||
|
</div>
|
8
templates/components/dashboard-plugin.html
Normal file
8
templates/components/dashboard-plugin.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}}</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
5
templates/components/dns-input.html
Normal file
5
templates/components/dns-input.html
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<h4>TODO DNS LATER</h4>
|
||||||
|
<p>For a temporary work around edit any domains DNS and before pressing save</p>
|
||||||
|
<p>Copy the text in the url after ?dns=</p>
|
||||||
|
<label for="{{param}}">{{paramName}}</label>
|
||||||
|
<input class="form-control" type="text" name="{{param}}" />
|
13
templates/components/dns-output.html
Normal file
13
templates/components/dns-output.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{dns | safe}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
4
templates/components/tx.html
Normal file
4
templates/components/tx.html
Normal file
@ -0,0 +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>
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
|
52
templates/import-wallet.html
Normal file
52
templates/import-wallet.html
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<!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>Import Wallet - 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/css/styles.min.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="bg-gradient-primary">
|
||||||
|
<div class="container">
|
||||||
|
<div class="card shadow-lg o-hidden border-0 my-5">
|
||||||
|
<div class="card-body p-0">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-5 d-none d-lg-flex">
|
||||||
|
<div class="flex-grow-1 bg-register-image" style="background: url("/assets/img/favicon.png") center / contain no-repeat;"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-7">
|
||||||
|
<div class="p-5">
|
||||||
|
<h1 class="text-center" style="color: rgb(255,0,0);">{{error}}</h1>
|
||||||
|
<div class="text-center">
|
||||||
|
<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="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>
|
||||||
|
<hr>
|
||||||
|
</form>
|
||||||
|
<div class="text-center"><a class="small" href="/login">Didn't mean to create a new wallet? Login!</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="/assets/js/script.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
@ -126,7 +126,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>{{plugins|safe}}
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
@ -37,7 +37,8 @@
|
|||||||
<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>
|
<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>
|
||||||
<hr>
|
<hr>
|
||||||
</form>
|
</form>
|
||||||
<div class="text-center"><a class="small" href="register">Create a wallet!</a></div>
|
<div class="text-center"><a class="small" href="register">Create a wallet</a></div>
|
||||||
|
<div class="text-center"><a class="small" href="import-wallet">Import an existing wallet</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
@ -68,7 +68,7 @@
|
|||||||
<h6 class="text-muted card-subtitle mb-2">Expires in {{expiry}} days</h6>
|
<h6 class="text-muted card-subtitle mb-2">Expires in {{expiry}} days</h6>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>{{plugins|safe}}
|
||||||
<div class="container-fluid" style="margin-top: 50px;">
|
<div class="container-fluid" style="margin-top: 50px;">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
|
79
templates/plugin-output.html
Normal file
79
templates/plugin-output.html
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html data-bs-theme="dark" lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||||
|
<title>{{name}} - 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/material-icons.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="/">
|
||||||
|
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
|
||||||
|
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
|
||||||
|
</a>
|
||||||
|
<hr class="sidebar-divider my-0">
|
||||||
|
<ul class="navbar-nav text-light" id="accordionSidebar">
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/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>
|
||||||
|
<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="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>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</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}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer class="sticky-footer" style="background: var(--bs-primary-text-emphasis);">
|
||||||
|
<div class="container my-auto">
|
||||||
|
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2024</span></div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div><a class="border rounded d-inline scroll-to-top" href="#page-top"><i class="fas fa-angle-up"></i></a>
|
||||||
|
</div>
|
||||||
|
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="/assets/js/script.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
81
templates/plugin.html
Normal file
81
templates/plugin.html
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html data-bs-theme="dark" lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||||
|
<title>{{name}} - 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/material-icons.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="/">
|
||||||
|
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
|
||||||
|
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
|
||||||
|
</a>
|
||||||
|
<hr class="sidebar-divider my-0">
|
||||||
|
<ul class="navbar-nav text-light" id="accordionSidebar">
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/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>
|
||||||
|
<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="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>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<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}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer class="sticky-footer" style="background: var(--bs-primary-text-emphasis);">
|
||||||
|
<div class="container my-auto">
|
||||||
|
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2024</span></div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div><a class="border rounded d-inline scroll-to-top" href="#page-top"><i class="fas fa-angle-up"></i></a>
|
||||||
|
</div>
|
||||||
|
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="/assets/js/script.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
80
templates/plugins.html
Normal file
80
templates/plugins.html
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html data-bs-theme="dark" lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||||
|
<title>Plugins - 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/material-icons.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="/">
|
||||||
|
<div class="sidebar-brand-icon"><img src="/assets/img/favicon.png" width="44"></div>
|
||||||
|
<div class="sidebar-brand-text mx-3"><span>FireWallet</span></div>
|
||||||
|
</a>
|
||||||
|
<hr class="sidebar-divider my-0">
|
||||||
|
<ul class="navbar-nav text-light" id="accordionSidebar">
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/tx"><i class="fas fa-table"></i><span>Transactions</span></a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/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>
|
||||||
|
<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="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>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h3 class="text-dark mb-1">Plugins</h3><ul class="list-group">
|
||||||
|
{{plugins | safe}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer class="sticky-footer" style="background: var(--bs-primary-text-emphasis);">
|
||||||
|
<div class="container my-auto">
|
||||||
|
<div class="text-center my-auto copyright"><span>Copyright © FireWallet 2024</span></div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div><a class="border rounded d-inline scroll-to-top" href="#page-top"><i class="fas fa-angle-up"></i></a>
|
||||||
|
</div>
|
||||||
|
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<script src="/assets/js/script.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,14 +27,14 @@
|
|||||||
<div class="p-5">
|
<div class="p-5">
|
||||||
<h1 class="text-center" style="color: rgb(255,0,0);">{{error}}</h1>
|
<h1 class="text-center" style="color: rgb(255,0,0);">{{error}}</h1>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h4 class="text-dark mb-4">Create an Account!</h4>
|
<h4 class="text-dark mb-4">Create a new wallet!</h4>
|
||||||
</div>
|
</div>
|
||||||
<form class="user" method="post">
|
<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" 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="row mb-3">
|
||||||
<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 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 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">Register Account</button>
|
</div><button class="btn btn-primary d-block btn-user w-100" type="submit">Create Wallet</button>
|
||||||
<hr>
|
<hr>
|
||||||
</form>
|
</form>
|
||||||
<div class="text-center"><a class="small" href="/login">Didn't mean to create a new wallet? Login!</a></div>
|
<div class="text-center"><a class="small" href="/login">Didn't mean to create a new wallet? Login!</a></div>
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
@ -68,7 +68,7 @@
|
|||||||
<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>
|
<h6 class="text-muted card-subtitle mb-2">Owner: {{owner}}</h6><a class="btn btn-primary" role="button" style="margin-right: 25px;" href="/manage/{{domain}}">Manage</a><a class="btn btn-primary" role="button" href="/auction/{{domain}}">Auction</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>{{plugins|safe}}
|
||||||
<div class="container-fluid" style="margin-top: 50px;">
|
<div class="container-fluid" style="margin-top: 50px;">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<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="/tx"><i class="fas fa-table"></i><span>Transactions</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="/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="/settings"><i class="material-icons">settings</i><span>Settings</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>
|
</ul>
|
||||||
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user