import { type CashuWallet, CheckStateEnum, type Proof } from "@cashu/cashu-ts"; import type { NDKNutzap } from "@nostr-dev-kit/ndk"; /** * Checks which proofs are unspent and returns the nutzap ids and proofs. * * It performs a sanity check on the proofs to ensure that we can spend them. * @param wallet * @param nutzaps * @param pubkeys -- Pubkeys the caller has the private key to, to make sure the proofs are not p2pk-locked to a key we do not have access to * @returns */ export async function getProofSpendState(wallet: CashuWallet, nutzaps: NDKNutzap[]): Promise { const result: GetProofSpendStateResult = { unspentProofs: [], spentProofs: [], nutzapsWithUnspentProofs: [], nutzapsWithSpentProofs: [], }; const proofCs = new Set(); const proofs: Proof[] = []; const nutzapMap = new Map(); // Map proof C to nutzap // Collect unique proofs for (const nutzap of nutzaps) { for (const proof of nutzap.proofs) { if (proofCs.has(proof.C)) continue; proofCs.add(proof.C); proofs.push(proof); nutzapMap.set(proof.C, nutzap); } } const states = await wallet.checkProofsStates(proofs); for (let i = 0; i < states.length; i++) { const state = states[i]; const proof = proofs[i]; const nutzap = nutzapMap.get(proof.C); if (!nutzap) continue; if (state.state === CheckStateEnum.SPENT) { result.spentProofs.push(proof); if (!result.nutzapsWithSpentProofs.some((n) => n.id === nutzap.id)) { result.nutzapsWithSpentProofs.push(nutzap); } } else if (state.state === CheckStateEnum.UNSPENT) { result.unspentProofs.push(proof); if (!result.nutzapsWithUnspentProofs.some((n) => n.id === nutzap.id)) { result.nutzapsWithUnspentProofs.push(nutzap); } } } return result; } type GetProofSpendStateResult = { unspentProofs: Proof[]; spentProofs: Proof[]; nutzapsWithUnspentProofs: NDKNutzap[]; nutzapsWithSpentProofs: NDKNutzap[]; };