thunder-bridge 0.8.1 → 0.8.3

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/index.d.cts CHANGED
@@ -1,255 +1,5 @@
1
- /** Where a payment stands, `paid` is the only status that carries a preimage */
2
- type PaymentStatus = "pending" | "paid" | "expired";
3
- /** A payment as the gateway reports it, every field is checkable against the recipient */
4
- interface Payment {
5
- id: string;
6
- lnAddress: string;
7
- amountMsat: number;
8
- status: PaymentStatus;
9
- paymentHash: string;
10
- bolt11: string;
11
- preimage: string | null;
12
- expiresAt: number;
13
- createdAt: number;
14
- verifyUrl: string;
15
- }
16
- /**
17
- * `lnAddresses` is a priority list, the gateway takes the first one that can
18
- * issue a provable invoice for `amountMsat` and the rest are the fallback
19
- */
20
- interface CreatePaymentParams {
21
- lnAddresses: string[];
22
- amountMsat: number;
23
- webhookUrl?: string;
24
- webhookSecret?: string;
25
- }
26
- /**
27
- * `lnAddresses` is the same priority list `createPayment` takes, and quoting it
28
- * mints nothing and charges the recipient's wallet nothing
29
- */
30
- interface CreateQuoteParams {
31
- lnAddresses: string[];
32
- amountMsat: number;
33
- }
34
- /**
35
- * Which address would serve an amount, and what the ones ahead of it refused.
36
- * `feeMsat` is always zero, the payer pays the recipient's own invoice and the
37
- * gateway is never in the money's path
38
- */
39
- interface Quote {
40
- lnAddress: string;
41
- amountMsat: number;
42
- feeMsat: number;
43
- minMsat: number;
44
- maxMsat: number;
45
- metadata: string;
46
- refusals: WalletFailure[];
47
- }
48
- /**
49
- * What the gateway reports about a payment it is watching, for a trigger stream
50
- * or for one you minted yourself. `lnAddress` and `amountMsat` are null when the
51
- * gateway was never told them, which is the point of `watchPayment`: what the
52
- * watcher needs but the gateway should not know travels in `sealed` instead
53
- */
54
- interface TriggerEvent {
55
- id: string;
56
- paymentHash: string;
57
- verifyUrl: string;
58
- status: PaymentStatus;
59
- preimage: string | null;
60
- expiresAt: number;
61
- createdAt: number;
62
- sealed: string | null;
63
- lnAddress: string | null;
64
- amountMsat: number | null;
65
- }
66
- /**
67
- * An invoice you obtained yourself, handed over to be watched. The gateway is
68
- * given no address and no amount, so it cannot refuse one recipient rather than
69
- * all of them
70
- */
71
- interface WatchPaymentParams {
72
- paymentHash: string;
73
- verifyUrl: string;
74
- expiresAt: number;
75
- trigger?: string;
76
- sealed?: string;
77
- }
78
- /** Why one wallet in the list could not be used */
79
- type WalletReason = "address-unusable" | "unreachable" | "amount-not-accepted" | "cannot-prove-delivery" | "invoice-refused";
80
- interface WalletFailure {
81
- address: string;
82
- reason: WalletReason;
83
- }
84
-
85
- interface ThunderBridgeOptions {
86
- /**
87
- * Prove every payment against the recipient's own server before handing it
88
- * back, and refuse a reported settlement whose preimage does not hash to the
89
- * payment hash, defaults to true
90
- */
91
- verify?: boolean;
92
- /**
93
- * Sent as `Authorization: Bearer`, which a gateway started with
94
- * `GATEWAY_TOKEN` requires on every call, the socket handshake included. No
95
- * browser WebSocket can carry a header, so setting this also puts every socket
96
- * through a ticket
97
- */
98
- token?: string;
99
- }
100
- interface WaitOptions {
101
- /** Give up when this aborts, `AbortSignal.timeout(ms)` covers the usual case */
102
- signal?: AbortSignal;
103
- /**
104
- * Mint a short-lived ticket and put that in the socket URL instead of the
105
- * payment id. Implied by `token`. The id stays readable inside the ticket,
106
- * what changes is that a URL out of a log stops opening anything after a
107
- * minute
108
- */
109
- tickets?: boolean;
110
- }
111
- interface CreateOptions {
112
- /**
113
- * Makes the POST safe to retry. A repeat of a finished request replays its
114
- * payment instead of asking a wallet for a second invoice, a repeat that
115
- * arrives while the first is still resolving throws
116
- * `IdempotencyConflictError`, and the key is held for 24 hours
117
- */
118
- idempotencyKey?: string;
119
- /**
120
- * Groups this payment with every other one carrying the same secret, so
121
- * `followTrigger` can watch the place rather than the payment. Only its
122
- * sha256 reaches the gateway, and the secret itself is what authorises the
123
- * stream, so keep it apart from any URL a payer sees
124
- */
125
- trigger?: string;
126
- }
127
- interface FollowOptions {
128
- /** Called for the recent settlements replayed on connect, then for each new one */
129
- onPayment: (settled: TriggerEvent) => void;
130
- /** Called when a connection drops or a frame is refused, the follow keeps going */
131
- onError?: (error: unknown) => void;
132
- /** Reconnect after a drop, defaults to true */
133
- reconnect?: boolean;
134
- /**
135
- * The first wait after a drop, doubling up to 30 seconds and jittered so a
136
- * fleet does not come back in lockstep, defaults to 3000. A connection that
137
- * opens puts it back to the first wait
138
- */
139
- reconnectDelayMs?: number;
140
- /**
141
- * Mint a short-lived ticket and put that in the socket URL instead of the
142
- * secret, one per connection. Keeps the secret out of access logs, at the cost
143
- * of a POST before each connect. Implied by `token`. Leave it off for a
144
- * microcontroller, where one hardcoded URL and a dumb reconnect loop is the
145
- * whole point
146
- */
147
- tickets?: boolean;
148
- }
149
- /** Talks to a Thunder Bridge gateway and trusts it for nothing it can check itself */
150
- declare class ThunderBridge {
151
- private readonly baseUrl;
152
- private readonly verify;
153
- private readonly token;
154
- constructor(baseUrl: string, options?: ThunderBridgeOptions);
155
- /**
156
- * Whether a token was given, which is what makes an instance yours: a gateway
157
- * started with `GATEWAY_TOKEN` answers nobody else, so anything you hand it
158
- * stays between you and it
159
- */
160
- get isPrivate(): boolean;
161
- /**
162
- * Ask the gateway for an invoice payable to the first address on your list
163
- * that can issue a provable one, throws `NoWalletAvailableError` when none can
164
- * and `GatewayCheatError` when what comes back is not what you asked for
165
- */
166
- createPayment(params: CreatePaymentParams, options?: CreateOptions): Promise<Payment>;
167
- /**
168
- * Ask which address would serve an amount without minting anything, throws
169
- * `NoWalletAvailableError` when none would. A quote is a probe and not a
170
- * promise: the address it names can still be refused at create time, because
171
- * whether a wallet returns a provable invoice cannot be known without asking
172
- * it for one, and asking mints it
173
- */
174
- createQuote(params: CreateQuoteParams): Promise<Quote>;
175
- /** Read a payment back, null when the gateway has never heard of it */
176
- getPayment(id: string): Promise<Payment | null>;
177
- /**
178
- * Read back a payment the gateway is only watching, null when it has never
179
- * heard of it. A watched payment carries no address, amount or invoice, so
180
- * `getPayment` refuses it and this reads the shape both rails share
181
- */
182
- getWatched(id: string): Promise<TriggerEvent | null>;
183
- /**
184
- * List what this gateway is watching, newest first. Only a gateway started
185
- * with `GATEWAY_TOKEN` serves this, because on a shared one it would hand
186
- * every caller everyone else's payments, so a public gateway answers 404.
187
- *
188
- * `scanned` says how many settled records were looked at to build the page.
189
- * Anything older than that window is not in the answer, and the list does not
190
- * pretend otherwise
191
- */
192
- listPayments(limit?: number): Promise<{
193
- payments: TriggerEvent[];
194
- scanned: number;
195
- }>;
196
- /**
197
- * Follow a payment over WebSocket until it is paid or expired, reconnecting
198
- * through a drop. A payment that never answers gives up after a few tries, and
199
- * one that has answered is followed until its own expiry, so the wait always
200
- * ends by itself
201
- */
202
- waitForPayment(id: string, options?: WaitOptions): Promise<Payment>;
203
- /**
204
- * Follow a payment the gateway is only watching, one it did not mint, until it
205
- * is paid or expired.
206
- *
207
- * A watched payment carries no address, no amount and no invoice, because the
208
- * gateway was told none of them, so it reads back as the shape a trigger
209
- * streams rather than as a `Payment`. That is every bank transfer, and every
210
- * Lightning invoice registered with `watchPayment` instead of `createPayment`.
211
- */
212
- waitForWatched(id: string, options?: WaitOptions): Promise<TriggerEvent>;
213
- private followed;
214
- /**
215
- * Wait on several payments and keep the first one that is really paid, then stop
216
- * waiting on the losers, which closes their sockets.
217
- *
218
- * This is how one order offers two rails. A Lightning invoice and a bank
219
- * transfer for the same thing are two payments here, and the payer picks one, so
220
- * what you want is the one that arrives and nothing further from the other.
221
- *
222
- * A leg that expires is a loser, not a winner, which is the whole reason this is
223
- * not a race: `waitForPayment` ends on `paid` and on `expired` alike, and a
224
- * Lightning invoice expires in an hour while a bank transfer takes days. `null`
225
- * means every leg ended without being paid.
226
- *
227
- * Stopping the wait is not revoking the invoice. Nobody can revoke one, because
228
- * the recipient's own wallet minted it, so a payer who pays the loser afterwards
229
- * really does pay twice and that shows up on `followTrigger` as a second
230
- * settlement to refund.
231
- */
232
- firstToSettle(ids: string[], options?: WaitOptions): Promise<TriggerEvent | null>;
233
- /**
234
- * Hand over an invoice you obtained yourself so the gateway watches it without
235
- * being told the address or the amount. It can then only refuse everyone
236
- * rather than one recipient, which is what makes leaving it cheap. Anything
237
- * the watcher needs goes in `sealed`, which the gateway cannot read
238
- */
239
- watchPayment(params: WatchPaymentParams): Promise<TriggerEvent>;
240
- /**
241
- * Follow every payment made to one trigger, replayed from the recent ones on
242
- * connect and then live, reconnecting on its own until the returned function
243
- * is called. A trigger has no terminal state, so this never resolves
244
- */
245
- followTrigger(secret: string, options: FollowOptions): () => void;
246
- private needsTicket;
247
- private wsTicket;
248
- private sending;
249
- private reading;
250
- private proven;
251
- private checked;
252
- }
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';
253
3
 
