lnbits-legend/lnbits/extensions/watchonly/crud.py

246 lines
6.9 KiB
Python
Raw Normal View History

import json
2021-10-14 11:45:30 +01:00
from typing import List, Optional
2021-10-18 10:58:09 +01:00
from lnbits.helpers import urlsafe_short_hash
from . import db
WatchOnly Extension - add Serial Port communication (#839) * feat: add `Share PSBT` button with options * feat: add basic communication via the serial port * chore: code format * feat: send data to and from serial port * fix: port disconnect * feat: handle psbt extract * feat: show signed transaction details * fix: handle Connect/Disconnect failure state * feat:small UI improvements * feat: broadcast transaction (partial solution) * feat: integrate psbt response from HWW * feat: login and send commands to HWW * feat: ui improvements * feat: ui/ux improvements * feat: more small UI impreovemsnts * feat: simplify UI * feat: add `help` command * feat: add wipe command * feet: add `seed` command * feat: add `restore` command * feat: always show PSBT input text (for outside PSBTs) * feat: show spinner while signing tx * feat: hide panels after transaction is broadcast * feat: basic use of custom components * refactor: move components one folder up * refactor: extract wallet-config * refactor: extract `wallet-list` component * refactor: clean-up * chore: code format html component files * refactor: extract address-list component * refactor: extract `history` component * refactor: extract `utxo-list` component * feat: UI/UX improvements * feat: partial payment redesign * refactor: rename `fee` to `fee-rate` * refactor: rename component * refactor: extract `send-to` component * refactor: payment: first migration * fix: init `sendToList` * fix: change address * fix: change address and `Select All` coins * feat: show custom fees & two way binding for addresses * fix: scanAddressesWithAmount * fix: max amount * fix: coin selection mode * chore: code clean-up * feat: shuffle the UI * fix: change amount * feat: update tx size in real time * fix: coin selection * fix: show erro messages * fix: psbt generation * refactor: move serial port logic * refactor: payment component * refactor: code clean-up; use `slot` for `serial-signer` * feat: toggle serial port * feat: add Disconnect command * feat: prompt for `Connect` and `Login` before signing * refactor: send psbt to device * feat: extract signed transaction * refactor: code clean-up * feat: show auth green icon * chore: code clean-up * feat: show console * feat: allow `Connect` from dropdown menu * fix: stop if serial port cannot be open * feat: confirm outputs and fee * feat: add cancel command * fix: add `sats-denominated` for confirmations * feat: wait for HWW to authenticate, then open dialog * feat: share PSBT as text * refactor: extract `refreshAddresses` * feat: small UI improvements * feat: add default `Mainnet` network * feat: fix mempool endpint * feat: propagate config update only when explicitly updated * feat: add network for wallet accounts * fix: stop scanning when network changed * chore: code clean-up * chore: code clean-up * feat: show hardware device Xpub option * fix: handle failed to parse psbt * feat: add accounts using the HWW * fix: testnet is in the bip32 derivation path * feat: add spinner while wallet account is created * fix: check network and masterpub for duplicate accounts * feat: integrate transaction broadcast * feat: add password confirmation for `Wipe` and `Restore` * fix: fingerprint is not unique per account (it is the fingerprint of the master) * chore: code clean-up, remove `masterpub_fingerprint` * fix: account name diplay * chore: code format * fix: memppol links * fix: shortcut buttons * fix: note update * chore: code format * chore: clean-up rebase left overs * chore: clean-up * feat: less technical labels for addresses * feat: add serial port config params * fix: address type selection * chore: drop `mempool` table * fix: change & fee value * fix: handle no input signed scenario * fix: sat/btc unit * fix: small UI stuff * doc: update the readme * Update README.md
2022-08-09 05:00:09 -04:00
from .helpers import derive_address
from .models import Address, Config, WalletAccount
2021-10-14 11:45:30 +01:00
##########################WALLETS####################
2022-10-21 15:49:17 +03:00
async def create_watch_wallet(user: str, w: WalletAccount) -> WalletAccount:
2021-10-14 11:45:30 +01:00
wallet_id = urlsafe_short_hash()
await db.execute(
"""
INSERT INTO watchonly.wallets (
id,
"user",
masterpub,
fingerprint,
2021-10-14 11:45:30 +01:00
title,
type,
2021-10-14 11:45:30 +01:00
address_no,
WatchOnly Extension - add Serial Port communication (#839) * feat: add `Share PSBT` button with options * feat: add basic communication via the serial port * chore: code format * feat: send data to and from serial port * fix: port disconnect * feat: handle psbt extract * feat: show signed transaction details * fix: handle Connect/Disconnect failure state * feat:small UI improvements * feat: broadcast transaction (partial solution) * feat: integrate psbt response from HWW * feat: login and send commands to HWW * feat: ui improvements * feat: ui/ux improvements * feat: more small UI impreovemsnts * feat: simplify UI * feat: add `help` command * feat: add wipe command * feet: add `seed` command * feat: add `restore` command * feat: always show PSBT input text (for outside PSBTs) * feat: show spinner while signing tx * feat: hide panels after transaction is broadcast * feat: basic use of custom components * refactor: move components one folder up * refactor: extract wallet-config * refactor: extract `wallet-list` component * refactor: clean-up * chore: code format html component files * refactor: extract address-list component * refactor: extract `history` component * refactor: extract `utxo-list` component * feat: UI/UX improvements * feat: partial payment redesign * refactor: rename `fee` to `fee-rate` * refactor: rename component * refactor: extract `send-to` component * refactor: payment: first migration * fix: init `sendToList` * fix: change address * fix: change address and `Select All` coins * feat: show custom fees & two way binding for addresses * fix: scanAddressesWithAmount * fix: max amount * fix: coin selection mode * chore: code clean-up * feat: shuffle the UI * fix: change amount * feat: update tx size in real time * fix: coin selection * fix: show erro messages * fix: psbt generation * refactor: move serial port logic * refactor: payment component * refactor: code clean-up; use `slot` for `serial-signer` * feat: toggle serial port * feat: add Disconnect command * feat: prompt for `Connect` and `Login` before signing * refactor: send psbt to device * feat: extract signed transaction * refactor: code clean-up * feat: show auth green icon * chore: code clean-up * feat: show console * feat: allow `Connect` from dropdown menu * fix: stop if serial port cannot be open * feat: confirm outputs and fee * feat: add cancel command * fix: add `sats-denominated` for confirmations * feat: wait for HWW to authenticate, then open dialog * feat: share PSBT as text * refactor: extract `refreshAddresses` * feat: small UI improvements * feat: add default `Mainnet` network * feat: fix mempool endpint * feat: propagate config update only when explicitly updated * feat: add network for wallet accounts * fix: stop scanning when network changed * chore: code clean-up * chore: code clean-up * feat: show hardware device Xpub option * fix: handle failed to parse psbt * feat: add accounts using the HWW * fix: testnet is in the bip32 derivation path * feat: add spinner while wallet account is created * fix: check network and masterpub for duplicate accounts * feat: integrate transaction broadcast * feat: add password confirmation for `Wipe` and `Restore` * fix: fingerprint is not unique per account (it is the fingerprint of the master) * chore: code clean-up, remove `masterpub_fingerprint` * fix: account name diplay * chore: code format * fix: memppol links * fix: shortcut buttons * fix: note update * chore: code format * chore: clean-up rebase left overs * chore: clean-up * feat: less technical labels for addresses * feat: add serial port config params * fix: address type selection * chore: drop `mempool` table * fix: change & fee value * fix: handle no input signed scenario * fix: sat/btc unit * fix: small UI stuff * doc: update the readme * Update README.md
2022-08-09 05:00:09 -04:00
balance,
2022-09-08 16:37:02 +03:00
network,
meta
2021-10-14 11:45:30 +01:00
)
2022-09-08 16:37:02 +03:00
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2021-10-14 11:45:30 +01:00
""",
(
wallet_id,
2022-10-21 15:49:17 +03:00
user,
w.masterpub,
w.fingerprint,
w.title,
w.type,
w.address_no,
w.balance,
WatchOnly Extension - add Serial Port communication (#839) * feat: add `Share PSBT` button with options * feat: add basic communication via the serial port * chore: code format * feat: send data to and from serial port * fix: port disconnect * feat: handle psbt extract * feat: show signed transaction details * fix: handle Connect/Disconnect failure state * feat:small UI improvements * feat: broadcast transaction (partial solution) * feat: integrate psbt response from HWW * feat: login and send commands to HWW * feat: ui improvements * feat: ui/ux improvements * feat: more small UI impreovemsnts * feat: simplify UI * feat: add `help` command * feat: add wipe command * feet: add `seed` command * feat: add `restore` command * feat: always show PSBT input text (for outside PSBTs) * feat: show spinner while signing tx * feat: hide panels after transaction is broadcast * feat: basic use of custom components * refactor: move components one folder up * refactor: extract wallet-config * refactor: extract `wallet-list` component * refactor: clean-up * chore: code format html component files * refactor: extract address-list component * refactor: extract `history` component * refactor: extract `utxo-list` component * feat: UI/UX improvements * feat: partial payment redesign * refactor: rename `fee` to `fee-rate` * refactor: rename component * refactor: extract `send-to` component * refactor: payment: first migration * fix: init `sendToList` * fix: change address * fix: change address and `Select All` coins * feat: show custom fees & two way binding for addresses * fix: scanAddressesWithAmount * fix: max amount * fix: coin selection mode * chore: code clean-up * feat: shuffle the UI * fix: change amount * feat: update tx size in real time * fix: coin selection * fix: show erro messages * fix: psbt generation * refactor: move serial port logic * refactor: payment component * refactor: code clean-up; use `slot` for `serial-signer` * feat: toggle serial port * feat: add Disconnect command * feat: prompt for `Connect` and `Login` before signing * refactor: send psbt to device * feat: extract signed transaction * refactor: code clean-up * feat: show auth green icon * chore: code clean-up * feat: show console * feat: allow `Connect` from dropdown menu * fix: stop if serial port cannot be open * feat: confirm outputs and fee * feat: add cancel command * fix: add `sats-denominated` for confirmations * feat: wait for HWW to authenticate, then open dialog * feat: share PSBT as text * refactor: extract `refreshAddresses` * feat: small UI improvements * feat: add default `Mainnet` network * feat: fix mempool endpint * feat: propagate config update only when explicitly updated * feat: add network for wallet accounts * fix: stop scanning when network changed * chore: code clean-up * chore: code clean-up * feat: show hardware device Xpub option * fix: handle failed to parse psbt * feat: add accounts using the HWW * fix: testnet is in the bip32 derivation path * feat: add spinner while wallet account is created * fix: check network and masterpub for duplicate accounts * feat: integrate transaction broadcast * feat: add password confirmation for `Wipe` and `Restore` * fix: fingerprint is not unique per account (it is the fingerprint of the master) * chore: code clean-up, remove `masterpub_fingerprint` * fix: account name diplay * chore: code format * fix: memppol links * fix: shortcut buttons * fix: note update * chore: code format * chore: clean-up rebase left overs * chore: clean-up * feat: less technical labels for addresses * feat: add serial port config params * fix: address type selection * chore: drop `mempool` table * fix: change & fee value * fix: handle no input signed scenario * fix: sat/btc unit * fix: small UI stuff * doc: update the readme * Update README.md
2022-08-09 05:00:09 -04:00
w.network,
2022-09-08 16:37:02 +03:00
w.meta,
),
2021-10-14 11:45:30 +01:00
)
return await get_watch_wallet(wallet_id)
async def get_watch_wallet(wallet_id: str) -> Optional[WalletAccount]:
2021-10-14 11:45:30 +01:00
row = await db.fetchone(
"SELECT * FROM watchonly.wallets WHERE id = ?", (wallet_id,)
)
return WalletAccount.from_row(row) if row else None
2021-10-14 11:45:30 +01:00
WatchOnly Extension - add Serial Port communication (#839) * feat: add `Share PSBT` button with options * feat: add basic communication via the serial port * chore: code format * feat: send data to and from serial port * fix: port disconnect * feat: handle psbt extract * feat: show signed transaction details * fix: handle Connect/Disconnect failure state * feat:small UI improvements * feat: broadcast transaction (partial solution) * feat: integrate psbt response from HWW * feat: login and send commands to HWW * feat: ui improvements * feat: ui/ux improvements * feat: more small UI impreovemsnts * feat: simplify UI * feat: add `help` command * feat: add wipe command * feet: add `seed` command * feat: add `restore` command * feat: always show PSBT input text (for outside PSBTs) * feat: show spinner while signing tx * feat: hide panels after transaction is broadcast * feat: basic use of custom components * refactor: move components one folder up * refactor: extract wallet-config * refactor: extract `wallet-list` component * refactor: clean-up * chore: code format html component files * refactor: extract address-list component * refactor: extract `history` component * refactor: extract `utxo-list` component * feat: UI/UX improvements * feat: partial payment redesign * refactor: rename `fee` to `fee-rate` * refactor: rename component * refactor: extract `send-to` component * refactor: payment: first migration * fix: init `sendToList` * fix: change address * fix: change address and `Select All` coins * feat: show custom fees & two way binding for addresses * fix: scanAddressesWithAmount * fix: max amount * fix: coin selection mode * chore: code clean-up * feat: shuffle the UI * fix: change amount * feat: update tx size in real time * fix: coin selection * fix: show erro messages * fix: psbt generation * refactor: move serial port logic * refactor: payment component * refactor: code clean-up; use `slot` for `serial-signer` * feat: toggle serial port * feat: add Disconnect command * feat: prompt for `Connect` and `Login` before signing * refactor: send psbt to device * feat: extract signed transaction * refactor: code clean-up * feat: show auth green icon * chore: code clean-up * feat: show console * feat: allow `Connect` from dropdown menu * fix: stop if serial port cannot be open * feat: confirm outputs and fee * feat: add cancel command * fix: add `sats-denominated` for confirmations * feat: wait for HWW to authenticate, then open dialog * feat: share PSBT as text * refactor: extract `refreshAddresses` * feat: small UI improvements * feat: add default `Mainnet` network * feat: fix mempool endpint * feat: propagate config update only when explicitly updated * feat: add network for wallet accounts * fix: stop scanning when network changed * chore: code clean-up * chore: code clean-up * feat: show hardware device Xpub option * fix: handle failed to parse psbt * feat: add accounts using the HWW * fix: testnet is in the bip32 derivation path * feat: add spinner while wallet account is created * fix: check network and masterpub for duplicate accounts * feat: integrate transaction broadcast * feat: add password confirmation for `Wipe` and `Restore` * fix: fingerprint is not unique per account (it is the fingerprint of the master) * chore: code clean-up, remove `masterpub_fingerprint` * fix: account name diplay * chore: code format * fix: memppol links * fix: shortcut buttons * fix: note update * chore: code format * chore: clean-up rebase left overs * chore: clean-up * feat: less technical labels for addresses * feat: add serial port config params * fix: address type selection * chore: drop `mempool` table * fix: change & fee value * fix: handle no input signed scenario * fix: sat/btc unit * fix: small UI stuff * doc: update the readme * Update README.md
2022-08-09 05:00:09 -04:00
async def get_watch_wallets(user: str, network: str) -> List[WalletAccount]:
2021-10-14 11:45:30 +01:00
rows = await db.fetchall(
WatchOnly Extension - add Serial Port communication (#839) * feat: add `Share PSBT` button with options * feat: add basic communication via the serial port * chore: code format * feat: send data to and from serial port * fix: port disconnect * feat: handle psbt extract * feat: show signed transaction details * fix: handle Connect/Disconnect failure state * feat:small UI improvements * feat: broadcast transaction (partial solution) * feat: integrate psbt response from HWW * feat: login and send commands to HWW * feat: ui improvements * feat: ui/ux improvements * feat: more small UI impreovemsnts * feat: simplify UI * feat: add `help` command * feat: add wipe command * feet: add `seed` command * feat: add `restore` command * feat: always show PSBT input text (for outside PSBTs) * feat: show spinner while signing tx * feat: hide panels after transaction is broadcast * feat: basic use of custom components * refactor: move components one folder up * refactor: extract wallet-config * refactor: extract `wallet-list` component * refactor: clean-up * chore: code format html component files * refactor: extract address-list component * refactor: extract `history` component * refactor: extract `utxo-list` component * feat: UI/UX improvements * feat: partial payment redesign * refactor: rename `fee` to `fee-rate` * refactor: rename component * refactor: extract `send-to` component * refactor: payment: first migration * fix: init `sendToList` * fix: change address * fix: change address and `Select All` coins * feat: show custom fees & two way binding for addresses * fix: scanAddressesWithAmount * fix: max amount * fix: coin selection mode * chore: code clean-up * feat: shuffle the UI * fix: change amount * feat: update tx size in real time * fix: coin selection * fix: show erro messages * fix: psbt generation * refactor: move serial port logic * refactor: payment component * refactor: code clean-up; use `slot` for `serial-signer` * feat: toggle serial port * feat: add Disconnect command * feat: prompt for `Connect` and `Login` before signing * refactor: send psbt to device * feat: extract signed transaction * refactor: code clean-up * feat: show auth green icon * chore: code clean-up * feat: show console * feat: allow `Connect` from dropdown menu * fix: stop if serial port cannot be open * feat: confirm outputs and fee * feat: add cancel command * fix: add `sats-denominated` for confirmations * feat: wait for HWW to authenticate, then open dialog * feat: share PSBT as text * refactor: extract `refreshAddresses` * feat: small UI improvements * feat: add default `Mainnet` network * feat: fix mempool endpint * feat: propagate config update only when explicitly updated * feat: add network for wallet accounts * fix: stop scanning when network changed * chore: code clean-up * chore: code clean-up * feat: show hardware device Xpub option * fix: handle failed to parse psbt * feat: add accounts using the HWW * fix: testnet is in the bip32 derivation path * feat: add spinner while wallet account is created * fix: check network and masterpub for duplicate accounts * feat: integrate transaction broadcast * feat: add password confirmation for `Wipe` and `Restore` * fix: fingerprint is not unique per account (it is the fingerprint of the master) * chore: code clean-up, remove `masterpub_fingerprint` * fix: account name diplay * chore: code format * fix: memppol links * fix: shortcut buttons * fix: note update * chore: code format * chore: clean-up rebase left overs * chore: clean-up * feat: less technical labels for addresses * feat: add serial port config params * fix: address type selection * chore: drop `mempool` table * fix: change & fee value * fix: handle no input signed scenario * fix: sat/btc unit * fix: small UI stuff * doc: update the readme * Update README.md
2022-08-09 05:00:09 -04:00
"""SELECT * FROM watchonly.wallets WHERE "user" = ? AND network = ?""",
(user, network),
2021-10-14 11:45:30 +01:00
)
return [WalletAccount(**row) for row in rows]
2021-10-14 11:45:30 +01:00
async def update_watch_wallet(wallet_id: str, **kwargs) -> Optional[WalletAccount]:
2021-10-14 11:45:30 +01:00
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(
f"UPDATE watchonly.wallets SET {q} WHERE id = ?", (*kwargs.values(), wallet_id)
)
row = await db.fetchone(
"SELECT * FROM watchonly.wallets WHERE id = ?", (wallet_id,)
)
return WalletAccount.from_row(row) if row else None
2021-10-14 11:45:30 +01:00
async def delete_watch_wallet(wallet_id: str) -> None:
await db.execute("DELETE FROM watchonly.wallets WHERE id = ?", (wallet_id,))
2022-07-05 13:26:07 +03:00
########################ADDRESSES#######################
2021-10-14 11:45:30 +01:00
2022-07-05 13:26:07 +03:00
async def get_fresh_address(wallet_id: str) -> Optional[Address]:
# todo: move logic to views_api after satspay refactoring
2021-10-14 11:45:30 +01:00
wallet = await get_watch_wallet(wallet_id)
if not wallet:
return None
2021-10-14 11:45:30 +01:00
wallet_addresses = await get_addresses(wallet_id)
receive_addresses = list(
filter(
lambda addr: addr.branch_index == 0 and addr.has_activity, wallet_addresses
)
)
last_receive_index = (
receive_addresses.pop().address_index if receive_addresses else -1
)
address_index = (
last_receive_index
if last_receive_index > wallet.address_no
else wallet.address_no
)
address = await get_address_at_index(wallet_id, 0, address_index + 1)
if not address:
addresses = await create_fresh_addresses(
wallet_id, address_index + 1, address_index + 2
)
address = addresses.pop()
await update_watch_wallet(wallet_id, **{"address_no": address_index + 1})
return address
2021-10-14 22:30:47 +01:00
async def create_fresh_addresses(
wallet_id: str,
start_address_index: int,
end_address_index: int,
change_address=False,
) -> List[Address]:
if start_address_index > end_address_index:
return None
wallet = await get_watch_wallet(wallet_id)
2021-10-14 11:45:30 +01:00
if not wallet:
return None
branch_index = 1 if change_address else 0
2021-10-14 11:45:30 +01:00
for address_index in range(start_address_index, end_address_index):
address = await derive_address(wallet.masterpub, address_index, branch_index)
await db.execute(
"""
2021-10-14 11:45:30 +01:00
INSERT INTO watchonly.addresses (
id,
address,
wallet,
amount,
branch_index,
address_index
)
VALUES (?, ?, ?, ?, ?, ?)
""",
(urlsafe_short_hash(), address, wallet_id, 0, branch_index, address_index),
2021-10-14 11:45:30 +01:00
)
# return fresh addresses
rows = await db.fetchall(
"""
SELECT * FROM watchonly.addresses
WHERE wallet = ? AND branch_index = ? AND address_index >= ? AND address_index < ?
ORDER BY branch_index, address_index
2021-10-14 11:45:30 +01:00
""",
(wallet_id, branch_index, start_address_index, end_address_index),
2021-10-14 11:45:30 +01:00
)
return [Address(**row) for row in rows]
2021-10-14 11:45:30 +01:00
async def get_address(address: str) -> Optional[Address]:
2021-10-14 11:45:30 +01:00
row = await db.fetchone(
"SELECT * FROM watchonly.addresses WHERE address = ?", (address,)
)
return Address.from_row(row) if row else None
async def get_address_at_index(
wallet_id: str, branch_index: int, address_index: int
) -> Optional[Address]:
row = await db.fetchone(
"""
SELECT * FROM watchonly.addresses
WHERE wallet = ? AND branch_index = ? AND address_index = ?
""",
(
wallet_id,
branch_index,
address_index,
),
)
return Address.from_row(row) if row else None
2021-10-14 11:45:30 +01:00
async def get_addresses(wallet_id: str) -> List[Address]:
2021-10-14 11:45:30 +01:00
rows = await db.fetchall(
"""
SELECT * FROM watchonly.addresses WHERE wallet = ?
ORDER BY branch_index, address_index
""",
(wallet_id,),
2021-10-14 11:45:30 +01:00
)
return [Address(**row) for row in rows]
2021-10-14 11:45:30 +01:00
async def update_address(id: str, **kwargs) -> Optional[Address]:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
2021-10-14 11:45:30 +01:00
await db.execute(
f"""UPDATE watchonly.addresses SET {q} WHERE id = ? """,
(*kwargs.values(), id),
)
row = await db.fetchone("SELECT * FROM watchonly.addresses WHERE id = ?", (id))
return Address.from_row(row) if row else None
async def delete_addresses_for_wallet(wallet_id: str) -> None:
await db.execute("DELETE FROM watchonly.addresses WHERE wallet = ?", (wallet_id,))
######################CONFIG#######################
async def create_config(user: str) -> Config:
config = Config()
await db.execute(
"""
INSERT INTO watchonly.config ("user", json_data)
VALUES (?, ?)
""",
(user, json.dumps(config.dict())),
)
row = await db.fetchone(
"""SELECT json_data FROM watchonly.config WHERE "user" = ?""", (user,)
)
return json.loads(row[0], object_hook=lambda d: Config(**d))
async def update_config(config: Config, user: str) -> Optional[Config]:
await db.execute(
f"""UPDATE watchonly.config SET json_data = ? WHERE "user" = ?""",
(json.dumps(config.dict()), user),
)
row = await db.fetchone(
"""SELECT json_data FROM watchonly.config WHERE "user" = ?""", (user,)
)
return json.loads(row[0], object_hook=lambda d: Config(**d))
async def get_config(user: str) -> Optional[Config]:
row = await db.fetchone(
"""SELECT json_data FROM watchonly.config WHERE "user" = ?""", (user,)
)
return json.loads(row[0], object_hook=lambda d: Config(**d)) if row else None