@lnurlcash/kit 0.14.0-rc.0 → 0.14.2

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/README.md CHANGED
@@ -82,8 +82,9 @@ npm pack --dry-run
82
82
  The package and wallet share a version. A wallet tag named `vX.Y.Z` publishes
83
83
  `@lnurlcash/kit@X.Y.Z` from the same commit through
84
84
  `.github/workflows/release-kit.yml` and npm trusted publishing; releases must
85
- not be published from a maintainer workstation. The one-time scoped-package
86
- bootstrap is documented in [RELEASING.md](./RELEASING.md).
85
+ not be published from a maintainer workstation. The release process and
86
+ trusted-publisher configuration are documented in
87
+ [RELEASING.md](./RELEASING.md).
87
88
 
88
89
  ## Licence
89
90
 
package/RELEASING.md CHANGED
@@ -3,27 +3,13 @@
3
3
  The final package is published from `lnurlcash/lnurl-wallet`, not from a
4
4
  workstation and not from the old standalone kit repository.
5
5
 
6
- ## One-time scoped-package bootstrap
6
+ ## Trusted publisher
7
7
 
8
- npm cannot configure a trusted publisher until the package exists. After this
9
- package source has been reviewed and merged, an `lnurlcash` npm organisation
10
- owner must make the one exceptional manual publish:
8
+ The one-time scoped-package bootstrap was completed with `0.14.0-rc.0`, then
9
+ `0.14.0` was published by the reviewed OIDC release workflow. Do not repeat the
10
+ manual bootstrap for later releases.
11
11
 
12
- 1. Build, test and pack the merged source from a disposable clean checkout,
13
- changing only its package version to `0.14.0-rc.0`.
14
- 2. Publish that tarball as a public prerelease with
15
- `npm publish --access public --tag next <tarball>`.
16
- 3. Verify that npm shows `@lnurlcash/kit@0.14.0-rc.0` under the `next` tag and
17
- that no `latest` tag has been created.
18
-
19
- Do not manually publish `0.14.0`: that version is reserved for the reviewed
20
- OIDC release. The prerelease only creates the scoped package so its trusted
21
- publisher can be configured; do not recommend it to production consumers.
22
-
23
- ## One-time trusted-publisher setup
24
-
25
- An npm package owner must configure the trusted publisher for
26
- `@lnurlcash/kit` as:
12
+ The trusted publisher for `@lnurlcash/kit` is configured as:
27
13
 
28
14
  - provider: GitHub Actions
29
15
  - organisation or user: `lnurlcash`
@@ -32,26 +18,31 @@ An npm package owner must configure the trusted publisher for
32
18
  - environment: `npm-publish`
33
19
  - allowed actions: enable direct `npm publish`
34
20
 
35
- A GitHub repository or organisation administrator should create the
36
- `npm-publish` environment, restrict it to `v*` tags and require a maintainer
37
- review. No npm token or GPG key belongs in GitHub secrets; npm uses the
38
- workflow's short-lived OIDC identity and records provenance.
39
-
40
- Do not create a final release until both sides are configured. A missing or
41
- mismatched trusted publisher should fail closed, but it is not a useful release
42
- rehearsal.
21
+ The GitHub `npm-publish` environment restricts deployments to tags matching
22
+ `v*.*.*` and requires a maintainer review. No npm token or GPG key belongs in
23
+ GitHub secrets; npm uses the workflow's short-lived OIDC identity and records
24
+ provenance. A missing or mismatched trusted publisher should fail closed.
43
25
 
44
26
  ## Each release
45
27
 
46
- 1. Choose the next version for both the wallet and kit, then update the kit's
47
- `package.json` and `CHANGELOG.md` in a reviewed pull request.
28
+ The version is never hand-bumped in `package.json` - `src/lib/package.json`'s
29
+ own checked-in `version` (`0.0.0-dev`) is a placeholder, overwritten by
30
+ `release-kit.yml`'s own `npm version "${RELEASE_TAG#v}" --no-git-tag-version`
31
+ step from whichever tag actually triggered the run. This mirrors how the
32
+ wallet's own displayed version already works (`scripts/git-version.mjs` -
33
+ `git describe --tags`, no hand-bumped field either): cutting a release is just
34
+ tagging a commit, nothing to remember to keep in sync first.
35
+
36
+ 1. (Optional but recommended) Add a `CHANGELOG.md` entry summarising what's
37
+ new, in a reviewed pull request.
48
38
  2. Require the wallet CI and the independent `src/lib` package gate to pass.
49
- 3. Merge, then create the shared `vX.Y.Z` tag at that exact merge commit. The
50
- tag must exactly equal `v` plus the version in `src/lib/package.json`.
39
+ 3. Merge, then create the shared `vX.Y.Z` tag at that exact merge commit -
40
+ any valid semver works, npm itself rejects anything else.
51
41
  4. Pushing the tag starts both release workflows. The wallet is tested and
52
- deployed at `X.Y.Z`; `release-kit.yml` independently rebuilds and tests the
53
- package, packs one tarball, performs a dry-run publish and uploads that same
54
- tarball through npm OIDC as `@lnurlcash/kit@X.Y.Z`.
42
+ deployed at `X.Y.Z`; `release-kit.yml` independently sets the package
43
+ version from the tag, rebuilds and tests the package, packs one tarball,
44
+ performs a dry-run publish and uploads that same tarball through npm OIDC
45
+ as `@lnurlcash/kit@X.Y.Z`.
55
46
  5. Verify the workflow, npm version, repository metadata and provenance before
56
47
  announcing the release.
57
48
 
