@openreceive/browser 0.1.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +63 -0
  2. package/dist/chunk-WLLNZH26.js +3051 -0
  3. package/dist/headless.d.ts +804 -0
  4. package/dist/headless.js +891 -0
  5. package/dist/index.d.ts +32 -4
  6. package/dist/index.js +32 -2
  7. package/dist/status-B1vDOhvh.d.ts +1001 -0
  8. package/dist/styles.css +3 -759
  9. package/package.json +57 -15
  10. package/dist/assets/icons/bank.svg +0 -12
  11. package/dist/assets/icons/bnb.svg +0 -1
  12. package/dist/assets/icons/card.svg +0 -14
  13. package/dist/assets/icons/doge.svg +0 -1
  14. package/dist/assets/pay_tutorials/boltz-1.webp +0 -0
  15. package/dist/assets/pay_tutorials/boltz-2.webp +0 -0
  16. package/dist/assets/pay_tutorials/cashapp-1.webp +0 -0
  17. package/dist/assets/pay_tutorials/cashapp-2.webp +0 -0
  18. package/dist/assets/pay_tutorials/cashapp-3.webp +0 -0
  19. package/dist/assets/pay_tutorials/cashapp-4.webp +0 -0
  20. package/dist/assets/pay_tutorials/cashapp-5.webp +0 -0
  21. package/dist/assets/pay_tutorials/cashapp-6.webp +0 -0
  22. package/dist/assets/pay_tutorials/coinbase-1.webp +0 -0
  23. package/dist/assets/pay_tutorials/coinbase-2.webp +0 -0
  24. package/dist/assets/pay_tutorials/fixedfloat-1.webp +0 -0
  25. package/dist/assets/pay_tutorials/fixedfloat-2.webp +0 -0
  26. package/dist/assets/pay_tutorials/kraken-1.webp +0 -0
  27. package/dist/assets/pay_tutorials/kraken-2.webp +0 -0
  28. package/dist/assets/pay_tutorials/kraken-3.webp +0 -0
  29. package/dist/assets/pay_tutorials/kraken-4.webp +0 -0
  30. package/dist/assets/pay_tutorials/strike-1.webp +0 -0
  31. package/dist/assets/pay_tutorials/strike-2.webp +0 -0
  32. package/dist/assets/pay_tutorials/strike-3.webp +0 -0
  33. package/dist/assets/pay_tutorials/strike-4.webp +0 -0
  34. package/dist/assets/provider-icons/aqua.png +0 -0
  35. package/dist/assets/provider-icons/belo.png +0 -0
  36. package/dist/assets/provider-icons/binance.png +0 -0
  37. package/dist/assets/provider-icons/bipa.png +0 -0
  38. package/dist/assets/provider-icons/bitfinex.png +0 -0
  39. package/dist/assets/provider-icons/bitget.png +0 -0
  40. package/dist/assets/provider-icons/bitnob.png +0 -0
  41. package/dist/assets/provider-icons/bitso.png +0 -0
  42. package/dist/assets/provider-icons/bity.png +0 -0
  43. package/dist/assets/provider-icons/blink.png +0 -0
  44. package/dist/assets/provider-icons/bluewallet.png +0 -0
  45. package/dist/assets/provider-icons/boltz.png +0 -0
  46. package/dist/assets/provider-icons/bringin.png +0 -0
  47. package/dist/assets/provider-icons/bullbitcoin.png +0 -0
  48. package/dist/assets/provider-icons/cakewallet.png +0 -0
  49. package/dist/assets/provider-icons/cashapp.png +0 -0
  50. package/dist/assets/provider-icons/changenow.png +0 -0
  51. package/dist/assets/provider-icons/chivo.png +0 -0
  52. package/dist/assets/provider-icons/coinbase.png +0 -0
  53. package/dist/assets/provider-icons/coincorner.png +0 -0
  54. package/dist/assets/provider-icons/fixedfloat.png +0 -0
  55. package/dist/assets/provider-icons/getalby.png +0 -0
  56. package/dist/assets/provider-icons/kraken.png +0 -0
  57. package/dist/assets/provider-icons/kryptex.png +0 -0
  58. package/dist/assets/provider-icons/kucoin.png +0 -0
  59. package/dist/assets/provider-icons/manifest.json +0 -207
  60. package/dist/assets/provider-icons/mtpelerin.png +0 -0
  61. package/dist/assets/provider-icons/muun.png +0 -0
  62. package/dist/assets/provider-icons/okcoin.png +0 -0
  63. package/dist/assets/provider-icons/okx.png +0 -0
  64. package/dist/assets/provider-icons/phoenix.png +0 -0
  65. package/dist/assets/provider-icons/pouch.png +0 -0
  66. package/dist/assets/provider-icons/ripio.png +0 -0
  67. package/dist/assets/provider-icons/river.png +0 -0
  68. package/dist/assets/provider-icons/rizful.png +0 -0
  69. package/dist/assets/provider-icons/shakepay.png +0 -0
  70. package/dist/assets/provider-icons/sideshift.png +0 -0
  71. package/dist/assets/provider-icons/simpleswap.png +0 -0
  72. package/dist/assets/provider-icons/speed.png +0 -0
  73. package/dist/assets/provider-icons/strike.png +0 -0
  74. package/dist/assets/provider-icons/trocador.png +0 -0
  75. package/dist/assets/provider-icons/walletofsatoshi.png +0 -0
  76. package/dist/assets/provider-icons/zeus.png +0 -0
  77. package/dist/country-map.d.ts +0 -5
  78. package/dist/country-map.js +0 -17
  79. package/dist/internal.d.ts +0 -834
  80. package/dist/internal.js +0 -2615
  81. package/dist/pay-tutorials.d.ts +0 -1
  82. package/dist/pay-tutorials.js +0 -1
  83. package/dist/provider-icons.d.ts +0 -1
  84. package/dist/provider-icons.js +0 -1
  85. package/dist/qrcode.d.ts +0 -11
  86. package/dist/status.d.ts +0 -9
  87. package/dist/status.js +0 -25
