From c5755ac5878e60d33c4b3cfde8c63b2c82b86855 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Mon, 25 Jul 2022 10:50:12 +0300 Subject: [PATCH] refactor: extract `wallet-list` component --- .../components/wallet-config/wallet-config.js | 2 +- .../components/wallet-list/wallet-list.html | 189 ++++++++++++++++ .../components/wallet-list/wallet-list.js | 184 ++++++++++++++++ .../extensions/watchonly/static/js/index.js | 174 +++------------ .../extensions/watchonly/static/js/tables.js | 33 +-- .../extensions/watchonly/static/js/utils.js | 4 +- .../watchonly/templates/watchonly/index.html | 201 ++---------------- 7 files changed, 422 insertions(+), 365 deletions(-) create mode 100644 lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.html create mode 100644 lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js diff --git a/lnbits/extensions/watchonly/static/components/wallet-config/wallet-config.js b/lnbits/extensions/watchonly/static/components/wallet-config/wallet-config.js index c822736d..3bd3fbf7 100644 --- a/lnbits/extensions/watchonly/static/components/wallet-config/wallet-config.js +++ b/lnbits/extensions/watchonly/static/components/wallet-config/wallet-config.js @@ -41,7 +41,7 @@ async function walletConfig(path) { } }, created: async function () { - await this.getConfig() + await this.getConfig() } }) } diff --git a/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.html b/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.html new file mode 100644 index 00000000..44055f61 --- /dev/null +++ b/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.html @@ -0,0 +1,189 @@ +
+ + +
+
+ Add Wallet Account + +
+ +
+
+ + + +
+
+ + + + +
+
+ + + + + + + + +
+ Add Watch-Only Account + Cancel +
+
+
+
+ +
\ No newline at end of file diff --git a/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js b/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js new file mode 100644 index 00000000..83383a71 --- /dev/null +++ b/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js @@ -0,0 +1,184 @@ +async function walletList(path) { + const template = await loadTemplateAsync(path) + Vue.component('wallet-list', { + name: 'wallet-list', + template, + + props: ['adminkey', 'inkey', 'sats-denominated', 'addresses'], + data: function () { + return { + walletAccounts: [], + address: {}, + formDialog: { + show: false, + data: {} + }, + filter: '', + walletsTable: { + columns: [ + { + name: 'new', + align: 'left', + label: '' + }, + { + name: 'title', + align: 'left', + label: 'Title', + field: 'title' + }, + { + name: 'amount', + align: 'left', + label: 'Amount' + }, + { + name: 'type', + align: 'left', + label: 'Type', + field: 'type' + }, + {name: 'id', align: 'left', label: 'ID', field: 'id'} + ], + pagination: { + rowsPerPage: 10 + }, + filter: '' + } + } + }, + + methods: { + satBtc(val, showUnit = true) { + return satOrBtc(val, showUnit, this['sats_denominated']) + }, + + addWalletAccount: async function () { + const data = _.omit(this.formDialog.data, 'wallet') + await this.createWalletAccount(data) + }, + createWalletAccount: async function (data) { + try { + const response = await LNbits.api.request( + 'POST', + '/watchonly/api/v1/wallet', + this.adminkey, + data + ) + this.walletAccounts.push(mapWalletAccount(response.data)) + this.formDialog.show = false + + await this.refreshWalletAccounts() + } catch (error) { + LNbits.utils.notifyApiError(error) + } + }, + deleteWalletAccount: function (walletAccountId) { + LNbits.utils + .confirmDialog( + 'Are you sure you want to delete this watch only wallet?' + ) + .onOk(async () => { + try { + await LNbits.api.request( + 'DELETE', + '/watchonly/api/v1/wallet/' + walletAccountId, + this.adminkey + ) + this.walletAccounts = _.reject(this.walletAccounts, function ( + obj + ) { + return obj.id === walletAccountId + }) + await this.refreshWalletAccounts() + + if ( + this.payment.changeWallet && + this.payment.changeWallet.id === walletAccountId + ) { + this.payment.changeWallet = this.walletAccounts[0] + this.selectChangeAddress(this.payment.changeWallet) + } + await this.scanAddressWithAmount() + } catch (error) { + this.$q.notify({ + type: 'warning', + message: + 'Error while deleting wallet account. Please try again.', + timeout: 10000 + }) + } + }) + }, + + getWatchOnlyWallets: async function () { + try { + const {data} = await LNbits.api.request( + 'GET', + '/watchonly/api/v1/wallet', + this.inkey + ) + return data + } catch (error) { + this.$q.notify({ + type: 'warning', + message: 'Failed to fetch wallets.', + timeout: 10000 + }) + LNbits.utils.notifyApiError(error) + } + return [] + }, + refreshWalletAccounts: async function () { + const wallets = await this.getWatchOnlyWallets() + this.walletAccounts = wallets.map(w => mapWalletAccount(w)) + this.$emit('accounts-update', this.walletAccounts) + }, + getAmmountForWallet: function (walletId) { + const amount = this.addresses + .filter(a => a.wallet === walletId) + .reduce((t, a) => t + a.amount || 0, 0) + return this.satBtc(amount) + }, + closeFormDialog: function () { + this.formDialog.data = { + is_unique: false + } + }, + getAccountDescription: function (accountType) { + return getAccountDescription(accountType) + }, + openGetFreshAddressDialog: async function (walletId) { + const {data} = await LNbits.api.request( + 'GET', + `/watchonly/api/v1/address/${walletId}`, + this.inkey + ) + const addressData = mapAddressesData(data) + + addressData.note = `Shared on ${currentDateTime()}` + const lastAcctiveAddress = + this.addresses + .filter( + a => + a.wallet === addressData.wallet && !a.isChange && a.hasActivity + ) + .pop() || {} + addressData.gapLimitExceeded = + !addressData.isChange && + addressData.addressIndex > + lastAcctiveAddress.addressIndex + DEFAULT_RECEIVE_GAP_LIMIT + + const wallet = this.walletAccounts.find(w => w.id === walletId) || {} + wallet.address_no = addressData.addressIndex + this.$emit('new-receive-address', addressData) + this.$emit('accounts-update', this.walletAccounts) + } + }, + created: async function () { + if (this.inkey) { + await this.refreshWalletAccounts() + } + } + }) +} diff --git a/lnbits/extensions/watchonly/static/js/index.js b/lnbits/extensions/watchonly/static/js/index.js index a57d59e3..1c7425f5 100644 --- a/lnbits/extensions/watchonly/static/js/index.js +++ b/lnbits/extensions/watchonly/static/js/index.js @@ -2,6 +2,7 @@ const watchOnly = async () => { Vue.component(VueQrcode.name, VueQrcode) await walletConfig('static/components/wallet-config/wallet-config.html') + await walletList('static/components/wallet-list/wallet-list.html') Vue.filter('reverse', function (value) { // slice to make a copy of array, then reverse the copy @@ -14,7 +15,7 @@ const watchOnly = async () => { data: function () { return { DUST_LIMIT: 546, - filter: '', + filter: '', // todo: remove? scan: { scanning: false, @@ -32,7 +33,7 @@ const watchOnly = async () => { receive_gap_limit: 20, change_gap_limit: 5 }, - DEFAULT_RECEIVE_GAP_LIMIT: 20, + show: false }, @@ -63,17 +64,14 @@ const watchOnly = async () => { psbtSent: false }, - formDialog: { - show: false, - data: {} - }, - qrCodeDialog: { show: false, data: null }, ...tables, - ...tableData + ...tableData, + + walletAccounts: [] } }, @@ -81,74 +79,6 @@ const watchOnly = async () => { //################### CONFIG ################### //################### WALLETS ################### - getWalletName: function (walletId) { - const wallet = this.walletAccounts.find(wl => wl.id === walletId) - return wallet ? wallet.title : 'unknown' - }, - addWalletAccount: async function () { - const wallet = this.g.user.wallets[0] - const data = _.omit(this.formDialog.data, 'wallet') - await this.createWalletAccount(wallet, data) - }, - createWalletAccount: async function (wallet, data) { - try { - const response = await LNbits.api.request( - 'POST', - '/watchonly/api/v1/wallet', - wallet.adminkey, - data - ) - this.walletAccounts.push(mapWalletAccount(response.data)) - this.formDialog.show = false - - await this.refreshWalletAccounts() - await this.refreshAddresses() - - if (!this.payment.changeWallett) { - this.payment.changeWallet = this.walletAccounts[0] - this.selectChangeAddress(this.payment.changeWallet) - } - } catch (error) { - LNbits.utils.notifyApiError(error) - } - }, - deleteWalletAccount: function (walletAccountId) { - LNbits.utils - .confirmDialog( - 'Are you sure you want to delete this watch only wallet?' - ) - .onOk(async () => { - try { - await LNbits.api.request( - 'DELETE', - '/watchonly/api/v1/wallet/' + walletAccountId, - this.g.user.wallets[0].adminkey - ) - this.walletAccounts = _.reject(this.walletAccounts, function ( - obj - ) { - return obj.id === walletAccountId - }) - await this.refreshWalletAccounts() - await this.refreshAddresses() - if ( - this.payment.changeWallet && - this.payment.changeWallet.id === walletAccountId - ) { - this.payment.changeWallet = this.walletAccounts[0] - this.selectChangeAddress(this.payment.changeWallet) - } - await this.scanAddressWithAmount() - } catch (error) { - this.$q.notify({ - type: 'warning', - message: - 'Error while deleting wallet account. Please try again.', - timeout: 10000 - }) - } - }) - }, getAddressesForWallet: async function (walletId) { try { const {data} = await LNbits.api.request( @@ -167,41 +97,17 @@ const watchOnly = async () => { } return [] }, - getWatchOnlyWallets: async function () { - try { - const {data} = await LNbits.api.request( - 'GET', - '/watchonly/api/v1/wallet', - this.g.user.wallets[0].inkey - ) - return data - } catch (error) { - this.$q.notify({ - type: 'warning', - message: 'Failed to fetch wallets.', - timeout: 10000 - }) - LNbits.utils.notifyApiError(error) - } - return [] + getWalletName: function (walletId) { + const wallet = this.walletAccounts.find(wl => wl.id === walletId) + return wallet ? wallet.title : 'unknown' }, - refreshWalletAccounts: async function () { - const wallets = await this.getWatchOnlyWallets() - this.walletAccounts = wallets.map(w => mapWalletAccount(w)) - }, - getAmmountForWallet: function (walletId) { - const amount = this.addresses.data - .filter(a => a.wallet === walletId) - .reduce((t, a) => t + a.amount || 0, 0) - return this.satBtc(amount) - }, - //################### ADDRESSES ################### refreshAddresses: async function () { - const wallets = await this.getWatchOnlyWallets() + // const wallets = await this.getWatchOnlyWallets() todo: revisit + // const wallets = this.addresses.data = [] - for (const {id, type} of wallets) { + for (const {id, type} of this.walletAccounts) { const newAddresses = await this.getAddressesForWallet(id) const uniqueAddresses = newAddresses.filter( newAddr => @@ -218,8 +124,7 @@ const watchOnly = async () => { a.gapLimitExceeded = !a.isChange && a.addressIndex > - lastAcctiveAddress.addressIndex + - this.config.DEFAULT_RECEIVE_GAP_LIMIT + lastAcctiveAddress.addressIndex + DEFAULT_RECEIVE_GAP_LIMIT }) this.addresses.data.push(...uniqueAddresses) } @@ -295,33 +200,6 @@ const watchOnly = async () => { ) return addresses }, - openGetFreshAddressDialog: async function (walletId) { - const {data} = await LNbits.api.request( - 'GET', - `/watchonly/api/v1/address/${walletId}`, - this.g.user.wallets[0].inkey - ) - const addressData = mapAddressesData(data) - - addressData.note = `Shared on ${currentDateTime()}` - const lastAcctiveAddress = - this.addresses.data - .filter( - a => - a.wallet === addressData.wallet && !a.isChange && a.hasActivity - ) - .pop() || {} - addressData.gapLimitExceeded = - !addressData.isChange && - addressData.addressIndex > - lastAcctiveAddress.addressIndex + - this.config.DEFAULT_RECEIVE_GAP_LIMIT - - this.openQrCodeDialog(addressData) - const wallet = this.walletAccounts.find(w => w.id === walletId) || {} - wallet.address_no = addressData.addressIndex - await this.refreshAddresses() - }, //################### ADDRESS HISTORY ################### addressHistoryFromTxs: function (addressData, txs) { @@ -1158,11 +1036,7 @@ const watchOnly = async () => { }, //################### OTHER ################### - closeFormDialog: function () { - this.formDialog.data = { - is_unique: false - } - }, + openQrCodeDialog: function (addressData) { this.currentAddress = addressData this.addresses.note = addressData.note || '' @@ -1176,13 +1050,27 @@ const watchOnly = async () => { satBtc(val, showUnit = true) { return satOrBtc(val, showUnit, this.config.data.sats_denominated) }, - getAccountDescription: function (accountType) { - return getAccountDescription(accountType) + updateAccounts: async function (accounts) { + this.walletAccounts = accounts + await this.refreshAddresses() + + if (this.payment.changeWallet) { + const changeAccount = this.walletAccounts.find( + w => w.id === this.payment.changeWallet.id + ) + // change account deleted + if (!changeAccount) { + this.payment.changeWallet = this.walletAccounts[0] + this.selectChangeAddress(this.payment.changeWallet) + } + } + }, + handleNewReceiveAddress: function (addressData) { + this.openQrCodeDialog(addressData) } }, created: async function () { if (this.g.user.wallets.length) { - await this.refreshWalletAccounts() await this.refreshAddresses() await this.scanAddressWithAmount() } diff --git a/lnbits/extensions/watchonly/static/js/tables.js b/lnbits/extensions/watchonly/static/js/tables.js index e03a2c1a..298760c9 100644 --- a/lnbits/extensions/watchonly/static/js/tables.js +++ b/lnbits/extensions/watchonly/static/js/tables.js @@ -1,35 +1,4 @@ const tables = { - walletsTable: { - columns: [ - { - name: 'new', - align: 'left', - label: '' - }, - { - name: 'title', - align: 'left', - label: 'Title', - field: 'title' - }, - { - name: 'amount', - align: 'left', - label: 'Amount' - }, - { - name: 'type', - align: 'left', - label: 'Type', - field: 'type' - }, - {name: 'id', align: 'left', label: 'ID', field: 'id'} - ], - pagination: { - rowsPerPage: 10 - }, - filter: '' - }, utxosTable: { columns: [ { @@ -225,7 +194,7 @@ const tables = { } const tableData = { - walletAccounts: [], + // walletAccounts: [], // todo: remove? addresses: { show: false, data: [], diff --git a/lnbits/extensions/watchonly/static/js/utils.js b/lnbits/extensions/watchonly/static/js/utils.js index 0dbdee56..d9559cf3 100644 --- a/lnbits/extensions/watchonly/static/js/utils.js +++ b/lnbits/extensions/watchonly/static/js/utils.js @@ -8,6 +8,8 @@ const COMMAND_WIPE = '/wipe' const COMMAND_SEED = '/seed' const COMMAND_RESTORE = '/restore' +const DEFAULT_RECEIVE_GAP_LIMIT = 20 + const blockTimeToDate = blockTime => blockTime ? moment(blockTime * 1000).format('LLL') : '' @@ -158,7 +160,7 @@ function loadTemplateAsync(path) { if (this.readyState == 4) { if (this.status == 200) resolve(this.responseText) - if (this.status == 404) resolve('Page not found.') + if (this.status == 404) resolve(`
Page not found: ${path}
`) } } diff --git a/lnbits/extensions/watchonly/templates/watchonly/index.html b/lnbits/extensions/watchonly/templates/watchonly/index.html index 7e3d8500..e80ae01e 100644 --- a/lnbits/extensions/watchonly/templates/watchonly/index.html +++ b/lnbits/extensions/watchonly/templates/watchonly/index.html @@ -7,157 +7,19 @@ :config="config" :adminkey="g.user.wallets[0].adminkey" > + + + {% raw %} - - - -
-
- Add Wallet Account - -
- -
-
- - - -
-
- - - - -
-
- + +
@@ -1403,44 +1265,6 @@
- - - - - - - -
- Add Watch-Only Account - Cancel -
-
-
-
- {% raw %} @@ -1648,5 +1472,6 @@ + {% endblock %}