@getalby/lightning-tools 8.0.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/402/l402.cjs +102 -0
- package/dist/cjs/402/l402.cjs.map +1 -1
- package/dist/cjs/402/x402.cjs +525 -518
- package/dist/cjs/402/x402.cjs.map +1 -1
- package/dist/cjs/402.cjs +116 -7
- package/dist/cjs/402.cjs.map +1 -1
- package/dist/cjs/bolt11.cjs +526 -518
- package/dist/cjs/bolt11.cjs.map +1 -1
- package/dist/cjs/index.cjs +597 -487
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/lnurl.cjs +14 -7
- package/dist/cjs/lnurl.cjs.map +1 -1
- package/dist/esm/402/l402.js +98 -1
- package/dist/esm/402/l402.js.map +1 -1
- package/dist/esm/402/x402.js +525 -518
- package/dist/esm/402/x402.js.map +1 -1
- package/dist/esm/402.js +112 -8
- package/dist/esm/402.js.map +1 -1
- package/dist/esm/bolt11.js +526 -519
- package/dist/esm/bolt11.js.map +1 -1
- package/dist/esm/index.js +592 -488
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lnurl.js +14 -7
- package/dist/esm/lnurl.js.map +1 -1
- package/dist/lightning-tools.umd.js +3 -3
- package/dist/lightning-tools.umd.js.map +1 -1
- package/dist/types/402/l402.d.ts +39 -1
- package/dist/types/402.d.ts +39 -2
- package/dist/types/bolt11.d.ts +2 -1
- package/dist/types/index.d.ts +40 -2
- package/package.json +1 -1
package/dist/esm/402.js
CHANGED
|
@@ -1174,6 +1174,19 @@ const decodeInvoice = (paymentRequest) => {
|
|
|
1174
1174
|
return null;
|
|
1175
1175
|
}
|
|
1176
1176
|
};
|
|
1177
|
+
function validatePreimage(preimage, paymentHash) {
|
|
1178
|
+
try {
|
|
1179
|
+
if (!/^[0-9a-fA-F]{64}$/.test(preimage))
|
|
1180
|
+
return false;
|
|
1181
|
+
if (!/^[0-9a-fA-F]{64}$/.test(paymentHash))
|
|
1182
|
+
return false;
|
|
1183
|
+
const preimageHash = bytesToHex(sha256(fromHexString(preimage)));
|
|
1184
|
+
return paymentHash === preimageHash;
|
|
1185
|
+
}
|
|
1186
|
+
catch {
|
|
1187
|
+
return false;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1177
1190
|
|
|
1178
1191
|
class Invoice {
|
|
1179
1192
|
constructor(args) {
|
|
@@ -1213,13 +1226,7 @@ class Invoice {
|
|
|
1213
1226
|
validatePreimage(preimage) {
|
|
1214
1227
|
if (!preimage || !this.paymentHash)
|
|
1215
1228
|
return false;
|
|
1216
|
-
|
|
1217
|
-
const preimageHash = bytesToHex(sha256(fromHexString(preimage)));
|
|
1218
|
-
return this.paymentHash === preimageHash;
|
|
1219
|
-
}
|
|
1220
|
-
catch {
|
|
1221
|
-
return false;
|
|
1222
|
-
}
|
|
1229
|
+
return validatePreimage(preimage, this.paymentHash);
|
|
1223
1230
|
}
|
|
1224
1231
|
async verifyPayment() {
|
|
1225
1232
|
try {
|
|
@@ -1262,6 +1269,11 @@ function createGuardedWallet(wallet, maxAmountSats) {
|
|
|
1262
1269
|
};
|
|
1263
1270
|
}
|
|
1264
1271
|
|
|
1272
|
+
/**
|
|
1273
|
+
* Client: parse "www-authenticate" header from server response
|
|
1274
|
+
* @param input
|
|
1275
|
+
* @returns details from the header value (token or macaroon, invoice)
|
|
1276
|
+
*/
|
|
1265
1277
|
const parseL402 = (input) => {
|
|
1266
1278
|
// Remove the L402 and LSAT identifiers
|
|
1267
1279
|
const string = input.replace("L402", "").replace("LSAT", "").trim();
|
|
@@ -1276,6 +1288,19 @@ const parseL402 = (input) => {
|
|
|
1276
1288
|
// Value is either match[3] (double-quoted), match[4] (single-quoted), or match[5] (unquoted)
|
|
1277
1289
|
keyValuePairs[match[1]] = match[3] || match[4] || match[5];
|
|
1278
1290
|
}
|
|
1291
|
+
if (!keyValuePairs["token"] && keyValuePairs["macaroon"]) {
|
|
1292
|
+
// fallback to old naming
|
|
1293
|
+
keyValuePairs["token"] = keyValuePairs["macaroon"];
|
|
1294
|
+
delete keyValuePairs["macaroon"];
|
|
1295
|
+
}
|
|
1296
|
+
if (!("token" in keyValuePairs) ||
|
|
1297
|
+
typeof keyValuePairs["token"] !== "string") {
|
|
1298
|
+
throw new Error("No macaroon or token found in www-authenticate header");
|
|
1299
|
+
}
|
|
1300
|
+
if (!("invoice" in keyValuePairs) ||
|
|
1301
|
+
typeof keyValuePairs["invoice"] !== "string") {
|
|
1302
|
+
throw new Error("No invoice found in www-authenticate header");
|
|
1303
|
+
}
|
|
1279
1304
|
return keyValuePairs;
|
|
1280
1305
|
};
|
|
1281
1306
|
|
|
@@ -1575,5 +1600,84 @@ const fetch402 = async (url, fetchArgs, options) => {
|
|
|
1575
1600
|
return initResp;
|
|
1576
1601
|
};
|
|
1577
1602
|
|
|
1578
|
-
|
|
1603
|
+
async function issueL402Macaroon(secret, paymentHash, params) {
|
|
1604
|
+
if (params !== undefined &&
|
|
1605
|
+
Object.prototype.hasOwnProperty.call(params, "paymentHash")) {
|
|
1606
|
+
throw new Error("paymentHash is reserved");
|
|
1607
|
+
}
|
|
1608
|
+
const payload = { ...params, paymentHash };
|
|
1609
|
+
const encoded = Buffer.from(JSON.stringify(payload)).toString("base64url");
|
|
1610
|
+
const mac = await sign(secret, encoded);
|
|
1611
|
+
return `${encoded}.${mac}`;
|
|
1612
|
+
}
|
|
1613
|
+
async function verifyL402Macaroon(secret, token) {
|
|
1614
|
+
const { timingSafeEqual } = await import('crypto');
|
|
1615
|
+
const dotIndex = token.lastIndexOf(".");
|
|
1616
|
+
if (dotIndex === -1)
|
|
1617
|
+
throw new Error("Invalid macaroon token");
|
|
1618
|
+
const encoded = token.slice(0, dotIndex);
|
|
1619
|
+
const mac = token.slice(dotIndex + 1);
|
|
1620
|
+
// Constant-time comparison to prevent timing attacks
|
|
1621
|
+
const expectedMac = await sign(secret, encoded);
|
|
1622
|
+
try {
|
|
1623
|
+
if (!timingSafeEqual(Buffer.from(mac, "hex"), Buffer.from(expectedMac, "hex"))) {
|
|
1624
|
+
throw new Error("Invalid macaroon token");
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
catch (e) {
|
|
1628
|
+
throw new Error("Invalid macaroon token");
|
|
1629
|
+
}
|
|
1630
|
+
try {
|
|
1631
|
+
const parsed = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
|
|
1632
|
+
if (parsed === null ||
|
|
1633
|
+
typeof parsed !== "object" ||
|
|
1634
|
+
Array.isArray(parsed) ||
|
|
1635
|
+
typeof parsed.paymentHash !== "string") {
|
|
1636
|
+
throw new Error("Invalid macaroon payload");
|
|
1637
|
+
}
|
|
1638
|
+
return parsed;
|
|
1639
|
+
}
|
|
1640
|
+
catch {
|
|
1641
|
+
throw new Error("Invalid macaroon token");
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
async function sign(secret, payload) {
|
|
1645
|
+
const { createHmac } = await import('crypto');
|
|
1646
|
+
return createHmac("sha256", secret).update(payload).digest("hex");
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
/**
|
|
1650
|
+
* Server: create a WWW-Authenticate header for a given macaroon and invoice
|
|
1651
|
+
* @param args the macaroon/token and invoice generated for the client's request
|
|
1652
|
+
* @returns the header value
|
|
1653
|
+
*/
|
|
1654
|
+
const makeL402AuthenticateHeader = (args) => {
|
|
1655
|
+
if (!args.token) {
|
|
1656
|
+
throw new Error("token must be provided");
|
|
1657
|
+
}
|
|
1658
|
+
return `L402 version="0" token="${args.token}", invoice="${args.invoice}"`;
|
|
1659
|
+
};
|
|
1660
|
+
/**
|
|
1661
|
+
* Server: parse "authorization" header sent from client
|
|
1662
|
+
* @param input value from authorization header
|
|
1663
|
+
* @returns the macaroon and preimage
|
|
1664
|
+
*/
|
|
1665
|
+
function parseL402Authorization(input) {
|
|
1666
|
+
// Backwards compat: LSAT was the former name of L402
|
|
1667
|
+
const normalized = input.replace(/^LSAT /, "L402 ");
|
|
1668
|
+
const prefix = "L402 ";
|
|
1669
|
+
if (!normalized.startsWith(prefix))
|
|
1670
|
+
return null;
|
|
1671
|
+
const credentials = normalized.slice(prefix.length);
|
|
1672
|
+
const colonIndex = credentials.indexOf(":");
|
|
1673
|
+
if (colonIndex === -1) {
|
|
1674
|
+
throw new Error("Invalid authorization header value");
|
|
1675
|
+
}
|
|
1676
|
+
return {
|
|
1677
|
+
token: credentials.slice(0, colonIndex),
|
|
1678
|
+
preimage: credentials.slice(colonIndex + 1),
|
|
1679
|
+
};
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
export { createGuardedWallet, fetch402, fetchWithL402, fetchWithMpp, fetchWithX402, issueL402Macaroon, makeL402AuthenticateHeader, parseL402, parseL402Authorization, verifyL402Macaroon };
|
|
1579
1683
|
//# sourceMappingURL=402.js.map
|