mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2024-11-19 09:54:21 +01:00
big bundle of changes.
* reorganize templates even more (and a small layout break) * rename wallets.hash and accounts.userhash to id * refactor /wallets so it's idempotent for each param combination * many small changes
This commit is contained in:
parent
1cee6dad42
commit
14dfa9ecc6
@ -1,13 +1,13 @@
|
||||
import lnurl
|
||||
import uuid
|
||||
import os
|
||||
import requests
|
||||
|
||||
from flask import Flask, jsonify, render_template, request
|
||||
from flask import Flask, jsonify, render_template, request, redirect, url_for
|
||||
|
||||
from . import bolt11
|
||||
from .db import Database
|
||||
from .helpers import encrypt
|
||||
from .settings import DATABASE_PATH, LNBITS_PATH, WALLET
|
||||
from .settings import DATABASE_PATH, LNBITS_PATH, WALLET, DEFAULT_USER_WALLET_NAME
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
@ -35,21 +35,24 @@ def home():
|
||||
|
||||
@app.route("/deletewallet")
|
||||
def deletewallet():
|
||||
theid = request.args.get("usr")
|
||||
thewal = request.args.get("wal")
|
||||
|
||||
with Database() as db:
|
||||
wallet_row = db.fetchone("SELECT * FROM wallets WHERE hash = ?", (thewal,))
|
||||
db.execute(
|
||||
"""
|
||||
UPDATE wallets AS w SET
|
||||
user = 'del:' || w.user,
|
||||
adminkey = 'del:' || w.adminkey,
|
||||
inkey = 'del:' || w.inkey
|
||||
WHERE id = ? AND user = ?
|
||||
""",
|
||||
(thewal, theid),
|
||||
)
|
||||
|
||||
if not wallet_row:
|
||||
return render_template("index.html")
|
||||
|
||||
db.execute("UPDATE wallets SET user = ? WHERE hash = ?", (f"del{wallet_row[4]}", wallet_row[0]))
|
||||
db.execute("UPDATE wallets SET adminkey = ? WHERE hash = ?", (f"del{wallet_row[5]}", wallet_row[0]))
|
||||
db.execute("UPDATE wallets SET inkey = ? WHERE hash = ?", (f"del{wallet_row[6]}", wallet_row[0]))
|
||||
|
||||
user_wallets = db.fetchall("SELECT * FROM wallets WHERE user = ?", (wallet_row[4],))
|
||||
if user_wallets:
|
||||
return render_template("deletewallet.html", theid=user_wallets[0][4], thewal=user_wallets[0][0])
|
||||
next_wallet = db.fetchone("SELECT hash FROM wallets WHERE user = ?", (theid,))
|
||||
if next_wallet:
|
||||
return redirect(url_for("wallet", usr=theid, wal=next_wallet[0]))
|
||||
|
||||
return render_template("index.html")
|
||||
|
||||
@ -60,13 +63,13 @@ def lnurlwallet():
|
||||
invoice = WALLET.create_invoice(withdraw_res.max_sats).json()
|
||||
payment_hash = invoice["payment_hash"]
|
||||
|
||||
rrr = requests.get(
|
||||
r = requests.get(
|
||||
withdraw_res.callback.base,
|
||||
params={**withdraw_res.callback.query_params, **{"k1": withdraw_res.k1, "pr": invoice["pay_req"]}},
|
||||
)
|
||||
dataaa = rrr.json()
|
||||
data = r.json()
|
||||
|
||||
if dataaa["status"] != "OK":
|
||||
if data["status"] != "OK":
|
||||
"""TODO: show some kind of error?"""
|
||||
return render_template("index.html")
|
||||
|
||||
@ -76,112 +79,104 @@ def lnurlwallet():
|
||||
data = r.json()
|
||||
|
||||
with Database() as db:
|
||||
adminkey = encrypt(payment_hash)[0:20]
|
||||
inkey = encrypt(adminkey)[0:20]
|
||||
thewal = encrypt(inkey)[0:20]
|
||||
theid = encrypt(thewal)[0:20]
|
||||
thenme = "Bitcoin LN Wallet"
|
||||
|
||||
db.execute("INSERT INTO accounts (userhash) VALUES (?)", (theid,))
|
||||
|
||||
adminkey = encrypt(theid)
|
||||
inkey = encrypt(adminkey)
|
||||
adminkey = uuid.uuid4().hex
|
||||
inkey = uuid.uuid4().hex
|
||||
thewal = uuid.uuid4().hex
|
||||
theid = uuid.uuid4().hex
|
||||
thenme = DEFAULT_USER_WALLET_NAME
|
||||
|
||||
db.execute("INSERT INTO accounts (id) VALUES (?)", (theid,))
|
||||
db.execute(
|
||||
"INSERT INTO wallets (hash, name, user, adminkey, inkey) VALUES (?, ?, ?, ?, ?)",
|
||||
"INSERT INTO wallets (id, name, user, adminkey, inkey) VALUES (?, ?, ?, ?, ?)",
|
||||
(thewal, thenme, theid, adminkey, inkey),
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"lnurlwallet.html",
|
||||
len=len("1"),
|
||||
walnme=thenme,
|
||||
walbal=withdraw_res.max_sats,
|
||||
theid=theid,
|
||||
thewal=thewal,
|
||||
adminkey=adminkey,
|
||||
inkey=inkey,
|
||||
)
|
||||
return redirect(url_for("wallet", usr=theid, wal=thewal))
|
||||
|
||||
|
||||
@app.route("/wallet")
|
||||
def wallet():
|
||||
theid = request.args.get("usr")
|
||||
thewal = request.args.get("wal")
|
||||
thenme = request.args.get("nme")
|
||||
usr = request.args.get("usr")
|
||||
wallet_id = request.args.get("wal")
|
||||
wallet_name = request.args.get("nme") or DEFAULT_USER_WALLET_NAME
|
||||
|
||||
if not thewal:
|
||||
return render_template("index.html")
|
||||
# just usr: return a the first user wallet or create one if none found
|
||||
# usr and wallet_id: return that wallet or create it if it doesn't exist
|
||||
# usr, wallet_id and wallet_name: same as above, but use the specified name
|
||||
# usr and wallet_name: generate a wallet_id and create
|
||||
# wallet_id and wallet_name: create a user, then move an existing wallet or create
|
||||
# just wallet_name: create a user, then generate a wallet_id and create
|
||||
# nothing: create everything
|
||||
|
||||
with Database() as db:
|
||||
user_exists = db.fetchone("SELECT * FROM accounts WHERE userhash = ?", (theid,))
|
||||
# ensure this user exists
|
||||
# -------------------------------
|
||||
|
||||
if not user_exists:
|
||||
# user does not exist: create an account
|
||||
# --------------------------------------
|
||||
|
||||
db.execute("INSERT INTO accounts (userhash) VALUES (?)", (theid,))
|
||||
|
||||
# user exists
|
||||
# -----------
|
||||
|
||||
user_wallets = db.fetchall("SELECT * FROM wallets WHERE user = ?", (theid,))
|
||||
|
||||
if user_wallets:
|
||||
|
||||
# user has wallets
|
||||
# ----------------
|
||||
|
||||
wallet_row = db.fetchone(
|
||||
"""
|
||||
SELECT
|
||||
(SELECT balance/1000 FROM balances WHERE wallet = wallets.hash),
|
||||
name,
|
||||
adminkey,
|
||||
inkey
|
||||
FROM wallets
|
||||
WHERE user = ? AND hash = ?
|
||||
""",
|
||||
(theid, thewal,),
|
||||
)
|
||||
|
||||
transactions = []
|
||||
|
||||
return render_template(
|
||||
"wallet.html",
|
||||
thearr=user_wallets,
|
||||
len=len(user_wallets),
|
||||
walnme=wallet_row[1],
|
||||
user=theid,
|
||||
walbal=wallet_row[0],
|
||||
theid=theid,
|
||||
thewal=thewal,
|
||||
transactions=transactions,
|
||||
adminkey=wallet_row[2],
|
||||
inkey=wallet_row[3],
|
||||
)
|
||||
|
||||
# user has no wallets
|
||||
# -------------------
|
||||
|
||||
adminkey = encrypt(theid)
|
||||
inkey = encrypt(adminkey)
|
||||
if not usr:
|
||||
usr = uuid.uuid4().hex
|
||||
return redirect(url_for("wallet", usr=usr, wal=wallet_id, nme=wallet_name))
|
||||
|
||||
db.execute(
|
||||
"INSERT INTO wallets (hash, name, user, adminkey, inkey) VALUES (?, ?, ?, ?, ?)",
|
||||
(thewal, thenme, theid, adminkey, inkey),
|
||||
"""
|
||||
INSERT INTO accounts (id) VALUES (?)
|
||||
ON CONFLICT (id) DO NOTHING
|
||||
""",
|
||||
(usr,),
|
||||
)
|
||||
|
||||
user_wallets = db.fetchall("SELECT * FROM wallets WHERE user = ?", (usr,))
|
||||
|
||||
if not wallet_id:
|
||||
# if not given, fetch the first wallet from this user or create
|
||||
# -------------------------------------------------------------
|
||||
if user_wallets:
|
||||
wallet_id = user_wallets[0]["id"]
|
||||
else:
|
||||
wallet_id = uuid.uuid4().hex
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO wallets (id, name, user, adminkey, inkey)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
""",
|
||||
(wallet_id, wallet_name, usr, uuid.uuid4().hex, uuid.uuid4().hex),
|
||||
)
|
||||
|
||||
return redirect(url_for("wallet", usr=usr, wal=wallet_id, nme=wallet_name))
|
||||
|
||||
# if wallet_id is given, try to move it to this user or create
|
||||
# ------------------------------------------------------------
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO wallets (id, name, user, adminkey, inkey)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON CONFLICT (id) DO UPDATE SET user = ?
|
||||
""",
|
||||
(wallet_id, wallet_name, usr, uuid.uuid4().hex, uuid.uuid4().hex, usr),
|
||||
)
|
||||
|
||||
# finally, get the wallet with balance and transactions
|
||||
# -----------------------------------------------------
|
||||
|
||||
wallet = db.fetchone(
|
||||
"""
|
||||
SELECT
|
||||
coalesce(
|
||||
(SELECT balance/1000 FROM balances WHERE wallet = wallets.id),
|
||||
0
|
||||
) AS balance,
|
||||
name,
|
||||
adminkey,
|
||||
inkey
|
||||
FROM wallets
|
||||
WHERE user = ? AND id = ?
|
||||
""",
|
||||
(usr, wallet_id),
|
||||
)
|
||||
|
||||
transactions = []
|
||||
|
||||
return render_template(
|
||||
"wallet.html",
|
||||
len=1,
|
||||
walnme=thenme,
|
||||
walbal=0,
|
||||
theid=theid,
|
||||
thewal=thewal,
|
||||
adminkey=adminkey,
|
||||
inkey=inkey,
|
||||
transactions=[],
|
||||
"wallet.html", user_wallets=user_wallets, wallet=wallet, user=usr, transactions=transactions,
|
||||
)
|
||||
|
||||
|
||||
@ -205,12 +200,12 @@ def api_invoices():
|
||||
return jsonify({"ERROR": "NO MEMO"}), 400
|
||||
|
||||
with Database() as db:
|
||||
wallet_row = db.fetchone(
|
||||
"SELECT hash FROM wallets WHERE inkey = ? OR adminkey = ?",
|
||||
wallet = db.fetchone(
|
||||
"SELECT id FROM wallets WHERE inkey = ? OR adminkey = ?",
|
||||
(request.headers["Grpc-Metadata-macaroon"], request.headers["Grpc-Metadata-macaroon"],),
|
||||
)
|
||||
|
||||
if not wallet_row:
|
||||
if not wallet:
|
||||
return jsonify({"ERROR": "NO KEY"}), 200
|
||||
|
||||
r = WALLET.create_invoice(postedjson["value"], postedjson["memo"])
|
||||
@ -218,10 +213,11 @@ def api_invoices():
|
||||
|
||||
pay_req = data["pay_req"]
|
||||
payment_hash = data["payment_hash"]
|
||||
amount_msat = int(postedjson["value"]) * 1000
|
||||
|
||||
db.execute(
|
||||
"INSERT INTO apipayments (payhash, amount, wallet, pending, memo) VALUES (?, ?, ?, true, ?)",
|
||||
(payment_hash, int(postedjson["value"]) * 1000, wallet_row[0], postedjson["memo"],),
|
||||
(payment_hash, amount_msat, wallet["id"], postedjson["memo"],),
|
||||
)
|
||||
|
||||
return jsonify({"pay_req": pay_req, "payment_hash": payment_hash}), 200
|
||||
@ -238,39 +234,11 @@ def api_transactions():
|
||||
return jsonify({"ERROR": "NO PAY REQ"}), 200
|
||||
|
||||
with Database() as db:
|
||||
wallet_row = db.fetchone(
|
||||
"SELECT hash FROM wallets WHERE adminkey = ?", (request.headers["Grpc-Metadata-macaroon"],)
|
||||
)
|
||||
wallet = db.fetchone("SELECT id FROM wallets WHERE adminkey = ?", (request.headers["Grpc-Metadata-macaroon"],))
|
||||
|
||||
if not wallet_row:
|
||||
if not wallet:
|
||||
return jsonify({"ERROR": "BAD AUTH"}), 200
|
||||
|
||||
# TODO: check this unused code
|
||||
# move sats calculation to a helper
|
||||
# ---------------------------------
|
||||
"""
|
||||
s = postedjson["payment_request"]
|
||||
result = re.search("lnbc(.*)1p", s)
|
||||
tempp = result.group(1)
|
||||
|
||||
alpha = ""
|
||||
num = ""
|
||||
|
||||
for i in range(len(tempp)):
|
||||
if tempp[i].isdigit():
|
||||
num = num + tempp[i]
|
||||
else:
|
||||
alpha += tempp[i]
|
||||
sats = ""
|
||||
if alpha == "n":
|
||||
sats = int(num) / 10
|
||||
elif alpha == "u":
|
||||
sats = int(num) * 100
|
||||
elif alpha == "m":
|
||||
sats = int(num) * 100000
|
||||
"""
|
||||
# ---------------------------------
|
||||
|
||||
# decode the invoice
|
||||
invoice = bolt11.decode(data["payment_request"])
|
||||
if invoice.amount_msat == 0:
|
||||
@ -283,13 +251,13 @@ def api_transactions():
|
||||
invoice.payment_hash,
|
||||
-int(invoice.amount_msat),
|
||||
-int(invoice.amount_msat * 0.01),
|
||||
wallet_row[0],
|
||||
wallet["id"],
|
||||
invoice.description,
|
||||
),
|
||||
)
|
||||
|
||||
# check balance
|
||||
balance = db.fetchone("SELECT balance/1000 FROM balances WHERE wallet = ?", (wallet_row[0],))[0]
|
||||
balance = db.fetchone("SELECT balance/1000 FROM balances WHERE wallet = ?", (wallet["id"],))[0]
|
||||
if balance < 0:
|
||||
return jsonify({"ERROR": "INSUFFICIENT BALANCE"}), 403
|
||||
|
||||
@ -321,24 +289,23 @@ def api_checkinvoice(payhash):
|
||||
return jsonify({"ERROR": "MUST BE JSON"}), 200
|
||||
|
||||
with Database() as db:
|
||||
payment_row = db.fetchone(
|
||||
payment = db.fetchone(
|
||||
"""
|
||||
SELECT pending FROM apipayments
|
||||
INNER JOIN wallets AS w ON apipayments.wallet = w.hash
|
||||
INNER JOIN wallets AS w ON apipayments.wallet = w.id
|
||||
WHERE payhash = ?
|
||||
AND (w.adminkey = ? OR w.inkey = ?)
|
||||
""",
|
||||
(payhash, request.headers["Grpc-Metadata-macaroon"], request.headers["Grpc-Metadata-macaroon"]),
|
||||
)
|
||||
|
||||
if not payment_row:
|
||||
if not payment:
|
||||
return jsonify({"ERROR": "NO INVOICE"}), 404
|
||||
|
||||
if not payment_row[0]: # pending
|
||||
if not payment["pending"]: # pending
|
||||
return jsonify({"PAID": "TRUE"}), 200
|
||||
|
||||
r = WALLET.get_invoice_status(payhash)
|
||||
|
||||
if not r.ok:
|
||||
return jsonify({"PAID": "FALSE"}), 400
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
CREATE TABLE IF NOT EXISTS accounts (
|
||||
userhash text PRIMARY KEY,
|
||||
id text PRIMARY KEY,
|
||||
email text,
|
||||
pass text
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wallets (
|
||||
hash text PRIMARY KEY,
|
||||
id text PRIMARY KEY,
|
||||
name text NOT NULL,
|
||||
user text NOT NULL,
|
||||
adminkey text NOT NULL,
|
||||
@ -21,9 +21,7 @@ CREATE TABLE IF NOT EXISTS apipayments (
|
||||
memo text
|
||||
);
|
||||
|
||||
DROP VIEW IF EXISTS balances;
|
||||
|
||||
CREATE VIEW balances AS
|
||||
CREATE VIEW IF NOT EXISTS balances AS
|
||||
SELECT wallet, coalesce(sum(s), 0) AS balance FROM (
|
||||
SELECT wallet, sum(amount) AS s -- incoming
|
||||
FROM apipayments
|
||||
|
@ -7,6 +7,7 @@ class Database:
|
||||
def __init__(self, db_path: str = DATABASE_PATH):
|
||||
self.path = db_path
|
||||
self.connection = sqlite3.connect(db_path)
|
||||
self.connection.row_factory = sqlite3.Row
|
||||
self.cursor = self.connection.cursor()
|
||||
|
||||
def __enter__(self):
|
||||
|
@ -1,5 +0,0 @@
|
||||
import hashlib
|
||||
|
||||
|
||||
def encrypt(string: str):
|
||||
return hashlib.sha256(string.encode()).hexdigest()
|
@ -14,3 +14,4 @@ WALLET = LntxbotWallet(
|
||||
|
||||
LNBITS_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||
DATABASE_PATH = os.getenv("DATABASE_PATH") or os.path.join(LNBITS_PATH, "data", "database.sqlite3")
|
||||
DEFAULT_USER_WALLET_NAME = os.getenv("DEFAULT_USER_WALLET_NAME") or "Bitcoin LN Wallet"
|
||||
|
@ -239,6 +239,61 @@
|
||||
></script>
|
||||
</head>
|
||||
<body class="skin-blue">
|
||||
{% block body %}{% endblock %}
|
||||
<div class="wrapper">
|
||||
<header class="main-header">
|
||||
<!-- Logo -->
|
||||
<a href="/" class="logo"><b>LN</b>bits</a>
|
||||
<!-- Header Navbar: style can be found in header.less -->
|
||||
<nav class="navbar navbar-static-top" role="navigation">
|
||||
<!-- Sidebar toggle button-->
|
||||
<a
|
||||
href="#"
|
||||
class="sidebar-toggle"
|
||||
data-toggle="offcanvas"
|
||||
role="button"
|
||||
>
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
</a>
|
||||
<div class="navbar-custom-menu">
|
||||
<ul class="nav navbar-nav">
|
||||
<!-- Messages: style can be found in dropdown.less-->
|
||||
<li class="dropdown messages-menu">
|
||||
{% block messages %}{% endblock %}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<!-- Left side column. contains the logo and sidebar -->
|
||||
<aside class="main-sidebar">
|
||||
<!-- sidebar: style can be found in sidebar.less -->
|
||||
<section class="sidebar">
|
||||
<!-- Sidebar user panel -->
|
||||
|
||||
<!-- /.search form -->
|
||||
<!-- sidebar menu: : style can be found in sidebar.less -->
|
||||
<ul class="sidebar-menu">
|
||||
<li class="header">MENU</li>
|
||||
{% block menuitems %}{% endblock %}
|
||||
</ul>
|
||||
</section>
|
||||
<!-- /.sidebar -->
|
||||
</aside>
|
||||
|
||||
{% block body %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<footer class="main-footer">
|
||||
<div class="pull-right hidden-xs">
|
||||
<b>BETA</b>
|
||||
</div>
|
||||
<strong
|
||||
>Learn more about LNbits
|
||||
<a href="https://github.com/arcbtc/FOSSAW"
|
||||
>https://github.com/arcbtc/lnbits</a
|
||||
></strong
|
||||
>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,146 +1,94 @@
|
||||
<!-- @format -->
|
||||
|
||||
{% extends "base.html" %} {% block body %}
|
||||
<div class="wrapper">
|
||||
<header class="main-header">
|
||||
<!-- Logo -->
|
||||
<a href="index.html" class="logo"><b>LN</b>bits</a>
|
||||
<!-- Header Navbar: style can be found in header.less -->
|
||||
<nav class="navbar navbar-static-top" role="navigation">
|
||||
<!-- Sidebar toggle button-->
|
||||
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
</a>
|
||||
<div class="navbar-custom-menu">
|
||||
<ul class="nav navbar-nav">
|
||||
<!-- Messages: style can be found in dropdown.less-->
|
||||
<li class="dropdown messages-menu"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<!-- Left side column. contains the logo and sidebar -->
|
||||
<aside class="main-sidebar">
|
||||
<!-- sidebar: style can be found in sidebar.less -->
|
||||
<section class="sidebar">
|
||||
<!-- Sidebar user panel -->
|
||||
|
||||
<!-- /.search form -->
|
||||
<!-- sidebar menu: : style can be found in sidebar.less -->
|
||||
<ul class="sidebar-menu">
|
||||
<li class="header">MAIN NAVIGATION</li>
|
||||
|
||||
<li>
|
||||
<a href="../documentation/index.html"
|
||||
><i class="fa fa-book"></i> Home</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<!-- /.sidebar -->
|
||||
</aside>
|
||||
|
||||
<!-- Right side column. Contains the navbar and content of the page -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<ol class="breadcrumb">
|
||||
<li>
|
||||
<a href="/index.html"><i class="fa fa-dashboard"></i> Home</a>
|
||||
</li>
|
||||
</ol>
|
||||
<br /><br />
|
||||
<div class="alert alert-danger alert-dismissable">
|
||||
<h4>
|
||||
Warning - Wallet is still in BETA and very, very #reckless, please be
|
||||
careful with your funds!
|
||||
</h4>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<!-- Default box -->
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<h1>
|
||||
<a href="index.html" class="logo"><b>LN</b>bits</a>
|
||||
<small>free and open-source lightning wallet</small>
|
||||
</h1>
|
||||
<p>
|
||||
LNbits is a simple, free and open-source lightning-network
|
||||
wallet for bits and bobs. You can run it on your own server, or
|
||||
use this one.
|
||||
<br /><br />
|
||||
The wallet can be used in a variety of ways, an instant wallet
|
||||
for LN demonstrations, a fallback wallet for the LNURL scheme,
|
||||
an accounts system to mitigate the risk of exposing applications
|
||||
to your full balance.
|
||||
<br /><br />
|
||||
The wallet can run on top of LND, lntxbot, paywall, opennode
|
||||
<br /><br />
|
||||
Please note that although one of the aims of this wallet is to
|
||||
mitigate exposure of all your funds, it’s still very BETA and
|
||||
may in fact do the opposite!
|
||||
<br />
|
||||
<a href="https://github.com/arcbtc/FOSSAW"
|
||||
>https://github.com/arcbtc/lnbits</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<!-- Default box -->
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<h1>
|
||||
<small>Make a wallet</small>
|
||||
</h1>
|
||||
<div class="form-group">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="walname"
|
||||
placeholder="Name your LNBits wallet"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
onclick="newwallet()"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- /.content -->
|
||||
</div>
|
||||
<!-- /.content-wrapper -->
|
||||
|
||||
<footer class="main-footer">
|
||||
<div class="pull-right hidden-xs">
|
||||
<b>BETA</b>
|
||||
{% extends "base.html" %} {% block menuitems %}
|
||||
<li>
|
||||
<a href="/"><i class="fa fa-book"></i> Home</a>
|
||||
</li>
|
||||
{% endblock %} {% block body %}
|
||||
<!-- Right side column. Contains the navbar and content of the page -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<ol class="breadcrumb">
|
||||
<li>
|
||||
<a href="/"><i class="fa fa-dashboard"></i> Home</a>
|
||||
</li>
|
||||
</ol>
|
||||
<br /><br />
|
||||
<div class="alert alert-danger alert-dismissable">
|
||||
<h4>
|
||||
Warning - Wallet is still in BETA and very, very #reckless, please be
|
||||
careful with your funds!
|
||||
</h4>
|
||||
</div>
|
||||
<strong
|
||||
>Learn more about LNbits
|
||||
<a href="https://github.com/arcbtc/FOSSAW"
|
||||
>https://github.com/arcbtc/lnbits</a
|
||||
></strong
|
||||
>
|
||||
</footer>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<!-- Default box -->
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<h1>
|
||||
<a href="index.html" class="logo"><b>LN</b>bits</a>
|
||||
<small>free and open-source lightning wallet</small>
|
||||
</h1>
|
||||
<p>
|
||||
LNbits is a simple, free and open-source lightning-network wallet
|
||||
for bits and bobs. You can run it on your own server, or use this
|
||||
one.
|
||||
<br /><br />
|
||||
The wallet can be used in a variety of ways, an instant wallet for
|
||||
LN demonstrations, a fallback wallet for the LNURL scheme, an
|
||||
accounts system to mitigate the risk of exposing applications to
|
||||
your full balance.
|
||||
<br /><br />
|
||||
The wallet can run on top of LND, lntxbot, paywall, opennode
|
||||
<br /><br />
|
||||
Please note that although one of the aims of this wallet is to
|
||||
mitigate exposure of all your funds, it’s still very BETA and may
|
||||
in fact do the opposite!
|
||||
<br />
|
||||
<a href="https://github.com/arcbtc/FOSSAW"
|
||||
>https://github.com/arcbtc/lnbits</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<!-- Default box -->
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<h1>
|
||||
<small>Make a wallet</small>
|
||||
</h1>
|
||||
<div class="form-group">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="walname"
|
||||
placeholder="Name your LNBits wallet"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary" onclick="newwallet()">
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- /.content -->
|
||||
</div>
|
||||
<!-- /.content-wrapper -->
|
||||
|
||||
<script>
|
||||
function makeid(length) {
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user