@run402/sdk 4.113.0 → 4.114.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/node/lightning-paid-fetch.d.ts +2 -0
  2. package/dist/node/lightning-paid-fetch.d.ts.map +1 -1
  3. package/dist/node/lightning-paid-fetch.js +44 -10
  4. package/dist/node/lightning-paid-fetch.js.map +1 -1
  5. package/dist/node/lightning-x402-lnbtc.d.ts +62 -0
  6. package/dist/node/lightning-x402-lnbtc.d.ts.map +1 -0
  7. package/dist/node/lightning-x402-lnbtc.js +170 -0
  8. package/dist/node/lightning-x402-lnbtc.js.map +1 -0
  9. package/dist/node/vendor/x402-lnbtc/LICENSE +201 -0
  10. package/dist/node/vendor/x402-lnbtc/VENDORED.md +25 -0
  11. package/dist/node/vendor/x402-lnbtc/binding.d.ts +80 -0
  12. package/dist/node/vendor/x402-lnbtc/binding.d.ts.map +1 -0
  13. package/dist/node/vendor/x402-lnbtc/binding.js +268 -0
  14. package/dist/node/vendor/x402-lnbtc/binding.js.map +1 -0
  15. package/dist/node/vendor/x402-lnbtc/bolt11.d.ts +39 -0
  16. package/dist/node/vendor/x402-lnbtc/bolt11.d.ts.map +1 -0
  17. package/dist/node/vendor/x402-lnbtc/bolt11.js +209 -0
  18. package/dist/node/vendor/x402-lnbtc/bolt11.js.map +1 -0
  19. package/dist/node/vendor/x402-lnbtc/constants.d.ts +75 -0
  20. package/dist/node/vendor/x402-lnbtc/constants.d.ts.map +1 -0
  21. package/dist/node/vendor/x402-lnbtc/constants.js +81 -0
  22. package/dist/node/vendor/x402-lnbtc/constants.js.map +1 -0
  23. package/dist/node/vendor/x402-lnbtc/exact/client/scheme.d.ts +58 -0
  24. package/dist/node/vendor/x402-lnbtc/exact/client/scheme.d.ts.map +1 -0
  25. package/dist/node/vendor/x402-lnbtc/exact/client/scheme.js +108 -0
  26. package/dist/node/vendor/x402-lnbtc/exact/client/scheme.js.map +1 -0
  27. package/dist/node/vendor/x402-lnbtc/jcs.d.ts +19 -0
  28. package/dist/node/vendor/x402-lnbtc/jcs.d.ts.map +1 -0
  29. package/dist/node/vendor/x402-lnbtc/jcs.js +81 -0
  30. package/dist/node/vendor/x402-lnbtc/jcs.js.map +1 -0
  31. package/dist/node/vendor/x402-lnbtc/types.d.ts +81 -0
  32. package/dist/node/vendor/x402-lnbtc/types.d.ts.map +1 -0
  33. package/dist/node/vendor/x402-lnbtc/types.js +2 -0
  34. package/dist/node/vendor/x402-lnbtc/types.js.map +1 -0
  35. package/dist/node/vendor/x402-lnbtc/validation.d.ts +94 -0
  36. package/dist/node/vendor/x402-lnbtc/validation.d.ts.map +1 -0
  37. package/dist/node/vendor/x402-lnbtc/validation.js +165 -0
  38. package/dist/node/vendor/x402-lnbtc/validation.js.map +1 -0
  39. package/package.json +1 -1