@@ -0,0 +1,16 @@
1
+ import { type HashWithdrawRequestInfo } from './request.js';
2
+ import { type Cx1 } from './recoverableNotes.js';
3
+ export declare const registerUsername: (server: string, username: string, cx1: string, indexZeroSecretKey: Uint8Array, npub?: string) => Promise<void>;
4
+ export declare const unregisterUsername: (server: string, username: string, indexZeroSecretKey: Uint8Array) => Promise<void>;
5
+ export type AddressScanResult = {
6
+ index: number;
7
+ cp1: string;
8
+ info: HashWithdrawRequestInfo;
9
+ };
10
+ export type AddressScanOptions = {
11
+ gapLimit?: number;
12
+ startIndex?: number;
13
+ onFound?: (result: AddressScanResult) => void;
14
+ rateLimitBackoffMs?: number;
15
+ };
16
+ export declare const scanForAddressNotes: (withdrawUrl: string, branch: Cx1, opts?: AddressScanOptions) => Promise<AddressScanResult[]>;
@@ -0,0 +1,8 @@
1
+ export declare const sameInvoice: (a: string, b: string) => boolean;
2
+ export declare const isPreimage: (value: string) => boolean;
3
+ export declare const isBolt11Invoice: (value: string) => boolean;
4
+ export declare const encodeBolt11AmountSuffix: (amountMsat: number) => string;
5
+ export declare const decodeBolt11AmountSuffix: (suffix: string) => number | null;
6
+ export declare const decodeBolt11AmountMsat: (pr: string) => number | null;
7
+ export declare const decodeBolt11PaymentHash: (pr: string) => string | null;
8
+ export declare const verifyMeltPreimage: (pr: string, preimage: string) => boolean;
@@ -0,0 +1,20 @@
1
+ export declare class AmbiguousMintError extends Error {
2
+ }
3
+ export declare class AmbiguousMutationError extends AmbiguousMintError {
4
+ readonly newSecrets: string[];
5
+ constructor(message: string, newSecrets: string[]);
6
+ }
7
+ export declare class ServiceError extends Error {
8
+ readonly reason: string;
9
+ constructor(reason: string);
10
+ }
11
+ export declare class PendingNoteError extends Error {
12
+ constructor();
13
+ }
14
+ export declare class NoteSpentError extends Error {
15
+ constructor(reason: string);
16
+ }
17
+ export declare class NoteUnknownError extends Error {
18
+ constructor(reason: string);
19
+ }
20
+ export declare const classifyNoteError: (err: Error) => Error;
package/dist/fees.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ export type MintFee = {
2
+ baseFeeMsat: number;
3
+ feePpm: number;
4
+ };
5
+ export declare const MIN_COMMENT_LENGTH_FOR_SECRET = 64;
6
+ export type PayRequestCommentInfo = {
7
+ commentAllowed?: number;
8
+ };
9
+ export declare const canUseMintComment: (info: PayRequestCommentInfo) => boolean;
10
+ export declare const requireMintComment: (info: PayRequestCommentInfo) => void;
11
+ export declare const parseMintFee: (metadata: string) => MintFee | null;
12
+ export declare const applyMintFee: (grossMsat: number, fee: MintFee) => number;
13
+ export declare const withinMintFeeBand: (grossMsat: number, netMsat: number, fee: MintFee) => boolean;
14
+ export declare const grossUpForMintFee: (netMsat: number, fee: MintFee) => number;
package/dist/index.d.ts CHANGED
@@ -1,275 +1,12 @@
1
- declare class AmbiguousMintError extends Error {
2
- }
3
- declare class AmbiguousMutationError extends AmbiguousMintError {
4
- readonly newSecrets: string[];
5
- constructor(message: string, newSecrets: string[]);
6
- }
7
- declare class ServiceError extends Error {
8
- readonly reason: string;
9
- constructor(reason: string);
10
- }
11
- declare class PendingNoteError extends Error {
12
- constructor();
13
- }
14
- declare class NoteSpentError extends Error {
15
- constructor(reason: string);
16
- }
17
- declare class NoteUnknownError extends Error {
18
- constructor(reason: string);
19
- }
20
- declare const classifyNoteError: (err: Error) => Error;
21
-
22
- declare const isBech32Lnurl: (data: string) => boolean;
23
- declare const toBech32Lnurl: (url: string) => string;
24
- declare const fromBech32Lnurl: (data: string) => string | null;
25
- declare const defaultSchemeFor: (hostish: string) => "http" | "https";
26
- declare const isAllowedServiceUrl: (value: string) => boolean;
27
- declare const fromLud17: (url: string) => string;
28
- declare const toLud17w: (url: string) => string;
29
- declare const isLightningAddress: (value: string) => boolean;
30
- declare const resolveMintInput: (value: string) => string | null;
31
- declare const mintAddressUrl: (payUrl: string) => string | null;
32
- declare const lightningAddressUsername: (payUrl: string) => string | null;
33
- declare const resolveLnurlInput: (value: string) => string | null;
34
- declare const noteK1: (url: string) => string | null;
35
- declare const requireNoteK1: (url: string) => string;
36
- declare const noteDeclaredAmount: (url: string) => number | null;
37
- declare const noteSignature: (url: string) => string | null;
38
- declare const isValidK1: (value: string) => boolean;
39
- declare const resolveNoteInput: (value: string) => string | null;
40
- declare const isValidNoteInput: (value: string) => boolean;
41
- declare const buildNoteUrl: (withdrawLink: string, k1: string, amountMsat?: number) => string;
42
- declare const withNewK1: (url: string, k1: string, amountMsat: number, signature?: string) => string;
43
- declare const withoutK1: (url: string, amountMsat: number, signature?: string) => string;
44
- declare const withoutSignature: (url: string) => string;
45
- declare const serverOf: (url: string) => string;
46
- declare const serviceOriginOf: (value: string) => string;
47
- declare const noteEndpointOf: (url: string) => string;
48
-
49
- declare const sameInvoice: (a: string, b: string) => boolean;
50
- declare const isPreimage: (value: string) => boolean;
51
- declare const isBolt11Invoice: (value: string) => boolean;
52
- declare const encodeBolt11AmountSuffix: (amountMsat: number) => string;
53
- declare const decodeBolt11AmountSuffix: (suffix: string) => number | null;
54
- declare const decodeBolt11AmountMsat: (pr: string) => number | null;
55
- declare const decodeBolt11PaymentHash: (pr: string) => string | null;
56
- declare const verifyMeltPreimage: (pr: string, preimage: string) => boolean;
57
-
58
- declare const MINT_PUBKEY_PATTERN: RegExp;
59
- declare const NOTE_SIGNATURE_PATTERN: RegExp;
60
- declare const parseMintKey: (body: any) => {
61
- mintPubkey: string;
62
- };
63
- declare const hashK1: (k1: string) => string;
64
- declare const verifyNoteSignature: (k1: string, amountMsat: number, signatureHex: string, mintPubkeyHex: string) => boolean;
65
- declare const verifyNoteSignatureHash: (h: string, amountMsat: number, signatureHex: string, mintPubkeyHex: string) => boolean;
66
- declare const signNoteOwnership: (secretKey: Uint8Array) => Uint8Array;
67
- declare const recoverNoteOwnershipPubkey: (signature: Uint8Array) => Uint8Array | null;
68
- type AddressProofAction = 'register' | 'unregister';
69
- declare const signAddressProof: (branchIndexZeroSecretKey: Uint8Array, action: AddressProofAction, username: string) => Uint8Array;
70
- declare const cp1FromCk1: (ck1: string) => string | null;
71
- declare const requireMutationSignature: (body: any, field: "sig" | "sig2") => string;
72
-
73
- type MintFee = {
74
- baseFeeMsat: number;
75
- feePpm: number;
76
- };
77
- declare const MIN_COMMENT_LENGTH_FOR_SECRET = 64;
78
- type PayRequestCommentInfo = {
79
- commentAllowed?: number;
80
- };
81
- declare const canUseMintComment: (info: PayRequestCommentInfo) => boolean;
82
- declare const requireMintComment: (info: PayRequestCommentInfo) => void;
83
- declare const parseMintFee: (metadata: string) => MintFee | null;
84
- declare const applyMintFee: (grossMsat: number, fee: MintFee) => number;
85
- declare const withinMintFeeBand: (grossMsat: number, netMsat: number, fee: MintFee) => boolean;
86
- declare const grossUpForMintFee: (netMsat: number, fee: MintFee) => number;
87
-
88
- type NetworkGuard = () => void;
89
- declare const configureNetworkGuard: (guard: NetworkGuard) => void;
90
- type Transport = (url: string, signal: AbortSignal, method: string) => Promise<Response>;
91
- declare const configureTransport: (next: Transport) => void;
92
- declare const lnurlFetch: (url: string | URL, method?: string) => Promise<any>;
93
-
94
- type WithdrawRequestInfo = {
95
- tag: 'withdrawRequest';
96
- callback: string;
97
- k1: string;
98
- minWithdrawable: number;
99
- maxWithdrawable: number;
100
- defaultDescription?: string;
101
- mintPubkey: string;
102
- sig?: string;
103
- };
104
- type HashWithdrawRequestInfo = Omit<WithdrawRequestInfo, 'k1'>;
105
- declare const fetchNoteInfoByHash: (url: string, h: string) => Promise<HashWithdrawRequestInfo>;
106
- declare const fetchNoteInfoByPubkey: (url: string, cp1Value: string) => Promise<HashWithdrawRequestInfo>;
107
- declare const fetchNoteInfo: (url: string) => Promise<WithdrawRequestInfo>;
108
- declare const probeBurnedNote: (url: string) => Promise<"live" | "gone" | "unknown">;
109
- type MintAddressInfo = {
110
- tag: 'withdrawRequest';
111
- callback: string;
112
- minWithdrawable: number;
113
- maxWithdrawable: number;
114
- defaultDescription?: string;
115
- mintPubkey: string;
116
- nodePubkey?: string;
117
- payLink: string;
118
- nodeAlias?: string;
119
- nodeUri?: string;
120
- nodeColor?: string;
121
- nodeCapacityMsat?: number;
122
- nodeNumChannels?: number;
123
- nodeNumPeers?: number;
124
- sunsetDate?: string;
125
- outstandingNotesMsat?: number;
126
- };
127
- declare const fetchMintAddress: (url: string) => Promise<MintAddressInfo>;
128
- type WithdrawSuccessResponse = {
129
- status: 'OK';
130
- sig?: string;
131
- sig2?: string;
132
- pr?: string;
133
- verify?: string;
134
- };
135
- type MeltResult = {
136
- verify?: string;
137
- pr?: string;
138
- };
139
- declare const meltNote: (callback: string, k1: string, pr: string) => Promise<MeltResult>;
140
- type HashedMutationResult = {
141
- signature: string;
142
- };
143
- declare const rotateNoteWithHash: (callback: string, k1: string, h: string) => Promise<HashedMutationResult>;
144
- type HashedSplitResult = {
145
- signature: string;
146
- changeSignature: string;
147
- };
148
- declare const splitNoteWithHash: (callback: string, k1s: string[], amountMsat: number, h: string, h2: string) => Promise<HashedSplitResult>;
149
- declare const mergeNotesWithHash: (callback: string, k1s: string[], h: string) => Promise<HashedMutationResult>;
150
- type RotateResult = {
151
- k1: string;
152
- signature: string;
153
- };
154
- declare const generateOutputSecret: (domain: string, preferPubkey: boolean) => string;
155
- declare const disclosedValue: (secret: string) => string;
156
- declare const rotateNote: (callback: string, k1: string) => Promise<RotateResult>;
157
- type SplitResult = {
158
- k1: string;
159
- signature: string;
160
- change: string;
161
- changeSignature: string;
162
- };
163
- declare const splitNote: (callback: string, k1s: string[], amountMsat: number) => Promise<SplitResult>;
164
- declare const mergeNotes: (callback: string, k1s: string[]) => Promise<RotateResult>;
165
- type SettledNote = {
166
- k1: string;
167
- amountMsat: number;
168
- signature?: string;
169
- callback: string;
170
- };
171
- declare const settleNote: (baseUrl: string, k1: string, expectedAmountMsat: number, signature: string | undefined) => Promise<SettledNote>;
172
-
173
- declare const encodeCp1: (pubkeyXOnly: Uint8Array) => string;
174
- declare const decodeCp1: (value: string) => Uint8Array | null;
175
- declare const isCp1: (value: string) => boolean;
176
- declare const encodeCk1: (signature: Uint8Array) => string;
177
- declare const decodeCk1: (value: string) => Uint8Array | null;
178
- declare const isCk1: (value: string) => boolean;
179
- declare const encodeCs1: (signature: Uint8Array) => string;
180
- declare const decodeCs1: (value: string) => Uint8Array | null;
181
- declare const isCs1: (value: string) => boolean;
182
- declare const encodeCs1WithAmount: (amountMsat: number, signature: Uint8Array) => string;
183
- declare const decodeCs1WithAmount: (value: string) => {
184
- amountMsat: number;
185
- signature: Uint8Array;
186
- } | null;
187
- declare const isCs1WithAmount: (value: string) => boolean;
188
- declare const decodeAnyCs1: (value: string) => Uint8Array | null;
189
- declare const isAnyCs1: (value: string) => boolean;
190
- type Cx1 = {
191
- pubkeyXOnly: Uint8Array;
192
- chainCode: Uint8Array;
193
- };
194
- declare const encodeCx1: (pubkeyXOnly: Uint8Array, chainCode: Uint8Array) => string;
195
- declare const decodeCx1: (value: string) => Cx1 | null;
196
- declare const isCx1: (value: string) => boolean;
197
- declare const deriveNotePubkey: (branchPubkeyXOnly: Uint8Array, chainCode: Uint8Array, index: number) => Uint8Array;
198
- declare const deriveNoteSecretKey: (branchPrivateKey: Uint8Array, chainCode: Uint8Array, index: number) => Uint8Array;
199
-
200
- type InternalTransferHint = {
201
- cx1: Cx1;
202
- startIndex: number;
203
- };
204
- declare const parseInternalTransferHint: (metadata: string) => InternalTransferHint | null;
205
- type InternalTransferResult = {
206
- kind: 'merge';
207
- index: number;
208
- signature: string;
209
- } | {
210
- kind: 'split';
211
- index: number;
212
- signature: string;
213
- change: string;
214
- changeSignature: string;
215
- };
216
- declare const payInternalTransfer: (callback: string, k1s: string[], amountMsat: number, totalInputMsat: number, hint: InternalTransferHint) => Promise<InternalTransferResult>;
217
-
218
- type PayRequestInfo = {
219
- tag: 'payRequest';
220
- callback: string;
221
- minSendable: number;
222
- maxSendable: number;
223
- metadata: string;
224
- withdrawLink?: string;
225
- mintPubkey?: string;
226
- mintFee?: MintFee;
227
- commentAllowed?: number;
228
- mintToHash?: boolean;
229
- internalTransfer?: InternalTransferHint;
230
- };
231
- declare const fetchPayRequest: (url: string) => Promise<PayRequestInfo>;
232
- type BoundMintCommitment = {
233
- h: string;
234
- amountMsat: number;
235
- signature?: string;
236
- };
237
- type InvoiceResult = {
238
- pr: string;
239
- verify?: string;
240
- disposable: boolean;
241
- mintToHash: boolean;
242
- mint?: BoundMintCommitment;
243
- };
244
- declare const requestInvoice: (payCallback: string, amountMsat: number, outputHash?: string) => Promise<InvoiceResult>;
245
- type VerifyResult = {
246
- settled: boolean;
247
- preimage: string | null;
248
- pr: string;
249
- mint?: BoundMintCommitment;
250
- };
251
- declare const fetchInvoiceVerification: (verifyUrl: string) => Promise<VerifyResult>;
252
- declare const requireBoundMintQuote: (invoice: InvoiceResult, expectedH: string, grossMsat: number, fee?: MintFee) => BoundMintCommitment;
253
- declare const validateBoundMintReceipt: (invoice: InvoiceResult, verification: VerifyResult, expectedH: string, expectedAmountMsat: number, mintPubkey: string) => Required<BoundMintCommitment>;
254
-
255
- declare const registerUsername: (server: string, username: string, cx1: string, indexZeroSecretKey: Uint8Array) => Promise<void>;
256
- declare const unregisterUsername: (server: string, username: string, indexZeroSecretKey: Uint8Array) => Promise<void>;
257
- type AddressScanResult = {
258
- index: number;
259
- cp1: string;
260
- info: HashWithdrawRequestInfo;
261
- };
262
- type AddressScanOptions = {
263
- gapLimit?: number;
264
- startIndex?: number;
265
- onFound?: (result: AddressScanResult) => void;
266
- rateLimitBackoffMs?: number;
267
- };
268
- declare const scanForAddressNotes: (withdrawUrl: string, branch: Cx1, opts?: AddressScanOptions) => Promise<AddressScanResult[]>;
269
-
270
- type SecretProvider = (domain: string) => string;
271
- declare const configureSecretProvider: (provider: SecretProvider) => void;
272
- type PubkeySecretProvider = (domain: string) => string | null;
273
- declare const configurePubkeySecretProvider: (provider: PubkeySecretProvider) => void;
274
-
275
- export { type AddressProofAction, type AddressScanOptions, type AddressScanResult, AmbiguousMintError, AmbiguousMutationError, type BoundMintCommitment, type Cx1, type HashWithdrawRequestInfo, type HashedMutationResult, type HashedSplitResult, type InternalTransferHint, type InternalTransferResult, type InvoiceResult, MINT_PUBKEY_PATTERN, MIN_COMMENT_LENGTH_FOR_SECRET, type MeltResult, type MintAddressInfo, type MintFee, NOTE_SIGNATURE_PATTERN, type NetworkGuard, NoteSpentError, NoteUnknownError, type PayRequestCommentInfo, type PayRequestInfo, PendingNoteError, type PubkeySecretProvider, type RotateResult, type SecretProvider, ServiceError, type SettledNote, type SplitResult, type Transport, type VerifyResult, type WithdrawRequestInfo, type WithdrawSuccessResponse, applyMintFee, buildNoteUrl, canUseMintComment, classifyNoteError, configureNetworkGuard, configurePubkeySecretProvider, configureSecretProvider, configureTransport, cp1FromCk1, decodeAnyCs1, decodeBolt11AmountMsat, decodeBolt11AmountSuffix, decodeBolt11PaymentHash, decodeCk1, decodeCp1, decodeCs1, decodeCs1WithAmount, decodeCx1, defaultSchemeFor, deriveNotePubkey, deriveNoteSecretKey, disclosedValue, encodeBolt11AmountSuffix, encodeCk1, encodeCp1, encodeCs1, encodeCs1WithAmount, encodeCx1, fetchInvoiceVerification, fetchMintAddress, fetchNoteInfo, fetchNoteInfoByHash, fetchNoteInfoByPubkey, fetchPayRequest, fromBech32Lnurl, fromLud17, generateOutputSecret, grossUpForMintFee, hashK1, isAllowedServiceUrl, isAnyCs1, isBech32Lnurl, isBolt11Invoice, isCk1, isCp1, isCs1, isCs1WithAmount, isCx1, isLightningAddress, isPreimage, isValidK1, isValidNoteInput, lightningAddressUsername, lnurlFetch, meltNote, mergeNotes, mergeNotesWithHash, mintAddressUrl, noteDeclaredAmount, noteEndpointOf, noteK1, noteSignature, parseInternalTransferHint, parseMintFee, parseMintKey, payInternalTransfer, probeBurnedNote, recoverNoteOwnershipPubkey, registerUsername, requestInvoice, requireBoundMintQuote, requireMintComment, requireMutationSignature, requireNoteK1, resolveLnurlInput, resolveMintInput, resolveNoteInput, rotateNote, rotateNoteWithHash, sameInvoice, scanForAddressNotes, serverOf, serviceOriginOf, settleNote, signAddressProof, signNoteOwnership, splitNote, splitNoteWithHash, toBech32Lnurl, toLud17w, unregisterUsername, validateBoundMintReceipt, verifyMeltPreimage, verifyNoteSignature, verifyNoteSignatureHash, withNewK1, withinMintFeeBand, withoutK1, withoutSignature };
1
+ export * from './errors.js';
2
+ export * from './urls.js';
3
+ export * from './bolt11.js';
4
+ export * from './signature.js';
5
+ export * from './fees.js';
6
+ export * from './net.js';
7
+ export * from './request.js';
8
+ export * from './mintRequest.js';
9
+ export * from './addresses.js';
10
+ export * from './internalTransfer.js';
11
+ export * from './recoverableNotes.js';
12
+ export { configureSecretProvider, type SecretProvider, configurePubkeySecretProvider, type PubkeySecretProvider } from './secrets.js';
package/dist/index.js CHANGED
@@ -1,8 +1,3 @@
1
- import { bech32, bech32m } from '@scure/base';
2
- import { sha256 } from '@noble/hashes/sha2.js';
3
- import { utf8ToBytes, bytesToHex, hexToBytes } from '@noble/hashes/utils.js';
4
- import { schnorr, secp256k1 } from '@noble/curves/secp256k1.js';
5
-
6
1
  // errors.ts
