Browse Source

chore: minor fixes

fee_issues
Eneko Illarramendi 5 years ago
parent
commit
fb7dfb3a32
  1. 2
      lnbits/core/crud.py
  2. 51
      lnbits/core/templates/core/_api_docs.html
  3. 61
      lnbits/core/templates/core/wallet.html
  4. 26
      lnbits/static/css/base.css
  5. 8
      lnbits/static/js/base.js
  6. 18
      lnbits/static/scss/base.scss
  7. 265
      lnbits/templates/wallet.html

2
lnbits/core/crud.py

@ -1,8 +1,8 @@
from uuid import uuid4
from typing import List, Optional
from lnbits.db import open_db
from lnbits.settings import DEFAULT_WALLET_NAME, FEE_RESERVE
from typing import List, Optional
from .models import User, Wallet, Payment

51
lnbits/core/templates/core/_api_docs.html

@ -0,0 +1,51 @@
<q-expansion-item
group="extras"
icon="swap_vertical_circle"
label="API info"
:content-inset-level="0.5"
>
<q-expansion-item group="api" dense expand-separator label="Create an invoice (incoming)">
<q-card>
<q-card-section>
<code><span class="text-light-green">POST</span> /api/v1/payments</code>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"Grpc-Metadata-macaroon": "<i>{{ wallet.inkey }}</i>"}</code><br />
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
<code>{"out": false, "amount": &lt;int&gt;, "memo": &lt;string&gt;}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Returns 201 CREATED (application/json)</h5>
<code>{"checking_id": &lt;string&gt;, "payment_request": &lt;string&gt;}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code>curl -X POST http://127.0.0.1:5000/api/v1/payments -d '{"out": false, "amount": &lt;int&gt;, "memo": &lt;string&gt;}' -H "Grpc-Metadata-macaroon: <i>{{ wallet.inkey }}</i>" -H "Content-type: application/json"</code>
</q-card-section>
</q-card>
</q-expansion-item>
<q-expansion-item group="api" dense expand-separator label="Pay an invoice (outgoing)">
<q-card>
<q-card-section>
<code><span class="text-light-green">POST</span> /api/v1/payments</code>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"Grpc-Metadata-macaroon": "{{ wallet.adminkey }}"}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
<code>{"out": true, "bolt11": &lt;string&gt;}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Returns 201 CREATED (application/json)</h5>
<code>{"checking_id": &lt;string&gt;}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code>curl -X POST http://127.0.0.1:5000/api/v1/payments -d '{"out": true, "bolt11": &lt;string&gt;}' -H "Grpc-Metadata-macaroon: {{ wallet.adminkey }}"</i> -H "Content-type: application/json"</code>
</q-card-section>
</q-card>
</q-expansion-item>
<q-expansion-item group="api" dense expand-separator label="Check an invoice (incoming or outgoing)"
class="q-mb-md">
<q-card>
<q-card-section>
<code><span class="text-light-blue">GET</span> /api/v1/payments/&lt;checking_id&gt;</code>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"Grpc-Metadata-macaroon": "{{ wallet.inkey }}"}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Returns 200 OK (application/json)</h5>
<code>{"paid": &lt;bool&gt;}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code>curl -X GET http://127.0.0.1:5000/api/v1/payments/&lt;checking_id&gt; -H "Grpc-Metadata-macaroon: {{ wallet.inkey }}"</i> -H "Content-type: application/json"</code>
</q-card-section>
</q-card>
</q-expansion-item>
</q-expansion-item>

61
lnbits/core/templates/core/wallet.html

