thunder-bridge 0.8.3 → 0.8.4

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
@@ -166,7 +166,8 @@ const tipJar = lnurlToSvg("https://agora.gripe/tip");
166
166
  ```
167
167
 
168
168
  **Webhooks** - [`src/webhook.ts`](src/webhook.ts): `parseWebhookRequest`,
169
- `parseWebhook`, `verifyWebhookSignature`. See [Webhooks](#webhooks).
169
+ `parseWebhook`, `parseWatchedWebhookRequest`, `parseWatchedWebhook`,
170
+ `verifyWebhookSignature`. See [Webhooks](#webhooks).
170
171
 
171
172
  **Errors** - [`src/errors.ts`](src/errors.ts): `ProblemError`,
172
173
  `NoWalletAvailableError`, `GatewayCheatError`, `UnverifiedRecipientError`,
@@ -225,6 +226,27 @@ such as `nas`, the trailing-dot `localhost.`, and anything whose last label is
225
226
 
226
227
  It vets the first hop only. See below.
227
228
 
229
+ ### Which transfer counts as paying
230
+
231
+ `bankVerifyEndpoint` calls a credit a settlement when the amount and the currency
232
+ match exactly and the reference appears anywhere in what the payer wrote,
233
+ case-insensitively. With `fioStatement` "what the payer wrote" is four Fio columns
234
+ joined: the variable symbol, the user identification, the message for the recipient
235
+ and the payer's own reference. So a bank that prefixes, appends, or moves the text
236
+ between those fields still settles.
237
+
238
+ Two shapes do not settle, and both leave the payment `pending` while the money is
239
+ already in the account:
240
+
241
+ - **A shortened reference.** The match asks whether the reference is inside what the
242
+ bank forwarded, not the other way round, so a bank that truncates it never matches.
243
+ - **A payer whose bank forwards nothing but a numeric variable symbol.** The
244
+ reference is alphanumeric and cannot travel in a numeric field, and the match does
245
+ not read `X-VS` as an alternative.
246
+
247
+ Neither has been seen with Fio, which forwards the message untouched. Check it
248
+ against the banks your payers actually use before you promise them a rail.
249
+
228
250
  ## What is still trusted
229
251
 
230
252
  - **The gateway chooses which of your addresses gets paid.** Nothing here can
@@ -315,9 +337,9 @@ try {
315
337
 
316
338
  ## Webhooks
317
339
 
318
- Pass `webhookUrl` and optionally `webhookSecret` when you create a payment. Once
319
- it reaches `paid` the gateway POSTs the same JSON the API returns, so the body is
320
- a `Payment`. Every delivery carries `x-timestamp`, and with a secret set
340
+ Pass `webhookUrl` and optionally `webhookSecret` when you create a payment, or on
341
+ any rail. Once it reaches `paid` the gateway POSTs the same JSON the API returns,
342
+ so the body is a `Payment`. Every delivery carries `x-timestamp`, and with a secret set
321
343
  `x-signature: sha256=<hmac>` over `<timestamp>.<body>` rather than the body alone,
322
344
  so a captured delivery cannot be replayed at you later. Six attempts on a widening
323
345
  backoff, then it parks. An invoice that expires fires nothing.
@@ -339,6 +361,29 @@ app.post("/hooks/paid", async (context) => {
339
361
  });
340
362
  ```
341
363
 
364
+ ### A watched payment sends a different body
365
+
366
+ `bankRail` and `blindLightningRail` register a payment the gateway was told almost
367
+ nothing about, so its webhook carries no address, no amount and no invoice. That is
368
+ not a `Payment`, and `parseWebhook` answers `null` for it, which looks exactly like a
369
+ bad signature. Use `parseWatchedWebhookRequest` there instead and you get a
370
+ `TriggerEvent`, the shape `getWatched` hands back.
371
+
372
+ ```ts
373
+ import { parseWatchedWebhookRequest } from "thunder-bridge";
374
+
375
+ app.post("/hooks/bank", async (context) => {
376
+ const settled = await parseWatchedWebhookRequest(context.req.raw, secret);
377
+ if (settled === null) return context.text("bad signature", 401);
378
+
379
+ await fulfil(settled.id, settled.preimage);
380
+ return context.text("ok");
381
+ });
382
+ ```
383
+
384
+ Give each rail its own path, as above, and neither endpoint has to guess which body
385
+ it was handed.
386
+
342
387
  `parseWebhookRequest` refuses anything more than five minutes out of date,