@@ -0,0 +1,80 @@
1
+ import { HTTP_PROFILE, MCP_PROFILE } from "./constants.js";
2
+ export type RequestBindingProfile = typeof HTTP_PROFILE | typeof MCP_PROFILE;
3
+ /**
4
+ * The request-binding fields carried in `PaymentRequirements.extra`.
5
+ */
6
+ export interface RequestBindingExtra {
7
+ requestHash: string;
8
+ requestBindingProfile: RequestBindingProfile;
9
+ requestBindingParams: Record<string, unknown>;
10
+ }
11
+ /**
12
+ * A request binding computed from the actual request or tool call.
13
+ */
14
+ export interface RequestBinding extends RequestBindingExtra {
15
+ /** For `http:1`, the request URL that `PaymentRequired.resource.url` must equal. */
16
+ resourceUrl?: string;
17
+ }
18
+ /**
19
+ * HTTP request inputs for the `http:1` profile.
20
+ */
21
+ export interface HttpRequestInput {
22
+ /** HTTP method, case preserved (RFC 9421 `@method`). */
23
+ method: string;
24
+ /** Absolute http(s) target URI including the query, no fragment or userinfo. */
25
+ url: string;
26
+ /** Content bytes after transfer decoding, before content decoding; empty if absent. */
27
+ body?: Uint8Array;
28
+ /** Lowercase header names to bind, configured by the server for the resource. */
29
+ boundHeaders: readonly string[];
30
+ /** Header lookup by lowercase name; `undefined` when absent. */
31
+ getHeader: (name: string) => string | readonly string[] | undefined;
32
+ }
33
+ /**
34
+ * MCP `tools/call` inputs for the `mcp:1` profile.
35
+ */
36
+ export interface McpToolCallInput {
37
+ /** Configured absolute URI identifying the MCP server. */
38
+ server: string;
39
+ /** Actual `params.name`. */
40
+ name: string;
41
+ /** Actual `params.arguments`, before defaults; `undefined` when omitted. */
42
+ arguments?: unknown;
43
+ /** Actual `params._meta`; `undefined` when omitted. */
44
+ meta?: unknown;
45
+ /** `_meta` member names to bind, configured by the server for the tool. */
46
+ boundMetadata: readonly string[];
47
+ }
48
+ /**
49
+ * Computes the `http:1` binding for an HTTP request.
50
+ *
51
+ * @param input - The actual request and the configured bound headers
52
+ * @returns The binding, including the expected `PaymentRequired.resource.url`
53
+ * @throws LnbtcError `invalid_exact_lnbtc_request_binding` on malformed input
54
+ */
55
+ export declare function httpRequestBinding(input: HttpRequestInput): RequestBinding;
56
+ /**
57
+ * Computes the `mcp:1` binding for an MCP `tools/call`.
58
+ *
59
+ * @param input - The actual tool call and the configured server and metadata names
60
+ * @returns The binding
61
+ * @throws LnbtcError `invalid_exact_lnbtc_request_binding` on malformed input
62
+ */
63
+ export declare function mcpToolCallBinding(input: McpToolCallInput): RequestBinding;
64
+ /**
65
+ * Validates the binding fields of a requirements `extra` object.
66
+ *
67
+ * @param extra - `PaymentRequirements.extra`
68
+ * @returns The validated binding fields
69
+ * @throws LnbtcError `invalid_exact_lnbtc_request_binding` when missing or malformed
70
+ */
71
+ export declare function parseBindingExtra(extra: Record<string, unknown> | undefined): RequestBindingExtra;
72
+ /**
73
+ * Compares two validated bindings: hash, profile, and JCS-equal parameters.
74
+ *
75
+ * @param a - First binding
76
+ * @param b - Second binding
77
+ * @returns Whether they are equal
78
+ */
79
+ export declare function bindingsEqual(a: RequestBindingExtra, b: RequestBindingExtra): boolean;
80
+ //# sourceMappingURL=binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../../../src/node/vendor/x402-lnbtc/binding.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiC,YAAY,EAAc,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGtG,MAAM,MAAM,qBAAqB,GAAG,OAAO,YAAY,GAAG,OAAO,WAAW,CAAC;AAE7E;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACzD,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,uFAAuF;IACvF,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,iFAAiF;IACjF,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,gEAAgE;IAChE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CACrE;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uDAAuD;IACvD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2EAA2E;IAC3E,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAYD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,cAAc,CAwB1E;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,cAAc,CA4B1E;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,mBAAmB,CAcjG;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAMrF"}
@@ -0,0 +1,268 @@
1
+ import { sha256 } from "@noble/hashes/sha2.js";
2
+ import { bytesToHex } from "@noble/hashes/utils.js";
3
+ import { BINDING_DOMAIN_PREFIX, Errors, HTTP_PROFILE, LnbtcError, MCP_PROFILE } from "./constants.js";
4
+ import { canonicalize, isWellFormed } from "./jcs.js";
5
+ const TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
6
+ const LOWER_TOKEN = /^[!#$%&'*+\-.^_`|~0-9a-z]+$/;
7
+ const HEX64 = /^[0-9a-f]{64}$/;
8
+ // RFC 3986 URI characters (no fragment) with well-formed percent escapes.
9
+ // Square brackets are accepted outside the host too, as common clients send them raw.
10
+ const URI_SYNTAX = /^[A-Za-z][A-Za-z0-9+.-]*:(?:[A-Za-z0-9\-._~:/?[\]@!$&'()*+,;=]|%[0-9A-Fa-f]{2})*$/;
11
+ const ABSENT_HASH = bytesToHex(sha256(Uint8Array.of(0x00)));
12
+ const EXCLUDED_METADATA = new Set(["x402/payment", "progressToken"]);
13
+ /**
14
+ * Computes the `http:1` binding for an HTTP request.
15
+ *
16
+ * @param input - The actual request and the configured bound headers
17
+ * @returns The binding, including the expected `PaymentRequired.resource.url`
18
+ * @throws LnbtcError `invalid_exact_lnbtc_request_binding` on malformed input
19
+ */
20
+ export function httpRequestBinding(input) {
21
+ const params = { headers: [...input.boundHeaders] };
22
+ validateHttpParams(params);
23
+ if (typeof input.method !== "string" || !TOKEN.test(input.method))
24
+ fail();
25
+ validateAbsoluteUri(input.url, true);
26
+ if (input.body !== undefined && !(input.body instanceof Uint8Array))
27
+ fail();
28
+ const headers = params.headers.map(name => ({
29
+ name,
30
+ valueHash: headerValueHash(input.getHeader(name)),
31
+ }));
32
+ const binding = {
33
+ domain: `${BINDING_DOMAIN_PREFIX}${HTTP_PROFILE}`,
34
+ method: input.method,
35
+ url: input.url,
36
+ bodyHash: bytesToHex(sha256(input.body ?? new Uint8Array())),
37
+ headers,
38
+ };
39
+ return {
40
+ requestHash: hashBinding(binding),
41
+ requestBindingProfile: HTTP_PROFILE,
42
+ requestBindingParams: params,
43
+ resourceUrl: input.url,
44
+ };
45
+ }
46
+ /**
47
+ * Computes the `mcp:1` binding for an MCP `tools/call`.
48
+ *
49
+ * @param input - The actual tool call and the configured server and metadata names
50
+ * @returns The binding
51
+ * @throws LnbtcError `invalid_exact_lnbtc_request_binding` on malformed input
52
+ */
53
+ export function mcpToolCallBinding(input) {
54
+ const params = { server: input.server, metadata: [...input.boundMetadata] };
55
+ validateMcpParams(params);
56
+ if (typeof input.name !== "string" || input.name.length === 0)
57
+ fail();
58
+ const args = input.arguments === undefined ? {} : input.arguments;
59
+ if (!isPlainObject(args))
60
+ fail();
61
+ const meta = input.meta === undefined ? {} : input.meta;
62
+ if (!isPlainObject(meta))
63
+ fail();
64
+ const metadata = params.metadata.map(name => ({
65
+ name,
66
+ valueHash: Object.prototype.hasOwnProperty.call(meta, name)
67
+ ? hashPresent(new TextEncoder().encode(jcs(meta[name])))
68
+ : ABSENT_HASH,
69
+ }));
70
+ const binding = {
71
+ domain: `${BINDING_DOMAIN_PREFIX}${MCP_PROFILE}`,
72
+ server: params.server,
73
+ method: "tools/call",
74
+ name: input.name,
75
+ arguments: args,
76
+ metadata,
77
+ };
78
+ return {
79
+ requestHash: hashBinding(binding),
80
+ requestBindingProfile: MCP_PROFILE,
81
+ requestBindingParams: params,
82
+ };
83
+ }
84
+ /**
85
+ * Validates the binding fields of a requirements `extra` object.
86
+ *
87
+ * @param extra - `PaymentRequirements.extra`
88
+ * @returns The validated binding fields
89
+ * @throws LnbtcError `invalid_exact_lnbtc_request_binding` when missing or malformed
90
+ */
91
+ export function parseBindingExtra(extra) {
92
+ const requestHash = extra?.requestHash;
93
+ const profile = extra?.requestBindingProfile;
94
+ const params = extra?.requestBindingParams;
95
+ if (typeof requestHash !== "string" || !HEX64.test(requestHash))
96
+ fail();
97
+ if (!isPlainObject(params))
98
+ fail();
99
+ if (profile === HTTP_PROFILE)
100
+ validateHttpParams(params);
101
+ else if (profile === MCP_PROFILE)
102
+ validateMcpParams(params);
103
+ else
104
+ fail();
105
+ return {
106
+ requestHash,
107
+ requestBindingProfile: profile,
108
+ requestBindingParams: params,
109
+ };
110
+ }
111
+ /**
112
+ * Compares two validated bindings: hash, profile, and JCS-equal parameters.
113
+ *
114
+ * @param a - First binding
115
+ * @param b - Second binding
116
+ * @returns Whether they are equal
117
+ */
118
+ export function bindingsEqual(a, b) {
119
+ return (a.requestHash === b.requestHash &&
120
+ a.requestBindingProfile === b.requestBindingProfile &&
121
+ jcs(a.requestBindingParams) === jcs(b.requestBindingParams));
122
+ }
123
+ /**
124
+ * Validates `http:1` parameters: exactly `headers`, lowercase tokens, strictly
125
+ * ascending, excluding `payment-signature`.
126
+ *
127
+ * @param params - Candidate parameters
128
+ */
129
+ function validateHttpParams(params) {
130
+ if (Object.keys(params).length !== 1 || !Array.isArray(params.headers))
131
+ fail();
132
+ validateSortedNames(params.headers, name => LOWER_TOKEN.test(name));
133
+ if (params.headers.includes("payment-signature"))
134
+ fail();
135
+ }
136
+ /**
137
+ * Validates `mcp:1` parameters: exactly `server` and `metadata`.
138
+ *
139
+ * @param params - Candidate parameters
140
+ */
141
+ function validateMcpParams(params) {
142
+ const keys = Object.keys(params).sort();
143
+ if (keys.length !== 2 || keys[0] !== "metadata" || keys[1] !== "server")
144
+ fail();
145
+ if (typeof params.server !== "string")
146
+ fail();
147
+ validateAbsoluteUri(params.server, false);
148
+ if (!Array.isArray(params.metadata))
149
+ fail();
150
+ validateSortedNames(params.metadata, name => name.length > 0 && isWellFormed(name) && !EXCLUDED_METADATA.has(name));
151
+ }
152
+ /**
153
+ * Requires a strictly ascending list of valid names.
154
+ *
155
+ * @param names - Candidate names
156
+ * @param valid - Per-name validity check
157
+ */
158
+ function validateSortedNames(names, valid) {
159
+ for (let i = 0; i < names.length; i++) {
160
+ const name = names[i];
161
+ if (typeof name !== "string" || !valid(name))
162
+ fail();
163
+ // JS string comparison orders by UTF-16 code units: ASCII order for header
164
+ // names, JCS property order for metadata names.
165
+ if (i > 0 && names[i - 1] >= name)
166
+ fail();
167
+ }
168
+ }
169
+ /**
170
+ * Validates an absolute URI in RFC 3986 ASCII syntax with no userinfo or
171
+ * fragment, without normalizing it. `http` and `https` URIs need an authority
172
+ * with a host (`scheme://host...`).
173
+ *
174
+ * @param uri - Candidate URI
175
+ * @param httpOnly - Require the `http` or `https` scheme
176
+ */
177
+ function validateAbsoluteUri(uri, httpOnly) {
178
+ if (typeof uri !== "string" || !URI_SYNTAX.test(uri))
179
+ fail();
180
+ let parsed;
181
+ try {
182
+ parsed = new URL(uri);
183
+ }
184
+ catch {
185
+ fail();
186
+ }
187
+ if (parsed.username || parsed.password || /^[a-z][a-z0-9+.-]*:\/\/[^/?]*@/i.test(uri))
188
+ fail();
189
+ const isHttp = parsed.protocol === "http:" || parsed.protocol === "https:";
190
+ if (httpOnly && !isHttp)
191
+ fail();
192
+ if (isHttp && (!/^https?:\/\/[^/?]/i.test(uri) || parsed.hostname === ""))
193
+ fail();
194
+ }
195
+ /**
196
+ * Hashes a header per RFC 9421 section 2.1 default field-component rules.
197
+ *
198
+ * @param value - Header value(s), or `undefined` when absent
199
+ * @returns The value hash, lowercase hex
200
+ */
201
+ function headerValueHash(value) {
202
+ // No field lines (undefined or an empty list) means the header is absent.
203
+ if (value === undefined || (Array.isArray(value) && value.length === 0))
204
+ return ABSENT_HASH;
205
+ const lines = typeof value === "string" ? [value] : value;
206
+ const parts = lines.map(line => {
207
+ if (typeof line !== "string" || !/^[\t\x20-\x7e]*$/.test(line))
208
+ fail();
209
+ return line.replace(/^[\t ]+|[\t ]+$/g, "");
210
+ });
211
+ return hashPresent(new TextEncoder().encode(parts.join(", ")));
212
+ }
213
+ /**
214
+ * Hashes a present value as SHA-256 of `0x01 || bytes`.
215
+ *
216
+ * @param bytes - Value bytes
217
+ * @returns Lowercase hex digest
218
+ */
219
+ function hashPresent(bytes) {
220
+ const input = new Uint8Array(bytes.length + 1);
221
+ input[0] = 0x01;
222
+ input.set(bytes, 1);
223
+ return bytesToHex(sha256(input));
224
+ }
225
+ /**
226
+ * Hashes a binding object: SHA-256 of UTF-8 JCS.
227
+ *
228
+ * @param binding - The binding object
229
+ * @returns Lowercase hex request hash
230
+ */
231
+ function hashBinding(binding) {
232
+ return bytesToHex(sha256(new TextEncoder().encode(jcs(binding))));
233
+ }
234
+ /**
235
+ * Canonicalizes, mapping serialization errors to the binding error.
236
+ *
237
+ * @param value - Value to canonicalize
238
+ * @returns JCS text
239
+ */
240
+ function jcs(value) {
241
+ try {
242
+ return canonicalize(value);
243
+ }
244
+ catch {
245
+ fail();
246
+ }
247
+ }
248
+ /**
249
+ * Checks for a plain (non-array, non-null) object.
250
+ *
251
+ * @param value - Candidate value
252
+ * @returns Whether it is a plain object
253
+ */
254
+ function isPlainObject(value) {
255
+ if (value === null || typeof value !== "object" || Array.isArray(value))
256
+ return false;
257
+ const proto = Object.getPrototypeOf(value);
258
+ return proto === Object.prototype || proto === null;
259
+ }
260
+ /**
261
+ * Throws the request-binding error.
262
+ *
263
+ * @returns Never returns
264
+ */
265
+ function fail() {
266
+ throw new LnbtcError(Errors.requestBinding);
267
+ }
268
+ //# sourceMappingURL=binding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding.js","sourceRoot":"","sources":["../../../../src/node/vendor/x402-lnbtc/binding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Strictly decoded BOLT11 invoice fields used by the lnbtc scheme.
3
+ */
4
+ export interface DecodedInvoice {
5
+ /** BOLT11 currency prefix (e.g. `bc`, `tb`). */
6
+ currency: string;
7
+ /** Invoice amount in millisatoshis. */
8
+ amountMsat: bigint;
9
+ /** Creation time, Unix seconds. */
10
+ timestamp: number;
11
+ /** Expiry in seconds (BOLT11 default 3600 when the `x` field is absent). */
12
+ expirySeconds: number;
13
+ /** Payment hash, 64 lowercase hex characters. */
14
+ paymentHash: string;
15
+ /** Every valid `h` (description hash) field, lowercase hex. */
16
+ descriptionHashes: string[];
17
+ /** Number of `d` (inline description) fields. */
18
+ inlineDescriptionCount: number;
19
+ /** Signing node public key (compressed, lowercase hex), from `n` or recovered. */
20
+ payee: string;
21
+ /** Whether the invoice carried an explicit `n` field. */
22
+ hasPayeeField: boolean;
23
+ }
24
+ /**
25
+ * Decodes a BOLT11 invoice and verifies its signature.
26
+ *
27
+ * Strict: rejects mixed case, a `lightning:` prefix, a missing or zero amount,
28
+ * sub-millisatoshi amounts, amounts with leading zeros, fixed-length fields of
29
+ * the wrong length or with non-zero padding, duplicated payment hash, payment
30
+ * secret, payee, expiry, CLTV, or feature fields, non-minimal integer fields,
31
+ * a missing payment secret, a high-S signature verified against an `n` field,
32
+ * and an invalid signature.
33
+ *
34
+ * @param invoice - BOLT11 invoice text
35
+ * @returns The decoded invoice
36
+ * @throws Error when the invoice is malformed or its signature is invalid
37
+ */
38
+ export declare function decodeInvoice(invoice: string): DecodedInvoice;
39
+ //# sourceMappingURL=bolt11.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bolt11.d.ts","sourceRoot":"","sources":["../../../../src/node/vendor/x402-lnbtc/bolt11.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,iDAAiD;IACjD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,aAAa,EAAE,OAAO,CAAC;CACxB;AAoCD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CA+B7D"}
@@ -0,0 +1,209 @@
1
+ import { secp256k1 } from "@noble/curves/secp256k1.js";
2
+ import { sha256 } from "@noble/hashes/sha2.js";
3
+ import { bytesToHex, hexToBytes } from "@noble/hashes/utils.js";
4
+ import { bech32, utils as scure } from "@scure/base";
5
+ const SIGNATURE_WORDS = 104;
6
+ const TIMESTAMP_WORDS = 7;
7
+ const DEFAULT_EXPIRY_SECONDS = 3600;
8
+ const MSAT_PER_BTC = 100000000000n;
9
+ // Multiplier → divisor of the BTC amount in msat.
10
+ const MULTIPLIERS = {
11
+ m: 1000n, // milli: 1e-3 BTC = 1e8 msat
12
+ u: 1000000n,
13
+ n: 1000000000n,
14
+ p: 1000000000000n,
15
+ };
16
+ const TAG = { p: 1, s: 16, d: 13, h: 23, x: 6, n: 19, c: 24, features: 5 };
17
+ // BOLT11: a reader MUST fail when a fixed-length field has another length.
18
+ const FIXED_LENGTHS = new Map([
19
+ [TAG.p, 52],
20
+ [TAG.s, 52],
21
+ [TAG.h, 52],
22
+ [TAG.n, 53],
23
+ ]);
24
+ // Fields that may appear at most once; BOLT11 asks for minimal integer encodings.
25
+ const SINGLETON_TAGS = new Set([
26
+ TAG.p,
27
+ TAG.s,
28
+ TAG.n,
29
+ TAG.x,
30
+ TAG.c,
31
+ TAG.features,
32
+ ]);
33
+ const MINIMAL_TAGS = new Set([TAG.x, TAG.c, TAG.features]);
34
+ /**
35
+ * Decodes a BOLT11 invoice and verifies its signature.
36
+ *
37
+ * Strict: rejects mixed case, a `lightning:` prefix, a missing or zero amount,
38
+ * sub-millisatoshi amounts, amounts with leading zeros, fixed-length fields of
39
+ * the wrong length or with non-zero padding, duplicated payment hash, payment
40
+ * secret, payee, expiry, CLTV, or feature fields, non-minimal integer fields,
41
+ * a missing payment secret, a high-S signature verified against an `n` field,
42
+ * and an invalid signature.
43
+ *
44
+ * @param invoice - BOLT11 invoice text
45
+ * @returns The decoded invoice
46
+ * @throws Error when the invoice is malformed or its signature is invalid
47
+ */
48
+ export function decodeInvoice(invoice) {
49
+ if (typeof invoice !== "string" || invoice.length === 0)
50
+ throw new Error("empty invoice");
51
+ const { prefix, words } = bech32.decode(invoice, false);
52
+ const { currency, amountMsat } = parseHrp(prefix);
53
+ if (words.length < TIMESTAMP_WORDS + SIGNATURE_WORDS)
54
+ throw new Error("invoice too short");
55
+ const signed = words.slice(0, words.length - SIGNATURE_WORDS);
56
+ const sigBytes = bech32.fromWords(words.slice(words.length - SIGNATURE_WORDS));
57
+ const timestamp = wordsToNumber(signed.slice(0, TIMESTAMP_WORDS));
58
+ const fields = parseTaggedFields(signed.slice(TIMESTAMP_WORDS));
59
+ if (fields.paymentHash === undefined)
60
+ throw new Error("invoice has no payment hash");
61
+ if (!fields.hasPaymentSecret)
62
+ throw new Error("invoice has no payment secret");
63
+ const prefixBytes = new TextEncoder().encode(prefix);
64
+ const dataBytes = Uint8Array.from(scure.convertRadix2(signed, 5, 8, true));
65
+ const message = new Uint8Array(prefixBytes.length + dataBytes.length);
66
+ message.set(prefixBytes);
67
+ message.set(dataBytes, prefixBytes.length);
68
+ return {
69
+ currency,
70
+ amountMsat,
71
+ timestamp,
72
+ expirySeconds: fields.expiry ?? DEFAULT_EXPIRY_SECONDS,
73
+ paymentHash: fields.paymentHash,
74
+ descriptionHashes: fields.descriptionHashes,
75
+ inlineDescriptionCount: fields.inlineDescriptions,
76
+ payee: verifySignature(sigBytes, sha256(message), fields.payee),
77
+ hasPayeeField: fields.payee !== undefined,
78
+ };
79
+ }
80
+ /**
81
+ * Parses the human-readable part into currency and millisatoshi amount.
82
+ *
83
+ * @param prefix - The bech32 human-readable part
84
+ * @returns Currency prefix and amount in millisatoshis
85
+ */
86
+ function parseHrp(prefix) {
87
+ const match = /^ln([a-z]+?)([0-9]+)?([munp])?$/.exec(prefix);
88
+ if (!match)
89
+ throw new Error("invalid invoice prefix");
90
+ const [, currency, digits, multiplier] = match;
91
+ if (!digits)
92
+ throw new Error("invoice has no amount");
93
+ if (digits.length > 1 && digits.startsWith("0"))
94
+ throw new Error("amount has leading zeros");
95
+ const value = BigInt(digits);
96
+ if (value === 0n)
97
+ throw new Error("invoice amount is zero");
98
+ const scaled = value * MSAT_PER_BTC;
99
+ if (!multiplier)
100
+ return { currency, amountMsat: scaled };
101
+ const divisor = MULTIPLIERS[multiplier];
102
+ if (scaled % divisor !== 0n)
103
+ throw new Error("amount is not an integral millisatoshi");
104
+ return { currency, amountMsat: scaled / divisor };
105
+ }
106
+ /**
107
+ * Reads BOLT11 tagged fields, skipping unknown fields.
108
+ *
109
+ * @param words - 5-bit words after the timestamp, before the signature
110
+ * @returns The fields the scheme consumes
111
+ */
112
+ function parseTaggedFields(words) {
113
+ const out = {
114
+ hasPaymentSecret: false,
115
+ descriptionHashes: [],
116
+ inlineDescriptions: 0,
117
+ };
118
+ const seen = new Set();
119
+ let i = 0;
120
+ while (i < words.length) {
121
+ if (i + 3 > words.length)
122
+ throw new Error("truncated tagged field");
123
+ const tag = words[i];
124
+ const length = words[i + 1] * 32 + words[i + 2];
125
+ const data = words.slice(i + 3, i + 3 + length);
126
+ if (data.length !== length)
127
+ throw new Error("truncated tagged field");
128
+ i += 3 + length;
129
+ const fixedLength = FIXED_LENGTHS.get(tag);
130
+ if (fixedLength !== undefined && length !== fixedLength) {
131
+ throw new Error("tagged field has the wrong length");
132
+ }
133
+ if (SINGLETON_TAGS.has(tag)) {
134
+ if (seen.has(tag))
135
+ throw new Error("duplicate tagged field");
136
+ seen.add(tag);
137
+ }
138
+ if (MINIMAL_TAGS.has(tag) && data[0] === 0)
139
+ throw new Error("non-minimal integer field");
140
+ switch (tag) {
141
+ case TAG.p:
142
+ out.paymentHash = bytesToHex(bech32.fromWords(data));
143
+ break;
144
+ case TAG.s:
145
+ bech32.fromWords(data); // rejects non-zero padding
146
+ out.hasPaymentSecret = true;
147
+ break;
148
+ case TAG.h:
149
+ out.descriptionHashes.push(bytesToHex(bech32.fromWords(data)));
150
+ break;
151
+ case TAG.d:
152
+ out.inlineDescriptions += 1;
153
+ break;
154
+ case TAG.n:
155
+ out.payee = bytesToHex(bech32.fromWords(data));
156
+ break;
157
+ case TAG.x:
158
+ out.expiry = wordsToNumber(data);
159
+ break;
160
+ default:
161
+ break;
162
+ }
163
+ }
164
+ return out;
165
+ }
166
+ /**
167
+ * Verifies the invoice signature against `n` when present (low-S required, as
168
+ * BOLT11 demands), otherwise recovers the signing key (either S form accepted).
169
+ *
170
+ * @param sigBytes - 65 bytes: compact signature followed by the recovery id
171
+ * @param digest - SHA-256 of the signed invoice bytes
172
+ * @param payeeField - Public key from the `n` field, if present
173
+ * @returns The signing public key, compressed lowercase hex
174
+ */
175
+ function verifySignature(sigBytes, digest, payeeField) {
176
+ const recovery = sigBytes[64];
177
+ if (recovery > 3)
178
+ throw new Error("invalid recovery id");
179
+ const compact = sigBytes.subarray(0, 64);
180
+ if (payeeField !== undefined) {
181
+ const valid = secp256k1.verify(compact, digest, hexToBytes(payeeField), {
182
+ lowS: true,
183
+ format: "compact",
184
+ prehash: false,
185
+ });
186
+ if (!valid)
187
+ throw new Error("invalid invoice signature");
188
+ return payeeField;
189
+ }
190
+ // Recovery yields the unique key for which this signature verifies.
191
+ const signature = secp256k1.Signature.fromBytes(compact, "compact").addRecoveryBit(recovery);
192
+ return signature.recoverPublicKey(digest).toHex(true);
193
+ }
194
+ /**
195
+ * Interprets 5-bit words as a big-endian unsigned integer.
196
+ *
197
+ * @param words - 5-bit words
198
+ * @returns The integer value
199
+ */
200
+ function wordsToNumber(words) {
201
+ let value = 0;
202
+ for (const word of words) {
203
+ value = value * 32 + word;
204
+ if (!Number.isSafeInteger(value))
205
+ throw new Error("integer field too large");
206
+ }
207
+ return value;
208
+ }
209
+ //# sourceMappingURL=bolt11.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bolt11.js","sourceRoot":"","sources":["../../../../src/node/vendor/x402-lnbtc/bolt11.ts"],"names":[],"mappings":"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"}