from typing import List, Optional, Union from lnbits.helpers import urlsafe_short_hash from . import db from .models import Address, CreateAddressData, CreateDomainData, Domain async def get_domain(domain_id: str) -> Optional[Domain]: row = await db.fetchone( "SELECT * FROM nostrnip5.domains WHERE id = ?", (domain_id,) ) return Domain.from_row(row) if row else None async def get_domain_by_name(domain: str) -> Optional[Domain]: row = await db.fetchone( "SELECT * FROM nostrnip5.domains WHERE domain = ?", (domain,) ) return Domain.from_row(row) if row else None async def get_domains(wallet_ids: Union[str, List[str]]) -> List[Domain]: if isinstance(wallet_ids, str): wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( f"SELECT * FROM nostrnip5.domains WHERE wallet IN ({q})", (*wallet_ids,) ) return [Domain.from_row(row) for row in rows] async def get_address(domain_id: str, address_id: str) -> Optional[Address]: row = await db.fetchone( "SELECT * FROM nostrnip5.addresses WHERE domain_id = ? AND id = ?", ( domain_id, address_id, ), ) return Address.from_row(row) if row else None async def get_address_by_local_part( domain_id: str, local_part: str ) -> Optional[Address]: row = await db.fetchone( "SELECT * FROM nostrnip5.addresses WHERE domain_id = ? AND local_part = ?", ( domain_id, local_part.lower(), ), ) return Address.from_row(row) if row else None async def get_addresses(domain_id: str) -> List[Address]: rows = await db.fetchall( f"SELECT * FROM nostrnip5.addresses WHERE domain_id = ?", (domain_id,) ) return [Address.from_row(row) for row in rows] async def get_all_addresses(wallet_ids: Union[str, List[str]]) -> List[Address]: if isinstance(wallet_ids, str): wallet_ids = [wallet_ids] q = ",".join(["?"] * len(wallet_ids)) rows = await db.fetchall( f""" SELECT a.* FROM nostrnip5.addresses a JOIN nostrnip5.domains d ON d.id = a.domain_id WHERE d.wallet IN ({q}) """, (*wallet_ids,), ) return [Address.from_row(row) for row in rows] async def activate_address(domain_id: str, address_id: str) -> Address: await db.execute( """ UPDATE nostrnip5.addresses SET active = true WHERE domain_id = ? AND id = ? """, ( domain_id, address_id, ), ) address = await get_address(domain_id, address_id) assert address, "Newly updated address couldn't be retrieved" return address async def rotate_address(domain_id: str, address_id: str, pubkey: str) -> Address: await db.execute( """ UPDATE nostrnip5.addresses SET pubkey = ? WHERE domain_id = ? AND id = ? """, ( pubkey, domain_id, address_id, ), ) address = await get_address(domain_id, address_id) assert address, "Newly updated address couldn't be retrieved" return address async def delete_domain(domain_id) -> bool: await db.execute( """ DELETE FROM nostrnip5.addresses WHERE domain_id = ? """, (domain_id,), ) await db.execute( """ DELETE FROM nostrnip5.domains WHERE id = ? """, (domain_id,), ) return True async def delete_address(address_id): await db.execute( """ DELETE FROM nostrnip5.addresses WHERE id = ? """, (address_id,), ) async def create_address_internal(domain_id: str, data: CreateAddressData) -> Address: address_id = urlsafe_short_hash() await db.execute( """ INSERT INTO nostrnip5.addresses (id, domain_id, local_part, pubkey, active) VALUES (?, ?, ?, ?, ?) """, ( address_id, domain_id, data.local_part.lower(), data.pubkey, False, ), ) address = await get_address(domain_id, address_id) assert address, "Newly created address couldn't be retrieved" return address async def create_domain_internal(wallet_id: str, data: CreateDomainData) -> Domain: domain_id = urlsafe_short_hash() await db.execute( """ INSERT INTO nostrnip5.domains (id, wallet, currency, amount, domain) VALUES (?, ?, ?, ?, ?) """, (domain_id, wallet_id, data.currency, int(data.amount * 100), data.domain), ) domain = await get_domain(domain_id) assert domain, "Newly created domain couldn't be retrieved" return domain