fix(mint): close websocket when subscribed mint quotes expire unpaid#1036
fix(mint): close websocket when subscribed mint quotes expire unpaid#1036b-l-u-e wants to merge 1 commit into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1036 +/- ##
==========================================
+ Coverage 75.13% 75.18% +0.04%
==========================================
Files 110 110
Lines 12116 12152 +36
==========================================
+ Hits 9103 9136 +33
- Misses 3013 3016 +3 ☔ View full report in Codecov by Harness. |
118a270 to
8b9af9c
Compare
8b9af9c to
48fdfd2
Compare
Persist mint quote expiry in the database (migration + store path) and poll bolt11_mint_quote subscriptions so idle websocket connections are closed after all subscribed quotes are unpaid and past expiry. Fixes MintQuote.from_row not loading expiry and store_mint_quote not writing it (melt quotes already had expiry; mint quotes did not).
48fdfd2 to
a0b6d9f
Compare
|
Thank you all for the feedback made changes now we close WS once all subscribed mint quotes are terminal ( |
|
I may be not the best idea to enforce restrictions on the websocket as long as we don't restrict anything in the business logic (of minting itself) that depends on the expiry. We don't seem to have consensus on what to do with the expiry yet. |
Valid concern — makes sense to wait for consensus on expiry semantics before enforcing them here. Though I think closing connections once all subscribed quotes are paid is worth doing on its own, because a subscribed connection to an already-minted quote has no server-side cleanup mechanism. Also, scoping to just the paid case (for now) would leave the monitor structure in place, making it straightforward to add expiry-based handling once that's settled. |
Inspired by the quote lifecycle work in #1022 (wallet-side handling of unpaid/expired invoices), this PR hardens the mint side: websocket subscriptions to
bolt11_mint_quoteare closed when all subscribed quotes are unpaid and pastexpiry, instead of holding connections open untilmint_websocket_read_timeout(default 600s).Also fixes mint quote
expirynot being persisted or returned on GET: POST returnedexpiry, but GET and the websocket monitor sawnullbecausemint_quoteshad noexpirycolumn andstore_mint_quotenever wrote it.Problem
expirywas computed at quote creation but not stored inmint_quotes(unlikemelt_quotes), so REST GET,MintQuote.from_row, and the expiry monitor could not see it.Changes
MintQuote.from_row: loadexpiryfrom DB rows (SQLite + Postgres).store_mint_quote: persistexpiryon insert.m036_add_expiry_to_mint_quotes: addexpirycolumn tomint_quotes.LedgerEventClientManager: background poll (MINT_WEBSOCKET_QUOTE_EXPIRY_CHECK_INTERVAL, default 30s) closes WS with code1000/ reasonmint quote subscription expiredwhen every subscribed mint quote is unpaid andexpiry <= now.get_mint_quote.Verification
Local mint:
POST and GET both return matching expiry:
{ "quote": "k4D70Q30zKmxgnAGmxGcGLYSdRNKL71TXj8ZRttb", "state": "UNPAID", "expiry": 1780484602 }WebSocket (python3 /tmp/ws_quote_hold.py "$QUOTE_ID"), ~60s after quote creation:
Mint log:
After expiry, GET still returns state: "UNPAID" with expiry set expected: state tracks payment/mint progress; expiry is a separate deadline. Clients treat UNPAID + expiry < now as dead; POST /v1/mint/bolt11 rejects with quote expired.
Test plan