lnurlcash-kit 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  Semantic versioning. While the LUD-25 draft is unmerged, `0.x` minor bumps
4
4
  may carry breaking changes; pin an exact version.
5
5
 
6
+ ## 0.3.0 - 2026-08-24
7
+
8
+ - Additive bound-mint receipt parsing and validation for sealed signers:
9
+ `InvoiceResult.mint`, `VerifyResult.mint`, `requireBoundMintQuote` and
10
+ `validateBoundMintReceipt`. The quote must commit the requested `h` and
11
+ exact net amount before payment; the settled LUD-21 response must match the
12
+ invoice and commitment and carry a valid ordinary LUD-25 note signature.
13
+ - `noteSignatureMessageForHash`, `noteSignatureDigestForHash`,
14
+ `verifyNoteSignatureHash` and `verifyNoteSignatureHashAgainst` expose the
15
+ existing signature construction when a signer deliberately retains `k1`.
16
+ Existing secret-based helpers delegate to them unchanged.
17
+
6
18
  ## 0.2.1 - 2026-08-22
7
19
 
8
20
  - `WithdrawRequestInfo` carries `payLink`, the way home a SERVICE may
package/README.md CHANGED
@@ -358,6 +358,47 @@ is yours from the moment it exists. The claim GET does show the secret to the
358
358
  mint it is a claim on, which is a different thing from showing it to whoever
359
359
  scanned the QR, and you can still rotate if you want the offline signature.
360
360
 
361
+ ### A sealed signer: confirm without exporting the secret
362
+
363
+ A hardware vault cannot use the claim GET above without handing `k1` to its
364
+ companion. A receipt-capable mint can instead commit the quote to the requested
365
+ `h` and exact net amount, then place the ordinary LUD-25 note signature on its
366
+ settled LUD-21 response. The extension is optional; absence means use the
367
+ unchanged preimage-import-and-rotate flow before showing an invoice.
368
+
369
+ ```ts
370
+ import {
371
+ requestInvoice, fetchInvoiceVerification,
372
+ requireBoundMintQuote, validateBoundMintReceipt
373
+ } from 'lnurlcash-kit'
374
+
375
+ const staged = await vault.newSecret() // {id, h}; k1 stays in the vault
376
+ const expectedNetMsat = 21_000
377
+ const quote = await requestInvoice(pay.callback, 21_000, {h: staged.h})
378
+
379
+ // Do this before displaying or paying quote.pr.
380
+ requireBoundMintQuote(quote, staged.h, expectedNetMsat)
381
+ if (!quote.verify) throw new Error('No settlement receipt offered')
382
+
383
+ // After payment, poll quote.verify until settled.
384
+ const verification = await fetchInvoiceVerification(quote.verify)
385
+ const receipt = validateBoundMintReceipt(
386
+ quote,
387
+ verification,
388
+ staged.h,
389
+ expectedNetMsat,
390
+ pinnedMintPubkeys
391
+ )
392
+ await vault.confirm(staged.id, receipt.amountMsat, mintHost, receipt.signature)
393
+ ```
394
+
395
+ `quote.mint` is `{h, amountMsat}` in the typed API (`amount` on the wire).
396
+ The settled response must repeat that commitment and add `signature` (`sig`
397
+ on the wire). Validation matches the invoice, output and amount, refuses a
398
+ pre-settlement signature, and recovers the signer against the pinned current
399
+ or previous mint keys. The payment preimage remains proof of payment; it never
400
+ replaces the vault's staged secret.
401
+
361
402
  ## Asking to be paid
362
403
 
363
404
  "Send me 500 sat" today means handing over a Lightning Address, which is a
package/dist/index.d.ts CHANGED
@@ -133,6 +133,15 @@ type InvoiceResult = {
133
133
  verify?: string;
134
134
  disposable: boolean;
135
135
  mintToHash: boolean;
136
+ mint?: BoundMintCommitment;
137
+ };
138
+ type BoundMintCommitment = {
139
+ h: string;
140
+ amountMsat: number;
141
+ signature?: string;
142
+ };
143
+ type ValidatedBoundMintReceipt = Required<BoundMintCommitment> & {
144
+ pubkey: string;
136
145
  };
