@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 +3 -2
- package/RELEASING.md +25 -34
- package/dist/addresses.d.ts +16 -0
- package/dist/bolt11.d.ts +8 -0
- package/dist/errors.d.ts +20 -0
- package/dist/fees.d.ts +14 -0
- package/dist/index.d.ts +12 -275
- package/dist/index.js +183 -34
- package/dist/internalTransfer.d.ts +18 -0
- package/dist/mintRequest.d.ts +38 -0
- package/dist/net.d.ts +5 -0
- package/dist/recoverableNotes.d.ts +26 -0
- package/dist/request.d.ts +78 -0
- package/dist/secrets.d.ts +6 -0
- package/dist/signature.d.ts +14 -0
- package/dist/urls.d.ts +26 -0
- package/package.json +4 -4
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
|
|
86
|
-
|
|
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
|
-
##
|
|
6
|
+
## Trusted publisher
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
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
|
-
|
|
36
|
-
`
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
47
|
-
|
|
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
|
|
50
|
-
|
|
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
|
|
53
|
-
|
|
54
|
-
tarball through npm OIDC
|
|
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[]>;
|
package/dist/bolt11.d.ts
ADDED
|
@@ -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;
|
package/dist/errors.d.ts
ADDED
|
@@ -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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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${
|
|
180
|
-
var numberToBytesBE = (n, length) =>
|
|
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
|
|
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 =
|
|
225
|
+
const decoded = bech322.decode(
|
|
218
226
|
`LNURL1${safe.slice(6)}`,
|
|
219
227
|
2048
|
|
220
228
|
);
|
|
221
|
-
return new TextDecoder().decode(
|
|
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
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) =>
|
|
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
|
|
432
|
-
|
|
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 ?
|
|
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 =
|
|
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 (
|
|
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
|
-
|
|
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 = () =>
|
|
499
|
-
|
|
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
|
|
533
|
-
|
|
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
|
-
|
|
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 ?
|
|
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 ?
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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": "
|
|
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
|
-
"
|
|
68
|
-
"typescript": "^
|
|
67
|
+
"esbuild": "^0.27.7",
|
|
68
|
+
"typescript": "^7.0.2",
|
|
69
69
|
"vitest": "^5.0.0"
|
|
70
70
|
}
|
|
71
71
|
}
|