@ -108,6 +108,7 @@
<div class="col-12 col-md-4 col-lg-5 q-gutter-y-md">
<q-card>
<q-card-section>
<h6 class="text-subtitle1 q-mt-none q-mb-sm">LNbits wallet</h6>
<strong>Wallet name: </strong><em>{{ wallet.name }}</em><br>
<strong>Wallet ID: </strong><em>{{ wallet.id }}</em><br>
<strong>Admin key: </strong><em>{{ wallet.adminkey }}</em><br>
@ -116,57 +117,7 @@
<q-card-section class="q-pa-none">
<q-separator></q-separator>
<q-list>
<q-expansion-item
group="extras"
icon="swap_vertical_circle"
label="API info"
:content-inset-level="0.5"
>
<q-expansion-item group="api" dense expand-separator label="Create an invoice (incoming)">
<q-card>
<q-card-section>
<code><span class="text-light-green">POST</span> /api/v1/payments</code>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"Grpc-Metadata-macaroon": "<i>{{ wallet.inkey }}</i>"}</code><br />
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
<code>{"out": false, "amount": &lt;int&gt;, "memo": &lt;string&gt;}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Returns 201 CREATED (application/json)</h5>
<code>{"checking_id": &lt;string&gt;, "payment_request": &lt;string&gt;}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code>curl -X POST http://127.0.0.1:5000/api/v1/payments -d '{"out": false, "amount": &lt;int&gt;, "memo": &lt;string&gt;}' -H "Grpc-Metadata-macaroon: <i>{{ wallet.inkey }}</i>" -H "Content-type: application/json"</code>
</q-card-section>
</q-card>
</q-expansion-item>
<q-expansion-item group="api" dense expand-separator label="Pay an invoice (outgoing)">
<q-card>
<q-card-section>
<code><span class="text-light-green">POST</span> /api/v1/payments</code>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"Grpc-Metadata-macaroon": "{{ wallet.adminkey }}"}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
<code>{"out": true, "bolt11": &lt;string&gt;}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Returns 201 CREATED (application/json)</h5>
<code>{"checking_id": &lt;string&gt;}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code>curl -X POST http://127.0.0.1:5000/api/v1/payments -d '{"out": true, "bolt11": &lt;string&gt;}' -H "Grpc-Metadata-macaroon: {{ wallet.adminkey }}"</i> -H "Content-type: application/json"</code>
</q-card-section>
</q-card>
</q-expansion-item>
<q-expansion-item group="api" dense expand-separator label="Check an invoice (incoming or outgoing)"
class="q-mb-md">
<q-card>
<q-card-section>
<code><span class="text-light-blue">GET</span> /api/v1/payments/&lt;checking_id&gt;</code>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<code>{"Grpc-Metadata-macaroon": "{{ wallet.inkey }}"}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Returns 200 OK (application/json)</h5>
<code>{"paid": &lt;bool&gt;}</code>
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code>curl -X GET http://127.0.0.1:5000/api/v1/payments/&lt;checking_id&gt; -H "Grpc-Metadata-macaroon: {{ wallet.inkey }}"</i> -H "Content-type: application/json"</code>
</q-card-section>
</q-card>
</q-expansion-item>
</q-expansion-item>
{% include "core/_api_docs.html" %}
<q-separator></q-separator>
<q-expansion-item
group="extras"
@ -188,14 +139,14 @@
</div>
<q-dialog v-model="receive.show" position="top" @hide="closeReceiveDialog">
<q-card class="q-pa-lg q-mt-xl" style="width: 500px">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form v-if="!receive.paymentReq" class="q-gutter-md">
<q-input filled dense
v-model.number="receive.data.amount"
type="number"
label="Amount *"></q-input>
<q-input filled dense
v-model="receive.data.memo"
v-model.trim="receive.data.memo"
label="Memo"
placeholder="LNbits invoice"></q-input>
<div v-if="receive.status == 'pending'" class="row justify-between">
@ -226,11 +177,11 @@
</q-dialog>
<q-dialog v-model="send.show" position="top" @hide="closeSendDialog">
<q-card class="q-pa-lg q-mt-xl" style="width: 500px">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<div v-if="!send.invoice">
<q-form v-if="!sendCamera.show" class="q-gutter-md">
<q-input filled dense
v-model="send.data.bolt11"
v-model.trim="send.data.bolt11"
type="textarea"
label="Paste an invoice *"
>

26
lnbits/static/css/base.css

