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"])