@getalby/lightning-tools 6.0.0 → 7.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,13 @@
6
6
 
7
7
  An npm package that provides useful and common tools and helpers to build lightning web applications.
8
8
 
9
- ## 🚀 Quick Start
9
+ Before you start coding, look at example scenarios in our **[Developer Sandbox](https://sandbox.albylabs.com/)**
10
+
11
+ ## 🤖 🚀 ⚡ For Developers using Agents / LLMs / Vibe Coding
12
+
13
+ Skip the rest of this README and use the [Alby Bitcoin Payments Agent Skill](https://github.com/getAlby/alby-agent-skill) instead. It will handle the rest!
14
+
15
+ ## Manual Installation
10
16
 
11
17
  ```
12
18
  npm install @getalby/lightning-tools
@@ -175,7 +181,7 @@ This library includes a `fetchWithL402` function to consume L402 protected resou
175
181
  - url: the L402 protected URL
176
182
  - fetchArgs: arguments are passed to the underlying `fetch()` function used to do the HTTP request
177
183
  - options:
178
- - webln: the webln object used to call `sendPayment()` defaults to globalThis.webln
184
+ - wallet: any object that implements `sendPayment(paymentRequest)` and returns `{ preimage }`. Used to pay the L402 invoice.
179
185
  - store: a key/value store object to persiste the l402 for each URL. The store must implement a `getItem()`/`setItem()` function as the browser's localStorage. By default a memory storage is used.
180
186
  - headerKey: defaults to L402 but if you need to consume an old LSAT API set this to LSAT
181
187
 
@@ -184,12 +190,12 @@ This library includes a `fetchWithL402` function to consume L402 protected resou
184
190
  ```js
185
191
  import { fetchWithL402 } from "@getalby/lightning-tools/l402";
186
192
 
187
- // this will fetch the resource and pay the invoice with window.webln.
193
+ // pass a wallet that implements sendPayment()
188
194
  // the tokens/preimage data will be stored in the browser's localStorage and used for any following request
189
195
  await fetchWithL402(
190
196
  "https://lsat-weather-api.getalby.repl.co/kigali",
191
197
  {},
192
- { store: window.localStorage },
198
+ { wallet: myWallet, store: window.localStorage },
193
199
  )
194
200
  .then((res) => res.json())
195
201
  .then(console.log);
@@ -199,16 +205,16 @@ await fetchWithL402(
199
205
  import { fetchWithL402 } from "@getalby/lightning-tools/l402";
200
206
  import { NostrWebLNProvider } from "@getalby/sdk";
201
207
 
202
- // use a NWC WebLN provide to do the payments
208
+ // use a NWC provider as the wallet to do the payments
203
209
  const nwc = new NostrWebLNProvider({
204
210
  nostrWalletConnectUrl: loadNWCUrl(),
205
211
  });
206
212
 
207
- // this will fetch the resource and pay the invoice with a NWC webln object
213
+ // this will fetch the resource and pay the invoice using the NWC wallet
208
214
  await fetchWithL402(
209
215
  "https://lsat-weather-api.getalby.repl.co/kigali",
210
216
  {},
211
- { webln: nwc },
217
+ { wallet: nwc },
212
218
  )
213
219
  .then((res) => res.json())
214
220
  .then(console.log);
@@ -242,6 +248,10 @@ const { paymentHash, satoshi, description, createdDate, expiryDate } = invoice;
242
248
 
243
249
  Helpers to convert sats values to fiat and fiat values to sats.
244
250
 
251
+ ##### getFiatCurrencies(): Promise<FiatCurrency[]>
252
+
253
+ Returns the list of available fiat currencies sorted by priority
254
+
245
255
  ##### getFiatValue(satoshi: number, currency: string): number
246
256
 
247
257
  Returns the fiat value for a specified currency of a satoshi amount
@@ -257,6 +267,7 @@ Like `getFiatValue` but returns a formatted string for a given locale using Java
257
267
  #### Examples
258
268
 
259
269
  ```js
270
+ await fiat.getFiatCurrencies();
260
271
  await fiat.getFiatValue({ satoshi: 2100, currency: "eur" });
261
272
  await fiat.getSatoshiValue({ amount: 100, currency: "eur" }); // for 1 EUR
262
273
  await fiat.getFormattedFiatValue({
package/dist/cjs/fiat.cjs CHANGED
@@ -1,6 +1,26 @@
1
1
  'use strict';
2
2
 
3
3
  const numSatsInBtc = 100000000;
4
+ const getFiatCurrencies = async () => {
5
+ const url = "https://getalby.com/api/rates";
6
+ const response = await fetch(url);
7
+ if (!response.ok) {
8
+ throw new Error(`Failed to fetch currencies: ${response.status} ${response.statusText}`);
9
+ }
10
+ const data = await response.json();
11
+ const mappedCurrencies = Object.entries(data)
12
+ .filter(([code]) => code.toUpperCase() !== "BTC")
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ .map(([code, details]) => ({
15
+ code: code.toUpperCase(),
16
+ name: details.name,
17
+ priority: details.priority,
18
+ symbol: details.symbol,
19
+ }))
20
+ .sort((a, b) => a.name.localeCompare(b.name))
21
+ .sort((a, b) => a.priority - b.priority);
22
+ return mappedCurrencies;
23
+ };
4
24
  const getFiatBtcRate = async (currency) => {
5
25
  const url = "https://getalby.com/api/rates/" + currency.toLowerCase() + ".json";
6
26
  const response = await fetch(url);
@@ -30,6 +50,7 @@ const getFormattedFiatValue = async ({ satoshi, currency, locale, }) => {
30
50
  };
31
51
 
32
52
  exports.getFiatBtcRate = getFiatBtcRate;
53
+ exports.getFiatCurrencies = getFiatCurrencies;
33
54
  exports.getFiatValue = getFiatValue;
34
55
  exports.getFormattedFiatValue = getFormattedFiatValue;
35
56
  exports.getSatoshiValue = getSatoshiValue;
@@ -1 +1 @@
1
- {"version":3,"file":"fiat.cjs","sources":["../../src/fiat/fiat.ts"],"sourcesContent":["const numSatsInBtc = 100_000_000;\n\nexport const getFiatBtcRate = async (currency: string): Promise<number> => {\n const url =\n \"https://getalby.com/api/rates/\" + currency.toLowerCase() + \".json\";\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch rate: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n return data.rate_float / numSatsInBtc;\n};\n\nexport const getFiatValue = async ({\n satoshi,\n currency,\n}: {\n satoshi: number | string;\n currency: string;\n}) => {\n const rate = await getFiatBtcRate(currency);\n\n return Number(satoshi) * rate;\n};\n\nexport const getSatoshiValue = async ({\n amount,\n currency,\n}: {\n amount: number | string;\n currency: string;\n}) => {\n const rate = await getFiatBtcRate(currency);\n\n return Math.floor(Number(amount) / rate);\n};\n\nexport const getFormattedFiatValue = async ({\n satoshi,\n currency,\n locale,\n}: {\n satoshi: number | string;\n currency: string;\n locale: string;\n}) => {\n if (!locale) {\n locale = \"en\";\n }\n const fiatValue = await getFiatValue({ satoshi, currency });\n return fiatValue.toLocaleString(locale, {\n style: \"currency\",\n currency,\n });\n};\n"],"names":[],"mappings":";;AAAA,MAAM,YAAY,GAAG,SAAW;MAEnB,cAAc,GAAG,OAAO,QAAgB,KAAqB;IACxE,MAAM,GAAG,GACP,gCAAgC,GAAG,QAAQ,CAAC,WAAW,EAAE,GAAG,OAAO;AACrE,IAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC;AAEjC,IAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;AAChB,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,sBAAA,EAAyB,QAAQ,CAAC,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAC,UAAU,CAAA,CAAE,CAClE;IACH;AAEA,IAAA,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE;AAElC,IAAA,OAAO,IAAI,CAAC,UAAU,GAAG,YAAY;AACvC;AAEO,MAAM,YAAY,GAAG,OAAO,EACjC,OAAO,EACP,QAAQ,GAIT,KAAI;AACH,IAAA,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC;AAE3C,IAAA,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI;AAC/B;AAEO,MAAM,eAAe,GAAG,OAAO,EACpC,MAAM,EACN,QAAQ,GAIT,KAAI;AACH,IAAA,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC;IAE3C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;AAC1C;AAEO,MAAM,qBAAqB,GAAG,OAAO,EAC1C,OAAO,EACP,QAAQ,EACR,MAAM,GAKP,KAAI;IACH,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,GAAG,IAAI;IACf;IACA,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC3D,IAAA,OAAO,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE;AACtC,QAAA,KAAK,EAAE,UAAU;QACjB,QAAQ;AACT,KAAA,CAAC;AACJ;;;;;;;"}
1
+ {"version":3,"file":"fiat.cjs","sources":["../../src/fiat/fiat.ts"],"sourcesContent":["const numSatsInBtc = 100_000_000;\n\nexport interface FiatCurrency {\n code: string;\n name: string;\n symbol: string;\n priority: number;\n}\n\nexport const getFiatCurrencies = async (): Promise<FiatCurrency[]> => {\n const url = \"https://getalby.com/api/rates\";\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch currencies: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n const mappedCurrencies: FiatCurrency[] = Object.entries(data)\n .filter(([code]) => code.toUpperCase() !== \"BTC\")\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n .map(([code, details]: any) => ({\n code: code.toUpperCase(),\n name: details.name,\n priority: details.priority,\n symbol: details.symbol,\n }))\n .sort((a, b) => a.name.localeCompare(b.name))\n .sort((a, b) => a.priority - b.priority) as FiatCurrency[];\n\n return mappedCurrencies;\n};\n\nexport const getFiatBtcRate = async (currency: string): Promise<number> => {\n const url =\n \"https://getalby.com/api/rates/\" + currency.toLowerCase() + \".json\";\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch rate: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n return data.rate_float / numSatsInBtc;\n};\n\nexport const getFiatValue = async ({\n satoshi,\n currency,\n}: {\n satoshi: number | string;\n currency: string;\n}) => {\n const rate = await getFiatBtcRate(currency);\n\n return Number(satoshi) * rate;\n};\n\nexport const getSatoshiValue = async ({\n amount,\n currency,\n}: {\n amount: number | string;\n currency: string;\n}) => {\n const rate = await getFiatBtcRate(currency);\n\n return Math.floor(Number(amount) / rate);\n};\n\nexport const getFormattedFiatValue = async ({\n satoshi,\n currency,\n locale,\n}: {\n satoshi: number | string;\n currency: string;\n locale: string;\n}) => {\n if (!locale) {\n locale = \"en\";\n }\n const fiatValue = await getFiatValue({ satoshi, currency });\n return fiatValue.toLocaleString(locale, {\n style: \"currency\",\n currency,\n });\n};\n"],"names":[],"mappings":";;AAAA,MAAM,YAAY,GAAG,SAAW;AASzB,MAAM,iBAAiB,GAAG,YAAoC;IACnE,MAAM,GAAG,GAAG,+BAA+B;AAC3C,IAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC;AAEjC,IAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;AAChB,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,4BAAA,EAA+B,QAAQ,CAAC,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAC,UAAU,CAAA,CAAE,CACxE;IACH;AAEA,IAAA,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE;AAClC,IAAA,MAAM,gBAAgB,GAAmB,MAAM,CAAC,OAAO,CAAC,IAAI;AACzD,SAAA,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK;;SAE/C,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAM,MAAM;AAC9B,QAAA,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE;QACxB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;AACvB,KAAA,CAAC;AACD,SAAA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3C,SAAA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAmB;AAE5D,IAAA,OAAO,gBAAgB;AACzB;MAEa,cAAc,GAAG,OAAO,QAAgB,KAAqB;IACxE,MAAM,GAAG,GACP,gCAAgC,GAAG,QAAQ,CAAC,WAAW,EAAE,GAAG,OAAO;AACrE,IAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC;AAEjC,IAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;AAChB,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,sBAAA,EAAyB,QAAQ,CAAC,MAAM,CAAA,CAAA,EAAI,QAAQ,CAAC,UAAU,CAAA,CAAE,CAClE;IACH;AAEA,IAAA,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE;AAElC,IAAA,OAAO,IAAI,CAAC,UAAU,GAAG,YAAY;AACvC;AAEO,MAAM,YAAY,GAAG,OAAO,EACjC,OAAO,EACP,QAAQ,GAIT,KAAI;AACH,IAAA,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC;AAE3C,IAAA,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI;AAC/B;AAEO,MAAM,eAAe,GAAG,OAAO,EACpC,MAAM,EACN,QAAQ,GAIT,KAAI;AACH,IAAA,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC;IAE3C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;AAC1C;AAEO,MAAM,qBAAqB,GAAG,OAAO,EAC1C,OAAO,EACP,QAAQ,EACR,MAAM,GAKP,KAAI;IACH,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,GAAG,IAAI;IACf;IACA,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC3D,IAAA,OAAO,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE;AACtC,QAAA,KAAK,EAAE,UAAU;QACjB,QAAQ;AACT,KAAA,CAAC;AACJ;;;;;;;;"}
@@ -1693,17 +1693,21 @@ const parseL402 = (input) => {
1693
1693
  }
1694
1694
  return keyValuePairs;
1695
1695
  };
1696
+ const makeAuthenticateHeader = (args) => {
1697
+ const key = args.key || "L402";
1698
+ return `${key} macaroon="${args.macaroon}", invoice="${args.invoice}"`;
1699
+ };
1696
1700
 
1697
1701
  const memoryStorage = new MemoryStorage();
1698
- const HEADER_KEY = "L402"; // we have to update this to L402 at some point
1702
+ const HEADER_KEY = "L402";
1699
1703
  const fetchWithL402 = async (url, fetchArgs, options) => {
1700
1704
  if (!options) {
1701
1705
  options = {};
1702
1706
  }
1703
1707
  const headerKey = options.headerKey || HEADER_KEY;
1704
- const webln = options.webln || globalThis.webln;
1705
- if (!webln) {
1706
- throw new Error("WebLN is missing");
1708
+ const wallet = options.wallet;
1709
+ if (!wallet) {
1710
+ throw new Error("wallet is missing");
1707
1711
  }
1708
1712
  const store = options.store || memoryStorage;
1709
1713
  if (!fetchArgs) {
@@ -1730,8 +1734,7 @@ const fetchWithL402 = async (url, fetchArgs, options) => {
1730
1734
  const details = parseL402(header);
1731
1735
  const token = details.token || details.macaroon;
1732
1736
  const inv = details.invoice;
1733
- await webln.enable();
1734
- const invResp = await webln.sendPayment(inv);
1737
+ const invResp = await wallet.sendPayment(inv);
1735
1738
  store.setItem(url, JSON.stringify({
1736
1739
  token: token,
1737
1740
  preimage: invResp.preimage,
@@ -1742,6 +1745,26 @@ const fetchWithL402 = async (url, fetchArgs, options) => {
1742
1745
  };
1743
1746
 
1744
1747
  const numSatsInBtc = 100000000;
1748
+ const getFiatCurrencies = async () => {
1749
+ const url = "https://getalby.com/api/rates";
1750
+ const response = await fetch(url);
1751
+ if (!response.ok) {
1752
+ throw new Error(`Failed to fetch currencies: ${response.status} ${response.statusText}`);
1753
+ }
1754
+ const data = await response.json();
1755
+ const mappedCurrencies = Object.entries(data)
1756
+ .filter(([code]) => code.toUpperCase() !== "BTC")
1757
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1758
+ .map(([code, details]) => ({
1759
+ code: code.toUpperCase(),
1760
+ name: details.name,
1761
+ priority: details.priority,
1762
+ symbol: details.symbol,
1763
+ }))
1764
+ .sort((a, b) => a.name.localeCompare(b.name))
1765
+ .sort((a, b) => a.priority - b.priority);
1766
+ return mappedCurrencies;
1767
+ };
1745
1768
  const getFiatBtcRate = async (currency) => {
1746
1769
  const url = "https://getalby.com/api/rates/" + currency.toLowerCase() + ".json";
1747
1770
  const response = await fetch(url);
@@ -1782,11 +1805,13 @@ exports.fromHexString = fromHexString;
1782
1805
  exports.generateZapEvent = generateZapEvent;
1783
1806
  exports.getEventHash = getEventHash;
1784
1807
  exports.getFiatBtcRate = getFiatBtcRate;
1808
+ exports.getFiatCurrencies = getFiatCurrencies;
1785
1809
  exports.getFiatValue = getFiatValue;
1786
1810
  exports.getFormattedFiatValue = getFormattedFiatValue;
1787
1811
  exports.getSatoshiValue = getSatoshiValue;
1788
1812
  exports.isUrl = isUrl;
1789
1813
  exports.isValidAmount = isValidAmount;
1814
+ exports.makeAuthenticateHeader = makeAuthenticateHeader;
1790
1815
  exports.parseKeysendResponse = parseKeysendResponse;
1791
1816
  exports.parseL402 = parseL402;
1792
1817
  exports.parseLnUrlPayResponse = parseLnUrlPayResponse;