137
146
  type InvoiceRequestOptions = LnurlcashOptions & {
138
147
  h?: string;
@@ -142,8 +151,11 @@ type VerifyResult = {
142
151
  settled: boolean;
143
152
  preimage: string | null;
144
153
  pr: string;
154
+ mint?: BoundMintCommitment;
145
155
  };
146
156
  declare const fetchInvoiceVerification: (verifyUrl: string, options?: LnurlcashOptions) => Promise<VerifyResult>;
157
+ declare const requireBoundMintQuote: (invoice: InvoiceResult, expectedH: string, expectedAmountMsat: number) => BoundMintCommitment;
158
+ declare const validateBoundMintReceipt: (invoice: InvoiceResult, verification: VerifyResult, expectedH: string, expectedAmountMsat: number, mintPubkeys: string | string[]) => ValidatedBoundMintReceipt;
147
159
  type MintClaim = {
148
160
  state: 'minted' | 'unminted' | 'pending' | 'spent';
149
161
  k1: string;
@@ -226,7 +238,9 @@ declare const decodePaymentRequest: (value: string, { now }?: DecodeOptions) =>
226
238
  declare const isPaymentRequest: (value: string) => boolean;
227
239
 
228
240
  declare const noteSignatureMessage: (k1: string, amountMsat: number) => string;
241
+ declare const noteSignatureMessageForHash: (h: string, amountMsat: number) => string;
229
242
  declare const noteSignatureDigest: (k1: string, amountMsat: number) => Uint8Array;
243
+ declare const noteSignatureDigestForHash: (h: string, amountMsat: number) => Uint8Array;
230
244
  type SignatureCheck = {
231
245
  valid: true;
232
246
  pubkey: string;
@@ -235,7 +249,9 @@ type SignatureCheck = {
235
249
  pubkey: null;
236
250
  };
237
251
  declare const verifyNoteSignatureAgainst: (k1: string, amountMsat: number, signatureHex: string, mintPubkeys: string | string[]) => SignatureCheck;
252
+ declare const verifyNoteSignatureHashAgainst: (h: string, amountMsat: number, signatureHex: string, mintPubkeys: string | string[]) => SignatureCheck;
238
253
  declare const verifyNoteSignature: (k1: string, amountMsat: number, signatureHex: string, mintPubkeys: string | string[]) => boolean;
254
+ declare const verifyNoteSignatureHash: (h: string, amountMsat: number, signatureHex: string, mintPubkeys: string | string[]) => boolean;
239
255
 
240
256
  declare const isBolt11Invoice: (value: string) => boolean;
241
257
  declare const sameInvoice: (a: string, b: string) => boolean;
@@ -297,4 +313,4 @@ declare const createClient: (options?: LnurlcashOptions) => {
297
313
  };
298
314
  type LnurlcashClient = ReturnType<typeof createClient>;
299
315
 
300
- export { AmbiguousMintError, AmbiguousMutationError, type DecodeOptions, type HashedMutationResult, type HashedSplitResult, InsufficientValueError, type InvoiceRequestOptions, type InvoiceResult, type LnurlcashClient, LnurlcashError, type LnurlcashOptions, type MeltResult, type MintAddressInfo, type MintClaim, type MintContact, type MintFee, type MintFeeBand, NoteSpentError, NoteUnknownError, PAYMENT_REQUEST_PREFIX, type PayRequestInfo, type PaymentRequest, type PaymentRequestMethodDetails, PendingNoteError, ProtocolError, type RandomSecret, RequestRefusedError, type RestoreOptions, type RestoreResult, type RestoredNote, type RotateResult, ServiceRejectedError, type SettleForValueOptions, type SettledForValue, type SettledNote, type SignatureCheck, type SplitResult, type VerifyResult, type WithdrawRequestInfo, type WithdrawSuccessResponse, applyMintFee, buildNoteUrl, claimMintedNote, classifyNoteError, createClient, decodeBolt11AmountMsat, decodePaymentRequest, defaultRandomSecret, deriveNoteRoot, deriveNoteSecret, derivedSecretSource, describeMintFee, encodePaymentRequest, fetchInvoiceVerification, fetchMintAddress, fetchNoteInfo, fetchPayRequest, formatFeePercent, fromBech32Lnurl, fromLud17, grossUpForMintFee, hashK1, isAllowedServiceUrl, isBech32Lnurl, isBolt11Invoice, isLightningAddress, isPaymentRequest, isPreimage, isValidNoteInput, lightningAddressUsername, meltNote, mergeNotes, mergeNotesWithHash, mintAddressUrl, mintFeeBand, newSecretsOf, noteDeclaredAmount, noteK1, noteSignature, noteSignatureDigest, noteSignatureMessage, parseMintFee, paymentRequestAmountMsat, probeBurnedNote, requestInvoice, requireNoteK1, resolveLnurlInput, resolveMintInput, resolveNoteInput, restoreNotes, rotateNote, rotateNoteWithHash, sameInvoice, serverOf, settleNote, settleNoteForValue, splitNote, splitNoteWithHash, toBech32Lnurl, toLud17w, verifyNoteSignature, verifyNoteSignatureAgainst, withNewK1, withinMintFeeBand, withoutK1 };
316
+ export { AmbiguousMintError, AmbiguousMutationError, type BoundMintCommitment, type DecodeOptions, type HashedMutationResult, type HashedSplitResult, InsufficientValueError, type InvoiceRequestOptions, type InvoiceResult, type LnurlcashClient, LnurlcashError, type LnurlcashOptions, type MeltResult, type MintAddressInfo, type MintClaim, type MintContact, type MintFee, type MintFeeBand, NoteSpentError, NoteUnknownError, PAYMENT_REQUEST_PREFIX, type PayRequestInfo, type PaymentRequest, type PaymentRequestMethodDetails, PendingNoteError, ProtocolError, type RandomSecret, RequestRefusedError, type RestoreOptions, type RestoreResult, type RestoredNote, type RotateResult, ServiceRejectedError, type SettleForValueOptions, type SettledForValue, type SettledNote, type SignatureCheck, type SplitResult, type ValidatedBoundMintReceipt, type VerifyResult, type WithdrawRequestInfo, type WithdrawSuccessResponse, applyMintFee, buildNoteUrl, claimMintedNote, classifyNoteError, createClient, decodeBolt11AmountMsat, decodePaymentRequest, defaultRandomSecret, deriveNoteRoot, deriveNoteSecret, derivedSecretSource, describeMintFee, encodePaymentRequest, fetchInvoiceVerification, fetchMintAddress, fetchNoteInfo, fetchPayRequest, formatFeePercent, fromBech32Lnurl, fromLud17, grossUpForMintFee, hashK1, isAllowedServiceUrl, isBech32Lnurl, isBolt11Invoice, isLightningAddress, isPaymentRequest, isPreimage, isValidNoteInput, lightningAddressUsername, meltNote, mergeNotes, mergeNotesWithHash, mintAddressUrl, mintFeeBand, newSecretsOf, noteDeclaredAmount, noteK1, noteSignature, noteSignatureDigest, noteSignatureDigestForHash, noteSignatureMessage, noteSignatureMessageForHash, parseMintFee, paymentRequestAmountMsat, probeBurnedNote, requestInvoice, requireBoundMintQuote, requireNoteK1, resolveLnurlInput, resolveMintInput, resolveNoteInput, restoreNotes, rotateNote, rotateNoteWithHash, sameInvoice, serverOf, settleNote, settleNoteForValue, splitNote, splitNoteWithHash, toBech32Lnurl, toLud17w, validateBoundMintReceipt, verifyNoteSignature, verifyNoteSignatureAgainst, verifyNoteSignatureHash, verifyNoteSignatureHashAgainst, withNewK1, withinMintFeeBand, withoutK1 };
package/dist/index.js CHANGED
@@ -627,6 +627,62 @@ var describeMintFee = (fee) => [
627
627
  fee.baseFeeMsat > 0 ? `${Math.round(fee.baseFeeMsat / 1e3)} sat flat` : null,
628
628
  fee.feePpm > 0 ? `${formatFeePercent(fee.feePpm)}% of the amount paid` : null
629
629
  ].filter(Boolean).join(" + ");
630
+ var LIGHTNING_SIGNED_MESSAGE_PREFIX = utf8ToBytes("Lightning Signed Message:");
631
+ var noteSignatureMessage = (k1, amountMsat) => noteSignatureMessageForHash(hashK1(k1), amountMsat);
632
+ var noteSignatureMessageForHash = (h, amountMsat) => `LNURLcash:${amountMsat}:${h.trim().toLowerCase()}`;
633
+ var noteSignatureDigest = (k1, amountMsat) => noteSignatureDigestForHash(hashK1(k1), amountMsat);
634
+ var noteSignatureDigestForHash = (h, amountMsat) => sha256(
635
+ sha256(
636
+ new Uint8Array([
637
+ ...LIGHTNING_SIGNED_MESSAGE_PREFIX,
638
+ ...utf8ToBytes(noteSignatureMessageForHash(h, amountMsat))
639
+ ])
640
+ )
641
+ );
642
+ var NO_MATCH = { valid: false, pubkey: null };
643
+ var verifyNoteSignatureAgainst = (k1, amountMsat, signatureHex, mintPubkeys) => {
644
+ let h;
645
+ try {
646
+ h = hashK1(k1);
647
+ } catch {
648
+ return NO_MATCH;
649
+ }
650
+ return verifyNoteSignatureHashAgainst(h, amountMsat, signatureHex, mintPubkeys);
651
+ };
652
+ var verifyNoteSignatureHashAgainst = (h, amountMsat, signatureHex, mintPubkeys) => {
653
+ const targets = (Array.isArray(mintPubkeys) ? mintPubkeys : [mintPubkeys]).filter((key) => typeof key === "string").map((key) => key.trim().toLowerCase());
654
+ if (targets.length === 0) return NO_MATCH;
655
+ let wireSig;
656
+ try {
657
+ wireSig = hexToBytes(signatureHex);
658
+ } catch {
659
+ return NO_MATCH;
660
+ }
661
+ if (wireSig.length !== 65) return NO_MATCH;
662
+ let digest;
663
+ try {
664
+ if (!/^[0-9a-fA-F]{64}$/.test(h.trim())) return NO_MATCH;
665
+ digest = noteSignatureDigestForHash(h, amountMsat);
666
+ } catch {
667
+ return NO_MATCH;
668
+ }
669
+ const recoveryIdFirst = new Uint8Array([
670
+ wireSig[64],
671
+ ...wireSig.subarray(0, 64)
672
+ ]);
673
+ for (const candidate of [recoveryIdFirst, wireSig]) {
674
+ try {
675
+ const recovered = bytesToHex(
676
+ secp256k1.recoverPublicKey(candidate, digest, { prehash: false })
677
+ );
678
+ if (targets.includes(recovered)) return { valid: true, pubkey: recovered };
679
+ } catch {
680
+ }
681
+ }
682
+ return NO_MATCH;
683
+ };
684
+ var verifyNoteSignature = (k1, amountMsat, signatureHex, mintPubkeys) => verifyNoteSignatureAgainst(k1, amountMsat, signatureHex, mintPubkeys).valid;
685
+ var verifyNoteSignatureHash = (h, amountMsat, signatureHex, mintPubkeys) => verifyNoteSignatureHashAgainst(h, amountMsat, signatureHex, mintPubkeys).valid;
630
686
 
631
687
  // src/client.ts
632
688
  var fetchNoteInfo = async (url, options = {}) => {
@@ -905,6 +961,18 @@ var fetchPayRequest = async (url, options = {}) => {
905
961
  mintToHash: asBoolean(body.mintToHash)
906
962
  };
907
963
  };
964
+ var asBoundMintCommitment = (value) => {
965
+ if (!value || typeof value !== "object") return void 0;
966
+ const raw = value;
967
+ if (typeof raw.h !== "string" || !/^[0-9a-fA-F]{64}$/.test(raw.h) || typeof raw.amount !== "number" || !Number.isSafeInteger(raw.amount) || raw.amount <= 0 || raw.sig !== void 0 && typeof raw.sig !== "string") {
968
+ return void 0;
969
+ }
970
+ return {
971
+ h: raw.h.toLowerCase(),
972
+ amountMsat: raw.amount,
973
+ ...typeof raw.sig === "string" ? { signature: raw.sig } : {}
974
+ };
975
+ };
908
976
  var requestInvoice = async (payCallback, amountMsat, options = {}) => {
909
977
  const cbUrl = new URL(payCallback);
910
978
  cbUrl.searchParams.set("amount", String(amountMsat));
@@ -930,7 +998,8 @@ var requestInvoice = async (payCallback, amountMsat, options = {}) => {
930
998
  pr: body.pr,
931
999
  verify: typeof body.verify === "string" ? body.verify : void 0,
932
1000
  disposable: body.disposable !== false,
933
- mintToHash: body.mintToHash === true
1001
+ mintToHash: body.mintToHash === true,
1002
+ mint: asBoundMintCommitment(body.mint)
934
1003
  };
935
1004
  };
936
1005
  var fetchInvoiceVerification = async (verifyUrl, options = {}) => {
@@ -941,9 +1010,56 @@ var fetchInvoiceVerification = async (verifyUrl, options = {}) => {
941
1010
  return {
942
1011
  settled: body.settled,
943
1012
  preimage: typeof body.preimage === "string" ? body.preimage : null,
944
- pr: body.pr
1013
+ pr: body.pr,
1014
+ mint: asBoundMintCommitment(body.mint)
945
1015
  };
946
1016
  };
1017
+ var requireBoundMintQuote = (invoice, expectedH, expectedAmountMsat) => {
1018
+ const h = expectedH.trim().toLowerCase();
1019
+ if (!isPreimage(h)) throw new ProtocolError("The expected mint output hash is malformed.");
1020
+ if (!Number.isSafeInteger(expectedAmountMsat) || expectedAmountMsat <= 0) {
1021
+ throw new ProtocolError("The expected mint amount must be positive integer millisatoshis.");
1022
+ }
1023
+ if (!invoice.mintToHash || !invoice.mint) {
1024
+ throw new ProtocolError("The service did not commit this quote to a bound mint output.");
1025
+ }
1026
+ if (invoice.mint.h !== h) {
1027
+ throw new ProtocolError("The service committed the quote to a different mint output.");
1028
+ }
1029
+ if (invoice.mint.amountMsat !== expectedAmountMsat) {
1030
+ throw new ProtocolError("The service committed the quote to a different mint amount.");
1031
+ }
1032
+ if (invoice.mint.signature !== void 0) {
1033
+ throw new ProtocolError("The service signed a mint output before the invoice settled.");
1034
+ }
1035
+ return invoice.mint;
1036
+ };
1037
+ var validateBoundMintReceipt = (invoice, verification, expectedH, expectedAmountMsat, mintPubkeys) => {
1038
+ const quote = requireBoundMintQuote(invoice, expectedH, expectedAmountMsat);
1039
+ if (!verification.settled) {
1040
+ throw new ProtocolError("The invoice has not settled.");
1041
+ }
1042
+ if (!sameInvoice(invoice.pr, verification.pr)) {
1043
+ throw new ProtocolError("The settlement receipt names a different invoice.");
1044
+ }
1045
+ const receipt = verification.mint;
1046
+ if (!receipt || receipt.h !== quote.h || receipt.amountMsat !== quote.amountMsat) {
1047
+ throw new ProtocolError("The settlement receipt does not match the mint quote.");
1048
+ }
1049
+ if (!receipt.signature) {
1050
+ throw new ProtocolError("The settled mint receipt has no note signature.");
1051
+ }
1052
+ const checked = verifyNoteSignatureHashAgainst(
1053
+ receipt.h,
1054
+ receipt.amountMsat,
1055
+ receipt.signature,
1056
+ mintPubkeys
1057
+ );
1058
+ if (!checked.valid) {
1059
+ throw new ProtocolError("The settled mint receipt has an invalid note signature.");
1060
+ }
1061
+ return { ...receipt, signature: receipt.signature, pubkey: checked.pubkey };
1062
+ };
947
1063
  var claimMintedNote = async (withdrawLink, k1, options = {}) => {
948
1064
  const secret = k1.trim().toLowerCase();
949
1065
  if (!isPreimage(secret)) {
@@ -971,49 +1087,6 @@ var claimMintedNote = async (withdrawLink, k1, options = {}) => {
971
1087
  throw err;
972
1088
  }
973
1089
  };
974
- var LIGHTNING_SIGNED_MESSAGE_PREFIX = utf8ToBytes("Lightning Signed Message:");
975
- var noteSignatureMessage = (k1, amountMsat) => `LNURLcash:${amountMsat}:${hashK1(k1)}`;
976
- var noteSignatureDigest = (k1, amountMsat) => sha256(
977
- sha256(
978
- new Uint8Array([
979
- ...LIGHTNING_SIGNED_MESSAGE_PREFIX,
980
- ...utf8ToBytes(noteSignatureMessage(k1, amountMsat))
981
- ])
982
- )
983
- );
984
- var NO_MATCH = { valid: false, pubkey: null };
985
- var verifyNoteSignatureAgainst = (k1, amountMsat, signatureHex, mintPubkeys) => {
986
- const targets = (Array.isArray(mintPubkeys) ? mintPubkeys : [mintPubkeys]).filter((key) => typeof key === "string").map((key) => key.trim().toLowerCase());
987
- if (targets.length === 0) return NO_MATCH;
988
- let wireSig;
989
- try {
990
- wireSig = hexToBytes(signatureHex);
991
- } catch {
992
- return NO_MATCH;
993
- }
994
- if (wireSig.length !== 65) return NO_MATCH;
995
- let digest;
996
- try {
997
- digest = noteSignatureDigest(k1, amountMsat);
998
- } catch {
999
- return NO_MATCH;
1000
- }
1001
- const recoveryIdFirst = new Uint8Array([
1002
- wireSig[64],
1003
- ...wireSig.subarray(0, 64)
1004
- ]);
1005
- for (const candidate of [recoveryIdFirst, wireSig]) {
1006
- try {
1007
- const recovered = bytesToHex(
1008
- secp256k1.recoverPublicKey(candidate, digest, { prehash: false })
1009
- );
1010
- if (targets.includes(recovered)) return { valid: true, pubkey: recovered };
1011
- } catch {
1012
- }
1013
- }
1014
- return NO_MATCH;
1015
- };
1016
- var verifyNoteSignature = (k1, amountMsat, signatureHex, mintPubkeys) => verifyNoteSignatureAgainst(k1, amountMsat, signatureHex, mintPubkeys).valid;
1017
1090
 
1018
1091
  // src/settle.ts
1019
1092
  var normaliseHost = (value) => serverOf(value.trim().replace(/^@/, "")).toLowerCase();
@@ -1119,4 +1192,4 @@ var createClient = (options = {}) => ({
1119
1192
  settleNoteForValue: (noteUrl, terms) => settleNoteForValue(noteUrl, terms, options)
1120
1193
  });
1121
1194
 
1122
- export { AmbiguousMintError, AmbiguousMutationError, InsufficientValueError, LnurlcashError, NoteSpentError, NoteUnknownError, PAYMENT_REQUEST_PREFIX, PendingNoteError, ProtocolError, RequestRefusedError, ServiceRejectedError, applyMintFee, buildNoteUrl, claimMintedNote, classifyNoteError, createClient, decodeBolt11AmountMsat, decodePaymentRequest, defaultRandomSecret, deriveNoteRoot, deriveNoteSecret, derivedSecretSource, describeMintFee, encodePaymentRequest, fetchInvoiceVerification, fetchMintAddress, fetchNoteInfo, fetchPayRequest, formatFeePercent, fromBech32Lnurl, fromLud17, grossUpForMintFee, hashK1, isAllowedServiceUrl, isBech32Lnurl, isBolt11Invoice, isLightningAddress, isPaymentRequest, isPreimage, isValidNoteInput, lightningAddressUsername, meltNote, mergeNotes, mergeNotesWithHash, mintAddressUrl, mintFeeBand, newSecretsOf, noteDeclaredAmount, noteK1, noteSignature, noteSignatureDigest, noteSignatureMessage, parseMintFee, paymentRequestAmountMsat, probeBurnedNote, requestInvoice, requireNoteK1, resolveLnurlInput, resolveMintInput, resolveNoteInput, restoreNotes, rotateNote, rotateNoteWithHash, sameInvoice, serverOf, settleNote, settleNoteForValue, splitNote, splitNoteWithHash, toBech32Lnurl, toLud17w, verifyNoteSignature, verifyNoteSignatureAgainst, withNewK1, withinMintFeeBand, withoutK1 };
1195
+ export { AmbiguousMintError, AmbiguousMutationError, InsufficientValueError, LnurlcashError, NoteSpentError, NoteUnknownError, PAYMENT_REQUEST_PREFIX, PendingNoteError, ProtocolError, RequestRefusedError, ServiceRejectedError, applyMintFee, buildNoteUrl, claimMintedNote, classifyNoteError, createClient, decodeBolt11AmountMsat, decodePaymentRequest, defaultRandomSecret, deriveNoteRoot, deriveNoteSecret, derivedSecretSource, describeMintFee, encodePaymentRequest, fetchInvoiceVerification, fetchMintAddress, fetchNoteInfo, fetchPayRequest, formatFeePercent, fromBech32Lnurl, fromLud17, grossUpForMintFee, hashK1, isAllowedServiceUrl, isBech32Lnurl, isBolt11Invoice, isLightningAddress, isPaymentRequest, isPreimage, isValidNoteInput, lightningAddressUsername, meltNote, mergeNotes, mergeNotesWithHash, mintAddressUrl, mintFeeBand, newSecretsOf, noteDeclaredAmount, noteK1, noteSignature, noteSignatureDigest, noteSignatureDigestForHash, noteSignatureMessage, noteSignatureMessageForHash, parseMintFee, paymentRequestAmountMsat, probeBurnedNote, requestInvoice, requireBoundMintQuote, requireNoteK1, resolveLnurlInput, resolveMintInput, resolveNoteInput, restoreNotes, rotateNote, rotateNoteWithHash, sameInvoice, serverOf, settleNote, settleNoteForValue, splitNote, splitNoteWithHash, toBech32Lnurl, toLud17w, validateBoundMintReceipt, verifyNoteSignature, verifyNoteSignatureAgainst, verifyNoteSignatureHash, verifyNoteSignatureHashAgainst, withNewK1, withinMintFeeBand, withoutK1 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lnurlcash-kit",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "LNURLcash (LUD-25) bearer note client for TypeScript - mint, rotate, split, merge, melt, and verify offline",
5
5
  "author": "TheCryptoDonkey",
6
6
  "license": "MIT",
@@ -60,7 +60,7 @@
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/node": "^26.2.0",
63
- "lnurlcash-conformance": "^0.2.2",
63
+ "lnurlcash-conformance": "^0.3.0",
64
64
  "tsup": "^8.5.0",
65
65
  "typescript": "^5.7.0",
66
66
  "vitest": "^3.0.0"