From c62678b3aaf259cf1def73e90b9d04ccd87dfb09 Mon Sep 17 00:00:00 2001 From: benarc <ben@arc.wales> Date: Thu, 3 Dec 2020 17:26:11 +0000 Subject: [PATCH] generated fresh addresses nicely --- Pipfile | 1 + lnbits/extensions/watchonly/crud.py | 18 +-- lnbits/extensions/watchonly/migrations.py | 3 +- lnbits/extensions/watchonly/models.py | 3 +- .../templates/watchonly/_api_docs.html | 2 +- .../watchonly/templates/watchonly/index.html | 109 ++++++++++++------ lnbits/extensions/watchonly/views_api.py | 18 +-- 7 files changed, 97 insertions(+), 57 deletions(-) diff --git a/Pipfile b/Pipfile index 6d125eebd..6909f2f23 100644 --- a/Pipfile +++ b/Pipfile @@ -24,6 +24,7 @@ quart-trio = "*" trio = "==0.16.0" hypercorn = {extras = ["trio"], version = "*"} sqlalchemy-aio = "*" +embit = "*" [dev-packages] black = "==20.8b1" diff --git a/lnbits/extensions/watchonly/crud.py b/lnbits/extensions/watchonly/crud.py index e46a17b25..af2d68073 100644 --- a/lnbits/extensions/watchonly/crud.py +++ b/lnbits/extensions/watchonly/crud.py @@ -57,7 +57,6 @@ async def get_address(address: str) -> Addresses: row = await db.fetchone("SELECT * FROM addresses WHERE address = ?", (address,)) return Addresses.from_row(row) if row else None - async def get_addresses(wallet_id: str) -> List[Addresses]: rows = await db.fetchall("SELECT * FROM addresses WHERE wallet = ?", (wallet_id,)) return [Addresses(**row) for row in rows] @@ -90,6 +89,7 @@ async def get_watch_wallet(wallet_id: str) -> Wallets: row = await db.fetchone("SELECT * FROM wallets WHERE id = ?", (wallet_id,)) return Wallets.from_row(row) if row else None + async def get_watch_wallets(user: str) -> List[Wallets]: rows = await db.fetchall("SELECT * FROM wallets WHERE user = ?", (user,)) return [Wallets(**row) for row in rows] @@ -108,24 +108,25 @@ async def delete_watch_wallet(wallet_id: str) -> None: ###############PAYMENTS########################## -async def create_payment(*, user: str, ex_key: str, description: str, amount: int) -> Payments: +async def create_payment(*, walletid: str, user: str, title: str, time: str, amount: int) -> Payments: - address = await get_fresh_address(ex_key) + address = await get_fresh_address(walletid) payment_id = urlsafe_short_hash() await db.execute( """ INSERT INTO payments ( - payment_id, + id, user, - ex_key, + title, + wallet, address, + time_to_pay, amount ) - VALUES (?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?, ?) """, - (payment_id, user, ex_key, address, amount), + (payment_id, user, title, walletid, address.address, time, amount), ) - payment_id = db.cursor.lastrowid return await get_payment(payment_id) @@ -136,6 +137,7 @@ async def get_payment(payment_id: str) -> Payments: async def get_payments(user: str) -> List[Payments]: rows = await db.fetchall("SELECT * FROM payments WHERE user IN ?", (user,)) + print(rows[0]) return [Payments.from_row(row) for row in rows] diff --git a/lnbits/extensions/watchonly/migrations.py b/lnbits/extensions/watchonly/migrations.py index 7c0c4e6dc..3ef13a0d5 100644 --- a/lnbits/extensions/watchonly/migrations.py +++ b/lnbits/extensions/watchonly/migrations.py @@ -30,7 +30,8 @@ async def m001_initial(db): CREATE TABLE IF NOT EXISTS payments ( id TEXT NOT NULL PRIMARY KEY, user TEXT, - masterpub TEXT NOT NULL, + title TEXT, + wallet TEXT NOT NULL, address TEXT NOT NULL, time_to_pay INTEGER NOT NULL, amount INTEGER NOT NULL, diff --git a/lnbits/extensions/watchonly/models.py b/lnbits/extensions/watchonly/models.py index fc3a726ee..d415cec69 100644 --- a/lnbits/extensions/watchonly/models.py +++ b/lnbits/extensions/watchonly/models.py @@ -16,7 +16,8 @@ class Wallets(NamedTuple): class Payments(NamedTuple): id: str user: str - ex_key: str + wallet: str + title: str address: str time_to_pay: str amount: int diff --git a/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html b/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html index 9b83e05a3..fd5dd4ac0 100644 --- a/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html +++ b/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html @@ -1,6 +1,6 @@ <q-card> <q-card-section> - <p>The WatchOnly extension uses https://mempool.block for blockchain data.<br /> + <p>The WatchOnly extension uses https://mempool.space for blockchain data.<br /> <small> Created by, <a href="https://github.com/benarc">Ben Arc</a></small > diff --git a/lnbits/extensions/watchonly/templates/watchonly/index.html b/lnbits/extensions/watchonly/templates/watchonly/index.html index c798e7f7a..19407efb5 100644 --- a/lnbits/extensions/watchonly/templates/watchonly/index.html +++ b/lnbits/extensions/watchonly/templates/watchonly/index.html @@ -89,7 +89,7 @@ size="xs" icon="toll" :color="($q.dark.isActive) ? 'grey-7' : 'grey-5'" - @click="formDialogPayment.show = true" + @click="formDialogPayment.show = true, formDialogPayment.data.walletid = props.row.id" > <q-tooltip> @@ -157,20 +157,20 @@ <q-icon name="search"></q-icon> </template> </q-input> -{% endraw %} + </div> </div> <q-table flat dense - :data="payLinks" + :data="paymentLinks" row-key="id" - :columns="PaylinksTable.columns" - :pagination.sync="PaylinksTable.pagination" + :columns="PaymentsTable.columns" + :pagination.sync="PaymentsTable.pagination" :filter="filter" > - {% raw %} + <template v-slot:header="props"> <q-tr :props="props"> <q-th auto-width></q-th> @@ -360,21 +360,21 @@ <h5 class="text-subtitle1 q-my-none">Addresses</h5> <q-separator></q-separator><br/> <p><strong>Current:</strong> - {{ Addresses.data[0].address }} + {{ currentaddress }} <q-btn flat dense size="ms" icon="visibility" type="a" - :href="mempool.endpoint + '/address/' + Addresses.data[0].address" + :href="mempool.endpoint + '/address/' + currentaddress" target="_blank" ></q-btn> </p> <q-responsive :ratio="1" class="q-mx-xl q-mb-md"> <qrcode - :value="Addresses.data[0].address" + :value="currentaddress" :options="{width: 800}" class="rounded-borders" ></qrcode> @@ -382,7 +382,7 @@ <p style="word-break: break-all;"> <q-scroll-area style="height: 200px; max-width: 100%;"> - <q-list bordered v-for="data in Addresses.data"> + <q-list bordered v-for="data in Addresses.data.slice().reverse()"> <q-item> <q-item-section>{{ data.address }}</q-item-section> <q-btn @@ -424,7 +424,10 @@ </style> <script> Vue.component(VueQrcode.name, VueQrcode) - + Vue.filter('reverse', function(value) { + // slice to make a copy of array, then reverse the copy + return value.slice().reverse(); +}); var locationPath = [ window.location.protocol, '//', @@ -440,6 +443,15 @@ ) return obj } + var mapPayment = function (obj) { + obj._data = _.clone(obj) + obj.date = Quasar.utils.date.formatDate( + new Date(obj.time * 1000), + 'YYYY-MM-DD HH:mm' + ) + return obj + } + new Vue({ el: '#vue', @@ -449,7 +461,8 @@ filter: '', checker: null, walletLinks: [], - current: {}, + paymentLinks: [], + currentaddress: "", Addresses: { show: false, data: null @@ -483,7 +496,7 @@ rowsPerPage: 10 } }, - PaylinksTable: { + PaymentsTable: { columns: [ {name: 'id', align: 'left', label: 'ID', field: 'id'}, { @@ -555,10 +568,12 @@ ) .then(function (response) { - self.walletLinks = response.data.map(function (obj) { self.Addresses.data = response.data + self.currentaddress = self.Addresses.data[self.Addresses.data.length - 1].address + console.log(self.currentaddress) + }) - }) + .catch(function (error) { LNbits.utils.notifyApiError(error) }) @@ -573,13 +588,12 @@ this.g.user.wallets[0].inkey ) .then(function (response) { - self.Addresses.show = false - getAddresses(walletID) + console.log(response.data) + self.Addresses.data = response.data + self.currentaddress = self.Addresses.data[self.Addresses.data.length - 1].address }) - .catch(function (error) { - LNbits.utils.notifyApiError(error) - }) + }, addressRedirect: function (address){ window.location.href = this.mempool.endpoint + "/address/" + address; @@ -645,11 +659,13 @@ } }, openQrCodeDialog: function (linkId) { + var self = this var getAddresses = this.getAddresses getAddresses(linkId) - this.current = linkId - this.Addresses.show = true + self.current = linkId + self.Addresses.show = true }, + openUpdateDialog: function (linkId) { var link = _.findWhere(this.walletLinks, {id: linkId}) this.formDialog.data = _.clone(link._data) @@ -665,22 +681,36 @@ this.createWalletLink(wallet, data) } }, - sendFormDataPayLink: function () { - var wallet = this.g.user.wallets[0] - var data = _.omit(this.formDialogPayLink.data, 'wallet') - data.wait_time = - data.wait_time * - { - seconds: 1, - minutes: 60, - hours: 3600 - }[this.formDialogPayLink.secondMultiplier] + getPayments: function () { + var self = this + LNbits.api + .request( + 'GET', + '/watchonly/api/v1/payment', + this.g.user.wallets[0].inkey + ) + .then(function (response) { + self.paymentLinks = response.data.map(function (obj) { + return mapPayment(obj) + }) + }) + .catch(function (error) { + LNbits.utils.notifyApiError(error) + }) + }, + sendFormDataPayment: function () { + var self = this + var wallet = self.g.user.wallets[0] + var data = self.formDialogPayment.data + data.amount = parseInt(data.amount) + data.time = parseInt(data.time) + console.log(data) if (data.id) { - this.updatePayLink(wallet, data) + this.updatePayment(wallet, data) } else { - this.createPayLink(wallet, data) + this.createPayment(wallet, data) } }, updatePayment: function (wallet, data) { @@ -695,7 +725,7 @@ self.payment = _.reject(self.payment, function (obj) { return obj.id === data.id }) - self.payment.push(mapWalletLink(response.data)) + self.payment.push(mapPayment(response.data)) self.formDialogPayLink.show = false }) .catch(function (error) { @@ -708,14 +738,15 @@ LNbits.api .request('POST', '/watchonly/api/v1/payment', wallet.inkey, data) .then(function (response) { - self.payment.push(mapWalletLink(response.data)) - self.formDialogPayLink.show = false - console.log(response.data[1][1]) + self.paymentLinks.push(mapPayment(response.data)) + self.formDialogPayment.show = false + console.log(response.data) }) .catch(function (error) { LNbits.utils.notifyApiError(error) }) }, + deletePayment: function (linkId) { var self = this var link = _.findWhere(this.payment, {id: linkId}) @@ -803,6 +834,8 @@ if (this.g.user.wallets.length) { var getWalletLinks = this.getWalletLinks getWalletLinks() + var getPayments = this.getPayments + getPayments() var getMempool = this.getMempool getMempool() diff --git a/lnbits/extensions/watchonly/views_api.py b/lnbits/extensions/watchonly/views_api.py index f06c11669..3f4b5b8dd 100644 --- a/lnbits/extensions/watchonly/views_api.py +++ b/lnbits/extensions/watchonly/views_api.py @@ -120,8 +120,10 @@ async def api_get_addresses(wallet_id): async def api_payments_retrieve(): try: + payments = await get_payments(g.wallet.user) + print(payments) return ( - jsonify(get_payments(g.wallet.user)), + jsonify(payments), HTTPStatus.OK, ) except: @@ -146,21 +148,21 @@ async def api_payment_retrieve(payment_id): @api_check_wallet_key("invoice") @api_validate_post_request( schema={ - "ex_key": {"type": "string", "empty": False, "required": True}, - "pub_key": {"type": "string", "empty": False, "required": True}, - "time_to_pay": {"type": "integer", "min": 1, "required": True}, + "walletid": {"type": "string", "empty": False, "required": True}, + "title": {"type": "string", "empty": False, "required": True}, + "time": {"type": "integer", "min": 1, "required": True}, "amount": {"type": "integer", "min": 1, "required": True}, } ) async def api_payment_create_or_update(payment_id=None): if not payment_id: - payment = await create_payment(g.wallet.user, g.data.ex_key, g.data.pub_key, g.data.amount) - return jsonify(get_payment(payment)), HTTPStatus.CREATED + payment = await create_payment(user = g.wallet.user, **g.data) + return jsonify(payment), HTTPStatus.CREATED else: - payment = await update_payment(payment_id, g.data) - return jsonify({payment}), HTTPStatus.OK + payment = await update_payment(user = g.wallet.user, **g.data) + return jsonify(payment), HTTPStatus.OK @watchonly_ext.route("/api/v1/payment/<payment_id>", methods=["DELETE"])