7
2
  var AmbiguousMintError = class extends Error {
8
3
  };
@@ -50,6 +45,14 @@ var classifyNoteError = (err) => {
50
45
  if (/unknown|not found/i.test(reason)) return new NoteUnknownError(reason);
51
46
  return err;
52
47
  };
48
+
49
+ // urls.ts
50
+ import { bech32 as bech322 } from "@scure/base";
51
+
52
+ // bolt11.ts
53
+ import { bech32 } from "@scure/base";
54
+ import { sha256 } from "@noble/hashes/sha2.js";
55
+ import { bytesToHex, hexToBytes } from "@noble/hashes/utils.js";
53
56
  var sameInvoice = (a, b) => a.trim().toLowerCase() === b.trim().toLowerCase();
54
57
  var isPreimage = (value) => /^[0-9a-fA-F]{64}$/.test(value.trim());
55
58
  var isBolt11Invoice = (value) => /^ln(bc|tb|bcrt|tbs|sb)[0-9]*[munp]?1[a-z0-9]+$/.test(
@@ -123,6 +126,11 @@ var verifyMeltPreimage = (pr, preimage) => {
123
126
  if (!expected) return false;
124
127
  return bytesToHex(sha256(hexToBytes(preimage))) === expected;
125
128
  };
129
+
130
+ // recoverableNotes.ts
131
+ import { bech32m } from "@scure/base";
132
+ import { bytesToHex as bytesToHex2, hexToBytes as hexToBytes2 } from "@noble/hashes/utils.js";
133
+ import { schnorr } from "@noble/curves/secp256k1.js";
126
134
  var encodeFixed = (hrp, bytes, length) => {
127
135
  if (bytes.length !== length) {
128
136
  throw new Error(`${hrp}1... payload must be exactly ${length} bytes`);
@@ -176,8 +184,8 @@ var ser32BE = (index) => {
176
184
  new DataView(bytes.buffer).setUint32(0, index, false);
177
185
  return bytes;
178
186
  };
179
- var bytesToNumberBE = (bytes) => BigInt(`0x${bytesToHex(bytes)}`);
180
- var numberToBytesBE = (n, length) => hexToBytes(n.toString(16).padStart(length * 2, "0"));
187
+ var bytesToNumberBE = (bytes) => BigInt(`0x${bytesToHex2(bytes)}`);
188
+ var numberToBytesBE = (n, length) => hexToBytes2(n.toString(16).padStart(length * 2, "0"));
181
189
  var CURVE_ORDER = schnorr.Point.CURVE().n;
182
190
  var tweakScalar = (branchPubkeyXOnly, chainCode, index) => {
183
191
  const t = schnorr.utils.taggedHash(
@@ -208,17 +216,17 @@ var deriveNoteSecretKey = (branchPrivateKey, chainCode, index) => {
208
216
  var isBech32Lnurl = (data) => data.trim().toUpperCase().startsWith("LNURL1");
209
217
  var toBech32Lnurl = (url) => {
210
218
  const bytes = new TextEncoder().encode(url);
211
- return bech32.encode("lnurl", bech32.toWords(bytes), 2048).toUpperCase();
219
+ return bech322.encode("lnurl", bech322.toWords(bytes), 2048).toUpperCase();
212
220
  };
213
221
  var fromBech32Lnurl = (data) => {
214
222
  const safe = data.trim().toUpperCase();
215
223
  if (!safe.startsWith("LNURL1")) return null;
216
224
  try {
217
- const decoded = bech32.decode(
225
+ const decoded = bech322.decode(
218
226
  `LNURL1${safe.slice(6)}`,
219
227
  2048
220
228
  );
221
- return new TextDecoder().decode(bech32.fromWords(decoded.words));
229
+ return new TextDecoder().decode(bech322.fromWords(decoded.words));
222
230
  } catch {
223
231
  return null;
224
232
  }
@@ -329,10 +337,14 @@ var requireNoteK1 = (url) => {
329
337
  };
330
338
  var noteDeclaredAmount = (url) => {
331
339
  try {
332
- const raw = new URL(url).searchParams.get("amount");
333
- if (raw === null) return null;
334
- const n = Number(raw);
335
- return Number.isFinite(n) ? n : null;
340
+ const parsed = new URL(url);
341
+ const raw = parsed.searchParams.get("amount");
342
+ if (raw !== null) {
343
+ const n = Number(raw);
344
+ return Number.isFinite(n) ? n : null;
345
+ }
346
+ const sig = parsed.searchParams.get("sig");
347
+ return sig ? decodeCs1WithAmount(sig)?.amountMsat ?? null : null;
336
348
  } catch {
337
349
  return null;
338
350
  }
@@ -360,10 +372,15 @@ var buildNoteUrl = (withdrawLink, k1, amountMsat) => {
360
372
  }
361
373
  return url.toString();
362
374
  };
375
+ var amountIsImpliedBySignature = (signature) => Boolean(signature) && isCs1WithAmount(signature);
363
376
  var withNewK1 = (url, k1, amountMsat, signature) => {
364
377
  const newUrl = new URL(url);
365
378
  newUrl.searchParams.set("k1", k1);
366
- newUrl.searchParams.set("amount", String(amountMsat));
379
+ if (amountIsImpliedBySignature(signature)) {
380
+ newUrl.searchParams.delete("amount");
381
+ } else {
382
+ newUrl.searchParams.set("amount", String(amountMsat));
383
+ }
367
384
  if (signature) newUrl.searchParams.set("sig", signature);
368
385
  else newUrl.searchParams.delete("sig");
369
386
  return newUrl.toString();
@@ -371,13 +388,22 @@ var withNewK1 = (url, k1, amountMsat, signature) => {
371
388
  var withoutK1 = (url, amountMsat, signature) => {
372
389
  const newUrl = new URL(url);
373
390
  newUrl.searchParams.delete("k1");
374
- newUrl.searchParams.set("amount", String(amountMsat));
391
+ if (amountIsImpliedBySignature(signature)) {
392
+ newUrl.searchParams.delete("amount");
393
+ } else {
394
+ newUrl.searchParams.set("amount", String(amountMsat));
395
+ }
375
396
  if (signature) newUrl.searchParams.set("sig", signature);
376
397
  else newUrl.searchParams.delete("sig");
377
398
  return newUrl.toString();
378
399
  };
379
400
  var withoutSignature = (url) => {
380
401
  const newUrl = new URL(url);
402
+ const sig = newUrl.searchParams.get("sig");
403
+ if (sig && !newUrl.searchParams.has("amount")) {
404
+ const decoded = decodeCs1WithAmount(sig);
405
+ if (decoded) newUrl.searchParams.set("amount", String(decoded.amountMsat));
406
+ }
381
407
  newUrl.searchParams.delete("sig");
382
408
  return newUrl.toString();
383
409
  };
@@ -409,6 +435,11 @@ var noteEndpointOf = (url) => {
409
435
  return serverOf(url);
410
436
  }
411
437
  };
438
+
439
+ // signature.ts
440
+ import { sha256 as sha2562 } from "@noble/hashes/sha2.js";
441
+ import { secp256k1 } from "@noble/curves/secp256k1.js";
442
+ import { bytesToHex as bytesToHex3, hexToBytes as hexToBytes3, utf8ToBytes } from "@noble/hashes/utils.js";
412
443
  var MINT_PUBKEY_PATTERN = /^0[23][0-9a-f]{64}$/i;
413
444
  var NOTE_SIGNATURE_PATTERN = /^[0-9a-f]{130}$/i;
414
445
  var parseMintKey = (body) => {
@@ -419,7 +450,7 @@ var parseMintKey = (body) => {
419
450
  }
420
451
  return { mintPubkey: body.mintPubkey.toLowerCase() };
421
452
  };
422
- var hashK1 = (k1) => bytesToHex(sha256(hexToBytes(k1)));
453
+ var hashK1 = (k1) => bytesToHex3(sha2562(hexToBytes3(k1)));
423
454
  var LIGHTNING_SIGNED_MESSAGE_PREFIX = utf8ToBytes("Lightning Signed Message:");
424
455
  var noteSignatureDigestForHash = (h, amountMsat) => {
425
456
  if (!/^[0-9a-fA-F]{64}$/.test(h.trim())) {
@@ -428,22 +459,22 @@ var noteSignatureDigestForHash = (h, amountMsat) => {
428
459
  const message = utf8ToBytes(
429
460
  `LNURLcash:${amountMsat}:${h.trim().toLowerCase()}`
430
461
  );
431
- return sha256(
432
- sha256(new Uint8Array([...LIGHTNING_SIGNED_MESSAGE_PREFIX, ...message]))
462
+ return sha2562(
463
+ sha2562(new Uint8Array([...LIGHTNING_SIGNED_MESSAGE_PREFIX, ...message]))
433
464
  );
434
465
  };
435
466
  var noteSignatureDigest = (k1, amountMsat) => noteSignatureDigestForHash(hashK1(k1), amountMsat);
436
467
  var normalizeSignatureHex = (signature) => {
437
468
  if (NOTE_SIGNATURE_PATTERN.test(signature)) return signature.toLowerCase();
438
469
  const decoded = decodeAnyCs1(signature);
439
- return decoded ? bytesToHex(decoded) : null;
470
+ return decoded ? bytesToHex3(decoded) : null;
440
471
  };
441
472
  var verifyNoteSignatureDigest = (digest, signature, mintPubkeyHex) => {
442
473
  const signatureHex = normalizeSignatureHex(signature);
443
474
  if (!signatureHex) return false;
444
475
  let wireSig;
445
476
  try {
446
- wireSig = hexToBytes(signatureHex);
477
+ wireSig = hexToBytes3(signatureHex);
447
478
  } catch {
448
479
  return false;
449
480
  }
@@ -456,7 +487,7 @@ var verifyNoteSignatureDigest = (digest, signature, mintPubkeyHex) => {
456
487
  const recovered = secp256k1.recoverPublicKey(candidate, digest, {
457
488
  prehash: false
458
489
  });
459
- if (bytesToHex(recovered) === target) return true;
490
+ if (bytesToHex3(recovered) === target) return true;
460
491
  } catch {
461
492
  }
462
493
  }
@@ -467,7 +498,7 @@ var verifyNoteSignature = (k1, amountMsat, signatureHex, mintPubkeyHex) => {
467
498
  const signatureBytes = decodeCk1(k1);
468
499
  const pubkey = signatureBytes ? recoverNoteOwnershipPubkey(signatureBytes) : null;
469
500
  return pubkey ? verifyNoteSignatureHash(
470
- bytesToHex(pubkey),
501
+ bytesToHex3(pubkey),
471
502
  amountMsat,
472
503
  signatureHex,
473
504
  mintPubkeyHex
@@ -495,8 +526,8 @@ var verifyNoteSignatureHash = (h, amountMsat, signatureHex, mintPubkeyHex) => {
495
526
  }
496
527
  };
497
528
  var NOTE_OWNERSHIP_MESSAGE = utf8ToBytes("LNURLcash");
498
- var noteOwnershipDigest = () => sha256(
499
- sha256(
529
+ var noteOwnershipDigest = () => sha2562(
530
+ sha2562(
500
531
  new Uint8Array([
501
532
  ...LIGHTNING_SIGNED_MESSAGE_PREFIX,
502
533
  ...NOTE_OWNERSHIP_MESSAGE
@@ -529,8 +560,8 @@ var recoverNoteOwnershipPubkey = (signature) => {
529
560
  };
530
561
  var addressProofDigest = (action, username) => {
531
562
  const message = utf8ToBytes(`LNURLcash:${action}:${username}`);
532
- return sha256(
533
- sha256(new Uint8Array([...LIGHTNING_SIGNED_MESSAGE_PREFIX, ...message]))
563
+ return sha2562(
564
+ sha2562(new Uint8Array([...LIGHTNING_SIGNED_MESSAGE_PREFIX, ...message]))
534
565
  );
535
566
  };
536
567
  var signAddressProof = (branchIndexZeroSecretKey, action, username) => {
@@ -654,7 +685,10 @@ var lnurlFetch = async (url, method = "GET") => {
654
685
  }
655
686
  return body;
656
687
  };
657
- var defaultSecretProvider = () => bytesToHex(crypto.getRandomValues(new Uint8Array(32)));
688
+
689
+ // secrets.ts
690
+ import { bytesToHex as bytesToHex4 } from "@noble/hashes/utils.js";
691
+ var defaultSecretProvider = () => bytesToHex4(crypto.getRandomValues(new Uint8Array(32)));
658
692
  var secretProvider = defaultSecretProvider;
659
693
  var configureSecretProvider = (provider) => {
660
694
  secretProvider = provider;
@@ -1025,6 +1059,9 @@ var payInternalTransfer = async (callback, k1s, amountMsat, totalInputMsat, hint
1025
1059
  `${domain} kept reporting every index tried as already in use - could not complete the internal transfer.`
1026
1060
  );
1027
1061
  };
1062
+
1063
+ // mintRequest.ts
1064
+ import { bytesToHex as bytesToHex5 } from "@noble/hashes/utils.js";
1028
1065
  var fetchPayRequest = async (url) => {
1029
1066
  const body = await lnurlFetch(url);
1030
1067
  if (body?.tag !== "payRequest" || typeof body.callback !== "string") {
@@ -1044,12 +1081,12 @@ var normalizeNoteId = (value) => {
1044
1081
  const trimmed = value.trim().toLowerCase();
1045
1082
  if (/^[0-9a-f]{64}$/.test(trimmed)) return trimmed;
1046
1083
  const decoded = decodeCp1(trimmed);
1047
- return decoded ? bytesToHex(decoded) : null;
1084
+ return decoded ? bytesToHex5(decoded) : null;
1048
1085
  };
1049
1086
  var normalizeSignature = (value) => {
1050
1087
  if (/^[0-9a-f]{130}$/i.test(value)) return value.toLowerCase();
1051
1088
  const decoded = decodeAnyCs1(value);
1052
- return decoded ? bytesToHex(decoded) : null;
1089
+ return decoded ? bytesToHex5(decoded) : null;
1053
1090
  };
1054
1091
  var parseBoundMintCommitment = (value) => {
1055
1092
  if (!value || typeof value !== "object") return void 0;
@@ -1160,17 +1197,21 @@ var validateBoundMintReceipt = (invoice, verification, expectedH, expectedAmount
1160
1197
  }
1161
1198
  return { ...receipt, signature: receipt.signature };
1162
1199
  };
1200
+
1201
+ // addresses.ts
1202
+ import { bytesToHex as bytesToHex6 } from "@noble/hashes/utils.js";
1163
1203
  var addressProofUrl = (server, username, indexZeroSecretKey, action) => {
1164
1204
  const url = new URL(`/p/${encodeURIComponent(username)}`, server);
1165
1205
  url.searchParams.set(
1166
1206
  "sig",
1167
- bytesToHex(signAddressProof(indexZeroSecretKey, action, username))
1207
+ bytesToHex6(signAddressProof(indexZeroSecretKey, action, username))
1168
1208
  );
1169
1209
  return url;
1170
1210
  };
1171
- var registerUsername = async (server, username, cx1, indexZeroSecretKey) => {
1211
+ var registerUsername = async (server, username, cx1, indexZeroSecretKey, npub) => {
1172
1212
  const url = addressProofUrl(server, username, indexZeroSecretKey, "register");
1173
1213
  url.searchParams.set("cx1", cx1);
1214
+ if (npub) url.searchParams.set("npub", npub);
1174
1215
  const body = await lnurlFetch(url, "POST");
1175
1216
  if (body?.status !== "OK") {
1176
1217
  throw new Error("SERVICE did not confirm the registration.");
@@ -1227,5 +1268,113 @@ var scanForAddressNotes = async (withdrawUrl, branch, opts = {}) => {
1227
1268
  }
1228
1269
  return found;
1229
1270
  };
1230
-
1231
- export { AmbiguousMintError, AmbiguousMutationError, MINT_PUBKEY_PATTERN, MIN_COMMENT_LENGTH_FOR_SECRET, NOTE_SIGNATURE_PATTERN, NoteSpentError, NoteUnknownError, PendingNoteError, ServiceError, applyMintFee, buildNoteUrl, canUseMintComment, classifyNoteError, configureNetworkGuard, configurePubkeySecretProvider, configureSecretProvider, configureTransport, cp1FromCk1, decodeAnyCs1, decodeBolt11AmountMsat, decodeBolt11AmountSuffix, decodeBolt11PaymentHash, decodeCk1, decodeCp1, decodeCs1, decodeCs1WithAmount, decodeCx1, defaultSchemeFor, deriveNotePubkey, deriveNoteSecretKey, disclosedValue, encodeBolt11AmountSuffix, encodeCk1, encodeCp1, encodeCs1, encodeCs1WithAmount, encodeCx1, fetchInvoiceVerification, fetchMintAddress, fetchNoteInfo, fetchNoteInfoByHash, fetchNoteInfoByPubkey, fetchPayRequest, fromBech32Lnurl, fromLud17, generateOutputSecret, grossUpForMintFee, hashK1, isAllowedServiceUrl, isAnyCs1, isBech32Lnurl, isBolt11Invoice, isCk1, isCp1, isCs1, isCs1WithAmount, isCx1, isLightningAddress, isPreimage, isValidK1, isValidNoteInput, lightningAddressUsername, lnurlFetch, meltNote, mergeNotes, mergeNotesWithHash, mintAddressUrl, noteDeclaredAmount, noteEndpointOf, noteK1, noteSignature, parseInternalTransferHint, parseMintFee, parseMintKey, payInternalTransfer, probeBurnedNote, recoverNoteOwnershipPubkey, registerUsername, requestInvoice, requireBoundMintQuote, requireMintComment, requireMutationSignature, requireNoteK1, resolveLnurlInput, resolveMintInput, resolveNoteInput, rotateNote, rotateNoteWithHash, sameInvoice, scanForAddressNotes, serverOf, serviceOriginOf, settleNote, signAddressProof, signNoteOwnership, splitNote, splitNoteWithHash, toBech32Lnurl, toLud17w, unregisterUsername, validateBoundMintReceipt, verifyMeltPreimage, verifyNoteSignature, verifyNoteSignatureHash, withNewK1, withinMintFeeBand, withoutK1, withoutSignature };
1271
+ export {
1272
+ AmbiguousMintError,
1273
+ AmbiguousMutationError,
1274
+ MINT_PUBKEY_PATTERN,
1275
+ MIN_COMMENT_LENGTH_FOR_SECRET,
1276
+ NOTE_SIGNATURE_PATTERN,
1277
+ NoteSpentError,
1278
+ NoteUnknownError,
1279
+ PendingNoteError,
1280
+ ServiceError,
1281
+ applyMintFee,
1282
+ buildNoteUrl,
1283
+ canUseMintComment,
1284
+ classifyNoteError,
1285
+ configureNetworkGuard,
1286
+ configurePubkeySecretProvider,
1287
+ configureSecretProvider,
1288
+ configureTransport,
1289
+ cp1FromCk1,
1290
+ decodeAnyCs1,
1291
+ decodeBolt11AmountMsat,
1292
+ decodeBolt11AmountSuffix,
1293
+ decodeBolt11PaymentHash,
1294
+ decodeCk1,
1295
+ decodeCp1,
1296
+ decodeCs1,
1297
+ decodeCs1WithAmount,
1298
+ decodeCx1,
1299
+ defaultSchemeFor,
1300
+ deriveNotePubkey,
1301
+ deriveNoteSecretKey,
1302
+ disclosedValue,
1303
+ encodeBolt11AmountSuffix,
1304
+ encodeCk1,
1305
+ encodeCp1,
1306
+ encodeCs1,
1307
+ encodeCs1WithAmount,
1308
+ encodeCx1,
1309
+ fetchInvoiceVerification,
1310
+ fetchMintAddress,
1311
+ fetchNoteInfo,
1312
+ fetchNoteInfoByHash,
1313
+ fetchNoteInfoByPubkey,
1314
+ fetchPayRequest,
1315
+ fromBech32Lnurl,
1316
+ fromLud17,
1317
+ generateOutputSecret,
1318
+ grossUpForMintFee,
1319
+ hashK1,
1320
+ isAllowedServiceUrl,
1321
+ isAnyCs1,
1322
+ isBech32Lnurl,
1323
+ isBolt11Invoice,
1324
+ isCk1,
1325
+ isCp1,
1326
+ isCs1,
1327
+ isCs1WithAmount,
1328
+ isCx1,
1329
+ isLightningAddress,
1330
+ isPreimage,
1331
+ isValidK1,
1332
+ isValidNoteInput,
1333
+ lightningAddressUsername,
1334
+ lnurlFetch,
1335
+ meltNote,
1336
+ mergeNotes,
1337
+ mergeNotesWithHash,
1338
+ mintAddressUrl,
1339
+ noteDeclaredAmount,
1340
+ noteEndpointOf,
1341
+ noteK1,
1342
+ noteSignature,
1343
+ parseInternalTransferHint,
1344
+ parseMintFee,
1345
+ parseMintKey,
1346
+ payInternalTransfer,
1347
+ probeBurnedNote,
1348
+ recoverNoteOwnershipPubkey,
1349
+ registerUsername,
1350
+ requestInvoice,
1351
+ requireBoundMintQuote,
1352
+ requireMintComment,
1353
+ requireMutationSignature,
1354
+ requireNoteK1,
1355
+ resolveLnurlInput,
1356
+ resolveMintInput,
1357
+ resolveNoteInput,
1358
+ rotateNote,
1359
+ rotateNoteWithHash,
1360
+ sameInvoice,
1361
+ scanForAddressNotes,
1362
+ serverOf,
1363
+ serviceOriginOf,
1364
+ settleNote,
1365
+ signAddressProof,
1366
+ signNoteOwnership,
1367
+ splitNote,
1368
+ splitNoteWithHash,
1369
+ toBech32Lnurl,
1370
+ toLud17w,
1371
+ unregisterUsername,
1372
+ validateBoundMintReceipt,
1373
+ verifyMeltPreimage,
1374
+ verifyNoteSignature,
1375
+ verifyNoteSignatureHash,
1376
+ withNewK1,
1377
+ withinMintFeeBand,
1378
+ withoutK1,
1379
+ withoutSignature
1380
+ };
@@ -0,0 +1,18 @@
1
+ import { type Cx1 } from './recoverableNotes.js';
2
+ export type InternalTransferHint = {
3
+ cx1: Cx1;
4
+ startIndex: number;
5
+ };
6
+ export declare const parseInternalTransferHint: (metadata: string) => InternalTransferHint | null;
7
+ export type InternalTransferResult = {
8
+ kind: 'merge';
9
+ index: number;
10
+ signature: string;
11
+ } | {
12
+ kind: 'split';
13
+ index: number;
14
+ signature: string;
15
+ change: string;
16
+ changeSignature: string;
17
+ };
18
+ export declare const payInternalTransfer: (callback: string, k1s: string[], amountMsat: number, totalInputMsat: number, hint: InternalTransferHint) => Promise<InternalTransferResult>;
@@ -0,0 +1,38 @@
1
+ import type { MintFee } from './fees.js';
2
+ import type { InternalTransferHint } from './internalTransfer.js';
3
+ export type PayRequestInfo = {
4
+ tag: 'payRequest';
5
+ callback: string;
6
+ minSendable: number;
7
+ maxSendable: number;
8
+ metadata: string;
9
+ withdrawLink?: string;
10
+ mintPubkey?: string;
11
+ mintFee?: MintFee;
12
+ commentAllowed?: number;
13
+ mintToHash?: boolean;
14
+ internalTransfer?: InternalTransferHint;
15
+ };
16
+ export declare const fetchPayRequest: (url: string) => Promise<PayRequestInfo>;
17
+ export type BoundMintCommitment = {
18
+ h: string;
19
+ amountMsat: number;
20
+ signature?: string;
21
+ };
22
+ export type InvoiceResult = {
23
+ pr: string;
24
+ verify?: string;
25
+ disposable: boolean;
26
+ mintToHash: boolean;
27
+ mint?: BoundMintCommitment;
28
+ };
29
+ export declare const requestInvoice: (payCallback: string, amountMsat: number, outputHash?: string) => Promise<InvoiceResult>;
30
+ export type VerifyResult = {
31
+ settled: boolean;
32
+ preimage: string | null;
33
+ pr: string;
34
+ mint?: BoundMintCommitment;
35
+ };
36
+ export declare const fetchInvoiceVerification: (verifyUrl: string) => Promise<VerifyResult>;
37
+ export declare const requireBoundMintQuote: (invoice: InvoiceResult, expectedH: string, grossMsat: number, fee?: MintFee) => BoundMintCommitment;
38
+ export declare const validateBoundMintReceipt: (invoice: InvoiceResult, verification: VerifyResult, expectedH: string, expectedAmountMsat: number, mintPubkey: string) => Required<BoundMintCommitment>;
package/dist/net.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export type NetworkGuard = () => void;
2
+ export declare const configureNetworkGuard: (guard: NetworkGuard) => void;
3
+ export type Transport = (url: string, signal: AbortSignal, method: string) => Promise<Response>;
4
+ export declare const configureTransport: (next: Transport) => void;
5
+ export declare const lnurlFetch: (url: string | URL, method?: string) => Promise<any>;
@@ -0,0 +1,26 @@
1
+ export declare const encodeCp1: (pubkeyXOnly: Uint8Array) => string;
2
+ export declare const decodeCp1: (value: string) => Uint8Array | null;
3
+ export declare const isCp1: (value: string) => boolean;
4
+ export declare const encodeCk1: (signature: Uint8Array) => string;
5
+ export declare const decodeCk1: (value: string) => Uint8Array | null;
6
+ export declare const isCk1: (value: string) => boolean;
7
+ export declare const encodeCs1: (signature: Uint8Array) => string;
8
+ export declare const decodeCs1: (value: string) => Uint8Array | null;
9
+ export declare const isCs1: (value: string) => boolean;
10
+ export declare const encodeCs1WithAmount: (amountMsat: number, signature: Uint8Array) => string;
11
+ export declare const decodeCs1WithAmount: (value: string) => {
12
+ amountMsat: number;
13
+ signature: Uint8Array;
14
+ } | null;
15
+ export declare const isCs1WithAmount: (value: string) => boolean;
16
+ export declare const decodeAnyCs1: (value: string) => Uint8Array | null;
17
+ export declare const isAnyCs1: (value: string) => boolean;
18
+ export type Cx1 = {
19
+ pubkeyXOnly: Uint8Array;
20
+ chainCode: Uint8Array;
21
+ };
22
+ export declare const encodeCx1: (pubkeyXOnly: Uint8Array, chainCode: Uint8Array) => string;
23
+ export declare const decodeCx1: (value: string) => Cx1 | null;
24
+ export declare const isCx1: (value: string) => boolean;
25
+ export declare const deriveNotePubkey: (branchPubkeyXOnly: Uint8Array, chainCode: Uint8Array, index: number) => Uint8Array;
26
+ export declare const deriveNoteSecretKey: (branchPrivateKey: Uint8Array, chainCode: Uint8Array, index: number) => Uint8Array;
@@ -0,0 +1,78 @@
1
+ export type WithdrawRequestInfo = {
2
+ tag: 'withdrawRequest';
3
+ callback: string;
4
+ k1: string;
5
+ minWithdrawable: number;
6
+ maxWithdrawable: number;
7
+ defaultDescription?: string;
8
+ mintPubkey: string;
9
+ sig?: string;
10
+ };
11
+ export type HashWithdrawRequestInfo = Omit<WithdrawRequestInfo, 'k1'>;
12
+ export declare const fetchNoteInfoByHash: (url: string, h: string) => Promise<HashWithdrawRequestInfo>;
13
+ export declare const fetchNoteInfoByPubkey: (url: string, cp1Value: string) => Promise<HashWithdrawRequestInfo>;
14
+ export declare const fetchNoteInfo: (url: string) => Promise<WithdrawRequestInfo>;
15
+ export declare const probeBurnedNote: (url: string) => Promise<'live' | 'gone' | 'unknown'>;
16
+ export type MintAddressInfo = {
17
+ tag: 'withdrawRequest';
18
+ callback: string;
19
+ minWithdrawable: number;
20
+ maxWithdrawable: number;
21
+ defaultDescription?: string;
22
+ mintPubkey: string;
23
+ nodePubkey?: string;
24
+ payLink: string;
25
+ nodeAlias?: string;
26
+ nodeUri?: string;
27
+ nodeColor?: string;
28
+ nodeCapacityMsat?: number;
29
+ nodeNumChannels?: number;
30
+ nodeNumPeers?: number;
31
+ sunsetDate?: string;
32
+ outstandingNotesMsat?: number;
33
+ };
34
+ export declare const fetchMintAddress: (url: string) => Promise<MintAddressInfo>;
35
+ export type WithdrawSuccessResponse = {
36
+ status: 'OK';
37
+ sig?: string;
38
+ sig2?: string;
39
+ pr?: string;
40
+ verify?: string;
41
+ };
42
+ export type MeltResult = {
43
+ verify?: string;
44
+ pr?: string;
45
+ };
46
+ export declare const meltNote: (callback: string, k1: string, pr: string) => Promise<MeltResult>;
47
+ export type HashedMutationResult = {
48
+ signature: string;
49
+ };
50
+ export declare const rotateNoteWithHash: (callback: string, k1: string, h: string) => Promise<HashedMutationResult>;
51
+ export type HashedSplitResult = {
52
+ signature: string;
53
+ changeSignature: string;
54
+ };
55
+ export declare const splitNoteWithHash: (callback: string, k1s: string[], amountMsat: number, h: string, h2: string) => Promise<HashedSplitResult>;
56
+ export declare const mergeNotesWithHash: (callback: string, k1s: string[], h: string) => Promise<HashedMutationResult>;
57
+ export type RotateResult = {
58
+ k1: string;
59
+ signature: string;
60
+ };
61
+ export declare const generateOutputSecret: (domain: string, preferPubkey: boolean) => string;
62
+ export declare const disclosedValue: (secret: string) => string;
63
+ export declare const rotateNote: (callback: string, k1: string) => Promise<RotateResult>;
64
+ export type SplitResult = {
65
+ k1: string;
66
+ signature: string;
67
+ change: string;
68
+ changeSignature: string;
69
+ };
70
+ export declare const splitNote: (callback: string, k1s: string[], amountMsat: number) => Promise<SplitResult>;
71
+ export declare const mergeNotes: (callback: string, k1s: string[]) => Promise<RotateResult>;
72
+ export type SettledNote = {
73
+ k1: string;
74
+ amountMsat: number;
75
+ signature?: string;
76
+ callback: string;
77
+ };
78
+ export declare const settleNote: (baseUrl: string, k1: string, expectedAmountMsat: number, signature: string | undefined) => Promise<SettledNote>;
@@ -0,0 +1,6 @@
1
+ export type SecretProvider = (domain: string) => string;
2
+ export declare const configureSecretProvider: (provider: SecretProvider) => void;
3
+ export declare const generateSecret: (domain: string) => string;
4
+ export type PubkeySecretProvider = (domain: string) => string | null;
5
+ export declare const configurePubkeySecretProvider: (provider: PubkeySecretProvider) => void;
6
+ export declare const generatePubkeySecret: (domain: string) => string | null;
@@ -0,0 +1,14 @@
1
+ export declare const MINT_PUBKEY_PATTERN: RegExp;
2
+ export declare const NOTE_SIGNATURE_PATTERN: RegExp;
3
+ export declare const parseMintKey: (body: any) => {
4
+ mintPubkey: string;
5
+ };
6
+ export declare const hashK1: (k1: string) => string;
7
+ export declare const verifyNoteSignature: (k1: string, amountMsat: number, signatureHex: string, mintPubkeyHex: string) => boolean;
8
+ export declare const verifyNoteSignatureHash: (h: string, amountMsat: number, signatureHex: string, mintPubkeyHex: string) => boolean;
9
+ export declare const signNoteOwnership: (secretKey: Uint8Array) => Uint8Array;
10
+ export declare const recoverNoteOwnershipPubkey: (signature: Uint8Array) => Uint8Array | null;
11
+ export type AddressProofAction = 'register' | 'unregister';
12
+ export declare const signAddressProof: (branchIndexZeroSecretKey: Uint8Array, action: AddressProofAction, username: string) => Uint8Array;
13
+ export declare const cp1FromCk1: (ck1: string) => string | null;
14
+ export declare const requireMutationSignature: (body: any, field: 'sig' | 'sig2') => string;
package/dist/urls.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ export declare const isBech32Lnurl: (data: string) => boolean;
2
+ export declare const toBech32Lnurl: (url: string) => string;
3
+ export declare const fromBech32Lnurl: (data: string) => string | null;
4
+ export declare const defaultSchemeFor: (hostish: string) => 'http' | 'https';
5
+ export declare const isAllowedServiceUrl: (value: string) => boolean;
6
+ export declare const fromLud17: (url: string) => string;
7
+ export declare const toLud17w: (url: string) => string;
8
+ export declare const isLightningAddress: (value: string) => boolean;
9
+ export declare const resolveMintInput: (value: string) => string | null;
10
+ export declare const mintAddressUrl: (payUrl: string) => string | null;
11
+ export declare const lightningAddressUsername: (payUrl: string) => string | null;
12
+ export declare const resolveLnurlInput: (value: string) => string | null;
13
+ export declare const noteK1: (url: string) => string | null;
14
+ export declare const requireNoteK1: (url: string) => string;
15
+ export declare const noteDeclaredAmount: (url: string) => number | null;
16
+ export declare const noteSignature: (url: string) => string | null;
17
+ export declare const isValidK1: (value: string) => boolean;
18
+ export declare const resolveNoteInput: (value: string) => string | null;
19
+ export declare const isValidNoteInput: (value: string) => boolean;
20
+ export declare const buildNoteUrl: (withdrawLink: string, k1: string, amountMsat?: number) => string;
21
+ export declare const withNewK1: (url: string, k1: string, amountMsat: number, signature?: string) => string;
22
+ export declare const withoutK1: (url: string, amountMsat: number, signature?: string) => string;
23
+ export declare const withoutSignature: (url: string) => string;
24
+ export declare const serverOf: (url: string) => string;
25
+ export declare const serviceOriginOf: (value: string) => string;
26
+ export declare const noteEndpointOf: (url: string) => string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lnurlcash/kit",
3
- "version": "0.14.0-rc.0",
3
+ "version": "0.14.2",
4
4
  "description": "LNURLcash (LUD-25) protocol client for TypeScript",
5
5
  "author": "dni",
6
6
  "contributors": [
@@ -51,7 +51,7 @@
51
51
  }
52
52
  },
53
53
  "scripts": {
54
- "build": "tsup",
54
+ "build": "node build.mjs",
55
55
  "test": "vitest run",
56
56
  "typecheck": "tsc --noEmit",
57
57
  "check": "npm run typecheck && npm run test && npm run build",
@@ -64,8 +64,8 @@
64
64
  },
65
65
  "devDependencies": {
66
66
  "@types/node": "^26.2.0",
67
- "tsup": "^8.5.0",
68
- "typescript": "^5.7.0",
67
+ "esbuild": "^0.27.7",
68
+ "typescript": "^7.0.2",
69
69
  "vitest": "^5.0.0"
70
70
  }
71
71
  }