@@ -0,0 +1,1001 @@
1
+ import { PaymentWizardRoute, AssetIndexEntry } from '@openreceive/provider-data';
2
+ import { TransactionSettlementStatus } from '@openreceive/core';
3
+
4
+ /**
5
+ * A unix timestamp in **seconds** — the unit every OpenReceive wire field uses
6
+ * (`expires_at`, `provider_expires_at`, `settled_at`, `paid_at`) and therefore
7
+ * the unit every `now` option compares against.
8
+ *
9
+ * It is a plain `number`; the alias exists so the unit shows up where the
10
+ * option does. `Date.now()` is MILLISECONDS and is the wrong value here —
11
+ * {@link resolveNow} rejects it rather than letting every invoice read as
12
+ * expired. Use `Math.floor(Date.now() / 1000)`.
13
+ */
14
+ type UnixSeconds = number;
15
+
16
+ /**
17
+ * Trim insignificant trailing zeros from a decimal crypto amount for display,
18
+ * e.g. "12.25900000" -> "12.259" and "5.000" -> "5". Only fractional digits are
19
+ * stripped: integer amounts like "100" keep their zeros, and non-numeric input
20
+ * is returned unchanged.
21
+ */
22
+ declare function formatDepositAmount(amount: string): string;
23
+ declare function escapeHtml(value: string): string;
24
+ /**
25
+ * Throws on a non-amount, and every caller lets it: wire construction, amount
26
+ * validation, and the display sites share this formatter, and a malformed
27
+ * amount from our own server is a bug that must surface, not be smoothed over.
28
+ */
29
+ declare function formatMsats(amountMsats: number): string;
30
+ declare function formatFiatAmount(fiat: {
31
+ readonly currency?: string;
32
+ readonly value?: string;
33
+ } | null | undefined): string | undefined;
34
+ /** Combined QR caption, e.g. `19,174 sats / $12.00 US`. */
35
+ declare function formatAmountCaption(options: {
36
+ readonly amountLabel?: string;
37
+ readonly fiatLabel?: string;
38
+ readonly fiatCurrency?: string;
39
+ }): string | undefined;
40
+ /**
41
+ * Renders an invoice-side (Lightning receive) msat limit as a short amount for
42
+ * display under a disabled swap asset, e.g. "$10.00". Converts to the
43
+ * checkout's own fiat currency using its rate; falls back to a sats figure when
44
+ * the checkout is sats/BTC-denominated or no usable rate is available.
45
+ *
46
+ * Minimums ceil and maximums floor to the display scale so the note never
47
+ * understates a floor or overstates a ceiling.
48
+ */
49
+ declare function formatSwapLimit(checkout: {
50
+ readonly amount_msats: number;
51
+ readonly fiat?: {
52
+ readonly currency: string;
53
+ readonly value: string;
54
+ };
55
+ }, limitMsats: number | undefined, rounding?: "ceil" | "floor"): string | undefined;
56
+ /**
57
+ * ECHOES rather than throws on a value it cannot render — the one place this
58
+ * rule reads differently from the amount rule above, deliberately.
59
+ * `formatMsats` throws because wire construction and amount validation share
60
+ * it and a bad amount there must surface; nothing constructs or validates
61
+ * anything through this formatter, so degrading to the raw value is its
62
+ * contract.
63
+ */
64
+ declare function formatUnixTime(seconds: number): string;
65
+ /** The payer-facing labels a {@link CheckoutState} carries next to its raw fields. */
66
+ interface CheckoutStateLabels {
67
+ readonly amountLabel?: string;
68
+ readonly fiatLabel?: string;
69
+ readonly paymentHashLabel?: string;
70
+ }
71
+ /**
72
+ * THE label rule — one copy, applied everywhere a checkout is shown.
73
+ *
74
+ * `normalizeCheckoutState` runs it so every CheckoutState already carries its
75
+ * labels, and the elements renderer runs it over raw attributes in create mode,
76
+ * before there is an attempt to build a state from. It replaces the label half
77
+ * of the deleted `createCheckoutDisplayModel`; the other half (the `lightning:`
78
+ * URI) belongs to `createCheckoutState`, which is the only place that knows the
79
+ * rail.
80
+ *
81
+ * `transactionStateLabel` is deliberately NOT here: it was a verbatim copy of
82
+ * `transaction_state`, which the state already carries, and nothing read it.
83
+ */
84
+ declare function deriveCheckoutStateLabels(source: {
85
+ readonly amount_msats?: number;
86
+ readonly fiat_quote?: {
87
+ readonly fiat?: {
88
+ readonly currency?: string;
89
+ readonly value?: string;
90
+ };
91
+ } | null;
92
+ readonly payment_hash?: string;
93
+ }): CheckoutStateLabels;
94
+
95
+ declare const OPENRECEIVE_THEME_STORAGE_KEY: "openreceive.theme";
96
+ declare const OPENRECEIVE_DEFAULT_POLL_INTERVAL_MS: 3000;
97
+ /**
98
+ * Default base path the shipped OpenReceive router is mounted at. When a developer passes
99
+ * only an order id (React `<Checkout reference>` / `<openreceive-checkout reference>`), this is
100
+ * the prefix every route is derived from — see `checkoutRoutes` in ./routes.ts. It is
101
+ * the only URL input the checkout components accept.
102
+ */
103
+ declare const OPENRECEIVE_DEFAULT_PREFIX: "/openreceive";
104
+ declare const OPENRECEIVE_COPY_FEEDBACK_MS: 1800;
105
+ declare const OPENRECEIVE_CHECKOUT_ELEMENT_TAG_NAME: "openreceive-checkout";
106
+ declare const OPENRECEIVE_THEME_TOGGLE_ELEMENT_TAG_NAME: "openreceive-theme-toggle";
107
+ declare const OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS: {
108
+ readonly copy: "openreceive-copy";
109
+ readonly openWallet: "openreceive-open-wallet";
110
+ readonly state: "openreceive-state";
111
+ readonly settled: "openreceive-settled";
112
+ readonly providerCopy: "openreceive-provider-copy";
113
+ readonly startOver: "openreceive-start-over";
114
+ readonly error: "openreceive-error";
115
+ };
116
+ declare const OPENRECEIVE_THEME_TOGGLE_ELEMENT_EVENTS: {
117
+ readonly change: "openreceive-theme-change";
118
+ };
119
+ declare const OPENRECEIVE_PAYMENT_WIZARD_ATTRIBUTES: {
120
+ readonly root: "data-openreceive-wizard";
121
+ readonly breadcrumb: "data-or-breadcrumb";
122
+ readonly method: "data-or-method";
123
+ readonly route: "data-or-route";
124
+ readonly swapStart: "data-or-swap-start";
125
+ readonly swapBack: "data-or-swap-back";
126
+ readonly swapQr: "data-or-swap-qr";
127
+ readonly swapCopy: "data-or-swap-copy";
128
+ readonly swapCopyLabel: "data-or-swap-copy-label";
129
+ readonly swapSelectAll: "data-or-swap-select-all";
130
+ readonly swapNetwork: "data-or-swap-network";
131
+ readonly swapNetworkValue: "data-or-swap-network-value";
132
+ readonly pickerSelect: "data-or-picker-select";
133
+ readonly pickerContinue: "data-or-picker-continue";
134
+ readonly swapRefundForm: "data-or-swap-refund-form";
135
+ readonly swapRefundAddress: "data-or-swap-refund-address";
136
+ readonly swapRefundAllowed: "data-or-swap-refund-allowed";
137
+ readonly swapRefundConfirm: "data-or-swap-refund-confirm";
138
+ readonly swapRefundPayInAsset: "data-or-swap-refund-pay-in-asset";
139
+ readonly swapRefundNetworkLabel: "data-or-swap-refund-network-label";
140
+ readonly swapRefundError: "data-or-swap-refund-error";
141
+ readonly providerCopy: "data-or-provider-copy";
142
+ readonly providerTutorial: "data-or-provider-tutorial";
143
+ readonly providerTutorialIndex: "data-or-provider-tutorial-index";
144
+ };
145
+ declare const OPENRECEIVE_PAYMENT_WIZARD_SELECTORS: {
146
+ readonly root: "[data-openreceive-wizard]";
147
+ readonly breadcrumb: "[data-or-breadcrumb]";
148
+ readonly method: "[data-or-method]";
149
+ readonly route: "[data-or-route]";
150
+ readonly swapStart: "[data-or-swap-start]";
151
+ readonly swapBack: "[data-or-swap-back]";
152
+ readonly swapQr: "[data-or-swap-qr]";
153
+ readonly swapCopy: "[data-or-swap-copy]";
154
+ readonly swapCopyLabel: "[data-or-swap-copy-label]";
155
+ readonly swapSelectAll: "[data-or-swap-select-all]";
156
+ readonly swapNetwork: "[data-or-swap-network]";
157
+ readonly swapNetworkValue: "[data-or-swap-network-value]";
158
+ readonly pickerSelect: "[data-or-picker-select]";
159
+ readonly pickerContinue: "[data-or-picker-continue]";
160
+ readonly swapRefundForm: "[data-or-swap-refund-form]";
161
+ readonly swapRefundAddress: "[data-or-swap-refund-address]";
162
+ readonly swapRefundAllowed: "[data-or-swap-refund-allowed]";
163
+ readonly swapRefundConfirm: "[data-or-swap-refund-confirm]";
164
+ readonly swapRefundPayInAsset: "[data-or-swap-refund-pay-in-asset]";
165
+ readonly swapRefundNetworkLabel: "[data-or-swap-refund-network-label]";
166
+ readonly swapRefundError: "[data-or-swap-refund-error]";
167
+ readonly providerCopy: "[data-or-provider-copy]";
168
+ readonly providerTutorial: "[data-or-provider-tutorial]";
169
+ readonly providerTutorialIndex: "[data-or-provider-tutorial-index]";
170
+ };
171
+ declare const OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES: {
172
+ readonly root: "data-openreceive-checkout";
173
+ readonly qr: "data-openreceive-qr";
174
+ readonly meta: "data-openreceive-meta";
175
+ readonly state: "data-openreceive-state";
176
+ readonly actions: "data-openreceive-actions";
177
+ readonly theme: "data-openreceive-theme";
178
+ readonly themeToggle: "data-openreceive-theme-toggle";
179
+ };
180
+ declare const OPENRECEIVE_CHECKOUT_DATA_SELECTORS: {
181
+ readonly root: "[data-openreceive-checkout]";
182
+ readonly qr: "[data-openreceive-qr]";
183
+ readonly meta: "[data-openreceive-meta]";
184
+ readonly state: "[data-openreceive-state]";
185
+ readonly actions: "[data-openreceive-actions]";
186
+ readonly theme: "[data-openreceive-theme]";
187
+ readonly themeToggle: "[data-openreceive-theme-toggle]";
188
+ };
189
+ declare const OPENRECEIVE_CHECKOUT_ELEMENT_PARTS: {
190
+ readonly copy: "copy";
191
+ readonly startOver: "start-over";
192
+ };
193
+ declare const OPENRECEIVE_CHECKOUT_ELEMENT_PART_SELECTORS: {
194
+ readonly copy: "[part=\"copy\"]";
195
+ readonly startOver: "[part=\"start-over\"]";
196
+ };
197
+ declare const OPENRECEIVE_THEME_TOGGLE_ELEMENT_PARTS: {
198
+ readonly button: "button";
199
+ };
200
+ declare const OPENRECEIVE_THEME_TOGGLE_ELEMENT_PART_SELECTORS: {
201
+ readonly button: "[part=\"button\"]";
202
+ };
203
+ type CheckoutElementEventName = (typeof OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS)[keyof typeof OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS];
204
+ interface CheckoutProviderCopyEventDetail {
205
+ readonly providerId: string;
206
+ }
207
+ interface CheckoutStateEventDetail {
208
+ readonly state: CheckoutState;
209
+ }
210
+ interface CheckoutErrorEventDetail {
211
+ readonly error: unknown;
212
+ }
213
+ interface ThemeChangeEventDetail {
214
+ readonly theme: ThemePreference;
215
+ readonly resolvedTheme: ResolvedTheme;
216
+ }
217
+ declare function createCheckoutProviderCopyEvent(providerId: string): CustomEvent<CheckoutProviderCopyEventDetail>;
218
+ declare function createCheckoutActionEvent(eventName: typeof OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS.copy | typeof OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS.openWallet | typeof OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS.startOver): CustomEvent;
219
+ declare function createCheckoutStateEvent(eventName: typeof OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS.state | typeof OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS.settled, state: CheckoutState): CustomEvent<CheckoutStateEventDetail>;
220
+ declare function createCheckoutErrorEvent(error: unknown): CustomEvent<CheckoutErrorEventDetail>;
221
+ declare function createThemeChangeEvent(theme: ThemeModel): CustomEvent<ThemeChangeEventDetail>;
222
+ declare const OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES: {
223
+ readonly reference: "reference";
224
+ /**
225
+ * Base path the shipped router is mounted at (default `/openreceive`). The
226
+ * element's ONLY URL input: create, prepare, payment-check and the four swap
227
+ * routes are all derived from it. There is deliberately no per-route
228
+ * attribute — see `checkoutRoutes` in ../internal/routes.ts.
229
+ */
230
+ readonly prefix: "prefix";
231
+ /** JSON-encoded create-time metadata forwarded to the create request. */
232
+ readonly metadata: "metadata";
233
+ readonly invoiceId: "invoice-id";
234
+ readonly invoice: "invoice";
235
+ readonly rail: "rail";
236
+ readonly paymentHash: "payment-hash";
237
+ readonly amountMsats: "amount-msats";
238
+ readonly fiatCurrency: "fiat-currency";
239
+ readonly fiatValue: "fiat-value";
240
+ readonly status: "status";
241
+ readonly expiresAt: "expires-at";
242
+ readonly theme: "theme";
243
+ readonly paymentWizard: "payment-wizard";
244
+ /**
245
+ * Opt into History API URL sync to `{resume-path-prefix}/{reference}`.
246
+ * Summary fetch always runs in create mode; this only controls URL mutation.
247
+ */
248
+ readonly syncUrl: "sync-url";
249
+ /** History API path prefix when `sync-url` is set. Default `/checkout`. */
250
+ readonly resumePathPrefix: "resume-path-prefix";
251
+ /**
252
+ * Order id owned by the app router (e.g. Next.js). When set, the element does not
253
+ * push/replace the URL via the History API.
254
+ */
255
+ readonly routeReference: "route-reference";
256
+ /**
257
+ * Base URL of an external bolt11 decoder. When set, the checkout shows a
258
+ * "Decode" link to `{decode-link-url}?invoice={bolt11}`. Omitted (the
259
+ * default), no decode link is rendered and the invoice never leaves the page.
260
+ */
261
+ readonly decodeLinkUrl: "decode-link-url";
262
+ /** `polling="false"` renders the snapshot without status polling (no POST /payments/check). */
263
+ readonly polling: "polling";
264
+ /** Status poll cadence in milliseconds; defaults to OPENRECEIVE_DEFAULT_POLL_INTERVAL_MS. */
265
+ readonly pollIntervalMs: "poll-interval-ms";
266
+ };
267
+ declare const OPENRECEIVE_THEME_TOGGLE_ELEMENT_ATTRIBUTES: {
268
+ readonly rootSelector: "root-selector";
269
+ readonly checkoutSelector: "checkout-selector";
270
+ readonly defaultTheme: "default-theme";
271
+ readonly storageKey: "storage-key";
272
+ };
273
+
274
+ interface TransientFeedbackOptions<T> {
275
+ readonly resetValue: T;
276
+ readonly delayMs?: number;
277
+ readonly setTimeout?: typeof globalThis.setTimeout;
278
+ readonly clearTimeout?: typeof globalThis.clearTimeout;
279
+ readonly onValue: (value: T) => void;
280
+ }
281
+ interface TransientFeedbackController<T> {
282
+ show(value: T): void;
283
+ clear(): void;
284
+ }
285
+ interface TickingValueOptions {
286
+ readonly active?: boolean;
287
+ readonly intervalMs?: number;
288
+ /** Clock returning unix **seconds** ({@link UnixSeconds}), not milliseconds. */
289
+ readonly now?: () => UnixSeconds;
290
+ readonly setInterval?: typeof globalThis.setInterval;
291
+ readonly clearInterval?: typeof globalThis.clearInterval;
292
+ readonly onValue: (value: number) => void;
293
+ }
294
+ interface TickingValueController {
295
+ start(): void;
296
+ stop(): void;
297
+ refresh(): void;
298
+ }
299
+ interface QrEncoder {
300
+ toString(payload: string, options: Record<string, unknown>): Promise<string> | string;
301
+ toDataURL?(payload: string, options: Record<string, unknown>): Promise<string> | string;
302
+ }
303
+ interface QrOptions {
304
+ encoder?: QrEncoder;
305
+ width?: number;
306
+ }
307
+ interface CopyInvoiceOptions {
308
+ invoice: string;
309
+ clipboard?: Pick<Clipboard, "writeText">;
310
+ logger?: BrowserLoggerOption;
311
+ logContext?: BrowserLogContext;
312
+ }
313
+ interface OpenWalletOptions {
314
+ invoice: string;
315
+ open?: (uri: string) => void;
316
+ logger?: BrowserLoggerOption;
317
+ logContext?: BrowserLogContext;
318
+ }
319
+ type BrowserLogLevel = "debug" | "info" | "warn" | "error";
320
+ interface BrowserLogEntry {
321
+ readonly level: BrowserLogLevel;
322
+ readonly event: string;
323
+ readonly message: string;
324
+ readonly [key: string]: unknown;
325
+ }
326
+ type BrowserLogger = (entry: BrowserLogEntry) => void;
327
+ /**
328
+ * Browser logger option. Omit/`undefined` attaches the built-in console logger
329
+ * (honoring `LOG_LEVEL`). Pass `false` to disable OpenReceive browser logs.
330
+ */
331
+ type BrowserLoggerOption = BrowserLogger | false;
332
+ interface BrowserLogContext {
333
+ readonly reference?: string;
334
+ readonly invoice_id?: string;
335
+ readonly payment_hash?: string;
336
+ readonly amount_msats?: number;
337
+ readonly transaction_state?: string;
338
+ readonly workflow_state?: string;
339
+ readonly [key: string]: unknown;
340
+ }
341
+ type CheckoutPhase = "invoice_created" | "verifying" | "settled" | "expired" | "failed" | "cancelled";
342
+ type SwapProviderState = "creating_provider_order" | "awaiting_deposit" | "confirming" | "exchanging" | "paying_invoice" | "completed" | "expired" | "refund_required" | "refund_pending" | "refunded" | "attention" | "failed";
343
+ /**
344
+ * Provider-reported fiat equivalents of both sides of a swap. `pay_in_fiat` is the
345
+ * value of the crypto the payer must send; `payout_fiat` is the cart total delivered
346
+ * to the merchant. Their gap is the swap fee the payer absorbs.
347
+ */
348
+ interface CheckoutInvoiceSwapFee {
349
+ readonly currency: string;
350
+ readonly pay_in_fiat: string;
351
+ readonly payout_fiat: string;
352
+ }
353
+ interface CheckoutInvoiceSwapSnapshot {
354
+ readonly attempt_id?: string;
355
+ readonly provider: string;
356
+ readonly provider_order_id?: string;
357
+ readonly pay_in_asset: string;
358
+ readonly deposit_address: string;
359
+ readonly deposit_memo?: string;
360
+ readonly deposit_amount: string;
361
+ readonly provider_state: SwapProviderState;
362
+ readonly provider_expires_at: number;
363
+ readonly deposit_tx_id?: string;
364
+ readonly payout_tx_id?: string;
365
+ readonly refund_address?: string;
366
+ readonly refund_tx_id?: string;
367
+ readonly attention?: boolean;
368
+ readonly attention_reason?: string;
369
+ readonly refund_reason?: string;
370
+ readonly deposit_received_amount?: string;
371
+ readonly refund_amount?: string;
372
+ readonly fee?: CheckoutInvoiceSwapFee;
373
+ }
374
+ /**
375
+ * Formatted fee breakout for the deposit panel, explaining why the payer sends more
376
+ * than the cart total. All figures are display-ready fiat strings.
377
+ */
378
+ interface SwapFeeBreakdown {
379
+ /** Cart total delivered to the merchant, e.g. "$10.00". */
380
+ readonly cartTotal: string;
381
+ /** Fiat value of the crypto the payer sends, e.g. "$10.59". */
382
+ readonly youSend: string;
383
+ /** The swap fee absorbed by the payer (exchange spread + network fees), e.g. "$0.59". */
384
+ readonly fee: string;
385
+ /** The fee as a percentage of the cart total, e.g. "5.9%", when computable. */
386
+ readonly feePercent?: string;
387
+ }
388
+ interface SwapDisplayModel {
389
+ readonly provider: string;
390
+ readonly attemptId: string;
391
+ readonly payInAsset: string;
392
+ readonly assetLabel: string;
393
+ readonly networkLabel: string;
394
+ /** Strong deposit-panel alert title, e.g. "Wrong currency or network = lost funds". */
395
+ readonly networkWarningTitle: string;
396
+ /** Exact amount + asset + network to emphasize, e.g. "15.01 USDT on the Solana network". */
397
+ readonly networkWarningEmphasis: string;
398
+ /** Full plain-text network warning (accessible / non-HTML consumers). */
399
+ readonly networkWarning: string;
400
+ readonly depositAddress: string;
401
+ readonly depositMemo?: string;
402
+ readonly depositAmount: string;
403
+ readonly providerStateLabel: string;
404
+ readonly providerStateDetail: string;
405
+ readonly state: "creating" | "deposit" | "progress" | "settled" | "expired" | "refund_required" | "refund_pending" | "refunded" | "attention" | "failed";
406
+ readonly expiresInSeconds: number;
407
+ readonly countdownLabel: string;
408
+ readonly qrPayload: string;
409
+ /** Ready-to-render fee breakout, present when the provider reported fiat equivalents. */
410
+ readonly feeBreakdown?: SwapFeeBreakdown;
411
+ readonly depositTxId?: string;
412
+ readonly payoutTxId?: string;
413
+ readonly refundAddress?: string;
414
+ /**
415
+ * Whether the refund form may be submitted. The review-then-confirm gate is
416
+ * entirely client-side: OpenReceive mints no refund tokens, the server sends
417
+ * none, and the confirmed request carries only reference, payment_hash, and
418
+ * refund_address.
419
+ */
420
+ readonly refundAllowed: boolean;
421
+ readonly refundTxId?: string;
422
+ readonly refundReason?: string;
423
+ readonly depositReceivedAmount?: string;
424
+ readonly refundAmount?: string;
425
+ readonly providerOrderId?: string;
426
+ }
427
+ interface CheckoutInvoiceSnapshot {
428
+ readonly invoice_id: string;
429
+ readonly invoice?: string | null;
430
+ readonly rail: "lightning" | "swap" | "checkout_lock";
431
+ readonly payment_hash?: string;
432
+ readonly amount_msats?: number;
433
+ readonly fiat_quote?: {
434
+ readonly fiat?: {
435
+ readonly currency?: string;
436
+ readonly value?: string;
437
+ };
438
+ } | null;
439
+ readonly transaction_state?: string;
440
+ readonly workflow_state?: string;
441
+ readonly expires_at?: number;
442
+ readonly settled_at?: number;
443
+ readonly swap?: CheckoutInvoiceSwapSnapshot;
444
+ }
445
+ interface CheckoutPaymentMethod {
446
+ readonly pay_in_asset: string;
447
+ readonly label: string;
448
+ readonly network_label: string;
449
+ readonly provider: string;
450
+ readonly available: boolean;
451
+ readonly unavailable_reason?: string;
452
+ readonly unavailable_message?: string;
453
+ readonly pay_amount?: string;
454
+ readonly minimum_pay_amount?: string;
455
+ readonly maximum_pay_amount?: string;
456
+ readonly minimum_invoice_amount_msats?: number;
457
+ readonly maximum_invoice_amount_msats?: number;
458
+ }
459
+ /**
460
+ * Client-side snapshot of one Checkout (the server's `Checkout` /
461
+ * the wire's `WireCheckout`), aggregated across its payment
462
+ * attempts as the browser polls. Snake_case because it holds wire data
463
+ * verbatim.
464
+ */
465
+ interface CheckoutSnapshot {
466
+ readonly checkout_id: string;
467
+ readonly reference: string;
468
+ readonly status: "open" | "paid" | "expired";
469
+ readonly paid_at?: number;
470
+ readonly amount_msats: number;
471
+ readonly fiat?: {
472
+ readonly currency: string;
473
+ readonly value: string;
474
+ };
475
+ readonly active?: CheckoutInvoiceSnapshot;
476
+ readonly invoices: readonly CheckoutInvoiceSnapshot[];
477
+ readonly payment_methods?: readonly CheckoutPaymentMethod[];
478
+ }
479
+ interface CheckoutElementAttributeOptions {
480
+ /**
481
+ * Order id for create mode. When no checkout snapshot is supplied, the element is rendered
482
+ * with this as its `reference` attribute (paired with `prefix`) and owns the whole
483
+ * create/poll lifecycle itself. Ignored when a snapshot is supplied — the snapshot's
484
+ * `reference` wins.
485
+ */
486
+ readonly reference?: string;
487
+ /**
488
+ * Base path the shipped router is mounted at. Emitted as the element's `prefix` attribute
489
+ * so a create-mode element (`reference` with no `invoice`) can derive its create/order
490
+ * routes without spelling them out.
491
+ */
492
+ readonly prefix?: string;
493
+ /**
494
+ * Optional create-time metadata (parity with the React `<Checkout metadata>`
495
+ * prop): JSON-encoded onto the element's `metadata` attribute and sent with
496
+ * the Lightning mint request.
497
+ */
498
+ readonly metadata?: Record<string, unknown>;
499
+ readonly theme?: ResolvedTheme;
500
+ readonly paymentWizard?: boolean;
501
+ /**
502
+ * Opt into History API URL sync to `{resumePathPrefix}/{reference}` (default `/checkout/:id`).
503
+ * This controls URL mutation only; order-resume data remains a host concern.
504
+ */
505
+ readonly syncUrl?: boolean;
506
+ /** History API path prefix when `syncUrl` is set. Default `/checkout`. */
507
+ readonly resumePathPrefix?: string;
508
+ /**
509
+ * Order id from the app router (e.g. Next.js). When set, skip History API URL sync.
510
+ */
511
+ readonly routeReference?: string;
512
+ /**
513
+ * Base URL of an external bolt11 decoder. Omitted (the default), the element
514
+ * renders no "Decode" link and the invoice is never sent to a third party.
515
+ */
516
+ readonly decodeLinkUrl?: string;
517
+ /** False renders the snapshot without status polling (no POST /payments/check). */
518
+ readonly polling?: boolean;
519
+ /** Status poll cadence in milliseconds; defaults to OPENRECEIVE_DEFAULT_POLL_INTERVAL_MS. */
520
+ readonly pollIntervalMs?: number;
521
+ }
522
+ interface ThemeToggleElementAttributeOptions {
523
+ readonly rootSelector?: string;
524
+ readonly checkoutSelector?: string;
525
+ readonly defaultTheme?: ThemePreference;
526
+ readonly storageKey?: string;
527
+ }
528
+ type CheckoutElementAttributeName = (typeof OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES)[keyof typeof OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES];
529
+ type CheckoutElementAttributes = Partial<Record<CheckoutElementAttributeName, string>>;
530
+ type ThemeToggleElementAttributeName = (typeof OPENRECEIVE_THEME_TOGGLE_ELEMENT_ATTRIBUTES)[keyof typeof OPENRECEIVE_THEME_TOGGLE_ELEMENT_ATTRIBUTES];
531
+ type ThemeToggleElementAttributes = Partial<Record<ThemeToggleElementAttributeName, string>>;
532
+ interface CheckoutElementEventHandlers {
533
+ readonly onCopy?: (event: Event) => void;
534
+ readonly onOpenWallet?: (event: Event) => void;
535
+ readonly onState?: (event: Event) => void;
536
+ readonly onSettled?: (event: Event) => void;
537
+ readonly onProviderCopy?: (event: Event) => void;
538
+ readonly onStartOver?: (event: Event) => void;
539
+ readonly onError?: (event: Event) => void;
540
+ }
541
+ type CheckoutElementListeners = Partial<Record<CheckoutElementEventName, (event: Event) => void>>;
542
+ interface CheckoutShellOptions extends Omit<CheckoutElementAttributeOptions, "theme">, CheckoutElementEventHandlers, StoredThemeModelOptions {
543
+ readonly rootSelector?: string;
544
+ readonly checkoutSelector?: string;
545
+ /**
546
+ * When false, omit the package theme toggle and do not stamp `data-theme` on the
547
+ * shell root or checkout. The checkout inherits from an ancestor `[data-theme]`
548
+ * (e.g. React `ThemeScope`). Default true for standalone embeds.
549
+ */
550
+ readonly themeToggle?: boolean;
551
+ }
552
+ interface CheckoutShellCheckoutBinding {
553
+ readonly tagName: typeof OPENRECEIVE_CHECKOUT_ELEMENT_TAG_NAME;
554
+ readonly attributes: CheckoutElementAttributes;
555
+ readonly listeners: CheckoutElementListeners;
556
+ }
557
+ interface CheckoutShellThemeToggleBinding {
558
+ readonly tagName: typeof OPENRECEIVE_THEME_TOGGLE_ELEMENT_TAG_NAME;
559
+ readonly attributes: ThemeToggleElementAttributes;
560
+ }
561
+ interface CheckoutShellModel {
562
+ readonly theme: ThemeModel;
563
+ readonly rootAttributes: Partial<ThemeModel["attributes"]>;
564
+ readonly checkout: CheckoutShellCheckoutBinding;
565
+ readonly themeToggle: CheckoutShellThemeToggleBinding | null;
566
+ }
567
+ interface CheckoutElementDocument {
568
+ createElement(tagName: string): HTMLElement;
569
+ }
570
+ interface CreateOpenReceiveThemeToggleElementOptions extends ThemeToggleElementAttributeOptions {
571
+ readonly document?: CheckoutElementDocument;
572
+ }
573
+ interface CreateCheckoutShellOptions extends CheckoutShellOptions {
574
+ readonly document?: CheckoutElementDocument;
575
+ readonly root?: ThemeAttributeTarget | null;
576
+ }
577
+ interface CheckoutShellElements {
578
+ readonly theme: ThemeModel;
579
+ readonly rootAttributes: Partial<ThemeModel["attributes"]>;
580
+ readonly checkout: HTMLElement;
581
+ readonly themeToggle: HTMLElement | null;
582
+ }
583
+ /**
584
+ * The ONE derived view of a checkout: a snapshot plus a clock, flattened onto
585
+ * the attempt the payer is looking at, with the phase machine's verdict and the
586
+ * labels the UI prints. Produced only by `createCheckoutState`.
587
+ *
588
+ * It extends {@link CheckoutStateLabels}, so the labels ship with the state —
589
+ * including in the `openreceive-state` CustomEvent's `detail.state`.
590
+ */
591
+ interface CheckoutState extends CheckoutStateLabels {
592
+ readonly checkout_id: string;
593
+ readonly reference: string;
594
+ readonly invoice_id: string;
595
+ readonly invoice: string;
596
+ readonly rail: "lightning" | "swap" | "checkout_lock";
597
+ readonly lightning_uri: string;
598
+ readonly payment_hash?: string;
599
+ readonly amount_msats?: number;
600
+ readonly fiat_quote?: CheckoutInvoiceSnapshot["fiat_quote"];
601
+ readonly transaction_state: string;
602
+ readonly workflow_state: string;
603
+ readonly expires_at?: number;
604
+ readonly expires_in_seconds?: number;
605
+ readonly phase: CheckoutPhase;
606
+ readonly settled: boolean;
607
+ readonly terminal: boolean;
608
+ readonly paid: boolean;
609
+ readonly settled_at?: number;
610
+ readonly swap?: CheckoutInvoiceSwapSnapshot;
611
+ }
612
+ interface CheckoutStatusModelInput {
613
+ readonly phase?: CheckoutPhase;
614
+ readonly waiting?: boolean;
615
+ readonly expires_in_seconds?: number;
616
+ }
617
+ interface CheckoutStatusModel {
618
+ readonly phase: CheckoutPhase;
619
+ readonly waiting: boolean;
620
+ readonly title: string;
621
+ readonly detail: string;
622
+ readonly countdownPrefix: string;
623
+ readonly expires_in_seconds?: number;
624
+ readonly countdownLabel?: string;
625
+ }
626
+ type CheckoutStatusRefresh = (reference: string) => Promise<CheckoutSnapshot | null>;
627
+ interface RequestCheckoutOptions extends RequestCheckoutBaseOptions {
628
+ /**
629
+ * The snapshot already on screen — normally what {@link prepareCheckout}
630
+ * returned, or the running snapshot after an earlier attempt.
631
+ *
632
+ * `POST /checkouts` answers with the minted bolt11 alone; it does NOT carry
633
+ * the warmed `payment_methods` catalog that prepare returned. Without this,
634
+ * minting Lightning ERASES the method list a picker renders from: the payer
635
+ * selects Bitcoin, changes their mind, and the swap options are gone.
636
+ * Passing the previous snapshot folds the mint into it, keeping
637
+ * `payment_methods` and any sibling attempts.
638
+ */
639
+ readonly previous?: CheckoutSnapshot;
640
+ }
641
+ /**
642
+ * `prepareCheckout` posts only the order id — it locks the amount and lists
643
+ * payment methods without minting — so there is no memo or metadata to carry.
644
+ */
645
+ type PrepareCheckoutOptions = Pick<RequestCheckoutBaseOptions, "prefix" | "reference" | "fetch" | "headers">;
646
+ interface RequestCheckoutBaseOptions {
647
+ /**
648
+ * Base path the shipped router is mounted at (e.g. `/openreceive`). The create and
649
+ * prepare routes are derived from it — see {@link checkoutRoutes}. It is required
650
+ * because it is the only URL input: there is no per-route override.
651
+ */
652
+ readonly prefix: string;
653
+ readonly reference: string;
654
+ readonly fetch?: typeof globalThis.fetch;
655
+ readonly headers?: Readonly<Record<string, string>>;
656
+ readonly memo?: string;
657
+ readonly metadata?: Record<string, unknown>;
658
+ }
659
+ interface CreateOpenReceiveStatusFetcherOptions {
660
+ /**
661
+ * Base path the shipped router is mounted at. The fetcher polls
662
+ * `${prefix}/payments/check` and reads live swap state from
663
+ * `${prefix}/swaps/status` — see {@link checkoutRoutes}.
664
+ */
665
+ readonly prefix: string;
666
+ readonly snapshot: CheckoutSnapshot;
667
+ readonly fetch?: typeof globalThis.fetch;
668
+ readonly headers?: Readonly<Record<string, string>>;
669
+ }
670
+ interface CheckoutWatcherOptions {
671
+ readonly snapshot: CheckoutSnapshot;
672
+ readonly refreshStatus?: CheckoutStatusRefresh;
673
+ readonly pollIntervalMs?: number;
674
+ /** Clock returning unix **seconds** ({@link UnixSeconds}), not milliseconds. */
675
+ readonly now?: () => UnixSeconds;
676
+ readonly setInterval?: typeof globalThis.setInterval;
677
+ readonly clearInterval?: typeof globalThis.clearInterval;
678
+ readonly logger?: BrowserLoggerOption;
679
+ readonly onState: (state: CheckoutState) => void;
680
+ readonly onSnapshot?: (snapshot: CheckoutSnapshot) => void;
681
+ readonly onError?: (error: unknown) => void;
682
+ }
683
+ interface CheckoutControllerOptions extends Omit<CheckoutWatcherOptions, "onState"> {
684
+ readonly onState?: (state: CheckoutState) => void;
685
+ /**
686
+ * Base path the shipped router is mounted at. Omitted, the controller does no
687
+ * status polling of its own — pass `refreshStatus` instead, or nothing at all
688
+ * to render a snapshot without polling.
689
+ */
690
+ readonly prefix?: string;
691
+ readonly fetch?: typeof globalThis.fetch;
692
+ readonly statusHeaders?: Readonly<Record<string, string>>;
693
+ readonly clipboard?: Pick<Clipboard, "writeText">;
694
+ readonly open?: (uri: string) => void;
695
+ }
696
+ interface CheckoutController {
697
+ start(): CheckoutState;
698
+ stop(): void;
699
+ getState(): CheckoutState | undefined;
700
+ reloadState(): Promise<CheckoutState>;
701
+ /**
702
+ * Stop all timers and mark the checkout `cancelled`: the returned state (and
703
+ * every later `getState()`) carries the terminal `cancelled` phase.
704
+ */
705
+ cancel(): CheckoutState;
706
+ copyInvoice(): Promise<void>;
707
+ openWallet(): string;
708
+ }
709
+ interface CreateCheckoutStateOptions {
710
+ /**
711
+ * Unix timestamp in **seconds** ({@link UnixSeconds}) the expiry clock is
712
+ * measured against; defaults to the current time. Milliseconds
713
+ * (`Date.now()`) throw a RangeError — see the type.
714
+ */
715
+ readonly now?: UnixSeconds;
716
+ readonly logger?: BrowserLoggerOption;
717
+ /**
718
+ * How this state was produced. Controls which browser log events fire:
719
+ * - `create` (default): `checkout.state.created`
720
+ * - `refresh`: `checkout.state.refreshed` plus `swap.state.changed` when swap fields move
721
+ * - `countdown`: no log (avoids per-second spam from the expiry ticker)
722
+ */
723
+ readonly source?: "create" | "refresh" | "countdown";
724
+ /** Prior checkout state; used with `source: "refresh"` to emit swap transition audits. */
725
+ readonly previousState?: CheckoutState;
726
+ }
727
+ type PaymentMethod = "bitcoin";
728
+ type ThemePreference = "light" | "dark" | "system";
729
+ type ResolvedTheme = "light" | "dark";
730
+ interface PaymentMethodOption {
731
+ readonly id: PaymentMethod;
732
+ readonly title: string;
733
+ readonly detail: string;
734
+ }
735
+ interface ParseOpenReceiveOptionalIntegerOptions {
736
+ readonly label?: string;
737
+ }
738
+ interface ThemeModelOptions {
739
+ readonly systemDark?: boolean;
740
+ }
741
+ interface ThemeStorageOptions {
742
+ readonly storage?: Storage;
743
+ readonly storageKey?: string;
744
+ }
745
+ interface ReadThemePreferenceOptions extends ThemeStorageOptions {
746
+ readonly defaultTheme?: ThemePreference;
747
+ }
748
+ interface StoredThemeModelOptions extends ReadThemePreferenceOptions, ThemeModelOptions {
749
+ }
750
+ interface ThemeAttributeTarget {
751
+ getAttribute(name: string): string | null;
752
+ setAttribute(name: string, value: string): void;
753
+ }
754
+ interface ThemeLabelTarget {
755
+ textContent: string | null;
756
+ }
757
+ interface ThemeControlTargets {
758
+ readonly root?: ThemeAttributeTarget | null;
759
+ readonly checkout?: ThemeAttributeTarget | null;
760
+ readonly toggle?: ThemeLabelTarget | null;
761
+ }
762
+ interface ThemeModel {
763
+ readonly theme: ThemePreference;
764
+ readonly resolvedTheme: ResolvedTheme;
765
+ readonly nextTheme: ThemePreference;
766
+ readonly toggleLabel: string;
767
+ readonly attributes: {
768
+ readonly "data-theme": ResolvedTheme;
769
+ readonly "data-openreceive-theme": ResolvedTheme;
770
+ };
771
+ readonly checkoutElementAttributes: {
772
+ readonly theme: ResolvedTheme;
773
+ };
774
+ }
775
+ interface PaymentWizardSelection {
776
+ readonly selectedMethod: PaymentMethod | null;
777
+ readonly selectedBitcoinRoute: string | null;
778
+ }
779
+ type PaymentWizardSelectionAction = {
780
+ readonly type: "select_method";
781
+ readonly method: PaymentMethod;
782
+ } | {
783
+ readonly type: "change_method";
784
+ } | {
785
+ readonly type: "change_route";
786
+ } | {
787
+ readonly type: "select_route";
788
+ readonly route: string;
789
+ };
790
+ interface PaymentWizardState {
791
+ readonly selectedRouteId: string | null;
792
+ readonly routes: readonly PaymentWizardRoute[];
793
+ }
794
+ interface PaymentWizardModel {
795
+ readonly selection: PaymentWizardSelection;
796
+ readonly wizard: PaymentWizardState;
797
+ readonly routeAssets: readonly AssetIndexEntry[];
798
+ readonly selectedRoute: string | null;
799
+ }
800
+ interface PaymentWizardControllerOptions {
801
+ readonly selection?: PaymentWizardSelection;
802
+ readonly onSelection?: (selection: PaymentWizardSelection) => void;
803
+ }
804
+ interface PaymentWizardController {
805
+ getSelection(): PaymentWizardSelection;
806
+ getModel(): PaymentWizardModel;
807
+ update(action: PaymentWizardSelectionAction): PaymentWizardSelection;
808
+ selectMethod(method: PaymentMethod): PaymentWizardSelection;
809
+ changeMethod(): PaymentWizardSelection;
810
+ selectRoute(route: string): PaymentWizardSelection;
811
+ }
812
+ interface WizardRouteAssetDisplay {
813
+ readonly id: string;
814
+ readonly label: string;
815
+ readonly subtitle: string;
816
+ readonly icon: string;
817
+ readonly selected: boolean;
818
+ }
819
+ interface WizardProviderTutorialDisplay {
820
+ readonly index: number;
821
+ readonly path: string;
822
+ readonly image: string;
823
+ readonly caption: string;
824
+ }
825
+ interface WizardProviderDisplay {
826
+ readonly id: string;
827
+ readonly name: string;
828
+ readonly kind: string;
829
+ readonly url: string;
830
+ readonly icon: string;
831
+ readonly tutorials: readonly WizardProviderTutorialDisplay[];
832
+ readonly copyLabel: string;
833
+ readonly copiedLabel: string;
834
+ readonly openLabel: string;
835
+ }
836
+ interface WizardRouteDisplay {
837
+ readonly key: string;
838
+ readonly title: string;
839
+ readonly subtitle: string;
840
+ readonly providers: readonly WizardProviderDisplay[];
841
+ }
842
+ /**
843
+ * One display row for post-settlement transaction details. Values are already
844
+ * formatted for UI; `copyValue` is the full string when the display value is truncated.
845
+ * Never includes NWC secrets — those are not part of checkout public state.
846
+ * Optional `href` is a block-explorer or Lightning invoice decode link.
847
+ */
848
+ interface TransactionDetailRow {
849
+ readonly label: string;
850
+ readonly value: string;
851
+ readonly copyValue?: string;
852
+ readonly href?: string;
853
+ readonly hrefLabel?: string;
854
+ }
855
+ interface TransactionDetailsInput {
856
+ readonly reference?: string;
857
+ readonly checkout_id?: string;
858
+ readonly invoice_id?: string;
859
+ readonly invoice?: string | null;
860
+ readonly rail?: "lightning" | "swap" | "checkout_lock";
861
+ readonly payment_hash?: string;
862
+ readonly amount_msats?: number;
863
+ readonly fiat_quote?: CheckoutInvoiceSnapshot["fiat_quote"];
864
+ readonly transaction_state?: string;
865
+ readonly workflow_state?: string;
866
+ readonly expires_at?: number;
867
+ readonly settled_at?: number;
868
+ readonly swap?: CheckoutInvoiceSwapSnapshot;
869
+ /**
870
+ * Base URL of a host-chosen bolt11 decoder. Omitted (the default), the
871
+ * Lightning invoice row carries no decode link and the invoice is never
872
+ * handed to a third party.
873
+ */
874
+ readonly decodeLinkUrl?: string;
875
+ }
876
+
877
+ declare function assertDisplayInvoice(invoice: string): void;
878
+ declare function createLightningUri(invoice: string): string;
879
+
880
+ declare class BrowserRequestError extends Error {
881
+ readonly status: number;
882
+ readonly code?: string;
883
+ readonly retryable?: boolean;
884
+ readonly retryAfterSeconds?: number;
885
+ constructor(message: string, options: {
886
+ readonly status: number;
887
+ readonly code?: string;
888
+ readonly retryable?: boolean;
889
+ readonly retryAfterSeconds?: number;
890
+ });
891
+ }
892
+ declare function requestCheckout(options: RequestCheckoutOptions): Promise<CheckoutSnapshot>;
893
+ /**
894
+ * Lock the host order amount and load payment methods without minting Lightning.
895
+ * Bitcoin selection later calls {@link requestCheckout} to mint (or reuse) a bolt11.
896
+ */
897
+ declare function prepareCheckout(options: PrepareCheckoutOptions): Promise<CheckoutSnapshot>;
898
+ declare function createStatusFetcher(options: CreateOpenReceiveStatusFetcherOptions): CheckoutStatusRefresh;
899
+
900
+ declare function createQrSvg(invoice: string, options?: QrOptions): Promise<string>;
901
+ declare function createQrPayloadSvg(payload: string, options?: QrOptions): Promise<string>;
902
+ declare function createQrPngDataUrl(invoice: string, options?: QrOptions): Promise<string>;
903
+ declare function copyInvoice(options: CopyInvoiceOptions): Promise<void>;
904
+ declare function openWallet(options: OpenWalletOptions): string;
905
+
906
+ declare function createCheckoutController(options: CheckoutControllerOptions): CheckoutController;
907
+
908
+ /**
909
+ * Guest checkout resume helpers for no-account content sites.
910
+ *
911
+ * Pattern:
912
+ * - Put the public `reference` in the URL (`/checkout/:reference`) so refresh/share works.
913
+ * - Let the host authorize access to the order using its normal session or guest-order policy.
914
+ * - Mirror an optional host order summary in sessionStorage for instant same-tab restore;
915
+ * use the host-supplied `fetchOrder` when storage is empty.
916
+ *
917
+ */
918
+ interface GuestCheckoutResumeOptions<TOrder> {
919
+ /**
920
+ * URL path prefix before the order id. Default `"/checkout"` → `/checkout/:reference`.
921
+ * Leading/trailing slashes are normalized.
922
+ */
923
+ readonly pathPrefix?: string;
924
+ /** sessionStorage key prefix for host order summaries (required so hosts do not collide). */
925
+ readonly storageKeyPrefix: string;
926
+ /** Extract the public order id used as the storage/URL key. */
927
+ readonly referenceOf: (order: TOrder) => string;
928
+ /** Validate a value from storage or a fetch body as a host order. */
929
+ readonly parseOrder: (value: unknown) => TOrder | undefined;
930
+ /**
931
+ * Load an order when sessionStorage misses (new tab / shared link).
932
+ * Return `undefined` for missing or unauthorized orders.
933
+ */
934
+ readonly fetchOrder?: (reference: string) => Promise<TOrder | undefined>;
935
+ /** Path to push when leaving a checkout URL. Default `"/"`. */
936
+ readonly homePath?: string;
937
+ }
938
+ interface GuestCheckoutResumeController<TOrder> {
939
+ /** Normalized path prefix including a leading slash, e.g. `"/checkout"`. */
940
+ readonly pathPrefix: string;
941
+ checkoutPath(reference: string): string;
942
+ /** Parse `/checkout/:reference` from a pathname. Returns undefined when not a resume URL. */
943
+ parseReference(pathname: string): string | undefined;
944
+ rememberOrder(order: TOrder): void;
945
+ readRememberedOrder(reference: string): TOrder | undefined;
946
+ /** Forget one order, or every order under this storage prefix when `reference` is omitted. */
947
+ forgetOrder(reference?: string): void;
948
+ /** Push the checkout path when not already there (History API / SPAs). */
949
+ enterCheckout(reference: string): void;
950
+ /** Return to `homePath` when the current location is a checkout resume URL. */
951
+ leaveCheckout(): void;
952
+ /** sessionStorage first, then optional `fetchOrder`. */
953
+ loadOrderForResume(reference: string): Promise<TOrder | undefined>;
954
+ }
955
+ /**
956
+ * Create a host-owned guest resume controller. OpenReceive does not invent a host session —
957
+ * this is the reusable URL + sessionStorage glue so demos (and apps) do not copy-paste it.
958
+ */
959
+ declare function createGuestCheckoutResume<TOrder>(options: GuestCheckoutResumeOptions<TOrder>): GuestCheckoutResumeController<TOrder>;
960
+ /**
961
+ * Push `/checkout/:reference` (or a custom path prefix) via the History API when not already
962
+ * there. Used by `<Checkout syncUrl>` and hosts that sync the URL after creating an order.
963
+ * No-ops when `routeReference` is provided (app router already owns the URL).
964
+ */
965
+ declare function enterCheckoutResumePath(reference: string, options?: {
966
+ readonly pathPrefix?: string;
967
+ /** When set, skip History API sync (Next.js / file-based routes own the URL). */
968
+ readonly routeReference?: string;
969
+ }): void;
970
+ /**
971
+ * Guest resume fetch for a host-owned order endpoint. OpenReceive ships no order-read route.
972
+ * Pass the result as `fetchOrder` to {@link createGuestCheckoutResume}.
973
+ */
974
+ declare function createGuestOrderFetcher<TOrder>(options: {
975
+ readonly parseOrder: (value: unknown) => TOrder | undefined;
976
+ /**
977
+ * Build the URL of the HOST APPLICATION's own order endpoint (e.g. `/orders/:id`).
978
+ * Nothing here is an OpenReceive route: the mounted router's routes all come from
979
+ * `prefix` (see ./routes.ts), and it serves no order-read endpoint at all.
980
+ */
981
+ readonly hostOrderUrl: (reference: string) => string;
982
+ readonly fetch?: typeof globalThis.fetch;
983
+ }): (reference: string) => Promise<TOrder | undefined>;
984
+
985
+ /** The payer-facing status: exactly {@link TransactionSettlementStatus}, derived from the server's verdict and the expiry clock. */
986
+ type Status = TransactionSettlementStatus;
987
+ interface StatusInvoiceLike {
988
+ readonly transaction_state?: string;
989
+ readonly expires_at?: number | string | null;
990
+ }
991
+ /**
992
+ * @param options.now Unix timestamp in **seconds** ({@link UnixSeconds}) to
993
+ * compare `expires_at` against; defaults to the current time. Milliseconds
994
+ * (`Date.now()`) throw a RangeError rather than reading every invoice as
995
+ * expired.
996
+ */
997
+ declare function deriveStatus(invoice: StatusInvoiceLike, options?: {
998
+ readonly now?: UnixSeconds;
999
+ }): Status;
1000
+
1001
+ export { type CheckoutStatusRefresh as $, type ThemeToggleElementAttributes as A, type BrowserLoggerOption as B, type CheckoutInvoiceSnapshot as C, type StoredThemeModelOptions as D, type ThemeModel as E, type ThemeModelOptions as F, type ReadThemePreferenceOptions as G, type ThemeControlTargets as H, type ThemeStorageOptions as I, type PaymentWizardControllerOptions as J, type PaymentWizardController as K, type PaymentWizardSelection as L, type PaymentWizardModel as M, type WizardRouteDisplay as N, type PaymentWizardSelectionAction as O, type ParseOpenReceiveOptionalIntegerOptions as P, type BrowserLogContext as Q, type ResolvedTheme as R, type SwapDisplayModel as S, type ThemePreference as T, type UnixSeconds as U, type BrowserLogger as V, type WizardRouteAssetDisplay as W, BrowserRequestError as X, type CheckoutController as Y, type CheckoutControllerOptions as Z, type CheckoutPhase as _, type PaymentMethod as a, OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES as a0, OPENRECEIVE_CHECKOUT_DATA_SELECTORS as a1, OPENRECEIVE_CHECKOUT_ELEMENT_ATTRIBUTES as a2, OPENRECEIVE_CHECKOUT_ELEMENT_EVENTS as a3, OPENRECEIVE_CHECKOUT_ELEMENT_PARTS as a4, OPENRECEIVE_CHECKOUT_ELEMENT_PART_SELECTORS as a5, OPENRECEIVE_CHECKOUT_ELEMENT_TAG_NAME as a6, OPENRECEIVE_COPY_FEEDBACK_MS as a7, OPENRECEIVE_DEFAULT_POLL_INTERVAL_MS as a8, OPENRECEIVE_DEFAULT_PREFIX as a9, formatAmountCaption as aA, formatDepositAmount as aB, formatFiatAmount as aC, formatMsats as aD, formatSwapLimit as aE, formatUnixTime as aF, openWallet as aG, prepareCheckout as aH, requestCheckout as aI, type BrowserLogLevel as aJ, type BrowserLogEntry as aK, type CopyInvoiceOptions as aL, type GuestCheckoutResumeController as aM, type GuestCheckoutResumeOptions as aN, type OpenWalletOptions as aO, type PrepareCheckoutOptions as aP, type QrOptions as aQ, type RequestCheckoutOptions as aR, type StatusInvoiceLike as aS, createGuestCheckoutResume as aT, createGuestOrderFetcher as aU, createLightningUri as aV, createQrPngDataUrl as aW, OPENRECEIVE_PAYMENT_WIZARD_ATTRIBUTES as aa, OPENRECEIVE_PAYMENT_WIZARD_SELECTORS as ab, OPENRECEIVE_THEME_STORAGE_KEY as ac, OPENRECEIVE_THEME_TOGGLE_ELEMENT_ATTRIBUTES as ad, OPENRECEIVE_THEME_TOGGLE_ELEMENT_EVENTS as ae, OPENRECEIVE_THEME_TOGGLE_ELEMENT_PARTS as af, OPENRECEIVE_THEME_TOGGLE_ELEMENT_PART_SELECTORS as ag, OPENRECEIVE_THEME_TOGGLE_ELEMENT_TAG_NAME as ah, type QrEncoder as ai, type Status as aj, type WizardProviderDisplay as ak, assertDisplayInvoice as al, copyInvoice as am, createCheckoutActionEvent as an, createCheckoutController as ao, createCheckoutErrorEvent as ap, createCheckoutProviderCopyEvent as aq, createCheckoutStateEvent as ar, createQrPayloadSvg as as, createQrSvg as at, createStatusFetcher as au, createThemeChangeEvent as av, deriveCheckoutStateLabels as aw, deriveStatus as ax, enterCheckoutResumePath as ay, escapeHtml as az, type PaymentMethodOption as b, type TickingValueOptions as c, type TickingValueController as d, type TransientFeedbackOptions as e, type TransientFeedbackController as f, type CheckoutInvoiceSwapSnapshot as g, type CheckoutState as h, type TransactionDetailsInput as i, type TransactionDetailRow as j, type CheckoutSnapshot as k, type CreateCheckoutStateOptions as l, type CheckoutStatusModelInput as m, type CheckoutStatusModel as n, type CheckoutPaymentMethod as o, type ThemeAttributeTarget as p, type CheckoutElementAttributes as q, type CheckoutElementAttributeOptions as r, type CheckoutElementEventHandlers as s, type CheckoutElementListeners as t, type CreateCheckoutShellOptions as u, type CheckoutShellElements as v, type CheckoutShellOptions as w, type CheckoutShellModel as x, type CreateOpenReceiveThemeToggleElementOptions as y, type ThemeToggleElementAttributeOptions as z };