diff --git a/package-lock.json b/package-lock.json index e859c3b..3e53753 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "@quasar/extras": "^2.0.4", "@scure/bip32": "^2.3.0", "@scure/bip39": "^2.3.0", - "lnurlcash-kit": "0.1.1", + "lnurlcash-kit": "0.5.0", "nostr-tools": "2.24.3", "pinia": "^4.0.2", "qrcode.vue": "^3.10.0", @@ -46,7 +46,7 @@ "eslint": "^10.8.0", "eslint-plugin-vue": "^10.8.0", "globals": "^17.4.0", - "lnurlcash-conformance": "0.1.1", + "lnurlcash-conformance": "0.4.0", "postcss": "^8.5.8", "prettier": "^3.8.1", "sass": "^1.102.0", @@ -5961,9 +5961,9 @@ } }, "node_modules/lnurlcash-conformance": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/lnurlcash-conformance/-/lnurlcash-conformance-0.1.1.tgz", - "integrity": "sha512-12EXkom7x+tpkk4Pi2zanlMbDpA64hh+b5PKTPoKfahiWPG3GQbNusun1NHKpYjNwyevRISTP9487W+ZqEuEZw==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/lnurlcash-conformance/-/lnurlcash-conformance-0.4.0.tgz", + "integrity": "sha512-PsmjMrle5DE+OeTxLdBRD6ah63m9XPpNlPvB9f4FUdCtI6FbW6k5HcinMMt0mTkd9X9iOZHKG9SIqZ5HQJ0BDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5987,9 +5987,9 @@ } }, "node_modules/lnurlcash-kit": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/lnurlcash-kit/-/lnurlcash-kit-0.1.1.tgz", - "integrity": "sha512-O1rak4hcoKIBZdtbCMfQhCS4hp9HducJeJf8nEYxbPXtFm83EyPBqOAwWHYkzJMFKnyTqjJmvjjzfgL3ePQQOw==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/lnurlcash-kit/-/lnurlcash-kit-0.5.0.tgz", + "integrity": "sha512-ASX+/yduZjV9aLSoUXlP06dWNJ6Bt3IYrG0QoAqtvnC1h8lCs5rWVzw9RgmE0j1sZs16V2RicDlaSvON4JV8Pg==", "license": "MIT", "dependencies": { "@noble/curves": "^2.3.0", diff --git a/package.json b/package.json index 5a68016..e5fb4d1 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@quasar/extras": "^2.0.4", "@scure/bip32": "^2.3.0", "@scure/bip39": "^2.3.0", - "lnurlcash-kit": "0.1.1", + "lnurlcash-kit": "0.5.0", "nostr-tools": "2.24.3", "pinia": "^4.0.2", "qrcode.vue": "^3.10.0", @@ -57,7 +57,7 @@ "eslint": "^10.8.0", "eslint-plugin-vue": "^10.8.0", "globals": "^17.4.0", - "lnurlcash-conformance": "0.1.1", + "lnurlcash-conformance": "0.4.0", "postcss": "^8.5.8", "prettier": "^3.8.1", "sass": "^1.102.0", diff --git a/src/lnurlcash/mintContract.test.ts b/src/lnurlcash/mintContract.test.ts index fd7c4aa..e9f6c3a 100644 --- a/src/lnurlcash/mintContract.test.ts +++ b/src/lnurlcash/mintContract.test.ts @@ -116,9 +116,10 @@ describe('mint-address wire contract', () => { describe('withdraw-link forms', () => { it('accepts the lnurlw:// withdraw link the conformance mock mint advertises', async () => { - const m = await mint({testHooks: true}) + // conformance 0.4.0 defaults to plain https links; lnurlw:// (the form + // lnurl-mint emits under LUD-17) is an explicit option + const m = await mint({testHooks: true, withdrawLinkForm: 'lnurlw'}) const prepared = await prepareMint(`mint@127.0.0.1:${m.port}`, 21_000) - // published conformance 0.1.1 emits lnurlw:// by default - NOT https expect(prepared.withdrawLink).toMatch(/^lnurlw:\/\//) // and the link is fully usable: settle the invoice, claim the note diff --git a/src/lnurlcash/ops.mint-receive.cases.ts b/src/lnurlcash/ops.mint-receive.cases.ts index 9649448..3989d7c 100644 --- a/src/lnurlcash/ops.mint-receive.cases.ts +++ b/src/lnurlcash/ops.mint-receive.cases.ts @@ -2,7 +2,6 @@ import {describe, expect, it} from 'vitest' import { NoteSpentError, PendingNoteError, - buildNoteUrl, fetchNoteInfo, meltNote, noteK1, @@ -39,14 +38,32 @@ describe('mint -> claim -> rotate', () => { const instance = await mint({testHooks: true, baseFeeMsat: 1_000, feePpm: 2_000}) const prepared = await prepareMint(`mint@127.0.0.1:${instance.port}`, 100_000) expect(prepared.grossMsat).toBeGreaterThan(100_000) - const preimage = await settleLastInvoice(instance) - const info = await fetchNoteInfo( - buildNoteUrl(prepared.withdrawLink, preimage, prepared.expectedNoteValueMsat), - ) - expect(info.maxWithdrawable).toBeGreaterThanOrEqual(99_000) - expect(info.maxWithdrawable).toBeLessThanOrEqual(prepared.grossMsat) + await settleLastInvoice(instance) + const claimed = await claimMintedNote(prepared, { + intervalMs: 10, + intervalCapMs: 20, + maxWaitMs: 5_000, + }) + // the service's maxWithdrawable is authoritative: the fee is withheld + // from the gross, so the note nets between the asked value and the gross + expect(claimed.note.amount).toBeGreaterThanOrEqual(99_000) + expect(claimed.note.amount).toBeLessThanOrEqual(prepared.grossMsat) + expect(claimed.rotated).toBe(true) + }) + + it('refuses a verify response naming a different invoice', async () => { + const instance = await mint({testHooks: true}) + const prepared = await prepareMint(`mint@127.0.0.1:${instance.port}`, 21_000) + await settleLastInvoice(instance) + // a verify answer that names any invoice but the requested one must + // stop the claim - the preimage it carries belongs to another payment + const other = `${prepared.invoice.slice(0, -1)}${prepared.invoice.endsWith('q') ? 'p' : 'q'}` await expect( - claimMintedNote(prepared, {intervalMs: 10, intervalCapMs: 20, maxWaitMs: 500}), + claimMintedNote({...prepared, invoice: other}, { + intervalMs: 10, + intervalCapMs: 20, + maxWaitMs: 5_000, + }), ).rejects.toThrow(/different invoice/) })