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 +49 -4
- package/dist/index.cjs +26 -2
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +24 -2
- package/dist/{rail-Cyc5zTtA.d.cts → rail-QZtUN1D-.d.cts} +7 -1
- package/dist/{rail-Cyc5zTtA.d.ts → rail-QZtUN1D-.d.ts} +7 -1
- package/dist/server.cjs +3 -1
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +3 -1
- package/package.json +1 -1
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`, `
|
|
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
|
|
319
|
-
it reaches `paid` the gateway POSTs the same JSON the API returns,
|
|
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-
|
|
2
|
-
export { B as BankRailConfig,
|
|
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-
|
|
2
|
-
export { B as BankRailConfig,
|
|
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
|
|
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
|
|
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-
|
|
2
|
-
export { k as BlindLightningRailConfig, m as blindLightningRail } from './rail-
|
|
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-
|
|
2
|
-
export { k as BlindLightningRailConfig, m as blindLightningRail } from './rail-
|
|
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
|
+
"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",
|