diff --git a/www/js/version.json b/www/js/version.json index 8920f67..1e3ee75 100644 --- a/www/js/version.json +++ b/www/js/version.json @@ -1,5 +1,5 @@ { - "VERSION": "v0.7.68", - "VERSION_NUMBER": "0.7.68", - "BUILD_DATE": "2026-06-30T13:15:02.809Z" + "VERSION": "v0.7.69", + "VERSION_NUMBER": "0.7.69", + "BUILD_DATE": "2026-06-30T13:19:30.001Z" } diff --git a/www/ndk-worker.js b/www/ndk-worker.js index f3f56a0..18a8611 100644 --- a/www/ndk-worker.js +++ b/www/ndk-worker.js @@ -4616,8 +4616,13 @@ async function handleWalletPayInvoice(requestId, invoice, mint, port) { const meltQuote = await wallet.createMeltQuote(pr); const quoteAmount = Number(meltQuote?.amount || 0); const quoteFeeReserve = Number(meltQuote?.fee_reserve || 0); + // The mint's quoted fee_reserve is an estimate; the actual melt fee can be + // slightly higher, causing "not enough inputs provided for melt" errors. + // Add a safety buffer — any overpayment is returned as change proofs. + const FEE_RESERVE_BUFFER_SATS = 10; const required = quoteAmount + quoteFeeReserve; - log('mint attempt:quote', { mintUrl, quoteAmount, quoteFeeReserve, required }); + const sendAmount = required + FEE_RESERVE_BUFFER_SATS; + log('mint attempt:quote', { mintUrl, quoteAmount, quoteFeeReserve, required, sendAmount }); if (!Number.isFinite(required) || required <= 0) { log('mint attempt:invalid-quote', { mintUrl, required }); @@ -4625,28 +4630,28 @@ async function handleWalletPayInvoice(requestId, invoice, mint, port) { continue; } - if (proofBalance < required) { - log('mint attempt:insufficient', { mintUrl, proofBalance, required }); + if (proofBalance < sendAmount) { + log('mint attempt:insufficient', { mintUrl, proofBalance, sendAmount }); attemptErrors.push({ mint: mintUrl, message: `Insufficient funds on mint (${proofBalance} sats)` }); continue; } - const sendResult = await wallet.send(required, proofs); + const sendResult = await wallet.send(sendAmount, proofs); const keep = Array.isArray(sendResult?.keep) ? sendResult.keep : []; const sendProofs = Array.isArray(sendResult?.send) ? sendResult.send : []; - log('mint attempt:send-split', { mintUrl, keepCount: keep.length, sendCount: sendProofs.length }); + log('mint attempt:send-split', { mintUrl, keepCount: keep.length, sendCount: sendProofs.length, sendAmount }); const meltResult = await wallet.meltProofs(meltQuote, sendProofs); const change = Array.isArray(meltResult?.change) ? meltResult.change : []; upsertMintProofs(mintUrl, [...keep, ...change]); const changeAmount = getProofTotal(change); - const spentAmount = Math.max(0, required - changeAmount); + const spentAmount = Math.max(0, sendAmount - changeAmount); paidAmountSats = Number.isFinite(quoteAmount) && quoteAmount > 0 ? quoteAmount : spentAmount; - log('mint attempt:success', { mintUrl, paidAmountSats, changeAmount, preimage: meltResult?.preimage || null }); + log('mint attempt:success', { mintUrl, paidAmountSats, changeAmount, spentAmount, preimage: meltResult?.preimage || null }); usedMint = mintUrl; payResult = meltResult;