Skip to content

Commit

Permalink
feat: update sql and vue for v1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dni committed Sep 25, 2024
1 parent 990fed2 commit 7f00989
Show file tree
Hide file tree
Showing 7 changed files with 962 additions and 895 deletions.
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Onchain Wallet",
"short_description": "Onchain watch only wallets",
"tile": "/watchonly/static/bitcoin-wallet.png",
"min_lnbits_version": "0.11.0",
"min_lnbits_version": "1.0.0",
"contributors": [
{
"name": "motorina0",
Expand Down
179 changes: 83 additions & 96 deletions crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,82 +2,54 @@
from typing import Optional

from lnbits.db import Database
from lnbits.helpers import urlsafe_short_hash
from lnbits.helpers import insert_query, update_query, urlsafe_short_hash

from .helpers import derive_address
from .models import Address, Config, WalletAccount

db = Database("ext_watchonly")


async def create_watch_wallet(user: str, w: WalletAccount) -> WalletAccount:
wallet_id = urlsafe_short_hash()
async def create_watch_wallet(wallet: WalletAccount) -> WalletAccount:
await db.execute(
"""
INSERT INTO watchonly.wallets (
id,
"user",
masterpub,
fingerprint,
title,
type,
address_no,
balance,
network,
meta
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
wallet_id,
user,
w.masterpub,
w.fingerprint,
w.title,
w.type,
w.address_no,
w.balance,
w.network,
w.meta,
),
insert_query("watchonly.wallets", wallet),
wallet.dict(),
)
wallet = await get_watch_wallet(wallet_id)
assert wallet
return wallet


async def get_watch_wallet(wallet_id: str) -> Optional[WalletAccount]:
row = await db.fetchone(
"SELECT * FROM watchonly.wallets WHERE id = ?", (wallet_id,)
"SELECT * FROM watchonly.wallets WHERE id = :id",
{"id": wallet_id},
)
return WalletAccount.from_row(row) if row else None
return WalletAccount(**row) if row else None


async def get_watch_wallets(user: str, network: str) -> list[WalletAccount]:
rows = await db.fetchall(
"""SELECT * FROM watchonly.wallets WHERE "user" = ? AND network = ?""",
(user, network),
"""
SELECT * FROM watchonly.wallets
WHERE "user" = :user AND network = :network
""",
{"user": user, "network": network},
)
return [WalletAccount(**row) for row in rows]


async def update_watch_wallet(wallet_id: str, **kwargs) -> Optional[WalletAccount]:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])

async def update_watch_wallet(wallet: WalletAccount) -> WalletAccount:
await db.execute(
f"UPDATE watchonly.wallets SET {q} WHERE id = ?", (*kwargs.values(), wallet_id)
update_query("watchonly.wallets", wallet),
wallet.dict(),
)
row = await db.fetchone(
"SELECT * FROM watchonly.wallets WHERE id = ?", (wallet_id,)
)
return WalletAccount.from_row(row) if row else None
return wallet


async def delete_watch_wallet(wallet_id: str) -> None:
await db.execute("DELETE FROM watchonly.wallets WHERE id = ?", (wallet_id,))


########################ADDRESSES#######################
await db.execute(
"DELETE FROM watchonly.wallets WHERE id = :id",
{"id": wallet_id},
)


async def get_fresh_address(wallet_id: str) -> Optional[Address]:
Expand Down Expand Up @@ -110,7 +82,8 @@ async def get_fresh_address(wallet_id: str) -> Optional[Address]:
)
address = addresses.pop()

await update_watch_wallet(wallet_id, **{"address_no": address_index + 1})
wallet.address_no = address_index + 1
await update_watch_wallet(wallet)

return address

Expand All @@ -132,41 +105,55 @@ async def create_fresh_addresses(

for address_index in range(start_address_index, end_address_index):
address = await derive_address(wallet.masterpub, address_index, branch_index)
assert address # TODO: why optional

addr = Address(
id=urlsafe_short_hash(),
address=address,
wallet=wallet_id,
branch_index=branch_index,
address_index=address_index,
)

await db.execute(
"""
INSERT INTO watchonly.addresses (
id,
address,
wallet,
amount,
branch_index,
address_index
)
VALUES (?, ?, ?, ?, ?, ?)
""",
(urlsafe_short_hash(), address, wallet_id, 0, branch_index, address_index),
insert_query("watchonly.addresses", addr),
addr.dict(),
)

# return fresh addresses
rows = await db.fetchall(
"""
SELECT * FROM watchonly.addresses
WHERE wallet = ? AND branch_index = ?
AND address_index >= ? AND address_index < ?
SELECT * FROM watchonly.addresses WHERE wallet = :wallet
AND branch_index = :branch_index
AND address_index >= :start_address_index
AND address_index < :end_address_index
ORDER BY branch_index, address_index
""",
(wallet_id, branch_index, start_address_index, end_address_index),
{
"wallet": wallet_id,
"branch_index": branch_index,
"start_address_index": start_address_index,
"end_address_index": end_address_index,
},
)

return [Address(**row) for row in rows]


async def get_address(address: str) -> Optional[Address]:
row = await db.fetchone(
"SELECT * FROM watchonly.addresses WHERE address = ?", (address,)
"SELECT * FROM watchonly.addresses WHERE address = :address",
{"address": address},
)
return Address(**row) if row else None


async def get_address_by_id(address_id: str) -> Optional[Address]:
row = await db.fetchone(
"SELECT * FROM watchonly.addresses WHERE id = :id",
{"id": address_id},
)
return Address.from_row(row) if row else None
return Address(**row) if row else None


async def get_address_at_index(
Expand All @@ -175,75 +162,75 @@ async def get_address_at_index(
row = await db.fetchone(
"""
SELECT * FROM watchonly.addresses
WHERE wallet = ? AND branch_index = ? AND address_index = ?
WHERE wallet = :wallet AND branch_index = :branch_index
AND address_index = :address_index
""",
(
wallet_id,
branch_index,
address_index,
),
{
"wallet": wallet_id,
"branch_index": branch_index,
"address_index": address_index,
},
)
return Address.from_row(row) if row else None
return Address(**row) if row else None


async def get_addresses(wallet_id: str) -> list[Address]:
rows = await db.fetchall(
"""
SELECT * FROM watchonly.addresses WHERE wallet = ?
ORDER BY branch_index, address_index
SELECT * FROM watchonly.addresses WHERE wallet = :wallet
ORDER BY branch_index, address_index
""",
(wallet_id,),
{"wallet": wallet_id},
)

return [Address(**row) for row in rows]


async def update_address(address_id: str, **kwargs) -> Address:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])

async def update_address(address: Address) -> Address:
await db.execute(
f"""UPDATE watchonly.addresses SET {q} WHERE id = ? """,
(*kwargs.values(), address_id),
)
row = await db.fetchone(
"SELECT * FROM watchonly.addresses WHERE id = ?", (address_id,)
update_query("watchonly.addresses", address),
address.dict(),
)
assert row, "updated address not found"
return Address.from_row(row)
return address


async def delete_addresses_for_wallet(wallet_id: str) -> None:
await db.execute("DELETE FROM watchonly.addresses WHERE wallet = ?", (wallet_id,))
await db.execute(
"DELETE FROM watchonly.addresses WHERE wallet = :wallet", {"wallet": wallet_id}
)


async def create_config(user: str) -> Config:
config = Config()
await db.execute(
"""
INSERT INTO watchonly.config ("user", json_data)
VALUES (?, ?)
VALUES (:user, :data)
""",
(user, json.dumps(config.dict())),
{"user": user, "data": json.dumps(config.dict())},
)
row = await db.fetchone(
"""SELECT json_data FROM watchonly.config WHERE "user" = ?""", (user,)
"""SELECT json_data FROM watchonly.config WHERE "user" = :user""",
{"user": user},
)
return json.loads(row[0], object_hook=lambda d: Config(**d))


async def update_config(config: Config, user: str) -> Optional[Config]:
async def update_config(config: Config, user: str) -> Config:
await db.execute(
"""UPDATE watchonly.config SET json_data = ? WHERE "user" = ?""",
(json.dumps(config.dict()), user),
"""UPDATE watchonly.config SET json_data = :data WHERE "user" = :user""",
{"data": json.dumps(config.dict()), "user": user},
)
row = await db.fetchone(
"""SELECT json_data FROM watchonly.config WHERE "user" = ?""", (user,)
"""SELECT json_data FROM watchonly.config WHERE "user" = :user""",
{"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,)
"""SELECT json_data FROM watchonly.config WHERE "user" = :user""",
{"user": user},
)
return json.loads(row[0], object_hook=lambda d: Config(**d)) if row else None
10 changes: 1 addition & 9 deletions models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from sqlite3 import Row
from typing import Optional

from fastapi import Query
Expand All @@ -14,6 +13,7 @@ class CreateWallet(BaseModel):

class WalletAccount(BaseModel):
id: str
user: str
masterpub: str
fingerprint: str
title: str
Expand All @@ -23,10 +23,6 @@ class WalletAccount(BaseModel):
network: str = "Mainnet"
meta: str = "{}"

@classmethod
def from_row(cls, row: Row) -> "WalletAccount":
return cls(**dict(row))


class Address(BaseModel):
id: str
Expand All @@ -38,10 +34,6 @@ class Address(BaseModel):
note: Optional[str] = None
has_activity: bool = False

@classmethod
def from_row(cls, row: Row) -> "Address":
return cls(**dict(row))


class TransactionInput(BaseModel):
tx_id: str
Expand Down
Loading

0 comments on commit 7f00989

Please sign in to comment.