343
388
  adjustable with `toleranceSecs`. The signature proves the body came from someone
344
389
  holding your secret. It does not prove the payment happened, since the gateway
package/dist/index.cjs CHANGED
@@ -50,6 +50,8 @@ __export(index_exports, {
50
50
  minorScaleOf: () => minorScaleOf,
51
51
  minorUnitsOf: () => minorUnitsOf,
52
52
  msatFor: () => msatFor,
53
+ parseWatchedWebhook: () => parseWatchedWebhook,
54
+ parseWatchedWebhookRequest: () => parseWatchedWebhookRequest,
53
55
  parseWebhook: () => parseWebhook,
54
56
  parseWebhookRequest: () => parseWebhookRequest,
55
57
  preimageMatchesHash: () => preimageMatchesHash,
@@ -609,7 +611,8 @@ function watchRequestBody(params, trigger) {
609
611
  verify_url: params.verifyUrl,
610
612
  expires_at: expiresAt.toISOString(),
611
613
  trigger: trigger ?? void 0,
612
- sealed: params.sealed
614
+ sealed: params.sealed,
615
+ webhook: params.webhookUrl ? { url: params.webhookUrl, secret: params.webhookSecret } : void 0
613
616
  });
614
617
  }
615
618
  function triggerEventFromWire(body) {
@@ -1281,7 +1284,9 @@ async function bankTransfer(params) {
1281
1284
  verifyUrl,
1282
1285
  expiresAt: params.expiresAt,
1283
1286
  trigger: params.trigger,
1284
- sealed: params.sealed
1287
+ sealed: params.sealed,
1288
+ webhookUrl: params.webhookUrl,
1289
+ webhookSecret: params.webhookSecret
1285
1290
  });
1286
1291
  return { id: watched.id, paymentHash: watched.paymentHash, verifyUrl, spd };
1287
1292
  }
@@ -1602,6 +1607,8 @@ function bankRail(config) {
1602
1607
  trigger: config.trigger,
1603
1608
  sealed: await config.sealed?.(order),
1604
1609
  variableSymbol: config.variableSymbol?.(order),
1610
+ webhookUrl: config.webhookUrl,
1611
+ webhookSecret: config.webhookSecret,
1605
1612
  allowPublicGateway: config.allowPublicGateway
1606
1613
  });
