import type { Proof } from "@cashu/cashu-ts"; import type NDK from "@nostr-dev-kit/ndk"; import { NDKCashuToken, type NDKNutzap } from "@nostr-dev-kit/ndk"; import { createOutTxEvent } from "../cashu/wallet/txs.js"; import type { RedeemNutzapsOpts } from "../index.js"; import type { NDKNWCWallet } from "./index.js"; export async function redeemNutzaps( this: NDKNWCWallet, nutzaps: NDKNutzap[], privkey: string, { cashuWallet, proofs, mint }: RedeemNutzapsOpts, ): Promise { proofs ??= nutzaps.flatMap((n) => n.proofs); if (!cashuWallet) { if (!mint) throw new Error("No mint provided"); cashuWallet = await this.getCashuWallet(mint); } else { mint = cashuWallet.mint.mintUrl; } const info = await this.getInfo(); if (!info.methods.includes("make_invoice")) throw new Error("This NWC wallet does not support making invoices"); // get the total amount of the proofs const totalAvailable = proofs.reduce((acc, proof) => acc + proof.amount, 0); let sweepAmount = totalAvailable; while (sweepAmount > 0) { const invoice = await this.makeInvoice(sweepAmount * 1000, "Nutzap redemption"); const meltQuote = await cashuWallet.createMeltQuote(invoice.invoice); const totalRequired = meltQuote.amount + meltQuote.fee_reserve; if (totalRequired > totalAvailable) { sweepAmount -= meltQuote.fee_reserve; continue; } const result = await cashuWallet.meltProofs(meltQuote, proofs, { privkey }); let change: NDKCashuToken | undefined; if (result.change.length > 0) change = await saveChange(this.ndk, mint, result.change); const description = `Nutzap redemption to external wallet (${this.walletId})`; createOutTxEvent( this.ndk, { pr: invoice.invoice, paymentDescription: description, }, { result: { preimage: invoice.preimage }, mint: mint, fee: meltQuote.fee_reserve, proofsChange: { store: change?.proofs, mint }, stateUpdate: { created: change, }, }, this.relaySet, { nutzaps }, ); return sweepAmount; } throw new Error("Failed to redeem nutzaps"); } async function saveChange(ndk: NDK, mint: string, change: Proof[]): Promise { const totalChange = change.reduce((acc, proof) => acc + proof.amount, 0); if (totalChange === 0) return; const token = new NDKCashuToken(ndk); token.mint = mint; token.proofs = change; token.publish(); return token; }