From 8c87e84b680473606ab59111d94ca1b2a1c11bd8 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Thu, 8 Sep 2022 16:37:02 +0300 Subject: [PATCH] feat: show address details on device --- lnbits/extensions/watchonly/crud.py | 6 ++- lnbits/extensions/watchonly/migrations.py | 7 +++ lnbits/extensions/watchonly/models.py | 2 + .../serial-signer/serial-signer.html | 51 ++++++++++--------- .../components/serial-signer/serial-signer.js | 34 +++++++++---- .../components/wallet-list/wallet-list.html | 35 ++++++++++--- .../components/wallet-list/wallet-list.js | 15 +++++- .../extensions/watchonly/static/js/index.js | 24 +++++++-- lnbits/extensions/watchonly/static/js/map.js | 1 + .../extensions/watchonly/static/js/utils.js | 1 + .../watchonly/templates/watchonly/index.html | 5 +- lnbits/extensions/watchonly/views_api.py | 3 +- 12 files changed, 131 insertions(+), 53 deletions(-) diff --git a/lnbits/extensions/watchonly/crud.py b/lnbits/extensions/watchonly/crud.py index 21fea6f0..de338b91 100644 --- a/lnbits/extensions/watchonly/crud.py +++ b/lnbits/extensions/watchonly/crud.py @@ -23,9 +23,10 @@ async def create_watch_wallet(w: WalletAccount) -> WalletAccount: type, address_no, balance, - network + network, + meta ) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( wallet_id, @@ -37,6 +38,7 @@ async def create_watch_wallet(w: WalletAccount) -> WalletAccount: w.address_no, w.balance, w.network, + w.meta, ), ) diff --git a/lnbits/extensions/watchonly/migrations.py b/lnbits/extensions/watchonly/migrations.py index 0c06b738..76f7f951 100644 --- a/lnbits/extensions/watchonly/migrations.py +++ b/lnbits/extensions/watchonly/migrations.py @@ -93,3 +93,10 @@ async def m006_drop_mempool_table(db): Mempool data is now part of `config` """ await db.execute("DROP TABLE watchonly.mempool;") + + +async def m007_add_wallet_meta_data(db): + """ + Add 'meta' for storing various metadata about the wallet + """ + await db.execute("ALTER TABLE watchonly.wallets ADD COLUMN meta TEXT DEFAULT '{}';") diff --git a/lnbits/extensions/watchonly/models.py b/lnbits/extensions/watchonly/models.py index 0c08780d..cedaa210 100644 --- a/lnbits/extensions/watchonly/models.py +++ b/lnbits/extensions/watchonly/models.py @@ -9,6 +9,7 @@ class CreateWallet(BaseModel): masterpub: str = Query("") title: str = Query("") network: str = "Mainnet" + meta: str = "{}" class WalletAccount(BaseModel): @@ -21,6 +22,7 @@ class WalletAccount(BaseModel): balance: int type: Optional[str] = "" network: str = "Mainnet" + meta: str = "{}" @classmethod def from_row(cls, row: Row) -> "WalletAccount": diff --git a/lnbits/extensions/watchonly/static/components/serial-signer/serial-signer.html b/lnbits/extensions/watchonly/static/components/serial-signer/serial-signer.html index 68b81980..b256ea60 100644 --- a/lnbits/extensions/watchonly/static/components/serial-signer/serial-signer.html +++ b/lnbits/extensions/watchonly/static/components/serial-signer/serial-signer.html @@ -170,6 +170,31 @@ type="password" label="Password" > + + + + + + +

- -
- - - - -
+ Enter new password (8 numbers/letters)
Master Pubkey:
- + +
+
+ +
+
+
+
XPub:
+
+ +
+
+
-
Last Address Index:
diff --git a/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js b/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js index d5ad5e32..d8df84e1 100644 --- a/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js +++ b/lnbits/extensions/watchonly/static/components/wallet-list/wallet-list.js @@ -118,9 +118,11 @@ async function walletList(path) { }, createWalletAccount: async function (data) { try { + const meta = {accountPath: this.accountPath} if (this.formDialog.useSerialPort) { const {xpub, fingerprint} = await this.fetchXpubFromHww() if (!xpub) return + meta.xpub = xpub const path = this.accountPath.substring(2) const outputType = this.formDialog.addressType.id if (outputType === 'sh') { @@ -129,6 +131,7 @@ async function walletList(path) { data.masterpub = `${outputType}([${fingerprint}/${path}]${xpub}/{0,1}/*)` } } + data.meta = JSON.stringify(meta) const response = await LNbits.api.request( 'POST', '/watchonly/api/v1/wallet', @@ -247,7 +250,7 @@ async function walletList(path) { const wallet = this.walletAccounts.find(w => w.id === walletId) || {} wallet.address_no = addressData.addressIndex - this.$emit('new-receive-address', addressData) + this.$emit('new-receive-address', {addressData, wallet}) }, showAddAccountDialog: function () { this.formDialog.show = true @@ -283,6 +286,16 @@ async function walletList(path) { const addressType = this.addressTypeOptions.find(t => t.id === value.id) || {} this.accountPath = addressType[`path${this.network}`] + }, + // todo: bad. base.js not present in custom components + copyText: function (text, message, position) { + var notify = this.$q.notify + Quasar.utils.copyToClipboard(text).then(function () { + notify({ + message: message || 'Copied to clipboard!', + position: position || 'bottom' + }) + }) } }, created: async function () { diff --git a/lnbits/extensions/watchonly/static/js/index.js b/lnbits/extensions/watchonly/static/js/index.js index 61255c50..45f2293b 100644 --- a/lnbits/extensions/watchonly/static/js/index.js +++ b/lnbits/extensions/watchonly/static/js/index.js @@ -172,10 +172,6 @@ const watchOnly = async () => { this.$refs.paymentRef.updateSignedPsbt(psbtBase64) }, - //################### SERIAL PORT ################### - - //################### HARDWARE WALLET ################### - //################### UTXOs ################### scanAllAddresses: async function () { await this.refreshAddresses() @@ -380,6 +376,26 @@ const watchOnly = async () => { showAddressDetails: function (addressData) { this.openQrCodeDialog(addressData) }, + showAddressDetailsWithConfirmation: function ({addressData, wallet}) { + this.showAddressDetails(addressData) + if (this.$refs.serialSigner.isConnected()) { + if (this.$refs.serialSigner.isAuthenticated()) { + if (wallet.meta?.accountPath) { + const branchIndex = addressData.isChange ? 1 : 0 + const path = + wallet.meta.accountPath + + `/${branchIndex}/${addressData.addressIndex}` + this.$refs.serialSigner.hwwShowAddress(path, addressData.address) + } + } else { + this.$q.notify({ + type: 'warning', + message: 'Please login in order to confirm address on device', + timeout: 10000 + }) + } + } + }, initUtxos: function (addresses) { if (!this.fetchedUtxos && addresses.length) { this.fetchedUtxos = true diff --git a/lnbits/extensions/watchonly/static/js/map.js b/lnbits/extensions/watchonly/static/js/map.js index ecc0b316..81093936 100644 --- a/lnbits/extensions/watchonly/static/js/map.js +++ b/lnbits/extensions/watchonly/static/js/map.js @@ -74,6 +74,7 @@ const mapWalletAccount = function (o) { 'YYYY-MM-DD HH:mm' ) : '', + meta: o.meta ? JSON.parse(o.meta) : null, label: o.title, expanded: false }) diff --git a/lnbits/extensions/watchonly/static/js/utils.js b/lnbits/extensions/watchonly/static/js/utils.js index 5e39a37f..c73dd9c0 100644 --- a/lnbits/extensions/watchonly/static/js/utils.js +++ b/lnbits/extensions/watchonly/static/js/utils.js @@ -3,6 +3,7 @@ const PSBT_BASE64_PREFIX = 'cHNidP8' const COMMAND_PING = '/ping' const COMMAND_PASSWORD = '/password' const COMMAND_PASSWORD_CLEAR = '/password-clear' +const COMMAND_ADDRESS = '/address' const COMMAND_SEND_PSBT = '/psbt' const COMMAND_SIGN_PSBT = '/sign' const COMMAND_HELP = '/help' diff --git a/lnbits/extensions/watchonly/templates/watchonly/index.html b/lnbits/extensions/watchonly/templates/watchonly/index.html index 1a564489..f9ffc298 100644 --- a/lnbits/extensions/watchonly/templates/watchonly/index.html +++ b/lnbits/extensions/watchonly/templates/watchonly/index.html @@ -27,7 +27,7 @@ :addresses="addresses" :serial-signer-ref="$refs.serialSigner" @accounts-update="updateAccounts" - @new-receive-address="showAddressDetails" + @new-receive-address="showAddressDetailsWithConfirmation" > @@ -148,7 +148,8 @@
- {{SITE_TITLE}} Onchain Wallet (watch-only) Extension (v0.100) + {{SITE_TITLE}} Onchain Wallet (watch-only) Extension + (v0.100)
diff --git a/lnbits/extensions/watchonly/views_api.py b/lnbits/extensions/watchonly/views_api.py index 1a4b93ed..3bfa4707 100644 --- a/lnbits/extensions/watchonly/views_api.py +++ b/lnbits/extensions/watchonly/views_api.py @@ -93,6 +93,7 @@ async def api_wallet_create_or_update( address_no=-1, # so fresh address on empty wallet can get address with index 0 balance=0, network=network["name"], + meta=data.meta, ) wallets = await get_watch_wallets(w.wallet.user, network["name"]) @@ -137,7 +138,7 @@ async def api_wallet_delete(wallet_id, w: WalletTypeInfo = Depends(require_admin await delete_watch_wallet(wallet_id) await delete_addresses_for_wallet(wallet_id) - raise HTTPException(status_code=HTTPStatus.NO_CONTENT) + return "", HTTPStatus.NO_CONTENT #############################ADDRESSES##########################