254
4
  /**
255
5
  * Encrypt what the watcher needs and the gateway must not have. The gateway
@@ -264,72 +14,17 @@ declare function seal(secret: string, plaintext: string): Promise<string>;
264
14
  */
265
15
  declare function unseal(secret: string, sealed: string): Promise<string | null>;
266
16
 
267
- interface TriggerConfig {
268
- /** The gateway that quotes the addresses and mints the invoice */
269
- gateway: ThunderBridge;
270
- /** Priority list, quoted at payRequest and then pinned for the callback */
271
- lnAddresses: string[];
272
- /**
273
- * What this trigger costs right now, called once per payRequest. A plain
274
- * function, so a fiat peg or a time of day rule is just code you write
275
- */
276
- amountMsat: () => number | Promise<number>;
277
- /**
278
- * Signs the callback URL. Without it anyone could call the callback and make
279
- * this endpoint mint invoices on wallets of their choosing
280
- */
281
- secret: string;
282
- /** Groups every payment here so `followTrigger` can watch the place, keep it off the QR */
283
- watchSecret?: string;
284
- /** Override when a proxy hides the public URL from the request, no trailing slash */
285
- baseUrl?: string;
286
- /**
287
- * Resolve the address here and hand the gateway only a hash and a URL to poll,
288
- * instead of asking it to mint. It then cannot tell who is being paid beyond
289
- * the domain in the verify URL, nor how much at all, so the only refusal left
290
- * to it is refusing everyone. Costs one more round trip and gives up the
291
- * gateway's CORS proxying, which a server does not need anyway
292
- */
293
- blind?: boolean;
294
- /**
295
- * What the watcher needs and the gateway must not have. `data` returns it and
296
- * `secret` encrypts it, so there is no way to hand the gateway something it
297
- * can read. Needs 32 characters of randomness, not a passphrase, and every
298
- * watcher of this trigger holds the same one
299
- */
300
- sealed?: {
301
- secret: string;
302
- data: (minted: Minted) => unknown;
303
- };
304
- }
305
- interface Minted {
306
- lnAddress: string;
307
- amountMsat: number;
308
- bolt11: string;
309
- paymentHash: string;
310
- verifyUrl: string;
311
- expiresAt: number;
312
- }
313
- /**
314
- * An LNURL-pay endpoint standing in front of a priority list of addresses, as a
315
- * Fetch handler so it runs on Deno Deploy, Workers, Hono, Next and Node alike.
316
- *
317
- * It answers both halves of the flow on one path. A bare request is the
318
- * payRequest and quotes the list, and a signed one is the callback and mints.
319
- * The winner is chosen at payRequest and pinned into the callback URL because
320
- * LUD-06 binds the invoice to the metadata already served: if the callback
321
- * picked a different address the payer's wallet would refuse the invoice.
322
- *
323
- * Nothing is stored between the two, so this holds no state of its own.
324
- */
325
- declare function lnurlPayEndpoint(config: TriggerConfig): (request: Request) => Promise<Response>;
326
-
327
17
  /** One incoming payment as the bank booked it, in the smallest unit of its currency */