@ -20,17 +20,21 @@
body.body--dark .q-field--error .q-field__messages {
color: yellow !important; }
.lnbits__q-table__icon-td {
padding-left: 5px !important; }
.lnbits-drawer__q-list .q-item {
padding-top: 5px !important;
padding-bottom: 5px !important;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px; }
.lnbits-drawer__q-list .q-item.q-item--active {
color: inherit;
font-weight: bold; }
.lnbits-drawer__q-list .q-item {
padding-top: 5px !important;
padding-bottom: 5px !important;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px; }
.lnbits-drawer__q-list .q-item.q-item--active {
color: inherit;
font-weight: bold; }
.q-table--dense th:first-child, .q-table--dense td:first-child,
.q-table--dense .q-table__bottom {
padding-left: 6px !important; }
.q-table--dense th:last-child, .q-table--dense td:last-child,
.q-table--dense .q-table__bottom {
padding-right: 6px !important; }
video {
border-radius: 3px; }

8
lnbits/static/js/base.js

@ -57,6 +57,12 @@ var LNbits = {
}).sort(function (a, b) {
return a.name.localeCompare(b.name);
});
obj.walletOptions = obj.wallets.map(function (obj) {
return {
label: [obj.name, ' (', obj.id , ')'].join(''),
value: obj.id
};
});
return obj;
},
wallet: function (data) {
@ -158,7 +164,7 @@ var windowMixin = {
copyText: function (text, message) {
var notify = this.$q.notify;
Quasar.utils.copyToClipboard(text).then(function () {
notify({message: 'Copied to clipboard!'});
notify({message: message || 'Copied to clipboard!'});
});
}
},

18
lnbits/static/scss/base.scss

@ -36,10 +36,6 @@ body.body--dark .q-field--error {
}
}
.lnbits__q-table__icon-td {
padding-left: 5px !important;
}
.lnbits-drawer__q-list .q-item {
padding-top: 5px !important;
padding-bottom: 5px !important;
@ -52,6 +48,20 @@ body.body--dark .q-field--error {
}
}
.q-table--dense {
th:first-child,
td:first-child,
.q-table__bottom {
padding-left: 6px !important;
}
th:last-child,
td:last-child,
.q-table__bottom {
padding-right: 6px !important;
}
}
// QR video
video {

265
lnbits/templates/wallet.html

@ -1,265 +0,0 @@
<!-- @format -->
{% extends "legacy.html" %} {% block messages %}
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-bell-o"></i>
<span class="label label-danger">!</span>
</a>
<ul class="dropdown-menu">
<li class="header"><b>Instant wallet, bookmark to save</b></li>
<li></li>
</ul>
{% endblock %}
{% block menuitems %}
<li class="active treeview">
<a href="#">
<i class="fa fa-bitcoin"></i> <span>Wallets</span>
<i class="fa fa-angle-left pull-right"></i>
</a>
<ul class="treeview-menu">
{% for w in user_wallets %}
<li>
<a href="{{ url_for('wallet') }}?wal={{ w.id }}&usr={{ w.user }}"><i class="fa fa-bolt"></i> {{ w.name }}</a>
</li>
{% endfor %}
<li><a onclick="sidebarmake()">Add a wallet +</a></li>
<div id="sidebarmake"></div>
</ul>
</li>
<li class="treeview">
<a href="#">
<i class="fa fa-th"></i> <span>Extensions</span>
<i class="fa fa-angle-left pull-right"></i>
</a>
<ul class="treeview-menu">
{% for extension in EXTENSIONS %}
{% if extension.code in user_ext %}
<li>
<a href="{{ url_for(extension.code + '.index') }}?usr={{ user }}"><i class="fa fa-plus"></i> {{ extension.name }}</a>
</li>
{% endif %}
{% endfor %}
<li>
<a href="{{ url_for('core.extensions') }}?usr={{ user }}">Manager</a></li>
</ul>
</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">
<h1>
Wallet
<small
>Control panel
<div id="wonga"></div
></small>
</h1>
<ol class="breadcrumb">
<li>
<a href="#"><i class="fa fa-dashboard"></i> Home</a>
</li>
<li class="active">Wallets</li>
<li href="wallet?wal={{ wallet.id }}" class="active">
{{ wallet.name }}
</li>
</ol>
<br /><br />
<div class="row">
<div class="col-md-6">
<div class="alert alert-danger alert-dismissable">
<h4>
Wallet in BETA, use with caution.
</h4>
</div>
</div></div>
</section>
<!-- Main content -->
<section class="content">
<!-- Small boxes (Stat box) -->
<div class="row">
<div class="col-md-6">
<!-- small box -->
<div class="small-box bg-aqua">
<div class="inner">
<h3><b id="walletsats"></b></h3>
<h3>{{ wallet.name }}</h3>
</div>
<div class="icon">
<i class="ion ion-flash"></i>
</div>
</div>
</div>
</div>
<!-- ./col -->
<!-- /.row -->
<div class="row">
<div class="col-sm-3">
<button
onclick="sendfundsinput()"
class="btn btn-block btn-primary btn-lg"
data-toggle="modal"
data-target=".sends"
>
Send
</button>
</div>
<div class="col-sm-3">
<button
onclick="receive()"
class="btn btn-block btn-primary btn-lg"
data-toggle="modal"
data-target=".receives"
>
Receive
</button>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div id="receive"></div>
<div id="sendfunds"></div>
</div>
</div>
<br/>
<div class="row">
<div class="col-md-6">
<div class="box">
<div class="box-header">
<h3 class="box-title">Transactions <small style="padding-left:30px;cursor: pointer;" onclick="exportbut()"><i>(Export to CSV)</i></small></h3>
</div>
<!-- /.box-header -->
<div class="box-body no-padding">
<table id="pagnation" class="table table-bswearing anchorordered table-striped">
<tr>
<th>Memo</th>
<th style="width: 20%">date</th>
<th style="width: 20%">amount</th>
</tr>
<tbody id="transactions"></tbody>
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
</div>
<div id="satschart"></div>
<div class="row">
<div class="col-md-6">
<div class="box box-solid">
<div class="box-header with-border"></div>
<!-- /.box-header -->
<div class="box-body">
<div class="box-group" id="accordion">
<!-- we are adding the .panel class so bootstrap.js collapse plugin detects it -->
<div class="panel box box-primary">
<div class="box-header with-border">
<h4 class="box-title">
<a
data-toggle="collapse"
data-parent="#accordion"
href="#collapseThree"
class="collapsed"
aria-expanded="false"
>
Wallet "{{ wallet.name }}" API info
</a>
</h4>
</div>
<div
id="collapseThree"
class="panel-collapse collapse"
aria-expanded="false"
>
<div class="box-body" style="word-wrap: break-word;">
<b>Admin key: </b><i>{{ wallet.adminkey }}</i><br />
<b>Invoice/Read key: </b><i>{{ wallet.inkey }}</i><br />
Generate an invoice:<br /><code>POST /api/v1/invoices</code
><br />Header
<code
>{"Grpc-Metadata-macaroon": "<i>{{ wallet.inkey }}</i
>"}</code
><br />
Body <code>{"value": "200","memo": "beer"} </code><br />
Returns
<code>{"pay_req": string,"pay_id": string} </code><br />
*payment will not register in the wallet until the "check
invoice" endpoint is used<br /><br />
Check invoice:<br />
Check an invoice:<br /><code
>GET /api/v1/invoice/*payment_hash*</code
><br />Header
<code
>{"Grpc-Metadata-macaroon": "<i>{{ wallet.inkey }}</i
>"}</code
><br />
Returns
<code>{"PAID": "TRUE"}/{"PAID": "FALSE"} </code><br />
*if using LNTXBOT return will hang until paid<br /><br />
</div>
</div>
</div>
<div class="panel box box-danger">
<div class="box-header with-border">
<h4 class="box-title">
<a
data-toggle="collapse"
data-parent="#accordion"
href="#collapseTwo"
class="collapsed"
aria-expanded="false"
>
Delete wallet
</a>
</h4>
</div>
<div
id="collapseTwo"
class="panel-collapse collapse"
aria-expanded="false"
>
<div class="box-body">
This whole wallet will be deleted, the funds will be
UNRECOVERABLE <br /><br /><button
class="btn btn-danger"
onclick="deletewallet()"
>
Delete wallet
</button>
</div>
</div>
</div>
</div>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
</div>
<!-- /.content -->
</section>
<script>
window.user = {{ user | megajson | safe }}
window.user_wallets = {{ user_wallets | megajson | safe }}
window.wallet = {{ wallet | megajson | safe }}
window.transactions = {{ transactions | megajson | safe }}
document.getElementById("walletsats").innerHTML = Math.round({{ wallet.balance }}) + " sats";
</script>
</div>
{% endblock %}
Loading…
Cancel
Save