mirror of
https://github.com/minibits-cash/minibits_wallet.git
synced 2026-10-05 19:28:26 +00:00
One melt lifecycle, two rails. TransferOperationApi now handles both bolt11 (NUT-05) and onchain (NUT-30) melts; what differs between them is resolved once in resolveTransferMethod rather than branched on at each site that needs a fee or an expiry. There is deliberately one copy of the proof reservation, the preemptive swap, and the execute-error recovery matrix. cashu-ts' prepareMelt is already method-agnostic (it derives the NUT-08 blank count from inputs - quote.amount, not from fee_reserve), and fee_index rides along as extraPayload on completeMelt. So the prepare -> persist meltPreview -> complete split that melt-change recovery depends on survives intact. Substance, beyond the plumbing: - Onchain change can arrive at PENDING. The mint knows its miner fee the moment it builds the transaction, so it may return the unclaimed reserve with the spec-mandated PENDING response. bolt11's PENDING branch drops change on the floor (correctly - there is none yet); doing that here would strand signed proofs that nothing would ever look for again. execute() now commits change if present, and _finalizePaid subtracts what was already returned so banked change is not reported as fee. - Settlement is quote-driven, not proof-driven. The mint spending our inputs means it BROADCAST, not that the transaction confirmed. sync's _dispatchFinalize therefore routes TRANSFER_ONCHAIN to refresh() (which asks the mint and only completes on PAID) rather than finalize(), and sync now reports the status the dispatch actually reached instead of assuming COMPLETED - otherwise it would announce a Bitcoin payment as landed while it sat unconfirmed in the mempool. - Onchain transfers are never expired. The melt quote's expiry bounds executing the quote, not confirming the payment, which can outlive it by many blocks. - Mainnet only. The CDK fakewallet hands out regtest deposit addresses for topup quotes, so testers end up with one in their clipboard; pasting it back into Pay must not spend. Refused in the parser and again in prepare(), so a screen that forgets the check cannot move money. No websocket and no poller for onchain: settlement is bounded by block times, so the existing ~60s pending sweep is already finer-grained than what it waits for. Melts go through SyncQueue for the same counter-serialisation reason mints do. 87 tsc errors (unchanged baseline), 310/310 tests, i18n clean.