diff --git a/src/CashuWallet.ts b/src/CashuWallet.ts index 0442bb04e..3c684eb3b 100644 --- a/src/CashuWallet.ts +++ b/src/CashuWallet.ts @@ -415,6 +415,7 @@ class CashuWallet { * @param proofsToSend proofs to melt * @param options.keysetId? optionally set keysetId for blank outputs for returned change. * @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect + * @param options.privkey? optionally set a private key to unlock P2PK locked secrets * @returns */ async meltTokens( @@ -423,6 +424,7 @@ class CashuWallet { options?: { keysetId?: string; counter?: number; + privkey?: string; } ): Promise { const keys = await this.getKeys(options?.keysetId); @@ -432,6 +434,19 @@ class CashuWallet { keys.id, options?.counter ); + if (options?.privkey != undefined) { + proofsToSend = getSignedProofs( + proofsToSend.map((p) => { + return { + amount: p.amount, + C: pointFromHex(p.C), + id: p.id, + secret: new TextEncoder().encode(p.secret) + }; + }), + options.privkey + ).map((p: NUT11Proof) => serializeProof(p)); + } const meltPayload: MeltPayload = { quote: meltQuote.quote, inputs: proofsToSend, @@ -456,6 +471,7 @@ class CashuWallet { * @param meltQuote melt quote for the invoice * @param options.keysetId? optionally set keysetId for blank outputs for returned change. * @param options.counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect + * @param options.privkey? optionally set a private key to unlock P2PK locked secrets * @returns */ async payLnInvoice( @@ -465,6 +481,7 @@ class CashuWallet { options?: { keysetId?: string; counter?: number; + privkey?: string; } ): Promise { if (!meltQuote) { @@ -472,7 +489,8 @@ class CashuWallet { } return await this.meltTokens(meltQuote, proofsToSend, { keysetId: options?.keysetId, - counter: options?.counter + counter: options?.counter, + privkey: options?.privkey }); } diff --git a/test/integration.test.ts b/test/integration.test.ts index 2d069392d..64577585c 100644 --- a/test/integration.test.ts +++ b/test/integration.test.ts @@ -213,4 +213,27 @@ describe('mint api', () => { }, 0) ).toBe(64); }); + + test('mint and melt p2pk', async () => { + const mint = new CashuMint(mintUrl); + const wallet = new CashuWallet(mint); + + const privKeyBob = secp256k1.utils.randomPrivateKey(); + const pubKeyBob = secp256k1.getPublicKey(privKeyBob); + + const mintRequest = await wallet.createMintQuote(3000); + + const proofs = await wallet.mintTokens(3000, mintRequest.quote, { + pubkey: bytesToHex(pubKeyBob) + }); + + const meltRequest = await wallet.createMeltQuote(externalInvoice); + const fee = meltRequest.fee_reserve; + expect(fee).toBeGreaterThan(0); + const response = await wallet.meltTokens(meltRequest, proofs.proofs, { + privkey: bytesToHex(privKeyBob) + }); + expect(response).toBeDefined(); + expect(response.isPaid).toBe(true); + }); });