328
18
  interface Credit {
329
19
  amountMinor: number;
330
20
  currency: string;
331
21
  /** Whatever the payer wrote, wherever this bank puts it. Matching is a substring, so noise around it is fine */
332
22
  reference: string;
23
+ /**
24
+ * Unix seconds. A bank that books a day rather than an instant, as Fio does,
25
+ * gives the day's midnight in its own zone, so rendering this in UTC can show
26
+ * the day before. Nothing here matches on it, it is yours to read
27
+ */
333
28
  bookedAt: number;
334
29
  }
335
30
  /**
@@ -464,8 +159,9 @@ interface FioConfig {
464
159
  *
465
160
  * Every field on a Fio transaction is optional and arrives as `null` when it is
466
161
  * absent, the amount carries its direction in its sign rather than in a flag,
467
- * and the date is unix milliseconds. This reads all three the way the bank
468
- * documents them and treats a missing field as absent rather than guessing.
162
+ * and the date is a day and a UTC offset, `2026-07-15+0200`. This reads all
163
+ * three the way the bank answers them and treats a missing field as absent
164
+ * rather than guessing.
469
165
  */
470
166
  declare function fioStatement(config: FioConfig): Statement;
471
167
 
@@ -615,6 +311,14 @@ declare function lnurlToDataUrl(endpoint: string, options?: QrOptions): string;
615
311
  declare function spdToSvg(spd: string, options?: QrOptions): string;
