thunder-bridge 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -125
- package/dist/bank-B3mHISn1.d.cts +92 -0
- package/dist/bank-B3mHISn1.d.ts +92 -0
- package/dist/bank.cjs +141 -0
- package/dist/bank.d.cts +44 -0
- package/dist/bank.d.ts +44 -0
- package/dist/bank.js +114 -0
- package/dist/client-Cc5gtjGV.d.ts +733 -0
- package/dist/client-CzGZcByI.d.cts +733 -0
- package/dist/errors-0vbVoISA.d.ts +126 -0
- package/dist/errors-Dmh-Uoh8.d.cts +126 -0
- package/dist/index.cjs +1576 -1094
- package/dist/index.d.cts +11 -503
- package/dist/index.d.ts +11 -503
- package/dist/index.js +1556 -1052
- package/dist/{server.cjs → nwc.cjs} +261 -689
- package/dist/nwc.d.cts +120 -0
- package/dist/nwc.d.ts +120 -0
- package/dist/{server.js → nwc.js} +256 -667
- package/dist/price.cjs +240 -0
- package/dist/price.d.cts +17 -0
- package/dist/price.d.ts +17 -0
- package/dist/price.js +205 -0
- package/dist/qr-CF-YeXU1.d.cts +55 -0
- package/dist/qr-CF-YeXU1.d.ts +55 -0
- package/dist/qr.cjs +262 -0
- package/dist/qr.d.cts +1 -0
- package/dist/qr.d.ts +1 -0
- package/dist/qr.js +227 -0
- package/dist/types-BNPmVnA7.d.cts +252 -0
- package/dist/types-BNPmVnA7.d.ts +252 -0
- package/openapi.yaml +1 -1
- package/package.json +48 -9
- package/dist/rail-CqUfuYXJ.d.cts +0 -615
- package/dist/rail-CqUfuYXJ.d.ts +0 -615
- package/dist/server.d.cts +0 -145
- package/dist/server.d.ts +0 -145
|
@@ -0,0 +1,733 @@
|
|
|
1
|
+
import { R as Resolved, Q as QrOptions } from './qr-CF-YeXU1.js';
|
|
2
|
+
import { A as Amount, T as Ticker, C as Charge, e as MintedPayment, g as PaymentStatus, h as Priced, f as Msat, S as Settlement, P as Payment, Q as Quote, H as Handover, i as SocketTicket } from './types-BNPmVnA7.js';
|
|
3
|
+
import { a as BankTransferParams, B as BankTransfer, b as BankVerifyConfig } from './bank-B3mHISn1.js';
|
|
4
|
+
|
|
5
|
+
type Sent = {
|
|
6
|
+
method?: string;
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
body?: string;
|
|
9
|
+
deadline?: AbortSignal;
|
|
10
|
+
};
|
|
11
|
+
type Verified = {
|
|
12
|
+
address: string;
|
|
13
|
+
family: number;
|
|
14
|
+
};
|
|
15
|
+
/** Carries one request to an address ask() already verified, so nothing resolves the name again */
|
|
16
|
+
type Send = (url: string, sent: Sent, signal: AbortSignal, at: readonly Verified[]) => Promise<Response>;
|
|
17
|
+
|
|
18
|
+
/** What a shop knows about a sale before any rail exists */
|
|
19
|
+
interface Order {
|
|
20
|
+
/** The bank matches it on the statement, and Lightning keys idempotency on it */
|
|
21
|
+
reference: string;
|
|
22
|
+
/** The price in the smallest unit of `currency`, so 48055 is 480.55 CZK */
|
|
23
|
+
amountMinor: number;
|
|
24
|
+
/** ISO 4217. The bank rail moves this, Lightning converts it at `rate` */
|
|
25
|
+
currency: string;
|
|
26
|
+
}
|
|
27
|
+
/** One way to pay one order, already registered with the gateway */
|
|
28
|
+
interface Leg {
|
|
29
|
+
/** The watched payment's id, which is what `firstSettled`, `payment` and `settled` take */
|
|
30
|
+
id: string;
|
|
31
|
+
/** Which rail made it, so a shop can label a leg without knowing how it was built */
|
|
32
|
+
rail: string;
|
|
33
|
+
/** What the payer reads, a BOLT11 invoice or a Short Payment Descriptor */
|
|
34
|
+
scan: string;
|
|
35
|
+
/** The same thing as a QR has to encode it, which is not always `scan` itself */
|
|
36
|
+
qr: string;
|
|
37
|
+
expiresAt: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A payment method. Everything that differs between rails is bound once when the
|
|
41
|
+
* rail is built, so the only thing passed per sale is which sale it is
|
|
42
|
+
*/
|
|
43
|
+
type Rail = (order: Order) => Promise<Leg>;
|
|
44
|
+
/** What every rail takes, whatever it moves */
|
|
45
|
+
interface RailConfig {
|
|
46
|
+
/** Groups every payment from this rail so `follow` can watch the shop */
|
|
47
|
+
trigger?: string;
|
|
48
|
+
/** How many of that trigger's settlements the gateway keeps replayable past the hour */
|
|
49
|
+
replay?: number;
|
|
50
|
+
/** Where the gateway posts once the money lands, a public https URL */
|
|
51
|
+
webhookUrl?: string;
|
|
52
|
+
/** What `Leg.rail` says, so two rails of one kind can be told apart */
|
|
53
|
+
name?: string;
|
|
54
|
+
}
|
|
55
|
+
/** A Lightning rail the gateway mints for, bound once and then given one order at a time */
|
|
56
|
+
interface LightningRailConfig extends RailConfig {
|
|
57
|
+
/** Priority list, the first address that can prove an invoice wins */
|
|
58
|
+
paidTo: string | string[];
|
|
59
|
+
/**
|
|
60
|
+
* What to charge for one order, the order's own price converted at `rate` by
|
|
61
|
+
* default. Give it a function and the price is whatever you say
|
|
62
|
+
*/
|
|
63
|
+
amount?: (order: Order) => Amount;
|
|
64
|
+
/** Where the default conversion gets its rate, the median of four venues by default */
|
|
65
|
+
rate?: Ticker;
|
|
66
|
+
/** Makes the mint safe to retry, the order's reference by default */
|
|
67
|
+
idempotencyKey?: (order: Order) => string | undefined;
|
|
68
|
+
}
|
|
69
|
+
/** The same rail with the invoice resolved here, so the gateway is told neither address nor amount */
|
|
70
|
+
interface BlindLightningRailConfig extends LightningRailConfig {
|
|
71
|
+
/**
|
|
72
|
+
* What the watcher needs and the gateway must not read, sealed with `seal`
|
|
73
|
+
* before it goes anywhere near the gateway
|
|
74
|
+
*/
|
|
75
|
+
sealed?: (order: Order) => string | Promise<string>;
|
|
76
|
+
/**
|
|
77
|
+
* Where your own `serve.verify` endpoint is mounted, and its secret. Without
|
|
78
|
+
* it the gateway is handed the wallet's own URL, which a gateway enforcing its
|
|
79
|
+
* verify challenge will refuse to poll
|
|
80
|
+
*/
|
|
81
|
+
relayThrough?: {
|
|
82
|
+
endpoint: string;
|
|
83
|
+
secret: string;
|
|
84
|
+
};
|
|
85
|
+
/** How the rail reaches wallets, pinned to the address it verified unless you say otherwise */
|
|
86
|
+
send?: Send;
|
|
87
|
+
}
|
|
88
|
+
/** A bank rail: the account the money lands in, and where its arrival is read back from */
|
|
89
|
+
interface BankRailConfig extends RailConfig {
|
|
90
|
+
/** Long lived and server side. Every preimage is derived from it, so losing it loses every proof */
|
|
91
|
+
secret: string;
|
|
92
|
+
/** The account the money goes to, as an IBAN */
|
|
93
|
+
iban: string;
|
|
94
|
+
/** Where `serve.bankVerify` is mounted, a public https URL with no query of its own */
|
|
95
|
+
verifyUrl: string;
|
|
96
|
+
/** When this leg stops being payable, in unix seconds */
|
|
97
|
+
expiresAt: (order: Order) => number;
|
|
98
|
+
/** Sealed before the gateway sees it, the way the blind Lightning rail does */
|
|
99
|
+
sealed?: (order: Order) => string | Promise<string>;
|
|
100
|
+
/** The Czech variable symbol, taken off the reference's digits by default */
|
|
101
|
+
variableSymbol?: (order: Order) => string | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Register on a gateway you do not own anyway. The verify URL names the amount
|
|
104
|
+
* and the reference, so its operator could read your order book off the watches
|
|
105
|
+
*/
|
|
106
|
+
allowPublicGateway?: boolean;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* A provable invoice from the first address on the list that will issue one, which
|
|
110
|
+
* is what a client mints for itself rather than asking a gateway to. Everything the
|
|
111
|
+
* gateway needs to watch it comes back with everything you need to prove it came
|
|
112
|
+
* from the address you asked for, so you can hand over the first and keep the second.
|
|
113
|
+
*
|
|
114
|
+
* Server side: it resolves hostnames and refuses a private one, which no browser can
|
|
115
|
+
* do. Throws `NoWalletAvailableError` when no address on the list would serve
|
|
116
|
+
*/
|
|
117
|
+
declare function invoiceFrom(paidTo: string | string[], amount: Amount, send?: Send): Promise<Resolved>;
|
|
118
|
+
/**
|
|
119
|
+
* One call per sale, whatever the rail moves. Each of these was a free function
|
|
120
|
+
* taking the gateway as a config field, and reaching them through the gateway is
|
|
121
|
+
* what deleted that field
|
|
122
|
+
*/
|
|
123
|
+
declare class Rails {
|
|
124
|
+
private readonly gateway;
|
|
125
|
+
constructor(gateway: ThunderBridge);
|
|
126
|
+
/** Lightning, with the gateway minting against a priority list of addresses */
|
|
127
|
+
lightning(config: LightningRailConfig): Rail;
|
|
128
|
+
/**
|
|
129
|
+
* Lightning, with the invoice resolved here so the gateway is told neither the
|
|
130
|
+
* address nor the amount
|
|
131
|
+
*/
|
|
132
|
+
blindLightning(config: BlindLightningRailConfig): Rail;
|
|
133
|
+
/** A bank transfer, proved the way a Lightning payment is */
|
|
134
|
+
bank(config: BankRailConfig): Rail;
|
|
135
|
+
/**
|
|
136
|
+
* One bank transfer without building a rail first, for a shop that asks for
|
|
137
|
+
* them one at a time rather than beside another payment method
|
|
138
|
+
*/
|
|
139
|
+
transfer(params: BankTransferParams): Promise<BankTransfer>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* What to ask for: who is paid, how much, and how the QR should look. Every
|
|
144
|
+
* field beyond `paidTo` and `amount` has a default, so the shortest request
|
|
145
|
+
* names two
|
|
146
|
+
*/
|
|
147
|
+
interface PaymentRequestInit extends Charge, PaymentRequestOptions {
|
|
148
|
+
}
|
|
149
|
+
/** What `requestPayment` takes beyond the charge itself */
|
|
150
|
+
interface PaymentRequestOptions extends WaitOptions {
|
|
151
|
+
/** Makes the mint safe to retry, so a reloaded checkout replays one invoice */
|
|
152
|
+
idempotencyKey?: string;
|
|
153
|
+
/** Groups this request with every other one carrying the same secret, for `follow` */
|
|
154
|
+
trigger?: string;
|
|
155
|
+
/** How many of that trigger's settlements the gateway keeps replayable past the hour */
|
|
156
|
+
replay?: number;
|
|
157
|
+
/** Size and colour of `qr`, 256 pixels and black by default */
|
|
158
|
+
qr?: QrOptions;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* One payment asked for: the invoice to show, the QR to draw it with, and one
|
|
162
|
+
* way to find out it was paid. Everything on it is already proved against the
|
|
163
|
+
* recipient's own server, so nothing here is the gateway's word
|
|
164
|
+
*/
|
|
165
|
+
interface PaymentRequest {
|
|
166
|
+
/** What the gateway calls this payment, which is what `payment` and `settled` take */
|
|
167
|
+
readonly id: string;
|
|
168
|
+
readonly bolt11: string;
|
|
169
|
+
readonly paymentHash: string;
|
|
170
|
+
readonly lnAddress: string;
|
|
171
|
+
readonly amountMsat: number;
|
|
172
|
+
/** When the invoice stops being payable, in unix seconds */
|
|
173
|
+
readonly expiresAt: number;
|
|
174
|
+
/** The invoice as an SVG QR, ready to put in an element's `innerHTML` */
|
|
175
|
+
readonly qr: string;
|
|
176
|
+
/** The payment as the gateway first reported it, for anything the fields above leave out */
|
|
177
|
+
readonly payment: MintedPayment;
|
|
178
|
+
/**
|
|
179
|
+
* Resolves once the money has arrived, and rejects when the invoice expires
|
|
180
|
+
* unpaid or the wait is aborted. It follows a WebSocket and reconnects through
|
|
181
|
+
* a drop, so this is one await rather than a poll.
|
|
182
|
+
*
|
|
183
|
+
* `gateway.settled(id)` is the wider question and ends on an expiry too. This
|
|
184
|
+
* one is about the payment that was asked for, and one that expired was never paid
|
|
185
|
+
*/
|
|
186
|
+
paid(options?: WaitOptions): Promise<MintedPayment>;
|
|
187
|
+
/**
|
|
188
|
+
* The same wait as a callback, for a page that has something else to do.
|
|
189
|
+
* Returns a function that stops waiting
|
|
190
|
+
*/
|
|
191
|
+
onPaid(arrived: (payment: MintedPayment) => void, failed?: (reason: unknown) => void): () => void;
|
|
192
|
+
/**
|
|
193
|
+
* Ask the recipient's own server whether it settled, and get the preimage it
|
|
194
|
+
* released or null. This is the only answer that comes from somewhere other
|
|
195
|
+
* than the gateway, so it is the one to ask when a payment matters
|
|
196
|
+
*/
|
|
197
|
+
prove(): Promise<string | null>;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** The wallet's own LUD-21 URL and the hash its preimage has to match */
|
|
201
|
+
interface Relayed {
|
|
202
|
+
url: string;
|
|
203
|
+
hash: string;
|
|
204
|
+
}
|
|
205
|
+
/** The verify endpoint that asks the wallet for the gateway, and how often it may be asked */
|
|
206
|
+
interface LightningVerifyConfig {
|
|
207
|
+
/** The secret the sealed wallet URL was made with, and nothing else uses it */
|
|
208
|
+
secret: string;
|
|
209
|
+
/**
|
|
210
|
+
* How often you want the gateway to ask, in seconds. It goes out as
|
|
211
|
+
* `Cache-Control: max-age`, so the pace is yours rather than the operator's.
|
|
212
|
+
* Five by default, which is what a Lightning checkout wants
|
|
213
|
+
*/
|
|
214
|
+
pollEverySecs?: number;
|
|
215
|
+
/** How the relay reaches the wallet, pinned to the address it verified unless you say otherwise */
|
|
216
|
+
send?: Send;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* The URL to hand the gateway instead of the wallet's own, with the wallet's
|
|
220
|
+
* sealed inside it. Point it at wherever `lightningVerifyEndpoint` is mounted
|
|
221
|
+
*/
|
|
222
|
+
declare function relayedVerifyUrl(endpoint: string, wallet: Relayed, secret: string): Promise<string>;
|
|
223
|
+
|
|
224
|
+
/** An LNURL-pay endpoint of your own: whose wallets it stands for, and what it charges */
|
|
225
|
+
interface TriggerConfig {
|
|
226
|
+
/** Priority list, quoted at payRequest and then pinned for the callback */
|
|
227
|
+
paidTo: string | string[];
|
|
228
|
+
/**
|
|
229
|
+
* What this trigger costs right now, asked once per payRequest. `fiat` makes it
|
|
230
|
+
* a live rate, and any function of your own makes it a time of day rule.
|
|
231
|
+
*
|
|
232
|
+
* Give it a `{ least, most }` range instead and the payer chooses inside it,
|
|
233
|
+
* which is what a tip jar is. One amount pins the price and the wallet offers
|
|
234
|
+
* no field to type in
|
|
235
|
+
*/
|
|
236
|
+
amount: Amount | Range;
|
|
237
|
+
/**
|
|
238
|
+
* Signs the callback URL. Without it anyone could call the callback and make
|
|
239
|
+
* this endpoint mint invoices on wallets of their choosing
|
|
240
|
+
*/
|
|
241
|
+
secret: string;
|
|
242
|
+
/** Groups every payment here so `follow` can watch the place, keep it off the QR */
|
|
243
|
+
watchSecret?: string;
|
|
244
|
+
/**
|
|
245
|
+
* How many settlements of this place the gateway keeps replayable past the hour
|
|
246
|
+
* it would otherwise forget them in, up to the ceiling its operator set. What a
|
|
247
|
+
* page that opens later still gets to see. Needs `watchSecret`
|
|
248
|
+
*/
|
|
249
|
+
replay?: number;
|
|
250
|
+
/** How the endpoint reaches wallets, pinned to the address it verified unless you say otherwise */
|
|
251
|
+
send?: Send;
|
|
252
|
+
/** Override when a proxy hides the public URL from the request, no trailing slash */
|
|
253
|
+
baseUrl?: string;
|
|
254
|
+
/**
|
|
255
|
+
* Resolve the address here and hand the gateway only a hash and a URL to poll,
|
|
256
|
+
* instead of asking it to mint. It then cannot tell who is being paid beyond
|
|
257
|
+
* the domain in the verify URL, nor how much at all, so the only refusal left
|
|
258
|
+
* to it is refusing everyone. Costs one more round trip and gives up the
|
|
259
|
+
* gateway's CORS proxying, which a server does not need anyway.
|
|
260
|
+
*
|
|
261
|
+
* A gateway that enforces its verify challenge will not poll a wallet's own
|
|
262
|
+
* LUD-21 URL, so pass `relayThrough` as well and the poll comes to you
|
|
263
|
+
*/
|
|
264
|
+
blind?: boolean;
|
|
265
|
+
/**
|
|
266
|
+
* Where your own `serve.verify` endpoint is mounted, and the secret it was
|
|
267
|
+
* given. The wallet's URL is sealed inside the one the gateway is handed, so
|
|
268
|
+
* the gateway polls you and learns neither the wallet nor its provider
|
|
269
|
+
*/
|
|
270
|
+
relayThrough?: {
|
|
271
|
+
endpoint: string;
|
|
272
|
+
secret: string;
|
|
273
|
+
};
|
|
274
|
+
/**
|
|
275
|
+
* What the watcher needs and the gateway must not have. `data` returns it and
|
|
276
|
+
* `secret` encrypts it, so there is no way to hand the gateway something it
|
|
277
|
+
* can read. Needs 32 characters of randomness, not a passphrase, and every
|
|
278
|
+
* watcher of this trigger holds the same one
|
|
279
|
+
*/
|
|
280
|
+
sealed?: {
|
|
281
|
+
secret: string;
|
|
282
|
+
data: (minted: Minted) => unknown;
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/** What a blind mint produced, which is what the sealed payload is built from */
|
|
286
|
+
/**
|
|
287
|
+
* What a payer may choose to send, when the endpoint lets them choose at all.
|
|
288
|
+
* Both ends are asked once per payRequest, so a fiat range moves with the rate
|
|
289
|
+
*/
|
|
290
|
+
interface Range {
|
|
291
|
+
least: Amount;
|
|
292
|
+
most: Amount;
|
|
293
|
+
}
|
|
294
|
+
/** What a blind mint produced, which is what the sealed payload is built from */
|
|
295
|
+
interface Minted {
|
|
296
|
+
lnAddress: string;
|
|
297
|
+
amountMsat: number;
|
|
298
|
+
bolt11: string;
|
|
299
|
+
paymentHash: string;
|
|
300
|
+
verifyUrl: string;
|
|
301
|
+
expiresAt: number;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* A trigger's live stream is opened with a ticket rather than with the watch
|
|
305
|
+
* secret, so something has to hold the secret and trade it for tickets. That is
|
|
306
|
+
* what these two endpoints are, and they are the only place the gateway's token
|
|
307
|
+
* has to be
|
|
308
|
+
*/
|
|
309
|
+
interface WatchTicketConfig {
|
|
310
|
+
/** The trigger to open, the same secret `serve.lnurlPay` groups its payments under */
|
|
311
|
+
watchSecret: string;
|
|
312
|
+
/**
|
|
313
|
+
* How many of this trigger's settlements the socket replays on connect, so a
|
|
314
|
+
* page opened late still shows what it missed, up to the gateway's ceiling
|
|
315
|
+
*/
|
|
316
|
+
replay?: number;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* What a wrapping operator may charge over the recipient's own amount. This is a
|
|
321
|
+
* ceiling the client sets rather than a price the operator names, so it sits
|
|
322
|
+
* above what any operator lists and refuses only the ones reaching past it
|
|
323
|
+
*/
|
|
324
|
+
interface WrapAllowance {
|
|
325
|
+
/** As a fraction of the recipient's amount, `0.01` by default */
|
|
326
|
+
proportion?: number;
|
|
327
|
+
/** The floor in millisatoshi whatever the fraction works out to, `1000` by default */
|
|
328
|
+
baseMsat?: number;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Prove the invoice really is the one the recipient issued for what you asked,
|
|
332
|
+
* before the payer ever sees it, both fetches go straight to the recipient's own
|
|
333
|
+
* server and none of them goes back to the gateway
|
|
334
|
+
*
|
|
335
|
+
* Throws `GatewayCheatError` when a check fails and `UnverifiedRecipientError`
|
|
336
|
+
* when the recipient could not be reached to run one
|
|
337
|
+
*/
|
|
338
|
+
declare function proveOrigin(payment: MintedPayment, asked: Priced): Promise<void>;
|
|
339
|
+
/**
|
|
340
|
+
* Prove the money arrived by asking the recipient's own server, not the gateway,
|
|
341
|
+
* returns the preimage when the recipient says it settled and null when it says
|
|
342
|
+
* it has not, and runs the full origin proof first because a verify url the
|
|
343
|
+
* gateway made up would otherwise answer for itself
|
|
344
|
+
*/
|
|
345
|
+
declare function proveSettlement(payment: MintedPayment, asked: Priced): Promise<string | null>;
|
|
346
|
+
/** The least a report has to carry for its own proof to be checkable */
|
|
347
|
+
interface Provable {
|
|
348
|
+
status: PaymentStatus;
|
|
349
|
+
preimage: string | null;
|
|
350
|
+
paymentHash: string;
|
|
351
|
+
bolt11?: string | null;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* A report `carriesProof` has already accepted, so the preimage is there and the
|
|
355
|
+
* status is settled. Nothing downstream of the check needs a null guard
|
|
356
|
+
*/
|
|
357
|
+
type Proven<T extends Provable> = T & {
|
|
358
|
+
status: "paid";
|
|
359
|
+
preimage: string;
|
|
360
|
+
};
|
|
361
|
+
/**
|
|
362
|
+
* Whether a report proves what it claims: it says paid, and it carries a preimage
|
|
363
|
+
* that hashes to the payment hash it itself names. Where an invoice comes with it,
|
|
364
|
+
* the invoice's own hash has to agree too.
|
|
365
|
+
*
|
|
366
|
+
* A payment, a settlement delivered to a webhook and a frame off a trigger all
|
|
367
|
+
* answer this, because all three carry those fields and no other question about
|
|
368
|
+
* one matters.
|
|
369
|
+
*
|
|
370
|
+
* It asks nobody anything, so it costs no round trip and is not a proof of
|
|
371
|
+
* arrival. Only `proveSettlement` asks the recipient
|
|
372
|
+
*/
|
|
373
|
+
declare function carriesProof<T extends Provable>(report: T): report is Proven<T>;
|
|
374
|
+
/**
|
|
375
|
+
* The most an operator may add over the recipient's own amount, in millisatoshi.
|
|
376
|
+
* The proportion is what routing and the liquidity behind it costs, and the base
|
|
377
|
+
* is the floor it never drops below, because a fraction of a small payment
|
|
378
|
+
* rounds to nothing the operator can work for
|
|
379
|
+
*/
|
|
380
|
+
declare function wrapFeeCeiling(amountMsat: number, allowance?: WrapAllowance): Msat;
|
|
381
|
+
/**
|
|
382
|
+
* Prove a wrapping operator's invoice is the recipient's own payment in
|
|
383
|
+
* disguise, so paying it can only settle by the operator paying the recipient.
|
|
384
|
+
*
|
|
385
|
+
* It compares two invoices and asks nobody anything, so it runs in a browser and
|
|
386
|
+
* costs no round trip. Prove the recipient's own invoice with `proveOrigin`
|
|
387
|
+
* first, because this says nothing about where that one came from.
|
|
388
|
+
*
|
|
389
|
+
* There is no settlement check here and there does not need to be. Both invoices
|
|
390
|
+
* carry one payment hash, so the preimage that settles the wrap is the preimage
|
|
391
|
+
* the recipient released, and `proveSettlement` already reads it from the
|
|
392
|
+
* recipient's own server.
|
|
393
|
+
*
|
|
394
|
+
* Throws `WrapRefusedError` naming which binding failed
|
|
395
|
+
*/
|
|
396
|
+
declare function proveWrapped(wrapped: string, recipient: string, allowance?: WrapAllowance): void;
|
|
397
|
+
|
|
398
|
+
/** How far the gateway's clock may drift from yours before a webhook is refused */
|
|
399
|
+
type WebhookOptions = {
|
|
400
|
+
toleranceSecs?: number;
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* What checks a delivery: the hex the gateway publishes at `/webhook-key`. There
|
|
404
|
+
* is no shared secret to register, so a gateway holds nothing of yours. Rotating
|
|
405
|
+
* its cluster key rotates this too, so a signature that stops verifying is a
|
|
406
|
+
* reason to read the key again before it is a reason to distrust the gateway
|
|
407
|
+
*/
|
|
408
|
+
type WebhookCredential = {
|
|
409
|
+
publicKey: string;
|
|
410
|
+
};
|
|
411
|
+
/**
|
|
412
|
+
* Answer the challenge the gateway sends a verify URL before it will poll it,
|
|
413
|
+
* which is how a caller shows the endpoint agreed to the traffic rather than
|
|
414
|
+
* merely being named. Returns null for anything that is not a challenge, so a
|
|
415
|
+
* verify endpoint hands the request on to its own reading of a payment.
|
|
416
|
+
*
|
|
417
|
+
* The nonce is echoed to whoever asked, which grants them nothing, so there is
|
|
418
|
+
* no signature to check here and no secret to hold
|
|
419
|
+
*/
|
|
420
|
+
declare function answerVerifyChallenge(request: Request): Promise<Response | null>;
|
|
421
|
+
|
|
422
|
+
/** A Fetch handler, which is what every runtime this targets mounts */
|
|
423
|
+
type Handler = (request: Request) => Promise<Response>;
|
|
424
|
+
/** What to do with what the gateway delivers, and what to believe it with */
|
|
425
|
+
interface WebhookHandlers {
|
|
426
|
+
/**
|
|
427
|
+
* A settlement that proves itself: it says paid and its preimage hashes to the
|
|
428
|
+
* payment hash it names. This is the only callback a shop needs
|
|
429
|
+
*/
|
|
430
|
+
onSettled?: (settlement: Proven<Settlement>) => void | Promise<void>;
|
|
431
|
+
/**
|
|
432
|
+
* A delivery that carries no proof, so an expiry or a paid claim with no
|
|
433
|
+
* preimage behind it. Left unset, the handler answers `202` and does nothing,
|
|
434
|
+
* because acting on an unproven claim is the one thing this refuses to do
|
|
435
|
+
*/
|
|
436
|
+
onUnproven?: (settlement: Settlement) => void | Promise<void>;
|
|
437
|
+
/** A whole payment rather than a settlement, which is what an older gateway posts */
|
|
438
|
+
onPayment?: (payment: Payment) => void | Promise<void>;
|
|
439
|
+
/**
|
|
440
|
+
* The key that checks the signature, fetched from the gateway once and kept
|
|
441
|
+
* when you do not pass one. Pass it to pin the key you already read
|
|
442
|
+
*/
|
|
443
|
+
credential?: WebhookCredential;
|
|
444
|
+
/** How far the gateway's clock may drift from yours, five minutes by default */
|
|
445
|
+
toleranceSecs?: number;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Everything one gateway lets you mount, in one place so a caller never has to
|
|
449
|
+
* know which handler needs the gateway and which does not. Most of these took it
|
|
450
|
+
* as a config field before, and reaching them through the gateway deleted it.
|
|
451
|
+
*
|
|
452
|
+
* `verify` and `bankVerify` need nothing from the gateway and are here anyway,
|
|
453
|
+
* because a reader looking for a handler should find every handler in one list
|
|
454
|
+
*/
|
|
455
|
+
declare class Serve {
|
|
456
|
+
private readonly gateway;
|
|
457
|
+
constructor(gateway: ThunderBridge);
|
|
458
|
+
/**
|
|
459
|
+
* An LNURL-pay endpoint of your own, standing in front of a priority list of
|
|
460
|
+
* addresses, so a printed QR points at your domain and never expires
|
|
461
|
+
*/
|
|
462
|
+
lnurlPay(config: TriggerConfig): Handler;
|
|
463
|
+
/** Trades the watch secret for a one minute socket ticket, refusing anyone without it */
|
|
464
|
+
watchTicket(config: WatchTicketConfig): Handler;
|
|
465
|
+
/**
|
|
466
|
+
* Mints a socket ticket for anybody who asks, which makes the trigger's whole
|
|
467
|
+
* stream public, preimages included. Only for a board where that is the point
|
|
468
|
+
*/
|
|
469
|
+
publicWatchTicket(config: WatchTicketConfig): Handler;
|
|
470
|
+
/**
|
|
471
|
+
* A verify endpoint of your own that asks the recipient's wallet for you, so
|
|
472
|
+
* the gateway polls you and never the wallet
|
|
473
|
+
*/
|
|
474
|
+
verify(config: LightningVerifyConfig): Handler;
|
|
475
|
+
/** The verify endpoint a bank rail is polled at, answering off your own statement */
|
|
476
|
+
bankVerify(config: BankVerifyConfig): Handler;
|
|
477
|
+
/**
|
|
478
|
+
* The whole webhook route: it answers the gateway's challenge, checks the
|
|
479
|
+
* signature against the key the gateway publishes, refuses a settlement that
|
|
480
|
+
* proves nothing, and calls you for the one that does.
|
|
481
|
+
*
|
|
482
|
+
* `export const POST = gateway.serve.webhook({ onSettled: fulfil })` is the
|
|
483
|
+
* entire integration
|
|
484
|
+
*/
|
|
485
|
+
webhook(handlers: WebhookHandlers): Handler;
|
|
486
|
+
/** Verify a delivery and read the settlement out of it, null when it is not believable */
|
|
487
|
+
readSettlement(request: Request, options?: WebhookOptions): Promise<Settlement | null>;
|
|
488
|
+
/** Verify a delivery and read the payment out of it, null when it is not believable */
|
|
489
|
+
readPayment(request: Request, options?: WebhookOptions): Promise<Payment | null>;
|
|
490
|
+
/** Answer the challenge the gateway sends before it will post to a webhook of yours */
|
|
491
|
+
answerWebhookChallenge(request: Request, options?: WebhookOptions): Promise<Response | null>;
|
|
492
|
+
private credential;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/** How this instance talks to one gateway, and how much of what it says to check */
|
|
496
|
+
interface ThunderBridgeOptions {
|
|
497
|
+
/**
|
|
498
|
+
* Prove every payment against the recipient's own server before handing it
|
|
499
|
+
* back, and refuse a reported settlement whose preimage does not hash to the
|
|
500
|
+
* payment hash, defaults to true
|
|
501
|
+
*/
|
|
502
|
+
verify?: boolean;
|
|
503
|
+
/**
|
|
504
|
+
* Sent as `Authorization: Bearer`, which a gateway started with
|
|
505
|
+
* `GATEWAY_TOKEN` requires on every call, the socket handshake included. No
|
|
506
|
+
* browser WebSocket can carry a header, so setting this also puts every socket
|
|
507
|
+
* through a ticket
|
|
508
|
+
*/
|
|
509
|
+
token?: string;
|
|
510
|
+
/**
|
|
511
|
+
* The same long lived server side secret your rail derives its preimages from.
|
|
512
|
+
* Given here, every call carries a signature the gateway reads as your identity,
|
|
513
|
+
* so a payment you create is handed back to you and to nobody else. Withheld,
|
|
514
|
+
* you are anonymous and any holder of an id can read what it names
|
|
515
|
+
*/
|
|
516
|
+
secret?: string;
|
|
517
|
+
}
|
|
518
|
+
/** How long to wait on a payment, and what the socket URL is allowed to carry */
|
|
519
|
+
interface WaitOptions {
|
|
520
|
+
/** Give up when this aborts, `AbortSignal.timeout(ms)` covers the usual case */
|
|
521
|
+
signal?: AbortSignal;
|
|
522
|
+
/**
|
|
523
|
+
* Mint a short-lived ticket and put that in the socket URL instead of the
|
|
524
|
+
* payment id. Implied by `token`. The id stays readable inside the ticket,
|
|
525
|
+
* what changes is that a URL out of a log stops opening anything after a
|
|
526
|
+
* minute
|
|
527
|
+
*/
|
|
528
|
+
tickets?: boolean;
|
|
529
|
+
}
|
|
530
|
+
/** What a socket ticket opens beyond the trigger it names */
|
|
531
|
+
interface TicketOptions {
|
|
532
|
+
/**
|
|
533
|
+
* How many of this trigger's settlements the socket replays on connect, up to
|
|
534
|
+
* the ceiling the gateway's operator set
|
|
535
|
+
*/
|
|
536
|
+
replay?: number;
|
|
537
|
+
}
|
|
538
|
+
/** What a mint carries beyond the charge: a retry key, and which trigger it joins */
|
|
539
|
+
interface CreateOptions {
|
|
540
|
+
/**
|
|
541
|
+
* Makes the POST safe to retry. A repeat of a finished request replays its
|
|
542
|
+
* payment instead of asking a wallet for a second invoice, a repeat that
|
|
543
|
+
* arrives while the first is still resolving throws
|
|
544
|
+
* `IdempotencyConflictError`, and the key is held for 24 hours
|
|
545
|
+
*/
|
|
546
|
+
idempotencyKey?: string;
|
|
547
|
+
/**
|
|
548
|
+
* Groups this payment with every other one carrying the same secret, so
|
|
549
|
+
* `follow` can watch the place rather than the payment. Registering
|
|
550
|
+
* sends only its sha256, which is also all the gateway stores, so a stolen
|
|
551
|
+
* ledger cannot subscribe. Following sends the secret itself, because the
|
|
552
|
+
* gateway hashes what it is given to find the stream, so the operator of a
|
|
553
|
+
* gateway you do not own learns it the first time you connect. Keep it apart
|
|
554
|
+
* from any URL a payer sees
|
|
555
|
+
*/
|
|
556
|
+
trigger?: string;
|
|
557
|
+
/**
|
|
558
|
+
* How many of the trigger's settlements the gateway keeps replayable past the
|
|
559
|
+
* hour it would otherwise forget them in, up to the ceiling its operator set.
|
|
560
|
+
* Needs `trigger`, defaults to none
|
|
561
|
+
*/
|
|
562
|
+
replay?: number;
|
|
563
|
+
}
|
|
564
|
+
/** What to do with a trigger's settlements, and how hard to try to keep hearing them */
|
|
565
|
+
interface FollowOptions {
|
|
566
|
+
/** Called for the recent settlements replayed on connect, then for each new one */
|
|
567
|
+
onPayment: (settled: Payment) => void;
|
|
568
|
+
/**
|
|
569
|
+
* How many settlements to ask for on connect, defaults to the gateway's ten.
|
|
570
|
+
* It hands back what it still holds, which is the last hour unless the
|
|
571
|
+
* payments were minted with `replay`
|
|
572
|
+
*/
|
|
573
|
+
replay?: number;
|
|
574
|
+
/** Called when a connection drops or a frame is refused, the follow keeps going */
|
|
575
|
+
onError?: (error: unknown) => void;
|
|
576
|
+
/** Reconnect after a drop, defaults to true */
|
|
577
|
+
reconnect?: boolean;
|
|
578
|
+
/**
|
|
579
|
+
* The first wait after a drop, doubling up to 30 seconds and jittered so a
|
|
580
|
+
* fleet does not come back in lockstep, defaults to 3000. A connection that
|
|
581
|
+
* opens puts it back to the first wait
|
|
582
|
+
*/
|
|
583
|
+
reconnectDelayMs?: number;
|
|
584
|
+
/**
|
|
585
|
+
* Mint a short-lived ticket and put that in the socket URL instead of the
|
|
586
|
+
* secret, one per connection. Keeps the secret out of access logs, at the cost
|
|
587
|
+
* of a POST before each connect. Implied by `token`. Leave it off for a
|
|
588
|
+
* microcontroller, where one hardcoded URL and a dumb reconnect loop is the
|
|
589
|
+
* whole point
|
|
590
|
+
*/
|
|
591
|
+
tickets?: boolean;
|
|
592
|
+
}
|
|
593
|
+
/** Talks to a Thunder Bridge gateway and trusts it for nothing it can check itself */
|
|
594
|
+
declare class ThunderBridge {
|
|
595
|
+
private readonly baseUrl;
|
|
596
|
+
private readonly verify;
|
|
597
|
+
private readonly token;
|
|
598
|
+
private readonly secret;
|
|
599
|
+
private strangers;
|
|
600
|
+
private speaks;
|
|
601
|
+
private published;
|
|
602
|
+
/** Everything this gateway lets you mount, from an LNURL endpoint to a webhook route */
|
|
603
|
+
readonly serve: Serve;
|
|
604
|
+
/** One call per sale, whatever the rail moves */
|
|
605
|
+
readonly rails: Rails;
|
|
606
|
+
constructor(baseUrl: string, options?: ThunderBridgeOptions);
|
|
607
|
+
/**
|
|
608
|
+
* Whether a token was given to this instance, which is your side of the
|
|
609
|
+
* arrangement and says nothing about the gateway's. `refusesStrangers` is the
|
|
610
|
+
* one that asks the gateway, and it is the one to guard anything with
|
|
611
|
+
*/
|
|
612
|
+
get hasToken(): boolean;
|
|
613
|
+
/**
|
|
614
|
+
* Whether the gateway turns away a caller carrying no token, asked by making
|
|
615
|
+
* one unauthenticated read it would have to refuse. `hasToken` answers only
|
|
616
|
+
* whether you configured one, so a made-up token against a public instance
|
|
617
|
+
* reads as yours and is not. Asked once and remembered, because an instance
|
|
618
|
+
* does not change its mind. Anything other than a refusal counts as open, so
|
|
619
|
+
* an unreachable gateway fails closed
|
|
620
|
+
*/
|
|
621
|
+
refusesStrangers(): Promise<boolean>;
|
|
622
|
+
/**
|
|
623
|
+
* Ask to be paid for one thing. It mints the invoice, proves it came from the
|
|
624
|
+
* address you asked for, draws the QR and hands back one object with a way to
|
|
625
|
+
* wait for the money. This is `mint` plus the two things every caller does next
|
|
626
|
+
*/
|
|
627
|
+
requestPayment(asked: PaymentRequestInit): Promise<PaymentRequest>;
|
|
628
|
+
/**
|
|
629
|
+
* Ask the gateway for an invoice payable to the first address on your list
|
|
630
|
+
* that can issue a provable one, throws `NoWalletAvailableError` when none can
|
|
631
|
+
* and `GatewayCheatError` when what comes back is not what you asked for
|
|
632
|
+
*/
|
|
633
|
+
mint(charge: Charge, options?: CreateOptions): Promise<MintedPayment>;
|
|
634
|
+
/**
|
|
635
|
+
* Ask which address would serve an amount without minting anything, throws
|
|
636
|
+
* `NoWalletAvailableError` when none would. A quote is a probe and not a
|
|
637
|
+
* promise: the address it names can still be refused at create time, because
|
|
638
|
+
* whether a wallet returns a provable invoice cannot be known without asking
|
|
639
|
+
* it for one, and asking mints it
|
|
640
|
+
*/
|
|
641
|
+
quote(charge: Charge): Promise<Quote>;
|
|
642
|
+
/**
|
|
643
|
+
* The key this gateway signs webhooks with when you registered none of your own.
|
|
644
|
+
* `serve.webhook` reads it for you. Asked once and kept, because it is the same
|
|
645
|
+
* for every instance in the cluster
|
|
646
|
+
*/
|
|
647
|
+
webhookKey(): Promise<string>;
|
|
648
|
+
private publishedKey;
|
|
649
|
+
/**
|
|
650
|
+
* Read a payment back, null when the gateway has never heard of it. One method
|
|
651
|
+
* for both sorts: `kind` says whether the gateway minted it or was handed it,
|
|
652
|
+
* and the address, amount and invoice are null on one it was never told
|
|
653
|
+
*/
|
|
654
|
+
payment(id: string): Promise<Payment | null>;
|
|
655
|
+
/**
|
|
656
|
+
* List what this gateway is watching, newest first. Only a gateway started
|
|
657
|
+
* with `GATEWAY_TOKEN` serves this, because on a shared one it would hand
|
|
658
|
+
* every caller everyone else's payments, so a public gateway answers 404.
|
|
659
|
+
*
|
|
660
|
+
* `scanned` says how many settled records were looked at to build the page.
|
|
661
|
+
* Anything older than that window is not in the answer, and the list does not
|
|
662
|
+
* pretend otherwise
|
|
663
|
+
*/
|
|
664
|
+
payments(limit?: number): Promise<{
|
|
665
|
+
payments: Payment[];
|
|
666
|
+
scanned: number;
|
|
667
|
+
}>;
|
|
668
|
+
/**
|
|
669
|
+
* Follow a payment over WebSocket until it is paid or expired, reconnecting
|
|
670
|
+
* through a drop. A payment that never answers gives up after a few tries, and
|
|
671
|
+
* one that has answered is followed until its own expiry, so the wait always
|
|
672
|
+
* ends by itself
|
|
673
|
+
*/
|
|
674
|
+
settled(id: string, options?: WaitOptions): Promise<Payment>;
|
|
675
|
+
private followed;
|
|
676
|
+
/**
|
|
677
|
+
* Wait on several payments and keep the first one that is really paid, then stop
|
|
678
|
+
* waiting on the losers, which closes their sockets.
|
|
679
|
+
*
|
|
680
|
+
* This is how one order offers two rails. A Lightning invoice and a bank
|
|
681
|
+
* transfer for the same thing are two payments here, and the payer picks one, so
|
|
682
|
+
* what you want is the one that arrives and nothing further from the other.
|
|
683
|
+
*
|
|
684
|
+
* A leg that expires is a loser, not a winner, which is the whole reason this is
|
|
685
|
+
* not a race: `settled` ends on `paid` and on `expired` alike, and a
|
|
686
|
+
* Lightning invoice expires in an hour while a bank transfer takes days. `null`
|
|
687
|
+
* means every leg ended without being paid.
|
|
688
|
+
*
|
|
689
|
+
* Stopping the wait is not revoking the invoice. Nobody can revoke one, because
|
|
690
|
+
* the recipient's own wallet minted it, so a payer who pays the loser afterwards
|
|
691
|
+
* really does pay twice and that shows up on `follow` as a second settlement to
|
|
692
|
+
* refund.
|
|
693
|
+
*/
|
|
694
|
+
firstSettled(ids: string[], options?: WaitOptions): Promise<Payment | null>;
|
|
695
|
+
/**
|
|
696
|
+
* Hand over an invoice you obtained yourself so the gateway watches it without
|
|
697
|
+
* being told the address or the amount. It can then only refuse everyone
|
|
698
|
+
* rather than one recipient, which is what makes leaving it cheap. Anything
|
|
699
|
+
* the watcher needs goes in `sealed`, which the gateway cannot read
|
|
700
|
+
*/
|
|
701
|
+
watch(handover: Handover): Promise<Payment>;
|
|
702
|
+
/**
|
|
703
|
+
* What this payment is called, which you can work out before any gateway has
|
|
704
|
+
* heard of it. Every gateway you hand the same invoice to answers with the same
|
|
705
|
+
* name, so watching at several of them adds up to one payment rather than
|
|
706
|
+
* several, and no gateway's key is in the answer. Null when no secret was given,
|
|
707
|
+
* because then the gateway names the payment and only it can
|
|
708
|
+
*/
|
|
709
|
+
nameFor(paymentHash: string): Promise<string | null>;
|
|
710
|
+
/**
|
|
711
|
+
* Follow every payment made to one trigger, replayed from the recent ones on
|
|
712
|
+
* connect and then live, reconnecting on its own until the returned function
|
|
713
|
+
* is called. A trigger has no terminal state, so this never resolves
|
|
714
|
+
*/
|
|
715
|
+
follow(secret: string, options: FollowOptions): () => void;
|
|
716
|
+
/**
|
|
717
|
+
* A one minute pass onto one trigger's stream, for something that must hold
|
|
718
|
+
* neither the token nor the trigger secret. Mint it in a handler and answer
|
|
719
|
+
* with the ticket alone, because that is all a browser needs to connect and
|
|
720
|
+
* all it can do anything with. `serve.watchTicket` is this method already
|
|
721
|
+
* wrapped in a route
|
|
722
|
+
*/
|
|
723
|
+
ticket(trigger: string, options?: TicketOptions): Promise<SocketTicket>;
|
|
724
|
+
private needsTicket;
|
|
725
|
+
private wsTicket;
|
|
726
|
+
private mintedTicket;
|
|
727
|
+
private sending;
|
|
728
|
+
private reading;
|
|
729
|
+
private speaking;
|
|
730
|
+
private proven;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
export { relayedVerifyUrl as A, type BankRailConfig as B, type CreateOptions as C, wrapFeeCeiling as D, type FollowOptions as F, type Handler as H, type Leg as L, type Minted as M, type Order as O, type PaymentRequest as P, type RailConfig as R, type Send as S, ThunderBridge as T, type WaitOptions as W, type Rail as a, type ThunderBridgeOptions as b, type BlindLightningRailConfig as c, type LightningRailConfig as d, type LightningVerifyConfig as e, type PaymentRequestInit as f, type PaymentRequestOptions as g, type Provable as h, type Proven as i, Rails as j, type Range as k, type Relayed as l, Serve as m, type TicketOptions as n, type TriggerConfig as o, type WatchTicketConfig as p, type WebhookCredential as q, type WebhookHandlers as r, type WebhookOptions as s, type WrapAllowance as t, answerVerifyChallenge as u, carriesProof as v, invoiceFrom as w, proveOrigin as x, proveSettlement as y, proveWrapped as z };
|