mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-21 02:54:20 +01:00
* add websockets for quote updates * add test (not working) * wip: emit events to everyone * wip: emit events to everyone * wip, lots of things broken but invoice callback works * wip * add wip files * tests almost passing * add task * refactor nut constants * startup fix * works with old mints * wip cli * fix mypy * remove automatic invoice test now with websockets * remove comment * better logging * send back response * add rate limiter to websocket * add rate limiter to subscriptions * refactor websocket ratelimit * websocket tests * subscription kinds * doesnt start * remove circular import * update * fix mypy * move test file in test because it fails if it runs later... dunno why * adjust websocket NUT-06 settings * local import and small fix * disable websockets in CLI if "no_check" is selected * move subscription test to where it was * check proof state with callback, add tests * tests: run mint fixture per module instead of per session * subscription command name fix * test per session again * update test race conditions * fix tests * clean up * tmp * fix db issues and remove cached secrets * fix tests * blindly try pipeline * remove comments * comments
98 lines
3.6 KiB
Python
98 lines
3.6 KiB
Python
import asyncio
|
|
from typing import List, Optional
|
|
|
|
from loguru import logger
|
|
|
|
from ...core.base import Proof, ProofState, SpentState
|
|
from ...core.db import Connection, Database, get_db_connection
|
|
from ...core.errors import (
|
|
TransactionError,
|
|
)
|
|
from ..crud import LedgerCrud
|
|
from ..events.events import LedgerEventManager
|
|
|
|
|
|
class DbWriteHelper:
|
|
db: Database
|
|
crud: LedgerCrud
|
|
events: LedgerEventManager
|
|
proofs_pending_lock: asyncio.Lock = (
|
|
asyncio.Lock()
|
|
) # holds locks for proofs_pending database
|
|
|
|
def __init__(
|
|
self, db: Database, crud: LedgerCrud, events: LedgerEventManager
|
|
) -> None:
|
|
self.db = db
|
|
self.crud = crud
|
|
self.events = events
|
|
|
|
async def _set_proofs_pending(
|
|
self, proofs: List[Proof], quote_id: Optional[str] = None
|
|
) -> None:
|
|
"""If none of the proofs is in the pending table (_validate_proofs_pending), adds proofs to
|
|
the list of pending proofs or removes them. Used as a mutex for proofs.
|
|
|
|
Args:
|
|
proofs (List[Proof]): Proofs to add to pending table.
|
|
quote_id (Optional[str]): Melt quote ID. If it is not set, we assume the pending tokens to be from a swap.
|
|
|
|
Raises:
|
|
Exception: At least one proof already in pending table.
|
|
"""
|
|
# first we check whether these proofs are pending already
|
|
async with self.proofs_pending_lock:
|
|
async with get_db_connection(self.db) as conn:
|
|
await self._validate_proofs_pending(proofs, conn)
|
|
try:
|
|
for p in proofs:
|
|
await self.crud.set_proof_pending(
|
|
proof=p, db=self.db, quote_id=quote_id, conn=conn
|
|
)
|
|
await self.events.submit(
|
|
ProofState(Y=p.Y, state=SpentState.pending)
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Failed to set proofs pending: {e}")
|
|
raise TransactionError("Failed to set proofs pending.")
|
|
|
|
async def _unset_proofs_pending(self, proofs: List[Proof], spent=True) -> None:
|
|
"""Deletes proofs from pending table.
|
|
|
|
Args:
|
|
proofs (List[Proof]): Proofs to delete.
|
|
spent (bool): Whether the proofs have been spent or not. Defaults to True.
|
|
This should be False if the proofs were NOT invalidated before calling this function.
|
|
It is used to emit the unspent state for the proofs (otherwise the spent state is emitted
|
|
by the _invalidate_proofs function when the proofs are spent).
|
|
"""
|
|
async with self.proofs_pending_lock:
|
|
async with get_db_connection(self.db) as conn:
|
|
for p in proofs:
|
|
await self.crud.unset_proof_pending(proof=p, db=self.db, conn=conn)
|
|
if not spent:
|
|
await self.events.submit(
|
|
ProofState(Y=p.Y, state=SpentState.unspent)
|
|
)
|
|
|
|
async def _validate_proofs_pending(
|
|
self, proofs: List[Proof], conn: Optional[Connection] = None
|
|
) -> None:
|
|
"""Checks if any of the provided proofs is in the pending proofs table.
|
|
|
|
Args:
|
|
proofs (List[Proof]): Proofs to check.
|
|
|
|
Raises:
|
|
Exception: At least one of the proofs is in the pending table.
|
|
"""
|
|
if not (
|
|
len(
|
|
await self.crud.get_proofs_pending(
|
|
Ys=[p.Y for p in proofs], db=self.db, conn=conn
|
|
)
|
|
)
|
|
== 0
|
|
):
|
|
raise TransactionError("proofs are pending.")
|