616
312
  /** SVG data URL of the bank transfer's QR, for an `<img>` `src` */
617
313
  declare function spdToDataUrl(spd: string, options?: QrOptions): string;
314
+ /**
315
+ * Render any rail's `Leg.qr` as an SVG QR code. Each rail states its own payload,
316
+ * a BOLT11 invoice under the `LIGHTNING` scheme or a Short Payment Descriptor as
317
+ * it stands, so this draws a leg without being told which rail made it
318
+ */
319
+ declare function qrToSvg(payload: string, options?: QrOptions): string;
320
+ /** SVG data URL of a leg's QR, for an `<img>` `src` */
321
+ declare function qrToDataUrl(payload: string, options?: QrOptions): string;
618
322
 
619
323
  /**
620
324
  * Bech32-encode a pay endpoint as the `LNURL1` string LUD-01 defines, uppercase
@@ -675,14 +379,7 @@ declare class ProblemError extends Error {
675
379
  detail?: string;
676
380
  });
677
381
  }
678
- /**
679
- * Whether a problem document carries this type, accepting the namespace this
680
- * project used before `direct` left its name.
681
- *
682
- * A problem type is an identifier clients branch on, so renaming one is a breaking
683
- * change. The gateway emits only the new spelling, and this reads both, so a client
684
- * that has been updated still types the errors of an instance that has not
685
- */
382
+ /** Whether a problem document carries this type */
686
383
  declare function isProblemType(problem: {
687
384
  type?: string;
688
385
  }, type: string): boolean;
@@ -720,4 +417,4 @@ declare class NoWalletAvailableError extends ProblemError {
720
417
  }, wallets: WalletFailure[]);
721
418
  }
722
419
 
723
- export { type BankTransfer, type BankTransferParams, type BankVerifyConfig, type CreateOptions, type CreatePaymentParams, type CreateQuoteParams, type Credit, type FioConfig, type FollowOptions, type GatewayCheatCode, GatewayCheatError, IDEMPOTENCY_KEY_REUSED, type IdempotencyConflict, IdempotencyConflictError, type Invoice, type MedianOptions, type Minted, NO_WALLET_AVAILABLE, NoWalletAvailableError, PAYMENT_ALREADY_WATCHED, type Payment, type PaymentStatus, ProblemError, type QrOptions, type Quote, REQUEST_IN_FLIGHT, type Statement, ThunderBridge, type ThunderBridgeOptions, type Ticker, type TriggerConfig, type TriggerEvent, UnverifiedRecipientError, type WaitOptions, type WalletFailure, type WalletReason, type WatchPaymentParams, type WebhookOptions, bankTransfer, bankVerifyEndpoint, bitstamp, coinbase, coinmate, decodeInvoice, fioStatement, invoiceToDataUrl, invoiceToSvg, isProblemType, isProvablyPaid, kraken, lnurlPayEndpoint, lnurlToDataUrl, lnurlToSvg, medianOf, minorScaleOf, minorUnitsOf, msatFor, parseWebhook, parseWebhookRequest, preimageMatchesHash, proveOrigin, proveSettlement, seal, spdToDataUrl, spdToSvg, toLnurl, unseal, verifyWebhookSignature };
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 };