From 2e4194f9cc20778edb22cbbb85b43290fef44821 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Thu, 21 May 2026 10:57:26 +0200 Subject: [PATCH] fix(websocket): support generic quote kinds --- cashu/core/base.py | 46 +++++++++------- cashu/core/json_rpc/base.py | 29 +++++++++-- cashu/core/mint_info.py | 2 +- cashu/mint/events/client.py | 23 +++++--- cashu/mint/features.py | 10 ++-- cashu/wallet/mint_info.py | 2 +- cashu/wallet/wallet.py | 28 +++++----- tests/mint/test_mint_db.py | 12 ++--- tests/mint/test_mint_websocket_protocol.py | 52 +++++++++++++------ tests/wallet/test_wallet_subscription.py | 14 ++--- tests/wallet/test_wallet_subscription_unit.py | 3 +- 11 files changed, 143 insertions(+), 78 deletions(-) diff --git a/cashu/core/base.py b/cashu/core/base.py index c7f6b7889..b579bbd78 100644 --- a/cashu/core/base.py +++ b/cashu/core/base.py @@ -372,7 +372,7 @@ def identifier(self) -> str: @property def kind(self) -> JSONRPCSubscriptionKinds: - return JSONRPCSubscriptionKinds.BOLT11_MELT_QUOTE + return JSONRPCSubscriptionKinds.MELT_QUOTE @property def unpaid(self) -> bool: @@ -437,7 +437,11 @@ def from_row(cls, row: Row): # SQLITE: row is timestamp (string) created_time = int(row["created_time"]) if row["created_time"] else None paid_time = int(row["paid_time"]) if row["paid_time"] else None - issued_time = int(row["issued_time"]) if "issued_time" in row.keys() and row["issued_time"] else None + issued_time = ( + int(row["issued_time"]) + if "issued_time" in row.keys() and row["issued_time"] + else None + ) except Exception: # POSTGRES: row is datetime.datetime created_time = ( @@ -445,7 +449,9 @@ def from_row(cls, row: Row): ) paid_time = int(row["paid_time"].timestamp()) if row["paid_time"] else None issued_time = ( - int(row["issued_time"].timestamp()) if "issued_time" in row.keys() and row["issued_time"] else None + int(row["issued_time"].timestamp()) + if "issued_time" in row.keys() and row["issued_time"] + else None ) return cls( quote=row["quote"], @@ -487,7 +493,7 @@ def identifier(self) -> str: @property def kind(self) -> JSONRPCSubscriptionKinds: - return JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE + return JSONRPCSubscriptionKinds.MINT_QUOTE @property def unpaid(self) -> bool: @@ -558,11 +564,11 @@ def str(self, amount: int | float) -> str: elif self == Unit.msat: return f"{amount} msat" elif self == Unit.usd: - return f"${amount/100:.2f} USD" + return f"${amount / 100:.2f} USD" elif self == Unit.eur: - return f"{amount/100:.2f} EUR" + return f"{amount / 100:.2f} EUR" elif self == Unit.btc: - return f"{amount/1e8:.8f} BTC" + return f"{amount / 1e8:.8f} BTC" elif self == Unit.auth: return f"{amount} AUTH" else: @@ -623,18 +629,18 @@ def from_float(cls, amount: float, unit: Unit) -> "Amount": def sat_to_btc(self) -> str: if self.unit != Unit.sat: raise Exception("Amount must be in satoshis") - return f"{self.amount/1e8:.8f}" + return f"{self.amount / 1e8:.8f}" def msat_to_btc(self) -> str: if self.unit != Unit.msat: raise Exception("Amount must be in msat") sat_amount = Amount(Unit.msat, self.amount).to(Unit.sat, round="up") - return f"{sat_amount.amount/1e8:.8f}" + return f"{sat_amount.amount / 1e8:.8f}" def cents_to_usd(self) -> str: if self.unit != Unit.usd and self.unit != Unit.eur: raise Exception("Amount must be in cents") - return f"{self.amount/100:.2f}" + return f"{self.amount / 100:.2f}" def str(self) -> str: return self.unit.str(self.amount) @@ -924,8 +930,7 @@ def from_row(cls, row: Row): def public_keys_hex(self) -> Dict[int, str]: assert self.public_keys, "public keys not set" return { - int(amount): key.format().hex() - for amount, key in self.public_keys.items() + int(amount): key.format().hex() for amount, key in self.public_keys.items() } def generate_keys(self): @@ -966,7 +971,7 @@ def generate_keys(self): self.seed, self.derivation_path, self.amounts ) self.public_keys = derive_pubkeys(self.private_keys, self.amounts) # type: ignore - + if id_in_db: # If loading from DB, preserve existing ID self.id = id_in_db @@ -979,14 +984,19 @@ def generate_keys(self): self.seed, self.derivation_path, self.amounts ) self.public_keys = derive_pubkeys(self.private_keys, self.amounts) # type: ignore - + # KEYSETS V2: Use new keyset ID derivation if id_in_db: # If loading from DB, preserve existing ID self.id = id_in_db else: assert self.public_keys is not None - self.id = derive_keyset_id_v2(self.public_keys, self.unit.name, self.final_expiry, self.input_fee_ppk) + self.id = derive_keyset_id_v2( + self.public_keys, + self.unit.name, + self.final_expiry, + self.input_fee_ppk, + ) logger.info(f"Generated keyset v2 ID: {self.id}") @@ -1417,9 +1427,9 @@ def from_proof(cls, proof: Proof): def to_base64(self): serialize_dict = self.model_dump() serialize_dict.pop("amount", None) - return ( - self.prefix + base64.urlsafe_b64encode(json.dumps(serialize_dict).encode()).decode().rstrip("=") - ) + return self.prefix + base64.urlsafe_b64encode( + json.dumps(serialize_dict).encode() + ).decode().rstrip("=") @classmethod def from_base64(cls, base64_str: str): diff --git a/cashu/core/json_rpc/base.py b/cashu/core/json_rpc/base.py index c706865d4..a532bb1e3 100644 --- a/cashu/core/json_rpc/base.py +++ b/cashu/core/json_rpc/base.py @@ -1,7 +1,7 @@ from enum import Enum -from typing import Annotated, List +from typing import Annotated, List, Union -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, field_validator from ..constants import MAX_QUOTE_ID_LEN from ..settings import settings @@ -58,9 +58,27 @@ class JSONRPCMethods(Enum): class JSONRPCSubscriptionKinds(Enum): + MINT_QUOTE = "mint_quote" + MELT_QUOTE = "melt_quote" + PROOF_STATE = "proof_state" + + # TODO: Remove these deprecated bolt11-specific aliases once old websocket + # clients have been migrated to the method-independent NUT-17 kinds. BOLT11_MINT_QUOTE = "bolt11_mint_quote" BOLT11_MELT_QUOTE = "bolt11_melt_quote" - PROOF_STATE = "proof_state" + + @classmethod + def normalize( + cls, kind: Union["JSONRPCSubscriptionKinds", str] + ) -> "JSONRPCSubscriptionKinds": + parsed_kind = kind if isinstance(kind, cls) else cls(kind) + + if parsed_kind == cls.BOLT11_MINT_QUOTE: + return cls.MINT_QUOTE + if parsed_kind == cls.BOLT11_MELT_QUOTE: + return cls.MELT_QUOTE + + return parsed_kind class JSONRPCStatus(Enum): @@ -74,6 +92,11 @@ class JSONRPCSubscribeParams(BaseModel): ) subId: str + @field_validator("kind", mode="before") + @classmethod + def normalize_kind(cls, kind): + return JSONRPCSubscriptionKinds.normalize(kind) + class JSONRPCUnsubscribeParams(BaseModel): subId: str diff --git a/cashu/core/mint_info.py b/cashu/core/mint_info.py index 2ececcf58..ee1737e50 100644 --- a/cashu/core/mint_info.py +++ b/cashu/core/mint_info.py @@ -76,7 +76,7 @@ def supports_websocket_mint_quote(self, method: Method, unit: Unit) -> bool: websocket_supported = websocket_settings["supported"] for entry in websocket_supported: if entry["method"] == method.name and entry["unit"] == unit.name: - if "bolt11_mint_quote" in entry["commands"]: + if "mint_quote" in entry["commands"]: return True return False diff --git a/cashu/mint/events/client.py b/cashu/mint/events/client.py index 6dde914d6..2236bae2f 100644 --- a/cashu/mint/events/client.py +++ b/cashu/mint/events/client.py @@ -178,6 +178,8 @@ def add_subscription( filters: List[str], subId: str, ) -> None: + kind = JSONRPCSubscriptionKinds.normalize(kind) + if kind not in self.subscriptions: self.subscriptions[kind] = {} @@ -187,7 +189,7 @@ def add_subscription( for f in filters: logger.debug(f"Adding subscription {subId} for filter {f}") self.subscriptions[kind].setdefault(f, []).append(subId) - + # Initialize the subscriptions in batch asyncio.create_task(self._init_subscriptions(subId, filters, kind)) @@ -215,26 +217,35 @@ def serialize_event(self, event: LedgerEvent) -> dict: async def _init_subscriptions( self, subId: str, filters: List[str], kind: JSONRPCSubscriptionKinds ): + kind = JSONRPCSubscriptionKinds.normalize(kind) results = [] async with self.db_read.db.connect() as conn: - if kind == JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE: + if kind == JSONRPCSubscriptionKinds.MINT_QUOTE: for filter in filters: mint_quote = await self.db_read.crud.get_mint_quote( quote_id=filter, db=self.db_read.db, conn=conn ) if mint_quote: - results.append(PostMintQuoteResponse.from_mint_quote(mint_quote).model_dump()) - elif kind == JSONRPCSubscriptionKinds.BOLT11_MELT_QUOTE: + results.append( + PostMintQuoteResponse.from_mint_quote( + mint_quote + ).model_dump() + ) + elif kind == JSONRPCSubscriptionKinds.MELT_QUOTE: for filter in filters: melt_quote = await self.db_read.crud.get_melt_quote( quote_id=filter, db=self.db_read.db, conn=conn ) if melt_quote: - results.append(PostMeltQuoteResponse.from_melt_quote(melt_quote).model_dump()) + results.append( + PostMeltQuoteResponse.from_melt_quote( + melt_quote + ).model_dump() + ) elif kind == JSONRPCSubscriptionKinds.PROOF_STATE: proofs = await self.db_read.get_proofs_states(Ys=filters, conn=conn) for proof in proofs: results.append(proof.model_dump()) - + for result in results: await self._send_obj(result, subId) diff --git a/cashu/mint/features.py b/cashu/mint/features.py index 3234d4a46..d862959f5 100644 --- a/cashu/mint/features.py +++ b/cashu/mint/features.py @@ -36,8 +36,8 @@ _BOLT11 = "bolt11" _MPP = "mpp" _COMMANDS = "commands" -_BOLT11_MINT_QUOTE = "bolt11_mint_quote" -_BOLT11_MELT_QUOTE = "bolt11_melt_quote" +_MINT_QUOTE = "mint_quote" +_MELT_QUOTE = "melt_quote" _PROOF_STATE = "proof_state" _PROTECTED_ENDPOINTS = "protected_endpoints" _BAT_MAX_MINT = "bat_max_mint" @@ -148,7 +148,7 @@ def add_websocket_features( websocket_features: Dict[str, List[Dict[str, Union[str, List[str]]]]] = { _SUPPORTED: [] } - # we check the backend to see if "bolt11_mint_quote" is supported as well + # we check the backend to see if "mint_quote" is supported as well for method, unit_dict in self.backends.items(): if method == Method[_BOLT11]: for unit in unit_dict.keys(): @@ -156,7 +156,7 @@ def add_websocket_features( { _METHOD: method.name, _UNIT: unit.name, - _COMMANDS: [_BOLT11_MELT_QUOTE, _PROOF_STATE], + _COMMANDS: [_MELT_QUOTE, _PROOF_STATE], } ) if unit_dict[unit].supports_incoming_payment_stream: @@ -164,7 +164,7 @@ def add_websocket_features( websocket_features[_SUPPORTED][-1][_COMMANDS] ) websocket_features[_SUPPORTED][-1][_COMMANDS] = ( - supported_features + [_BOLT11_MINT_QUOTE] + supported_features + [_MINT_QUOTE] ) if websocket_features: diff --git a/cashu/wallet/mint_info.py b/cashu/wallet/mint_info.py index 991be9fd5..f6b348140 100644 --- a/cashu/wallet/mint_info.py +++ b/cashu/wallet/mint_info.py @@ -51,7 +51,7 @@ def supports_websocket_mint_quote(self, method: Method, unit: Unit) -> bool: websocket_supported = websocket_settings["supported"] for entry in websocket_supported: if entry["method"] == method.name and entry["unit"] == unit.name: - if "bolt11_mint_quote" in entry["commands"]: + if "mint_quote" in entry["commands"]: return True return False diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index f788935b5..e9a4da471 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -281,7 +281,9 @@ async def load_mint_info(self, reload=False, offline=False) -> MintInfo | None: logger.debug("Updating mint info in db.") await update_mint( db=self.db, - mint=WalletMint(url=self.url, info=json.dumps(self.mint_info.model_dump())), + mint=WalletMint( + url=self.url, info=json.dumps(self.mint_info.model_dump()) + ), ) return self.mint_info else: @@ -482,7 +484,7 @@ async def request_mint_with_callback( target=subscriptions.connect, name="SubscriptionManager", daemon=True ).start() subscriptions.subscribe( - kind=JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE, + kind=JSONRPCSubscriptionKinds.MINT_QUOTE, filters=[mint_quote.quote], callback=callback, ) @@ -700,9 +702,9 @@ async def split( send_outputs, keep_outputs, secret_lock ) - assert len(secrets) == len( - amounts - ), "number of secrets does not match number of outputs" + assert len(secrets) == len(amounts), ( + "number of secrets does not match number of outputs" + ) # verify that we didn't accidentally reuse a secret await self._check_used_secrets(secrets) @@ -947,9 +949,9 @@ def verify_proofs_dleq(self, proofs: List[Proof]): return logger.trace("Verifying DLEQ proof.") assert proof.id - assert ( - proof.id in self.keysets - ), f"Keyset {proof.id} not known, can not verify DLEQ." + assert proof.id in self.keysets, ( + f"Keyset {proof.id} not known, can not verify DLEQ." + ) if not b_dhke.carol_verify_dleq( secret_msg=proof.secret, C=PublicKey(bytes.fromhex(proof.C)), @@ -1060,9 +1062,9 @@ def _construct_outputs( Raises: AssertionError: if len(amounts) != len(secrets) """ - assert len(amounts) == len( - secrets - ), f"len(amounts)={len(amounts)} not equal to len(secrets)={len(secrets)}" + assert len(amounts) == len(secrets), ( + f"len(amounts)={len(amounts)} not equal to len(secrets)={len(secrets)}" + ) keyset_id = keyset_id or self.keyset_id outputs: List[BlindedMessage] = [] rs_ = [None] * len(amounts) if not rs else rs @@ -1077,9 +1079,7 @@ def _construct_outputs( assert r rs_return.append(r) - output = BlindedMessage( - amount=amount, B_=B_.format().hex(), id=keyset_id - ) + output = BlindedMessage(amount=amount, B_=B_.format().hex(), id=keyset_id) outputs.append(output) logger.trace(f"Constructing output: {output}, r: {r.to_hex()}") diff --git a/tests/mint/test_mint_db.py b/tests/mint/test_mint_db.py index 058adbe98..2a7b8c399 100644 --- a/tests/mint/test_mint_db.py +++ b/tests/mint/test_mint_db.py @@ -278,16 +278,15 @@ async def test_db_events_add_client(wallet: Wallet, ledger: Ledger): websocket_mock.accept.assert_called_once() # add subscription - client.add_subscription( - JSONRPCSubscriptionKinds.BOLT11_MELT_QUOTE, [quote.quote], "subId" - ) + client.add_subscription(JSONRPCSubscriptionKinds.MELT_QUOTE, [quote.quote], "subId") await asyncio.sleep(0.1) quote_pending = await ledger.db_write._set_melt_quote_pending(quote) await asyncio.sleep(0.1) notification = JSONRPCNotification( method=JSONRPCMethods.SUBSCRIBE.value, params=JSONRPCNotficationParams( - subId="subId", payload=PostMeltQuoteResponse.from_melt_quote(quote_pending).model_dump() + subId="subId", + payload=PostMeltQuoteResponse.from_melt_quote(quote_pending).model_dump(), ).model_dump(), ) @@ -483,9 +482,10 @@ async def test_get_melt_quotes_by_checking_id_different_checking_ids(ledger: Led @pytest.mark.asyncio async def test_mint_quote_paid_time_update(wallet: Wallet, ledger: Ledger): import time + # Create a mint quote mint_quote = await wallet.request_mint(128) - + # Check that paid_time is None initially quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db) assert quote is not None @@ -495,7 +495,7 @@ async def test_mint_quote_paid_time_update(wallet: Wallet, ledger: Ledger): # Simulate payment await pay_if_regtest(mint_quote.request) - + # Trigger check at mint (this updates the state in DB) _ = await ledger.get_mint_quote(mint_quote.quote) # Check that paid_time is now set diff --git a/tests/mint/test_mint_websocket_protocol.py b/tests/mint/test_mint_websocket_protocol.py index 07b07d41e..f614eb18b 100644 --- a/tests/mint/test_mint_websocket_protocol.py +++ b/tests/mint/test_mint_websocket_protocol.py @@ -103,16 +103,16 @@ async def test_handle_request_subscribe_and_unsubscribe_roundtrip(monkeypatch): id=1, method=JSONRPCMethods.SUBSCRIBE.value, params={ - "kind": JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE.value, + "kind": JSONRPCSubscriptionKinds.MINT_QUOTE.value, "filters": ["quote-1"], "subId": "sub-1", }, ) resp = await manager._handle_request(req) assert resp.result["subId"] == "sub-1" - assert manager.subscriptions[JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE][ - "quote-1" - ] == ["sub-1"] + assert manager.subscriptions[JSONRPCSubscriptionKinds.MINT_QUOTE]["quote-1"] == [ + "sub-1" + ] req_unsub = JSONRPCRequest( id=2, @@ -121,11 +121,35 @@ async def test_handle_request_subscribe_and_unsubscribe_roundtrip(monkeypatch): ) resp_unsub = await manager._handle_request(req_unsub) assert resp_unsub.result["subId"] == "sub-1" - assert ( - manager.subscriptions[JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE]["quote-1"] - == [] + assert manager.subscriptions[JSONRPCSubscriptionKinds.MINT_QUOTE]["quote-1"] == [] + + +@pytest.mark.asyncio +async def test_handle_request_subscribe_accepts_deprecated_bolt11_kind(monkeypatch): + manager = _client_manager(FakeWebSocket()) + monkeypatch.setattr( + "cashu.mint.events.client.asyncio.create_task", + lambda coro: (coro.close(), None)[1], + ) + req = JSONRPCRequest( + id=1, + method=JSONRPCMethods.SUBSCRIBE.value, + params={ + "kind": JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE.value, + "filters": ["quote-1"], + "subId": "sub-1", + }, ) + resp = await manager._handle_request(req) + + assert resp.result["subId"] == "sub-1" + # TODO: Drop this deprecated bolt11-specific compatibility assertion once the + # mint no longer accepts legacy websocket subscription kinds. + assert manager.subscriptions[JSONRPCSubscriptionKinds.MINT_QUOTE]["quote-1"] == [ + "sub-1" + ] + def test_add_subscription_rejects_when_max_reached(): manager = _client_manager(FakeWebSocket()) @@ -161,7 +185,7 @@ async def test_init_subscription_sends_initial_snapshots(): proof_state = ProofState(Y="Y1", state=ProofSpentState.unspent) from contextlib import asynccontextmanager - + @asynccontextmanager async def mock_connect(): yield object() @@ -199,10 +223,10 @@ async def send_obj(data: dict, subId: str): cast(Any, manager)._send_obj = send_obj await manager._init_subscriptions( - "sub-mint", ["quote-1"], JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE + "sub-mint", ["quote-1"], JSONRPCSubscriptionKinds.MINT_QUOTE ) await manager._init_subscriptions( - "sub-melt", ["melt-1"], JSONRPCSubscriptionKinds.BOLT11_MELT_QUOTE + "sub-melt", ["melt-1"], JSONRPCSubscriptionKinds.MELT_QUOTE ) await manager._init_subscriptions( "sub-proof", ["Y1"], JSONRPCSubscriptionKinds.PROOF_STATE @@ -229,12 +253,8 @@ async def _send_obj(self, data: dict, subId: str): manager.clients = cast( Any, [ - FakeClient( - {JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE: {"quote-1": ["sub-1"]}} - ), - FakeClient( - {JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE: {"quote-2": ["sub-2"]}} - ), + FakeClient({JSONRPCSubscriptionKinds.MINT_QUOTE: {"quote-1": ["sub-1"]}}), + FakeClient({JSONRPCSubscriptionKinds.MINT_QUOTE: {"quote-2": ["sub-2"]}}), ], ) diff --git a/tests/wallet/test_wallet_subscription.py b/tests/wallet/test_wallet_subscription.py index 1f3eed2f3..1cb8bfbe0 100644 --- a/tests/wallet/test_wallet_subscription.py +++ b/tests/wallet/test_wallet_subscription.py @@ -29,8 +29,8 @@ async def wallet(mint): @pytest.mark.asyncio async def test_wallet_subscription_mint(wallet: Wallet): """The state will go from UNPAID to PAID to ISSUED. After the state becomes 'PAID', the - wallet must take action (see the 'def callback' below) to convert the PAID invoice - to ISSUED + wallet must take action (see the 'def callback' below) to convert the PAID invoice + to ISSUED """ if not wallet.mint_info.supports_nut(WEBSOCKETS_NUT): pytest.skip("No websocket support") @@ -38,7 +38,7 @@ async def test_wallet_subscription_mint(wallet: Wallet): if not wallet.mint_info.supports_websocket_mint_quote( Method["bolt11"], wallet.unit ): - pytest.skip("No websocket support for bolt11_mint_quote") + pytest.skip("No websocket support for mint_quote") triggered = False msg_stack: list[JSONRPCNotficationParams] = [] @@ -47,7 +47,7 @@ def callback(msg: JSONRPCNotficationParams): nonlocal triggered, msg_stack triggered = True msg_stack.append(msg) - if msg.payload['state'] == 'PAID': + if msg.payload["state"] == "PAID": asyncio.run(wallet.mint(int(mint_quote.amount), quote_id=mint_quote.quote)) mint_quote, sub = await wallet.request_mint_with_callback(128, callback=callback) @@ -130,7 +130,7 @@ async def test_wallet_subscription_multiple_listeners_receive_updates(wallet: Wa if not wallet.mint_info.supports_websocket_mint_quote( Method["bolt11"], wallet.unit ): - pytest.skip("No websocket support for bolt11_mint_quote") + pytest.skip("No websocket support for mint_quote") # Request a quote without auto-subscribing mint_quote = await wallet.request_mint(123) @@ -153,12 +153,12 @@ def cb2(msg: JSONRPCNotficationParams): stack2.append(msg) subs.subscribe( - kind=JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE, + kind=JSONRPCSubscriptionKinds.MINT_QUOTE, filters=[mint_quote.quote], callback=cb1, ) subs.subscribe( - kind=JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE, + kind=JSONRPCSubscriptionKinds.MINT_QUOTE, filters=[mint_quote.quote], callback=cb2, ) diff --git a/tests/wallet/test_wallet_subscription_unit.py b/tests/wallet/test_wallet_subscription_unit.py index 59c3061f4..d7b81209f 100644 --- a/tests/wallet/test_wallet_subscription_unit.py +++ b/tests/wallet/test_wallet_subscription_unit.py @@ -51,12 +51,13 @@ def test_subscription_manager_subscribe_and_close(monkeypatch): def callback(params): calls.append(params) - manager.subscribe(JSONRPCSubscriptionKinds.BOLT11_MINT_QUOTE, ["quote-1"], callback) + manager.subscribe(JSONRPCSubscriptionKinds.MINT_QUOTE, ["quote-1"], callback) assert manager.id_counter == 1 assert "sub-1" in manager.callback_map sent = json.loads(cast(Any, manager).websocket.sent[0]) assert sent["method"] == JSONRPCMethods.SUBSCRIBE.value + assert sent["params"]["kind"] == JSONRPCSubscriptionKinds.MINT_QUOTE.value assert sent["params"]["subId"] == "sub-1" manager.close()