1607
1614
  return {
@@ -1781,6 +1788,21 @@ async function parseWebhookRequest(request, secret, options = {}) {
1781
1788
  if (signature === null || timestamp === null) return null;
1782
1789
  return parseWebhook(await request.text(), signature, secret, timestamp, options);
1783
1790
  }
1791
+ async function parseWatchedWebhook(body, signature, secret, timestamp, options = {}) {
1792
+ if (!await verifyWebhookSignature(body, signature, secret, timestamp, options)) return null;
1793
+ const text2 = typeof body === "string" ? body : new TextDecoder().decode(body);
1794
+ try {
1795
+ return triggerEventFromWire(JSON.parse(text2));
1796
+ } catch {
1797
+ return null;
1798
+ }
1799
+ }
1800
+ async function parseWatchedWebhookRequest(request, secret, options = {}) {
1801
+ const signature = request.headers.get(SIGNATURE_HEADER);
1802
+ const timestamp = request.headers.get(TIMESTAMP_HEADER);
1803
+ if (signature === null || timestamp === null) return null;
1804
+ return parseWatchedWebhook(await request.text(), signature, secret, timestamp, options);
1805
+ }
1784
1806
  function recent(timestamp, toleranceSecs) {
1785
1807
  const sent = Number(timestamp);
1786
1808
  if (!Number.isFinite(sent)) return false;
@@ -1830,6 +1852,8 @@ function signed(timestamp, body) {
1830
1852
  minorScaleOf,
1831
1853
  minorUnitsOf,
1832
1854
  msatFor,
1855
+ parseWatchedWebhook,
1856
+ parseWatchedWebhookRequest,
1833
1857
  parseWebhook,
1834
1858
  parseWebhookRequest,
1835
1859
  preimageMatchesHash,
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as ThunderBridge, P as Payment, C as CreatePaymentParams, W as WalletFailure } from './rail-Cyc5zTtA.cjs';
2
- export { B as BankRailConfig, a as CreateOptions, b as CreateQuoteParams, F as FollowOptions, L as Leg, c as LightningRailConfig, O as Order, d as PaymentStatus, Q as Quote, R as Rail, e as ThunderBridgeOptions, f as TriggerEvent, g as WaitOptions, h as WalletReason, i as WatchPaymentParams, j as bankRail, l as lightningRail } from './rail-Cyc5zTtA.cjs';
1
+ import { T as ThunderBridge, P as Payment, C as CreatePaymentParams, a as TriggerEvent, W as WalletFailure } from './rail-QZtUN1D-.cjs';
2
+ export { B as BankRailConfig, b as CreateOptions, c as CreateQuoteParams, F as FollowOptions, L as Leg, d as LightningRailConfig, O as Order, e as PaymentStatus, Q as Quote, R as Rail, f as ThunderBridgeOptions, g as WaitOptions, h as WalletReason, i as WatchPaymentParams, j as bankRail, l as lightningRail } from './rail-QZtUN1D-.cjs';
3
3
 
4
4
  /**
5
5
  * Encrypt what the watcher needs and the gateway must not have. The gateway
@@ -66,6 +66,13 @@ interface BankTransferParams {
66
66
  * without asking anyone. `seal` it and the gateway cannot read it either
67
67
  */
68
68
  sealed?: string;
69
+ /**
70
+ * Where the gateway posts once the money lands, a public https URL. Without one
71
+ * a transfer is only ever learned by following the trigger or asking
72
+ */
73
+ webhookUrl?: string;
74
+ /** Signs that delivery, so `verifyWebhookSignature` can tell it came from the gateway */
75
+ webhookSecret?: string;
69
76
  /**
70
77
  * Register on a gateway you do not own anyway. The verify URL names the amount
71
78
  * and the reference, so its operator ends up reading your order book, and the
@@ -340,6 +347,14 @@ declare function parseWebhook(body: string | Uint8Array, signature: string, secr
340
347
  * Cloudflare Workers and Deno, WebCrypto only so it runs anywhere fetch does
341
348
  */
342
349
  declare function parseWebhookRequest(request: Request, secret: string, options?: WebhookOptions): Promise<Payment | null>;
350
+ /**
351
+ * The same, for a payment the gateway only watched. A bank transfer and a blind
352
+ * Lightning leg carry no address, amount or invoice, so they arrive in the shape
353
+ * `followTrigger` and `getWatched` hand back rather than the minted one
354
+ */
355
+ declare function parseWatchedWebhook(body: string | Uint8Array, signature: string, secret: string, timestamp: string, options?: WebhookOptions): Promise<TriggerEvent | null>;
356
+ /** `parseWatchedWebhook` from a Fetch API `Request`, the way `parseWebhookRequest` is */
357
+ declare function parseWatchedWebhookRequest(request: Request, secret: string, options?: WebhookOptions): Promise<TriggerEvent | null>;
343
358
 
344
359
  /**
345
360
  * The way a gateway was caught out, every code is a check that held against the
@@ -417,4 +432,4 @@ declare class NoWalletAvailableError extends ProblemError {
417
432
  }, wallets: WalletFailure[]);
418
433
  }
419
434
 
420
- export { type BankTransfer, type BankTransferParams, type BankVerifyConfig, CreatePaymentParams, type Credit, type FioConfig, type GatewayCheatCode, GatewayCheatError, IDEMPOTENCY_KEY_REUSED, type IdempotencyConflict, IdempotencyConflictError, type Invoice, type MedianOptions, NO_WALLET_AVAILABLE, NoWalletAvailableError, PAYMENT_ALREADY_WATCHED, Payment, ProblemError, type QrOptions, REQUEST_IN_FLIGHT, type Statement, ThunderBridge, type Ticker, UnverifiedRecipientError, WalletFailure, type WebhookOptions, bankTransfer, bankVerifyEndpoint, bitstamp, coinbase, coinmate, decodeInvoice, fioStatement, invoiceToDataUrl, invoiceToSvg, isProblemType, isProvablyPaid, kraken, lnurlToDataUrl, lnurlToSvg, medianOf, minorScaleOf, minorUnitsOf, msatFor, parseWebhook, parseWebhookRequest, preimageMatchesHash, proveOrigin, proveSettlement, qrToDataUrl, qrToSvg, seal, spdToDataUrl, spdToSvg, toLnurl, unseal, verifyWebhookSignature };
435
+ export { type BankTransfer, type BankTransferParams, type BankVerifyConfig, CreatePaymentParams, type Credit, type FioConfig, type GatewayCheatCode, GatewayCheatError, IDEMPOTENCY_KEY_REUSED, type IdempotencyConflict, IdempotencyConflictError, type Invoice, type MedianOptions, NO_WALLET_AVAILABLE, NoWalletAvailableError, PAYMENT_ALREADY_WATCHED, Payment, ProblemError, type QrOptions, REQUEST_IN_FLIGHT, type Statement, ThunderBridge, type Ticker, TriggerEvent, UnverifiedRecipientError, WalletFailure, type WebhookOptions, bankTransfer, bankVerifyEndpoint, bitstamp, coinbase, coinmate, decodeInvoice, fioStatement, invoiceToDataUrl, invoiceToSvg, isProblemType, isProvablyPaid, kraken, lnurlToDataUrl, lnurlToSvg, medianOf, minorScaleOf, minorUnitsOf, msatFor, parseWatchedWebhook, parseWatchedWebhookRequest, parseWebhook, parseWebhookRequest, preimageMatchesHash, proveOrigin, proveSettlement, qrToDataUrl, qrToSvg, seal, spdToDataUrl, spdToSvg, toLnurl, unseal, verifyWebhookSignature };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as ThunderBridge, P as Payment, C as CreatePaymentParams, W as WalletFailure } from './rail-Cyc5zTtA.js';
2
- export { B as BankRailConfig, a as CreateOptions, b as CreateQuoteParams, F as FollowOptions, L as Leg, c as LightningRailConfig, O as Order, d as PaymentStatus, Q as Quote, R as Rail, e as ThunderBridgeOptions, f as TriggerEvent, g as WaitOptions, h as WalletReason, i as WatchPaymentParams, j as bankRail, l as lightningRail } from './rail-Cyc5zTtA.js';
1
+ import { T as ThunderBridge, P as Payment, C as CreatePaymentParams, a as TriggerEvent, W as WalletFailure } from './rail-QZtUN1D-.js';
2
+ export { B as BankRailConfig, b as CreateOptions, c as CreateQuoteParams, F as FollowOptions, L as Leg, d as LightningRailConfig, O as Order, e as PaymentStatus, Q as Quote, R as Rail, f as ThunderBridgeOptions, g as WaitOptions, h as WalletReason, i as WatchPaymentParams, j as bankRail, l as lightningRail } from './rail-QZtUN1D-.js';
3
3
 
4
4
  /**
5
5
  * Encrypt what the watcher needs and the gateway must not have. The gateway
@@ -66,6 +66,13 @@ interface BankTransferParams {
66
66
  * without asking anyone. `seal` it and the gateway cannot read it either
67
67
  */
68
68
  sealed?: string;
69
+ /**
70
+ * Where the gateway posts once the money lands, a public https URL. Without one
71
+ * a transfer is only ever learned by following the trigger or asking
72
+ */
73
+ webhookUrl?: string;
74
+ /** Signs that delivery, so `verifyWebhookSignature` can tell it came from the gateway */
75
+ webhookSecret?: string;
69
76
  /**
70
77
  * Register on a gateway you do not own anyway. The verify URL names the amount
71
78
  * and the reference, so its operator ends up reading your order book, and the
@@ -340,6 +347,14 @@ declare function parseWebhook(body: string | Uint8Array, signature: string, secr
340
347
  * Cloudflare Workers and Deno, WebCrypto only so it runs anywhere fetch does
341
348
  */
342
349
  declare function parseWebhookRequest(request: Request, secret: string, options?: WebhookOptions): Promise<Payment | null>;
350
+ /**
351
+ * The same, for a payment the gateway only watched. A bank transfer and a blind
352
+ * Lightning leg carry no address, amount or invoice, so they arrive in the shape
353
+ * `followTrigger` and `getWatched` hand back rather than the minted one
354
+ */
355
+ declare function parseWatchedWebhook(body: string | Uint8Array, signature: string, secret: string, timestamp: string, options?: WebhookOptions): Promise<TriggerEvent | null>;
356
+ /** `parseWatchedWebhook` from a Fetch API `Request`, the way `parseWebhookRequest` is */
357
+ declare function parseWatchedWebhookRequest(request: Request, secret: string, options?: WebhookOptions): Promise<TriggerEvent | null>;
343
358
 
344
359
  /**
345
360
  * The way a gateway was caught out, every code is a check that held against the
@@ -417,4 +432,4 @@ declare class NoWalletAvailableError extends ProblemError {
417
432
  }, wallets: WalletFailure[]);
418
433
  }
419
434
 
420
- export { type BankTransfer, type BankTransferParams, type BankVerifyConfig, CreatePaymentParams, type Credit, type FioConfig, type GatewayCheatCode, GatewayCheatError, IDEMPOTENCY_KEY_REUSED, type IdempotencyConflict, IdempotencyConflictError, type Invoice, type MedianOptions, NO_WALLET_AVAILABLE, NoWalletAvailableError, PAYMENT_ALREADY_WATCHED, Payment, ProblemError, type QrOptions, REQUEST_IN_FLIGHT, type Statement, ThunderBridge, type Ticker, UnverifiedRecipientError, WalletFailure, type WebhookOptions, bankTransfer, bankVerifyEndpoint, bitstamp, coinbase, coinmate, decodeInvoice, fioStatement, invoiceToDataUrl, invoiceToSvg, isProblemType, isProvablyPaid, kraken, lnurlToDataUrl, lnurlToSvg, medianOf, minorScaleOf, minorUnitsOf, msatFor, parseWebhook, parseWebhookRequest, preimageMatchesHash, proveOrigin, proveSettlement, qrToDataUrl, qrToSvg, seal, spdToDataUrl, spdToSvg, toLnurl, unseal, verifyWebhookSignature };
435
+ export { type BankTransfer, type BankTransferParams, type BankVerifyConfig, CreatePaymentParams, type Credit, type FioConfig, type GatewayCheatCode, GatewayCheatError, IDEMPOTENCY_KEY_REUSED, type IdempotencyConflict, IdempotencyConflictError, type Invoice, type MedianOptions, NO_WALLET_AVAILABLE, NoWalletAvailableError, PAYMENT_ALREADY_WATCHED, Payment, ProblemError, type QrOptions, REQUEST_IN_FLIGHT, type Statement, ThunderBridge, type Ticker, TriggerEvent, UnverifiedRecipientError, WalletFailure, type WebhookOptions, bankTransfer, bankVerifyEndpoint, bitstamp, coinbase, coinmate, decodeInvoice, fioStatement, invoiceToDataUrl, invoiceToSvg, isProblemType, isProvablyPaid, kraken, lnurlToDataUrl, lnurlToSvg, medianOf, minorScaleOf, minorUnitsOf, msatFor, parseWatchedWebhook, parseWatchedWebhookRequest, parseWebhook, parseWebhookRequest, preimageMatchesHash, proveOrigin, proveSettlement, qrToDataUrl, qrToSvg, seal, spdToDataUrl, spdToSvg, toLnurl, unseal, verifyWebhookSignature };
package/dist/index.js CHANGED
@@ -541,7 +541,8 @@ function watchRequestBody(params, trigger) {
541
541
  verify_url: params.verifyUrl,
542
542
  expires_at: expiresAt.toISOString(),
543
543
  trigger: trigger ?? void 0,
544
- sealed: params.sealed
544
+ sealed: params.sealed,
545
+ webhook: params.webhookUrl ? { url: params.webhookUrl, secret: params.webhookSecret } : void 0
545
546
  });
546
547
  }
547
548
  function triggerEventFromWire(body) {
@@ -1213,7 +1214,9 @@ async function bankTransfer(params) {
1213
1214
  verifyUrl,
1214
1215
  expiresAt: params.expiresAt,
1215
1216
  trigger: params.trigger,
1216
- sealed: params.sealed
1217
+ sealed: params.sealed,
1218
+ webhookUrl: params.webhookUrl,
1219
+ webhookSecret: params.webhookSecret
1217
1220
  });
1218
1221
  return { id: watched.id, paymentHash: watched.paymentHash, verifyUrl, spd };
1219
1222
  }
@@ -1534,6 +1537,8 @@ function bankRail(config) {
1534
1537
  trigger: config.trigger,
1535
1538
  sealed: await config.sealed?.(order),
1536
1539
  variableSymbol: config.variableSymbol?.(order),
1540
+ webhookUrl: config.webhookUrl,
1541
+ webhookSecret: config.webhookSecret,
1537
1542
  allowPublicGateway: config.allowPublicGateway
1538
1543
  });
1539
1544
  return {
@@ -1713,6 +1718,21 @@ async function parseWebhookRequest(request, secret, options = {}) {
1713
1718
  if (signature === null || timestamp === null) return null;
1714
1719
  return parseWebhook(await request.text(), signature, secret, timestamp, options);
1715
1720
  }
1721
+ async function parseWatchedWebhook(body, signature, secret, timestamp, options = {}) {
1722
+ if (!await verifyWebhookSignature(body, signature, secret, timestamp, options)) return null;
1723
+ const text2 = typeof body === "string" ? body : new TextDecoder().decode(body);
1724
+ try {
1725
+ return triggerEventFromWire(JSON.parse(text2));
1726
+ } catch {
1727
+ return null;
1728
+ }
1729
+ }
1730
+ async function parseWatchedWebhookRequest(request, secret, options = {}) {
1731
+ const signature = request.headers.get(SIGNATURE_HEADER);
1732
+ const timestamp = request.headers.get(TIMESTAMP_HEADER);
1733
+ if (signature === null || timestamp === null) return null;
1734
+ return parseWatchedWebhook(await request.text(), signature, secret, timestamp, options);
1735
+ }
1716
1736
  function recent(timestamp, toleranceSecs) {
1717
1737
  const sent = Number(timestamp);
1718
1738
  if (!Number.isFinite(sent)) return false;
@@ -1761,6 +1781,8 @@ export {
1761
1781
  minorScaleOf,
1762
1782
  minorUnitsOf,
1763
1783
  msatFor,
1784
+ parseWatchedWebhook,
1785
+ parseWatchedWebhookRequest,
1764
1786
  parseWebhook,
1765
1787
  parseWebhookRequest,
1766
1788
  preimageMatchesHash,
@@ -74,6 +74,8 @@ interface WatchPaymentParams {
74
74
  expiresAt: number;
75
75
  trigger?: string;
76
76
  sealed?: string;
77
+ webhookUrl?: string;
78
+ webhookSecret?: string;
77
79
  }
78
80
  /** Why one wallet in the list could not be used */
79
81
  type WalletReason = "address-unusable" | "unreachable" | "amount-not-accepted" | "cannot-prove-delivery" | "invoice-refused";
@@ -312,6 +314,8 @@ interface BankRailConfig {
312
314
  sealed?: (order: Order) => string | Promise<string>;
313
315
  /** Up to ten digits, for accounting systems that still want one */
314
316
  variableSymbol?: (order: Order) => string | undefined;
317
+ webhookUrl?: string;
318
+ webhookSecret?: string;
315
319
  /** Register on a gateway you do not own anyway, on the terms `bankTransfer` sets out */
316
320
  allowPublicGateway?: boolean;
317
321
  /** What `Leg.rail` reads, for a shop running more than one account */
@@ -347,6 +351,8 @@ interface BlindLightningRailConfig {
347
351
  trigger?: string;
348
352
  /** Only a watched leg has anywhere to carry this */
349
353
  sealed?: (order: Order) => string | Promise<string>;
354
+ webhookUrl?: string;
355
+ webhookSecret?: string;
350
356
  /** What `Leg.rail` reads, for a shop running more than one wallet */
351
357
  name?: string;
352
358
  }
@@ -372,4 +378,4 @@ declare function lightningRail(config: LightningRailConfig): Rail;
372
378
  */
373
379
  declare function blindLightningRail(config: BlindLightningRailConfig): Rail;
374
380
 
375
- export { type BankRailConfig as B, type CreatePaymentParams as C, type FollowOptions as F, type Leg as L, type Order as O, type Payment as P, type Quote as Q, type Rail as R, ThunderBridge as T, type WalletFailure as W, type CreateOptions as a, type CreateQuoteParams as b, type LightningRailConfig as c, type PaymentStatus as d, type ThunderBridgeOptions as e, type TriggerEvent as f, type WaitOptions as g, type WalletReason as h, type WatchPaymentParams as i, bankRail as j, type BlindLightningRailConfig as k, lightningRail as l, blindLightningRail as m };
381
+ export { type BankRailConfig as B, type CreatePaymentParams as C, type FollowOptions as F, type Leg as L, type Order as O, type Payment as P, type Quote as Q, type Rail as R, ThunderBridge as T, type WalletFailure as W, type TriggerEvent as a, type CreateOptions as b, type CreateQuoteParams as c, type LightningRailConfig as d, type PaymentStatus as e, type ThunderBridgeOptions as f, type WaitOptions as g, type WalletReason as h, type WatchPaymentParams as i, bankRail as j, type BlindLightningRailConfig as k, lightningRail as l, blindLightningRail as m };
@@ -74,6 +74,8 @@ interface WatchPaymentParams {
74
74
  expiresAt: number;
75
75
  trigger?: string;
76
76
  sealed?: string;
77
+ webhookUrl?: string;
78
+ webhookSecret?: string;
77
79
  }
78
80
  /** Why one wallet in the list could not be used */
79
81
  type WalletReason = "address-unusable" | "unreachable" | "amount-not-accepted" | "cannot-prove-delivery" | "invoice-refused";
@@ -312,6 +314,8 @@ interface BankRailConfig {
312
314
  sealed?: (order: Order) => string | Promise<string>;
313
315
  /** Up to ten digits, for accounting systems that still want one */
314
316
  variableSymbol?: (order: Order) => string | undefined;
317
+ webhookUrl?: string;
318
+ webhookSecret?: string;
315
319
  /** Register on a gateway you do not own anyway, on the terms `bankTransfer` sets out */
316
320
  allowPublicGateway?: boolean;
317
321
  /** What `Leg.rail` reads, for a shop running more than one account */
@@ -347,6 +351,8 @@ interface BlindLightningRailConfig {
347
351
  trigger?: string;
348
352
  /** Only a watched leg has anywhere to carry this */
349
353
  sealed?: (order: Order) => string | Promise<string>;
354
+ webhookUrl?: string;
355
+ webhookSecret?: string;
350
356
  /** What `Leg.rail` reads, for a shop running more than one wallet */
351
357
  name?: string;
352
358
  }
@@ -372,4 +378,4 @@ declare function lightningRail(config: LightningRailConfig): Rail;
372
378
  */
373
379
  declare function blindLightningRail(config: BlindLightningRailConfig): Rail;
374
380
 
375
- export { type BankRailConfig as B, type CreatePaymentParams as C, type FollowOptions as F, type Leg as L, type Order as O, type Payment as P, type Quote as Q, type Rail as R, ThunderBridge as T, type WalletFailure as W, type CreateOptions as a, type CreateQuoteParams as b, type LightningRailConfig as c, type PaymentStatus as d, type ThunderBridgeOptions as e, type TriggerEvent as f, type WaitOptions as g, type WalletReason as h, type WatchPaymentParams as i, bankRail as j, type BlindLightningRailConfig as k, lightningRail as l, blindLightningRail as m };
381
+ export { type BankRailConfig as B, type CreatePaymentParams as C, type FollowOptions as F, type Leg as L, type Order as O, type Payment as P, type Quote as Q, type Rail as R, ThunderBridge as T, type WalletFailure as W, type TriggerEvent as a, type CreateOptions as b, type CreateQuoteParams as c, type LightningRailConfig as d, type PaymentStatus as e, type ThunderBridgeOptions as f, type WaitOptions as g, type WalletReason as h, type WatchPaymentParams as i, bankRail as j, type BlindLightningRailConfig as k, lightningRail as l, blindLightningRail as m };
package/dist/server.cjs CHANGED
@@ -777,7 +777,9 @@ function blindLightningRail(config) {
777
777
  verifyUrl: resolved.verifyUrl,
778
778
  expiresAt: resolved.expiresAt,
779
779
  trigger: config.trigger,
780
- sealed: await config.sealed?.(order)
780
+ sealed: await config.sealed?.(order),
781
+ webhookUrl: config.webhookUrl,
782
+ webhookSecret: config.webhookSecret
781
783
  });
782
784
  return {
783
785
  id: watched.id,
package/dist/server.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as ThunderBridge } from './rail-Cyc5zTtA.cjs';
2
- export { k as BlindLightningRailConfig, m as blindLightningRail } from './rail-Cyc5zTtA.cjs';
1
+ import { T as ThunderBridge } from './rail-QZtUN1D-.cjs';
2
+ export { k as BlindLightningRailConfig, m as blindLightningRail } from './rail-QZtUN1D-.cjs';
3
3
 
4
4
  interface TriggerConfig {
5
5
  /** The gateway that quotes the addresses and mints the invoice */
package/dist/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as ThunderBridge } from './rail-Cyc5zTtA.js';
2
- export { k as BlindLightningRailConfig, m as blindLightningRail } from './rail-Cyc5zTtA.js';
1
+ import { T as ThunderBridge } from './rail-QZtUN1D-.js';
2
+ export { k as BlindLightningRailConfig, m as blindLightningRail } from './rail-QZtUN1D-.js';
3
3
 
4
4
  interface TriggerConfig {
5
5
  /** The gateway that quotes the addresses and mints the invoice */
package/dist/server.js CHANGED
@@ -740,7 +740,9 @@ function blindLightningRail(config) {
740
740
  verifyUrl: resolved.verifyUrl,
741
741
  expiresAt: resolved.expiresAt,
742
742
  trigger: config.trigger,
743
- sealed: await config.sealed?.(order)
743
+ sealed: await config.sealed?.(order),
744
+ webhookUrl: config.webhookUrl,
745
+ webhookSecret: config.webhookSecret
744
746
  });
745
747
  return {
746
748
  id: watched.id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thunder-bridge",
3
- "version": "0.8.3",
3
+ "version": "0.8.4",
4
4
  "description": "Trustless JavaScript client for the Thunder Bridge Lightning payment gateway. Proves the invoice came from your own wallet before the payer sees it.",
5
5
  "author": "i-am-fatik",
6
6
  "homepage": "https://agora.gripe/en/tools/thunder-bridge",