diff --git a/cashu/core/base.py b/cashu/core/base.py index 6310df0..1cb946d 100644 --- a/cashu/core/base.py +++ b/cashu/core/base.py @@ -29,6 +29,10 @@ class KeyBase(BaseModel): ) +from typing import Optional +from cashu.core.db import Connection, Database + + class Keyset: id: str private_keys: Dict[int, PrivateKey] diff --git a/cashu/core/crud.py b/cashu/core/crud.py index 0ed3f44..235094c 100644 --- a/cashu/core/crud.py +++ b/cashu/core/crud.py @@ -6,8 +6,8 @@ from cashu.core.db import Connection, Database async def store_keyset( keyset: Keyset, - mint_url: str, - db: Database, + mint_url: str = None, + db: Database = None, conn: Optional[Connection] = None, ): @@ -19,7 +19,7 @@ async def store_keyset( """, ( keyset.id, - mint_url, + mint_url or keyset.mint_url, keyset.valid_from, keyset.valid_to, keyset.first_seen, @@ -55,7 +55,7 @@ async def get_keyset( """, tuple(values), ) - return Keyset.from_row(row) + return Keyset.from_row(row) if row is not None else None async def store_mint_pubkey( diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py index d98553a..c495947 100644 --- a/cashu/mint/ledger.py +++ b/cashu/mint/ledger.py @@ -16,6 +16,7 @@ from cashu.core.secp import PublicKey from cashu.core.settings import LIGHTNING, MAX_ORDER from cashu.core.split import amount_split from cashu.lightning import WALLET +from cashu.core.crud import get_keyset, store_keyset from cashu.mint.crud import ( get_lightning_invoice, get_proofs_used, @@ -36,6 +37,11 @@ class Ledger: async def load_used_proofs(self): self.proofs_used = set(await get_proofs_used(db=self.db)) + async def store_keyset(self): + keyset_local: Keyset = await get_keyset(self.keyset.id, db=self.db) + if keyset_local is None: + await store_keyset(keyset=self.keyset, db=self.db) + async def _generate_promises(self, amounts: List[int], B_s: List[str]): """Generates promises that sum to the given amount.""" return [ diff --git a/cashu/mint/migrations.py b/cashu/mint/migrations.py index b1d7329..c3b2559 100644 --- a/cashu/mint/migrations.py +++ b/cashu/mint/migrations.py @@ -95,11 +95,11 @@ async def m003_mint_keysets(db: Database): f""" CREATE TABLE IF NOT EXISTS keysets ( id TEXT NOT NULL, - mint_url TEXT NOT NULL, - valid_from TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}, - valid_to TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}, - first_seen TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}, - active BOOL NOT NULL DEFAULT TRUE, + mint_url TEXT, + valid_from TIMESTAMP DEFAULT {db.timestamp_now}, + valid_to TIMESTAMP DEFAULT {db.timestamp_now}, + first_seen TIMESTAMP DEFAULT {db.timestamp_now}, + active BOOL DEFAULT TRUE, UNIQUE (id, mint_url) diff --git a/cashu/mint/startup.py b/cashu/mint/startup.py index 0fdc108..1f3dd66 100644 --- a/cashu/mint/startup.py +++ b/cashu/mint/startup.py @@ -14,6 +14,7 @@ async def load_ledger(): await migrate_databases(ledger.db, migrations) # await asyncio.wait([m001_initial(ledger.db)]) await ledger.load_used_proofs() + await ledger.store_keyset() if LIGHTNING: error_message, balance = await WALLET.status() diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index 25e206c..30fc154 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -49,7 +49,7 @@ class LedgerAPI: def __init__(self, url): self.url = url - def _get_keys(self, url): + async def _get_keys(self, url): resp = requests.get(url + "/keys").json() keys = resp assert len(keys), Exception("did not receive any keys") @@ -96,10 +96,13 @@ class LedgerAPI: assert len( self.url ), "Ledger not initialized correctly: mint URL not specified yet. " - keyset = self._get_keys(self.url) - keyset_local: Keyset = await get_keyset(keyset.id, self.url, db=self.db) + keyset = await self._get_keys(self.url) + keyset_local: Keyset = await get_keyset(keyset.id, db=self.db) if keyset_local is None: await store_keyset(keyset=keyset, db=self.db) + # keyset_local: Keyset = await get_keyset(keyset.id, self.url, db=self.db) + # if keyset_local is None: + # await store_keyset(keyset=keyset, db=self.db) self.keys = keyset.public_keys self.keyset_id = keyset.id assert len(self.keys) > 0, "did not receive keys from mint." @@ -291,6 +294,16 @@ class Wallet(LedgerAPI): for proof in proofs: await store_proof(proof, db=self.db) + @staticmethod + def _sum_proofs(proofs: List[Proof], available_only=False): + if available_only: + return sum([p.amount for p in proofs if not p.reserved]) + return sum([p.amount for p in proofs]) + + @staticmethod + def _get_proofs_per_keyset(proofs: List[Proof]): + return {key: list(group) for key, group in groupby(proofs, lambda p: p.id)} + async def request_mint(self, amount): return super().request_mint(amount) @@ -357,7 +370,9 @@ class Wallet(LedgerAPI): return token async def _get_spendable_proofs(self, proofs: List[Proof]): - proofs = [p for p in proofs if p.id == self.keyset_id or not p.id] + proofs = [ + p for p in proofs if p.id == self.keyset_id or not p.id + ] # "or not p.id" is for backwards compatibility with proofs without a keyset id proofs = [p for p in proofs if not p.reserved] return proofs @@ -425,16 +440,6 @@ class Wallet(LedgerAPI): f"Balance: {self.balance} sat (available: {self.available_balance} sat in {len([p for p in self.proofs if not p.reserved])} tokens)" ) - @staticmethod - def _sum_proofs(proofs: List[Proof], available_only=False): - if available_only: - return sum([p.amount for p in proofs if not p.reserved]) - return sum([p.amount for p in proofs]) - - @staticmethod - def _get_proofs_per_keyset(proofs: List[Proof]): - return {key: list(group) for key, group in groupby(proofs, lambda p: p.id)} - def balance_per_keyset(self): return { key: {