@openreceive/react 0.2.3 → 0.3.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/dist/index.d.ts +36 -9
- package/dist/index.js +386 -330
- package/dist/styles.css +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -56,7 +56,6 @@ import {
|
|
|
56
56
|
OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES,
|
|
57
57
|
copyInvoice as copyInvoiceHelper,
|
|
58
58
|
createCheckoutStatusModel,
|
|
59
|
-
createPaymentDataEntries,
|
|
60
59
|
createQrSvg,
|
|
61
60
|
formatAmountCaption,
|
|
62
61
|
checkoutLabels,
|
|
@@ -320,31 +319,6 @@ function SettledCheckIcon() {
|
|
|
320
319
|
})
|
|
321
320
|
);
|
|
322
321
|
}
|
|
323
|
-
function PaymentData(props) {
|
|
324
|
-
const entries = createPaymentDataEntries(props.source);
|
|
325
|
-
if (entries.length === 0) return null;
|
|
326
|
-
return React3.createElement(
|
|
327
|
-
"details",
|
|
328
|
-
{ className: joinClassNames(orClasses.paymentData, props.className) },
|
|
329
|
-
React3.createElement(
|
|
330
|
-
"summary",
|
|
331
|
-
{ className: orClasses.paymentDataTitle },
|
|
332
|
-
checkoutLabels.viewPaymentData
|
|
333
|
-
),
|
|
334
|
-
React3.createElement(
|
|
335
|
-
"div",
|
|
336
|
-
{ className: orClasses.paymentDataBody },
|
|
337
|
-
entries.map(
|
|
338
|
-
(entry) => React3.createElement(
|
|
339
|
-
"div",
|
|
340
|
-
{ key: entry.label, className: orClasses.paymentDataRow },
|
|
341
|
-
React3.createElement("span", { className: orClasses.paymentDataKey }, entry.label),
|
|
342
|
-
React3.createElement("p", { className: orClasses.paymentDataValue }, entry.value)
|
|
343
|
-
)
|
|
344
|
-
)
|
|
345
|
-
)
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
322
|
function WaitingState(props) {
|
|
349
323
|
const status = props.status ?? createCheckoutStatusModel({
|
|
350
324
|
phase: props.phase,
|
|
@@ -447,17 +421,106 @@ function SatsDetail(props) {
|
|
|
447
421
|
);
|
|
448
422
|
}
|
|
449
423
|
|
|
450
|
-
// src/
|
|
424
|
+
// src/transaction-details.ts
|
|
425
|
+
import {
|
|
426
|
+
checkoutLabels as checkoutLabels2,
|
|
427
|
+
orClasses as orClasses2,
|
|
428
|
+
resolveTransactionDetailRows
|
|
429
|
+
} from "@openreceive/browser/headless";
|
|
451
430
|
import * as React4 from "react";
|
|
431
|
+
function TransactionDetails(props) {
|
|
432
|
+
const rows = resolveTransactionDetailRows(props.state);
|
|
433
|
+
if (rows.length === 0) return null;
|
|
434
|
+
return React4.createElement(
|
|
435
|
+
"details",
|
|
436
|
+
{
|
|
437
|
+
className: joinClassNames(orClasses2.transactionDetails, props.className),
|
|
438
|
+
open: props.open === true ? true : void 0
|
|
439
|
+
},
|
|
440
|
+
React4.createElement(
|
|
441
|
+
"summary",
|
|
442
|
+
{ className: orClasses2.transactionDetailsTitle },
|
|
443
|
+
checkoutLabels2.transactionDetails
|
|
444
|
+
),
|
|
445
|
+
React4.createElement(
|
|
446
|
+
"div",
|
|
447
|
+
{ className: orClasses2.transactionDetailsContent },
|
|
448
|
+
React4.createElement(
|
|
449
|
+
"dl",
|
|
450
|
+
{ className: orClasses2.swapDetails },
|
|
451
|
+
rows.flatMap(
|
|
452
|
+
(row) => renderTransactionDetailRow(row, {
|
|
453
|
+
clipboard: props.clipboard,
|
|
454
|
+
onError: props.onError
|
|
455
|
+
})
|
|
456
|
+
)
|
|
457
|
+
)
|
|
458
|
+
)
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
function renderTransactionDetailRow(row, options) {
|
|
462
|
+
const copyValue = row.copyValue ?? row.value;
|
|
463
|
+
return [
|
|
464
|
+
React4.createElement(
|
|
465
|
+
"dt",
|
|
466
|
+
{ key: `${row.label}-label`, className: orClasses2.swapDetailsDt },
|
|
467
|
+
row.label
|
|
468
|
+
),
|
|
469
|
+
React4.createElement(
|
|
470
|
+
"dd",
|
|
471
|
+
{ key: `${row.label}-value`, className: orClasses2.swapDetailsDd },
|
|
472
|
+
React4.createElement("code", { className: orClasses2.swapDetailsCode }, row.value),
|
|
473
|
+
React4.createElement(
|
|
474
|
+
"div",
|
|
475
|
+
{ className: orClasses2.swapDetailsActions },
|
|
476
|
+
React4.createElement(TransactionDetailCopyButton, {
|
|
477
|
+
value: copyValue,
|
|
478
|
+
clipboard: options.clipboard,
|
|
479
|
+
onError: options.onError
|
|
480
|
+
}),
|
|
481
|
+
row.href === void 0 ? null : React4.createElement(
|
|
482
|
+
"a",
|
|
483
|
+
{
|
|
484
|
+
className: orClasses2.swapDetailsLink,
|
|
485
|
+
href: row.href,
|
|
486
|
+
rel: "noreferrer",
|
|
487
|
+
target: "_blank"
|
|
488
|
+
},
|
|
489
|
+
row.hrefLabel ?? checkoutLabels2.viewOnExplorer
|
|
490
|
+
)
|
|
491
|
+
)
|
|
492
|
+
)
|
|
493
|
+
];
|
|
494
|
+
}
|
|
495
|
+
function TransactionDetailCopyButton(props) {
|
|
496
|
+
const [copied, setCopied] = useTransientValue(false);
|
|
497
|
+
const label = copied ? checkoutLabels2.copied : "Copy";
|
|
498
|
+
return React4.createElement(
|
|
499
|
+
"button",
|
|
500
|
+
{
|
|
501
|
+
className: orClasses2.detailCopy,
|
|
502
|
+
type: "button",
|
|
503
|
+
"aria-label": label,
|
|
504
|
+
title: label,
|
|
505
|
+
onClick: () => {
|
|
506
|
+
void copyText(props.value, props.clipboard).then(() => setCopied(true)).catch((error) => props.onError?.(error));
|
|
507
|
+
}
|
|
508
|
+
},
|
|
509
|
+
React4.createElement(ClipboardIcon)
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// src/theme.ts
|
|
514
|
+
import * as React5 from "react";
|
|
452
515
|
import {
|
|
453
516
|
OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES as OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES2,
|
|
454
517
|
OPENRECEIVE_THEME_STORAGE_KEY,
|
|
455
518
|
createThemeModel,
|
|
456
|
-
orClasses as
|
|
519
|
+
orClasses as orClasses3,
|
|
457
520
|
readThemePreference,
|
|
458
521
|
writeThemePreference
|
|
459
522
|
} from "@openreceive/browser/headless";
|
|
460
|
-
var ThemeContext =
|
|
523
|
+
var ThemeContext = React5.createContext(null);
|
|
461
524
|
var storedThemeListeners = /* @__PURE__ */ new Set();
|
|
462
525
|
var lastSetTheme = /* @__PURE__ */ new Map();
|
|
463
526
|
function notifyStoredThemeChange() {
|
|
@@ -486,9 +549,9 @@ function useLocalTheme(options = {}) {
|
|
|
486
549
|
const storageKey = options.storageKey ?? OPENRECEIVE_THEME_STORAGE_KEY;
|
|
487
550
|
const storage = options.storage;
|
|
488
551
|
const defaultTheme = options.defaultTheme;
|
|
489
|
-
const theme =
|
|
552
|
+
const theme = React5.useSyncExternalStore(
|
|
490
553
|
subscribeStoredTheme,
|
|
491
|
-
|
|
554
|
+
React5.useCallback(
|
|
492
555
|
() => readThemePreference({
|
|
493
556
|
storage,
|
|
494
557
|
storageKey,
|
|
@@ -496,7 +559,7 @@ function useLocalTheme(options = {}) {
|
|
|
496
559
|
}),
|
|
497
560
|
[storage, storageKey, defaultTheme]
|
|
498
561
|
),
|
|
499
|
-
|
|
562
|
+
React5.useCallback(
|
|
500
563
|
() => (
|
|
501
564
|
// A host-supplied storage is readable on the server (that is how SSR theming is
|
|
502
565
|
// wired); the implicit browser localStorage is not, so fall back to the default.
|
|
@@ -505,13 +568,13 @@ function useLocalTheme(options = {}) {
|
|
|
505
568
|
[storage, storageKey, defaultTheme]
|
|
506
569
|
)
|
|
507
570
|
);
|
|
508
|
-
const systemDark =
|
|
571
|
+
const systemDark = React5.useSyncExternalStore(
|
|
509
572
|
subscribeSystemDark,
|
|
510
573
|
getSystemDark,
|
|
511
574
|
getServerSystemDark
|
|
512
575
|
);
|
|
513
576
|
const themeModel = createThemeModel(theme, { systemDark });
|
|
514
|
-
const setTheme =
|
|
577
|
+
const setTheme = React5.useCallback(
|
|
515
578
|
(nextTheme) => {
|
|
516
579
|
lastSetTheme.set(storageKey, nextTheme);
|
|
517
580
|
writeThemePreference(nextTheme, {
|
|
@@ -522,7 +585,7 @@ function useLocalTheme(options = {}) {
|
|
|
522
585
|
},
|
|
523
586
|
[storage, storageKey]
|
|
524
587
|
);
|
|
525
|
-
const toggleTheme =
|
|
588
|
+
const toggleTheme = React5.useCallback(() => {
|
|
526
589
|
setTheme(themeModel.nextTheme);
|
|
527
590
|
}, [setTheme, themeModel.nextTheme]);
|
|
528
591
|
return {
|
|
@@ -539,7 +602,7 @@ function useLocalTheme(options = {}) {
|
|
|
539
602
|
};
|
|
540
603
|
}
|
|
541
604
|
function useTheme(options = {}) {
|
|
542
|
-
const scoped =
|
|
605
|
+
const scoped = React5.useContext(ThemeContext);
|
|
543
606
|
const local = useLocalTheme(options);
|
|
544
607
|
const storageKey = options.storageKey ?? OPENRECEIVE_THEME_STORAGE_KEY;
|
|
545
608
|
if (scoped !== null && options.storage === void 0 && (options.storageKey === void 0 || options.storageKey === storageKey) && options.defaultTheme === void 0) {
|
|
@@ -566,7 +629,7 @@ function ThemeToggle(props) {
|
|
|
566
629
|
const componentProps = {
|
|
567
630
|
...buttonProps,
|
|
568
631
|
"aria-label": themeModel.toggleLabel,
|
|
569
|
-
className: joinClassNames(
|
|
632
|
+
className: joinClassNames(orClasses3.themeToggle, buttonProps.className),
|
|
570
633
|
title: themeModel.toggleLabel,
|
|
571
634
|
type,
|
|
572
635
|
[OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES2.themeToggle]: "",
|
|
@@ -577,7 +640,7 @@ function ThemeToggle(props) {
|
|
|
577
640
|
if (onThemeChange === void 0) fallback.setTheme(themeModel.nextTheme);
|
|
578
641
|
}
|
|
579
642
|
};
|
|
580
|
-
return
|
|
643
|
+
return React5.createElement(ButtonComponent, componentProps, children ?? themeModel.toggleLabel);
|
|
581
644
|
}
|
|
582
645
|
function ThemeScope(props) {
|
|
583
646
|
const {
|
|
@@ -598,22 +661,22 @@ function ThemeScope(props) {
|
|
|
598
661
|
storage
|
|
599
662
|
});
|
|
600
663
|
const scopedChildren = typeof children === "function" ? children(theme) : children;
|
|
601
|
-
return
|
|
664
|
+
return React5.createElement(
|
|
602
665
|
ThemeContext.Provider,
|
|
603
666
|
{ value: theme },
|
|
604
667
|
// Variadic children, not an array: an array child needs a key on every entry.
|
|
605
|
-
|
|
668
|
+
React5.createElement(
|
|
606
669
|
Element,
|
|
607
670
|
{
|
|
608
671
|
...elementProps,
|
|
609
672
|
...theme.attributes
|
|
610
673
|
},
|
|
611
|
-
themeToggle ?
|
|
674
|
+
themeToggle ? React5.createElement(
|
|
612
675
|
"div",
|
|
613
676
|
{
|
|
614
677
|
className: topbarClassName
|
|
615
678
|
},
|
|
616
|
-
|
|
679
|
+
React5.createElement(ThemeToggle, {
|
|
617
680
|
className: themeToggleClassName,
|
|
618
681
|
theme: theme.theme,
|
|
619
682
|
resolvedTheme: theme.resolvedTheme,
|
|
@@ -627,7 +690,7 @@ function ThemeScope(props) {
|
|
|
627
690
|
}
|
|
628
691
|
|
|
629
692
|
// src/use-checkout.ts
|
|
630
|
-
import * as
|
|
693
|
+
import * as React6 from "react";
|
|
631
694
|
import {
|
|
632
695
|
copyInvoice as copyInvoiceHelper2,
|
|
633
696
|
createCheckoutController,
|
|
@@ -639,46 +702,46 @@ import {
|
|
|
639
702
|
function useCheckout(options) {
|
|
640
703
|
const checkout = options.checkout;
|
|
641
704
|
const [copied, showCopied] = useTransientValue(false);
|
|
642
|
-
const [latestSnapshot, setLatestSnapshot] =
|
|
705
|
+
const [latestSnapshot, setLatestSnapshot] = React6.useState(checkout);
|
|
643
706
|
const incomingIdentity = `${checkout.checkout_id} ${checkout.reference}`;
|
|
644
|
-
const checkoutRef =
|
|
707
|
+
const checkoutRef = React6.useRef(checkout);
|
|
645
708
|
checkoutRef.current = checkout;
|
|
646
|
-
|
|
709
|
+
React6.useEffect(() => {
|
|
647
710
|
setLatestSnapshot(checkoutRef.current);
|
|
648
711
|
}, [incomingIdentity]);
|
|
649
712
|
const snapshot = latestSnapshot;
|
|
650
|
-
const [state, setState] =
|
|
713
|
+
const [state, setState] = React6.useState(
|
|
651
714
|
() => createCheckoutState(snapshot, {
|
|
652
715
|
logger: options.logger
|
|
653
716
|
})
|
|
654
717
|
);
|
|
655
|
-
const controllerRef =
|
|
656
|
-
const onStateRef =
|
|
718
|
+
const controllerRef = React6.useRef(null);
|
|
719
|
+
const onStateRef = React6.useRef(options.onState);
|
|
657
720
|
onStateRef.current = options.onState;
|
|
658
|
-
const onSettledRef =
|
|
721
|
+
const onSettledRef = React6.useRef(options.onSettled);
|
|
659
722
|
onSettledRef.current = options.onSettled;
|
|
660
|
-
const loggerRef =
|
|
723
|
+
const loggerRef = React6.useRef(options.logger);
|
|
661
724
|
loggerRef.current = options.logger;
|
|
662
|
-
const onErrorRef =
|
|
725
|
+
const onErrorRef = React6.useRef(options.onError);
|
|
663
726
|
onErrorRef.current = options.onError;
|
|
664
|
-
const onCopyRef =
|
|
727
|
+
const onCopyRef = React6.useRef(options.onCopy);
|
|
665
728
|
onCopyRef.current = options.onCopy;
|
|
666
|
-
const onOpenWalletRef =
|
|
729
|
+
const onOpenWalletRef = React6.useRef(options.onOpenWallet);
|
|
667
730
|
onOpenWalletRef.current = options.onOpenWallet;
|
|
668
|
-
const settledAnnouncementRef =
|
|
731
|
+
const settledAnnouncementRef = React6.useRef({
|
|
669
732
|
reference: snapshot.reference,
|
|
670
733
|
fired: false
|
|
671
734
|
});
|
|
672
|
-
const logContext =
|
|
735
|
+
const logContext = React6.useMemo(() => getCheckoutLogContext(state), [state]);
|
|
673
736
|
const refreshStatus = options.polling === false ? void 0 : options.refreshStatus;
|
|
674
|
-
const refreshStatusRef =
|
|
737
|
+
const refreshStatusRef = React6.useRef(refreshStatus);
|
|
675
738
|
refreshStatusRef.current = refreshStatus;
|
|
676
739
|
const polls = refreshStatus !== void 0;
|
|
677
740
|
const prefix = options.polling === false ? void 0 : options.prefix;
|
|
678
|
-
const snapshotRef =
|
|
741
|
+
const snapshotRef = React6.useRef(snapshot);
|
|
679
742
|
snapshotRef.current = snapshot;
|
|
680
743
|
const checkoutIdentity = `${snapshot.checkout_id} ${snapshot.reference}`;
|
|
681
|
-
|
|
744
|
+
React6.useEffect(() => {
|
|
682
745
|
const controller = createCheckoutController({
|
|
683
746
|
snapshot: snapshotRef.current,
|
|
684
747
|
...polls ? {
|
|
@@ -715,7 +778,7 @@ function useCheckout(options) {
|
|
|
715
778
|
}, [checkoutIdentity, polls, prefix, options.pollIntervalMs]);
|
|
716
779
|
const publicStatus = deriveStatus(state);
|
|
717
780
|
const richStatus = createCheckoutStatusModel2(state);
|
|
718
|
-
|
|
781
|
+
React6.useEffect(() => {
|
|
719
782
|
const announced = settledAnnouncementRef.current;
|
|
720
783
|
if (announced.reference !== snapshot.reference) {
|
|
721
784
|
settledAnnouncementRef.current = {
|
|
@@ -724,7 +787,7 @@ function useCheckout(options) {
|
|
|
724
787
|
};
|
|
725
788
|
}
|
|
726
789
|
}, [snapshot.reference]);
|
|
727
|
-
|
|
790
|
+
React6.useEffect(() => {
|
|
728
791
|
const announced = settledAnnouncementRef.current;
|
|
729
792
|
if (publicStatus !== "settled" || announced.fired) return;
|
|
730
793
|
settledAnnouncementRef.current = {
|
|
@@ -733,7 +796,7 @@ function useCheckout(options) {
|
|
|
733
796
|
};
|
|
734
797
|
onSettledRef.current?.();
|
|
735
798
|
}, [publicStatus, snapshot.reference]);
|
|
736
|
-
const copyInvoice =
|
|
799
|
+
const copyInvoice = React6.useCallback(async () => {
|
|
737
800
|
try {
|
|
738
801
|
const controller = controllerRef.current;
|
|
739
802
|
if (controller === null) {
|
|
@@ -753,7 +816,7 @@ function useCheckout(options) {
|
|
|
753
816
|
throw error;
|
|
754
817
|
}
|
|
755
818
|
}, [logContext, state.invoice, options.clipboard, options.logger, showCopied]);
|
|
756
|
-
const openWallet =
|
|
819
|
+
const openWallet = React6.useCallback(() => {
|
|
757
820
|
try {
|
|
758
821
|
const controller = controllerRef.current;
|
|
759
822
|
const uri = controller === null ? openWalletHelper2({
|
|
@@ -769,7 +832,7 @@ function useCheckout(options) {
|
|
|
769
832
|
throw error;
|
|
770
833
|
}
|
|
771
834
|
}, [logContext, state.invoice, options.open, options.logger]);
|
|
772
|
-
const reloadState =
|
|
835
|
+
const reloadState = React6.useCallback(async () => {
|
|
773
836
|
try {
|
|
774
837
|
const next = await controllerRef.current?.reloadState();
|
|
775
838
|
if (next !== void 0) setState(next);
|
|
@@ -779,10 +842,42 @@ function useCheckout(options) {
|
|
|
779
842
|
}
|
|
780
843
|
}, []);
|
|
781
844
|
const retry = reloadState;
|
|
782
|
-
const cancel =
|
|
845
|
+
const cancel = React6.useCallback(() => {
|
|
783
846
|
const next = controllerRef.current?.cancel();
|
|
784
847
|
if (next !== void 0) setState(next);
|
|
785
848
|
}, []);
|
|
849
|
+
const swapRefundController = React6.useCallback(() => {
|
|
850
|
+
const controller = controllerRef.current;
|
|
851
|
+
if (controller === null) {
|
|
852
|
+
throw new Error("Swap refunds need a started checkout controller.");
|
|
853
|
+
}
|
|
854
|
+
return controller;
|
|
855
|
+
}, []);
|
|
856
|
+
const stageSwapRefund = React6.useCallback(
|
|
857
|
+
async (refund) => {
|
|
858
|
+
try {
|
|
859
|
+
return await swapRefundController().stageSwapRefund(refund);
|
|
860
|
+
} catch (error) {
|
|
861
|
+
onErrorRef.current?.(error);
|
|
862
|
+
throw error;
|
|
863
|
+
}
|
|
864
|
+
},
|
|
865
|
+
[swapRefundController]
|
|
866
|
+
);
|
|
867
|
+
const confirmSwapRefund = React6.useCallback(
|
|
868
|
+
async (refund) => {
|
|
869
|
+
try {
|
|
870
|
+
return await swapRefundController().confirmSwapRefund(refund);
|
|
871
|
+
} catch (error) {
|
|
872
|
+
onErrorRef.current?.(error);
|
|
873
|
+
throw error;
|
|
874
|
+
}
|
|
875
|
+
},
|
|
876
|
+
[swapRefundController]
|
|
877
|
+
);
|
|
878
|
+
const clearSwapRefundStaging = React6.useCallback(() => {
|
|
879
|
+
controllerRef.current?.clearSwapRefundStaging();
|
|
880
|
+
}, []);
|
|
786
881
|
return {
|
|
787
882
|
// The state IS the view model now: one derivation, one set of display
|
|
788
883
|
// fields. `status` stays on top of it because the component's terminal
|
|
@@ -801,12 +896,15 @@ function useCheckout(options) {
|
|
|
801
896
|
retry,
|
|
802
897
|
cancel,
|
|
803
898
|
copyInvoice,
|
|
804
|
-
openWallet
|
|
899
|
+
openWallet,
|
|
900
|
+
stageSwapRefund,
|
|
901
|
+
confirmSwapRefund,
|
|
902
|
+
clearSwapRefundStaging
|
|
805
903
|
};
|
|
806
904
|
}
|
|
807
|
-
var CheckoutContext =
|
|
905
|
+
var CheckoutContext = React6.createContext(null);
|
|
808
906
|
function useCheckoutContext() {
|
|
809
|
-
const checkout =
|
|
907
|
+
const checkout = React6.useContext(CheckoutContext);
|
|
810
908
|
if (checkout === null) {
|
|
811
909
|
throw new Error("useCheckoutContext must be used within CheckoutProvider.");
|
|
812
910
|
}
|
|
@@ -816,7 +914,7 @@ function CheckoutProvider(props) {
|
|
|
816
914
|
const { children, ...options } = props;
|
|
817
915
|
const checkout = useCheckout(options);
|
|
818
916
|
const content = typeof children === "function" ? children(checkout) : children;
|
|
819
|
-
return
|
|
917
|
+
return React6.createElement(CheckoutContext.Provider, { value: checkout }, content);
|
|
820
918
|
}
|
|
821
919
|
|
|
822
920
|
// src/wizard.ts
|
|
@@ -825,12 +923,12 @@ import {
|
|
|
825
923
|
buildMethodGridEntries,
|
|
826
924
|
checkoutLabels as checkoutLabels5,
|
|
827
925
|
copyInvoice as copyInvoiceHelper3,
|
|
926
|
+
createAssetBaseUrlResolver,
|
|
927
|
+
createMethodGridDisplay,
|
|
828
928
|
createPaymentWizardController,
|
|
829
929
|
createPaymentWizardModel,
|
|
830
930
|
createWizardRouteAssetDisplays,
|
|
831
931
|
createWizardRouteDisplays,
|
|
832
|
-
findSwapGridGroup,
|
|
833
|
-
formatChooseNetworkHeading,
|
|
834
932
|
formatNetworkSummary,
|
|
835
933
|
getNetworkIcon,
|
|
836
934
|
getPaymentMethodIcon,
|
|
@@ -841,32 +939,28 @@ import {
|
|
|
841
939
|
networkMobileRevealClasses,
|
|
842
940
|
networkSummaryIconClasses,
|
|
843
941
|
orClasses as orClasses6,
|
|
844
|
-
overlaySwapRefundStaging,
|
|
845
|
-
paymentAccentId,
|
|
846
942
|
paymentMethods,
|
|
943
|
+
resolveWizardSelection,
|
|
847
944
|
requestSwapRefund,
|
|
945
|
+
selectCurrentSwapInvoice,
|
|
848
946
|
swapAssetMatchesRoute,
|
|
849
|
-
|
|
850
|
-
swapOptionLimitMessage as swapOptionLimitMessage2,
|
|
851
|
-
swapPickerKey,
|
|
852
|
-
updateSelectedSwapNetworks,
|
|
853
|
-
wizardNetworkGroupIds
|
|
947
|
+
swapOptionLimitMessage as swapOptionLimitMessage2
|
|
854
948
|
} from "@openreceive/browser/headless";
|
|
855
949
|
import * as React9 from "react";
|
|
856
950
|
|
|
857
951
|
// src/provider-tutorial.ts
|
|
858
952
|
import {
|
|
859
953
|
createLightningInvoiceDecodeUrl,
|
|
860
|
-
checkoutLabels as
|
|
861
|
-
orClasses as
|
|
954
|
+
checkoutLabels as checkoutLabels3,
|
|
955
|
+
orClasses as orClasses4
|
|
862
956
|
} from "@openreceive/browser/headless";
|
|
863
|
-
import * as
|
|
957
|
+
import * as React7 from "react";
|
|
864
958
|
function renderProviderOpenAction(provider, onOpenTutorial) {
|
|
865
959
|
if (provider.tutorials.length === 0) {
|
|
866
|
-
return
|
|
960
|
+
return React7.createElement(
|
|
867
961
|
"a",
|
|
868
962
|
{
|
|
869
|
-
className:
|
|
963
|
+
className: orClasses4.providerOpen,
|
|
870
964
|
href: provider.url,
|
|
871
965
|
rel: "noreferrer",
|
|
872
966
|
target: "_blank"
|
|
@@ -874,10 +968,10 @@ function renderProviderOpenAction(provider, onOpenTutorial) {
|
|
|
874
968
|
provider.openLabel
|
|
875
969
|
);
|
|
876
970
|
}
|
|
877
|
-
return
|
|
971
|
+
return React7.createElement(
|
|
878
972
|
"button",
|
|
879
973
|
{
|
|
880
|
-
className:
|
|
974
|
+
className: orClasses4.providerOpen,
|
|
881
975
|
onClick: onOpenTutorial,
|
|
882
976
|
type: "button"
|
|
883
977
|
},
|
|
@@ -886,8 +980,8 @@ function renderProviderOpenAction(provider, onOpenTutorial) {
|
|
|
886
980
|
}
|
|
887
981
|
function ProviderTutorialModal(options) {
|
|
888
982
|
const { provider } = options;
|
|
889
|
-
const dialogRef =
|
|
890
|
-
|
|
983
|
+
const dialogRef = React7.useRef(null);
|
|
984
|
+
React7.useEffect(() => {
|
|
891
985
|
const dialog = dialogRef.current;
|
|
892
986
|
if (dialog === null) return;
|
|
893
987
|
const opener = dialog.ownerDocument.activeElement instanceof HTMLElement ? dialog.ownerDocument.activeElement : null;
|
|
@@ -925,13 +1019,13 @@ function ProviderTutorialModal(options) {
|
|
|
925
1019
|
const nextIndex = Math.min(provider.tutorials.length, stepIndex + 1);
|
|
926
1020
|
const isFinalStep = stepIndex === provider.tutorials.length;
|
|
927
1021
|
const decodeHref = createLightningInvoiceDecodeUrl(options.invoice, options.decodeLinkUrl);
|
|
928
|
-
return
|
|
1022
|
+
return React7.createElement(
|
|
929
1023
|
"div",
|
|
930
1024
|
{
|
|
931
1025
|
ref: dialogRef,
|
|
932
|
-
"aria-label": `${
|
|
1026
|
+
"aria-label": `${checkoutLabels3.tutorialTitlePrefix} ${provider.name}`,
|
|
933
1027
|
"aria-modal": true,
|
|
934
|
-
className:
|
|
1028
|
+
className: orClasses4.tutorialModal,
|
|
935
1029
|
onClick: (event) => {
|
|
936
1030
|
if (event.target === event.currentTarget) options.onClose();
|
|
937
1031
|
},
|
|
@@ -942,143 +1036,143 @@ function ProviderTutorialModal(options) {
|
|
|
942
1036
|
role: "dialog",
|
|
943
1037
|
tabIndex: -1
|
|
944
1038
|
},
|
|
945
|
-
|
|
1039
|
+
React7.createElement(
|
|
946
1040
|
"div",
|
|
947
1041
|
{
|
|
948
|
-
className:
|
|
1042
|
+
className: orClasses4.tutorialBox
|
|
949
1043
|
},
|
|
950
|
-
|
|
1044
|
+
React7.createElement(
|
|
951
1045
|
"div",
|
|
952
1046
|
{
|
|
953
|
-
className:
|
|
1047
|
+
className: orClasses4.tutorialHeader
|
|
954
1048
|
},
|
|
955
|
-
|
|
1049
|
+
React7.createElement(
|
|
956
1050
|
"div",
|
|
957
1051
|
{
|
|
958
|
-
className:
|
|
1052
|
+
className: orClasses4.tutorialTitle
|
|
959
1053
|
},
|
|
960
|
-
|
|
1054
|
+
React7.createElement("img", {
|
|
961
1055
|
alt: "",
|
|
962
|
-
className:
|
|
1056
|
+
className: orClasses4.tutorialHeaderLogo,
|
|
963
1057
|
src: provider.icon
|
|
964
1058
|
}),
|
|
965
|
-
|
|
1059
|
+
React7.createElement("h3", null, `${checkoutLabels3.tutorialTitlePrefix} ${provider.name}`)
|
|
966
1060
|
),
|
|
967
|
-
|
|
1061
|
+
React7.createElement(
|
|
968
1062
|
"button",
|
|
969
1063
|
{
|
|
970
|
-
"aria-label":
|
|
971
|
-
className:
|
|
1064
|
+
"aria-label": checkoutLabels3.tutorialClose,
|
|
1065
|
+
className: orClasses4.tutorialClose,
|
|
972
1066
|
onClick: options.onClose,
|
|
973
1067
|
type: "button"
|
|
974
1068
|
},
|
|
975
1069
|
"X"
|
|
976
1070
|
)
|
|
977
1071
|
),
|
|
978
|
-
stepIndex === 0 ?
|
|
1072
|
+
stepIndex === 0 ? React7.createElement(
|
|
979
1073
|
"div",
|
|
980
1074
|
{
|
|
981
|
-
className:
|
|
1075
|
+
className: orClasses4.tutorialIntro
|
|
982
1076
|
},
|
|
983
|
-
|
|
1077
|
+
React7.createElement("img", {
|
|
984
1078
|
alt: "",
|
|
985
|
-
className:
|
|
1079
|
+
className: orClasses4.tutorialProviderLogo,
|
|
986
1080
|
src: provider.icon
|
|
987
1081
|
}),
|
|
988
|
-
|
|
1082
|
+
React7.createElement(
|
|
989
1083
|
"p",
|
|
990
1084
|
null,
|
|
991
|
-
`${
|
|
1085
|
+
`${checkoutLabels3.tutorialIntroPrefix} ${provider.name}.`
|
|
992
1086
|
),
|
|
993
|
-
|
|
994
|
-
|
|
1087
|
+
React7.createElement("p", null, checkoutLabels3.tutorialIntroCopy),
|
|
1088
|
+
React7.createElement(
|
|
995
1089
|
"button",
|
|
996
1090
|
{
|
|
997
|
-
className:
|
|
1091
|
+
className: orClasses4.tutorialCopy,
|
|
998
1092
|
onClick: () => void options.onCopy(),
|
|
999
1093
|
type: "button"
|
|
1000
1094
|
},
|
|
1001
|
-
|
|
1095
|
+
checkoutLabels3.copyInvoice
|
|
1002
1096
|
),
|
|
1003
|
-
decodeHref === void 0 ? null :
|
|
1097
|
+
decodeHref === void 0 ? null : React7.createElement(
|
|
1004
1098
|
"a",
|
|
1005
1099
|
{
|
|
1006
|
-
className:
|
|
1100
|
+
className: orClasses4.tutorialCopy,
|
|
1007
1101
|
href: decodeHref,
|
|
1008
1102
|
rel: "noreferrer",
|
|
1009
1103
|
target: "_blank"
|
|
1010
1104
|
},
|
|
1011
|
-
|
|
1105
|
+
checkoutLabels3.decodeInvoice
|
|
1012
1106
|
),
|
|
1013
|
-
options.copied ?
|
|
1107
|
+
options.copied ? React7.createElement(
|
|
1014
1108
|
"p",
|
|
1015
1109
|
{
|
|
1016
|
-
className:
|
|
1110
|
+
className: orClasses4.tutorialCopyMessage
|
|
1017
1111
|
},
|
|
1018
|
-
|
|
1112
|
+
checkoutLabels3.tutorialCopiedContinue
|
|
1019
1113
|
) : null
|
|
1020
|
-
) :
|
|
1021
|
-
|
|
1114
|
+
) : React7.createElement(
|
|
1115
|
+
React7.Fragment,
|
|
1022
1116
|
null,
|
|
1023
|
-
|
|
1117
|
+
React7.createElement(
|
|
1024
1118
|
"div",
|
|
1025
1119
|
{
|
|
1026
|
-
className:
|
|
1120
|
+
className: orClasses4.tutorialFrame
|
|
1027
1121
|
},
|
|
1028
|
-
|
|
1122
|
+
React7.createElement("img", {
|
|
1029
1123
|
alt: tutorial?.caption ?? "",
|
|
1030
|
-
className:
|
|
1124
|
+
className: orClasses4.tutorialImage,
|
|
1031
1125
|
src: tutorial?.image ?? ""
|
|
1032
1126
|
})
|
|
1033
1127
|
),
|
|
1034
|
-
|
|
1128
|
+
React7.createElement(
|
|
1035
1129
|
"p",
|
|
1036
1130
|
{
|
|
1037
|
-
className:
|
|
1131
|
+
className: orClasses4.tutorialCaption
|
|
1038
1132
|
},
|
|
1039
1133
|
tutorial?.caption ?? ""
|
|
1040
1134
|
)
|
|
1041
1135
|
),
|
|
1042
|
-
|
|
1136
|
+
React7.createElement(
|
|
1043
1137
|
"div",
|
|
1044
1138
|
{
|
|
1045
1139
|
"aria-hidden": "true",
|
|
1046
|
-
className:
|
|
1140
|
+
className: orClasses4.tutorialSteps
|
|
1047
1141
|
},
|
|
1048
1142
|
Array.from(
|
|
1049
1143
|
{ length: totalSteps },
|
|
1050
|
-
(_, index) =>
|
|
1051
|
-
className: index === stepIndex ?
|
|
1144
|
+
(_, index) => React7.createElement("span", {
|
|
1145
|
+
className: index === stepIndex ? orClasses4.tutorialStepActive : orClasses4.tutorialStep,
|
|
1052
1146
|
key: index
|
|
1053
1147
|
})
|
|
1054
1148
|
)
|
|
1055
1149
|
),
|
|
1056
|
-
|
|
1150
|
+
React7.createElement(
|
|
1057
1151
|
"p",
|
|
1058
1152
|
{
|
|
1059
|
-
className:
|
|
1153
|
+
className: orClasses4.tutorialProgress
|
|
1060
1154
|
},
|
|
1061
1155
|
`Step ${stepIndex + 1} of ${totalSteps}`
|
|
1062
1156
|
),
|
|
1063
|
-
|
|
1157
|
+
React7.createElement(
|
|
1064
1158
|
"div",
|
|
1065
1159
|
{
|
|
1066
|
-
className:
|
|
1160
|
+
className: orClasses4.tutorialControls
|
|
1067
1161
|
},
|
|
1068
|
-
|
|
1162
|
+
React7.createElement(
|
|
1069
1163
|
"button",
|
|
1070
1164
|
{
|
|
1071
|
-
className:
|
|
1165
|
+
className: orClasses4.btn,
|
|
1072
1166
|
disabled: stepIndex === 0,
|
|
1073
1167
|
onClick: () => options.onStep(previousIndex),
|
|
1074
1168
|
type: "button"
|
|
1075
1169
|
},
|
|
1076
|
-
|
|
1170
|
+
checkoutLabels3.tutorialBack
|
|
1077
1171
|
),
|
|
1078
|
-
|
|
1172
|
+
React7.createElement(
|
|
1079
1173
|
"button",
|
|
1080
1174
|
{
|
|
1081
|
-
className:
|
|
1175
|
+
className: orClasses4.btn,
|
|
1082
1176
|
onClick: () => {
|
|
1083
1177
|
if (isFinalStep) {
|
|
1084
1178
|
options.onClose();
|
|
@@ -1088,7 +1182,7 @@ function ProviderTutorialModal(options) {
|
|
|
1088
1182
|
},
|
|
1089
1183
|
type: "button"
|
|
1090
1184
|
},
|
|
1091
|
-
isFinalStep ?
|
|
1185
|
+
isFinalStep ? checkoutLabels3.tutorialExit : checkoutLabels3.tutorialNext
|
|
1092
1186
|
)
|
|
1093
1187
|
)
|
|
1094
1188
|
)
|
|
@@ -1109,97 +1203,6 @@ import {
|
|
|
1109
1203
|
selectCheckoutDisplayInvoice
|
|
1110
1204
|
} from "@openreceive/browser/headless";
|
|
1111
1205
|
import * as React8 from "react";
|
|
1112
|
-
|
|
1113
|
-
// src/transaction-details.ts
|
|
1114
|
-
import {
|
|
1115
|
-
checkoutLabels as checkoutLabels3,
|
|
1116
|
-
orClasses as orClasses4,
|
|
1117
|
-
resolveTransactionDetailRows
|
|
1118
|
-
} from "@openreceive/browser/headless";
|
|
1119
|
-
import * as React7 from "react";
|
|
1120
|
-
function TransactionDetails(props) {
|
|
1121
|
-
const rows = resolveTransactionDetailRows(props.state);
|
|
1122
|
-
if (rows.length === 0) return null;
|
|
1123
|
-
return React7.createElement(
|
|
1124
|
-
"details",
|
|
1125
|
-
{
|
|
1126
|
-
className: joinClassNames(orClasses4.transactionDetails, props.className),
|
|
1127
|
-
open: props.open === true ? true : void 0
|
|
1128
|
-
},
|
|
1129
|
-
React7.createElement(
|
|
1130
|
-
"summary",
|
|
1131
|
-
{ className: orClasses4.transactionDetailsTitle },
|
|
1132
|
-
checkoutLabels3.transactionDetails
|
|
1133
|
-
),
|
|
1134
|
-
React7.createElement(
|
|
1135
|
-
"div",
|
|
1136
|
-
{ className: orClasses4.transactionDetailsContent },
|
|
1137
|
-
React7.createElement(
|
|
1138
|
-
"dl",
|
|
1139
|
-
{ className: orClasses4.swapDetails },
|
|
1140
|
-
rows.flatMap(
|
|
1141
|
-
(row) => renderTransactionDetailRow(row, {
|
|
1142
|
-
clipboard: props.clipboard,
|
|
1143
|
-
onError: props.onError
|
|
1144
|
-
})
|
|
1145
|
-
)
|
|
1146
|
-
)
|
|
1147
|
-
)
|
|
1148
|
-
);
|
|
1149
|
-
}
|
|
1150
|
-
function renderTransactionDetailRow(row, options) {
|
|
1151
|
-
const copyValue = row.copyValue ?? row.value;
|
|
1152
|
-
return [
|
|
1153
|
-
React7.createElement(
|
|
1154
|
-
"dt",
|
|
1155
|
-
{ key: `${row.label}-label`, className: orClasses4.swapDetailsDt },
|
|
1156
|
-
row.label
|
|
1157
|
-
),
|
|
1158
|
-
React7.createElement(
|
|
1159
|
-
"dd",
|
|
1160
|
-
{ key: `${row.label}-value`, className: orClasses4.swapDetailsDd },
|
|
1161
|
-
React7.createElement("code", { className: orClasses4.swapDetailsCode }, row.value),
|
|
1162
|
-
React7.createElement(
|
|
1163
|
-
"div",
|
|
1164
|
-
{ className: orClasses4.swapDetailsActions },
|
|
1165
|
-
React7.createElement(TransactionDetailCopyButton, {
|
|
1166
|
-
value: copyValue,
|
|
1167
|
-
clipboard: options.clipboard,
|
|
1168
|
-
onError: options.onError
|
|
1169
|
-
}),
|
|
1170
|
-
row.href === void 0 ? null : React7.createElement(
|
|
1171
|
-
"a",
|
|
1172
|
-
{
|
|
1173
|
-
className: orClasses4.swapDetailsLink,
|
|
1174
|
-
href: row.href,
|
|
1175
|
-
rel: "noreferrer",
|
|
1176
|
-
target: "_blank"
|
|
1177
|
-
},
|
|
1178
|
-
row.hrefLabel ?? checkoutLabels3.viewOnExplorer
|
|
1179
|
-
)
|
|
1180
|
-
)
|
|
1181
|
-
)
|
|
1182
|
-
];
|
|
1183
|
-
}
|
|
1184
|
-
function TransactionDetailCopyButton(props) {
|
|
1185
|
-
const [copied, setCopied] = useTransientValue(false);
|
|
1186
|
-
const label = copied ? checkoutLabels3.copied : "Copy";
|
|
1187
|
-
return React7.createElement(
|
|
1188
|
-
"button",
|
|
1189
|
-
{
|
|
1190
|
-
className: orClasses4.detailCopy,
|
|
1191
|
-
type: "button",
|
|
1192
|
-
"aria-label": label,
|
|
1193
|
-
title: label,
|
|
1194
|
-
onClick: () => {
|
|
1195
|
-
void copyText(props.value, props.clipboard).then(() => setCopied(true)).catch((error) => props.onError?.(error));
|
|
1196
|
-
}
|
|
1197
|
-
},
|
|
1198
|
-
React7.createElement(ClipboardIcon)
|
|
1199
|
-
);
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
// src/swap.ts
|
|
1203
1206
|
function renderSwapActions(options) {
|
|
1204
1207
|
const shown = options.options.filter((option) => option.provider.length > 0);
|
|
1205
1208
|
if (!options.enabled || shown.length === 0) return null;
|
|
@@ -1303,7 +1306,6 @@ function renderSwapDepositPanel(options) {
|
|
|
1303
1306
|
options.now === void 0 ? {} : { now: options.now }
|
|
1304
1307
|
);
|
|
1305
1308
|
if (display === void 0) return null;
|
|
1306
|
-
const memo = display.depositMemo;
|
|
1307
1309
|
const backButton = React8.createElement(
|
|
1308
1310
|
"button",
|
|
1309
1311
|
{
|
|
@@ -1519,16 +1521,14 @@ function renderSwapDepositPanel(options) {
|
|
|
1519
1521
|
{
|
|
1520
1522
|
className: orClasses5.swapDetails
|
|
1521
1523
|
},
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
memo === void 0 ? null : renderSwapCopyRow("Memo", memo, options),
|
|
1531
|
-
renderSwapCopyRow("Amount", display.depositAmount, { ...options, selectable: true })
|
|
1524
|
+
...display.copyRows.flatMap(
|
|
1525
|
+
(row) => renderSwapCopyRow(
|
|
1526
|
+
row.label,
|
|
1527
|
+
row.copyValue ?? row.value,
|
|
1528
|
+
{ ...options, selectable: row.selectable },
|
|
1529
|
+
row.value
|
|
1530
|
+
)
|
|
1531
|
+
)
|
|
1532
1532
|
),
|
|
1533
1533
|
waitingCard(display.countdownLabel),
|
|
1534
1534
|
renderSwapFeeBreakdown(display.feeBreakdown)
|
|
@@ -1553,16 +1553,18 @@ function renderSwapDepositPanel(options) {
|
|
|
1553
1553
|
);
|
|
1554
1554
|
}
|
|
1555
1555
|
function renderSwapNetworkWarning(display) {
|
|
1556
|
+
const alarm = display.depositRisk !== "pinned";
|
|
1556
1557
|
const emphasisStart = display.networkWarning.indexOf(display.networkWarningEmphasis);
|
|
1557
1558
|
const before = emphasisStart === -1 ? display.networkWarning : display.networkWarning.slice(0, emphasisStart);
|
|
1558
1559
|
const after = emphasisStart === -1 ? "" : display.networkWarning.slice(emphasisStart + display.networkWarningEmphasis.length);
|
|
1559
1560
|
return React8.createElement(
|
|
1560
1561
|
"div",
|
|
1561
1562
|
{
|
|
1562
|
-
role: "alert",
|
|
1563
|
-
|
|
1563
|
+
...alarm ? { role: "alert" } : {},
|
|
1564
|
+
"data-or-deposit-risk": display.depositRisk,
|
|
1565
|
+
className: alarm ? orClasses5.swapNetworkWarning : orClasses5.swapNetworkNotice
|
|
1564
1566
|
},
|
|
1565
|
-
React8.createElement(
|
|
1567
|
+
alarm ? React8.createElement(
|
|
1566
1568
|
"svg",
|
|
1567
1569
|
{
|
|
1568
1570
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1577,7 +1579,7 @@ function renderSwapNetworkWarning(display) {
|
|
|
1577
1579
|
strokeWidth: 2,
|
|
1578
1580
|
d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
1579
1581
|
})
|
|
1580
|
-
),
|
|
1582
|
+
) : null,
|
|
1581
1583
|
React8.createElement(
|
|
1582
1584
|
"div",
|
|
1583
1585
|
{ className: orClasses5.swapNetworkWarningContent },
|
|
@@ -1901,7 +1903,8 @@ function PaymentWizard(props) {
|
|
|
1901
1903
|
setSelectedPickerKey(null);
|
|
1902
1904
|
setSelectedSwapNetworks({});
|
|
1903
1905
|
session.clearSwapStartError();
|
|
1904
|
-
|
|
1906
|
+
props.swapRefund?.clearSwapRefundStaging();
|
|
1907
|
+
}, [session, props.swapRefund]);
|
|
1905
1908
|
const onSwapFocusChange = props.onSwapFocusChange;
|
|
1906
1909
|
React9.useEffect(() => {
|
|
1907
1910
|
onSwapFocusChange?.(selectedSwapAsset !== null);
|
|
@@ -1912,7 +1915,10 @@ function PaymentWizard(props) {
|
|
|
1912
1915
|
return { enabled: methods.length > 0, options: methods };
|
|
1913
1916
|
}, [checkout]);
|
|
1914
1917
|
const currentSwapInvoice = React9.useMemo(
|
|
1915
|
-
() => selectCurrentSwapInvoice(checkout,
|
|
1918
|
+
() => selectCurrentSwapInvoice(checkout, {
|
|
1919
|
+
started: startedSwapInvoice,
|
|
1920
|
+
dismissedInvoiceId: dismissedSwapInvoiceId
|
|
1921
|
+
}),
|
|
1916
1922
|
[checkout, startedSwapInvoice, dismissedSwapInvoiceId]
|
|
1917
1923
|
);
|
|
1918
1924
|
const now = useTickingUnixSeconds(currentSwapInvoice !== void 0);
|
|
@@ -1925,6 +1931,7 @@ function PaymentWizard(props) {
|
|
|
1925
1931
|
},
|
|
1926
1932
|
[props.prefix, session]
|
|
1927
1933
|
);
|
|
1934
|
+
const swapRefund = props.swapRefund;
|
|
1928
1935
|
const refundSwap = React9.useCallback(
|
|
1929
1936
|
async (attemptId, refundAddress, confirm) => {
|
|
1930
1937
|
const prefix = props.prefix;
|
|
@@ -1932,12 +1939,17 @@ function PaymentWizard(props) {
|
|
|
1932
1939
|
return;
|
|
1933
1940
|
}
|
|
1934
1941
|
try {
|
|
1935
|
-
const invoice = await
|
|
1942
|
+
const invoice = swapRefund !== void 0 ? await (confirm ? swapRefund.confirmSwapRefund : swapRefund.stageSwapRefund).call(
|
|
1943
|
+
swapRefund,
|
|
1944
|
+
{ attemptId, refundAddress }
|
|
1945
|
+
) : await requestSwapRefund({
|
|
1936
1946
|
fetch: fetcher,
|
|
1937
1947
|
prefix,
|
|
1938
1948
|
reference,
|
|
1939
|
-
|
|
1940
|
-
|
|
1949
|
+
paymentHash: resolveAttemptPaymentHash(
|
|
1950
|
+
[startedSwapInvoice, ...checkout?.invoices ?? []],
|
|
1951
|
+
attemptId
|
|
1952
|
+
),
|
|
1941
1953
|
refundAddress,
|
|
1942
1954
|
confirm,
|
|
1943
1955
|
...props.logger === void 0 ? {} : { logger: props.logger }
|
|
@@ -1954,6 +1966,7 @@ function PaymentWizard(props) {
|
|
|
1954
1966
|
fetcher,
|
|
1955
1967
|
props.onError,
|
|
1956
1968
|
props.logger,
|
|
1969
|
+
swapRefund,
|
|
1957
1970
|
startedSwapInvoice,
|
|
1958
1971
|
checkout?.invoices
|
|
1959
1972
|
]
|
|
@@ -1966,10 +1979,14 @@ function PaymentWizard(props) {
|
|
|
1966
1979
|
);
|
|
1967
1980
|
const model = createPaymentWizardModel(selection);
|
|
1968
1981
|
const { wizard } = model;
|
|
1982
|
+
const resolveAssetUrl = props.resolveAssetUrl ?? (props.assetBaseUrl === void 0 || props.assetBaseUrl.trim() === "" ? void 0 : createAssetBaseUrlResolver(props.assetBaseUrl));
|
|
1969
1983
|
const routeAssetDisplays = createWizardRouteAssetDisplays(model.routeAssets, {
|
|
1970
|
-
selectedRoute: model.selectedRoute
|
|
1984
|
+
selectedRoute: model.selectedRoute,
|
|
1985
|
+
...resolveAssetUrl === void 0 ? {} : { resolveAssetUrl }
|
|
1986
|
+
});
|
|
1987
|
+
const routeDisplays = createWizardRouteDisplays(wizard.routes, {
|
|
1988
|
+
...resolveAssetUrl === void 0 ? {} : { resolveAssetUrl }
|
|
1971
1989
|
});
|
|
1972
|
-
const routeDisplays = createWizardRouteDisplays(wizard.routes);
|
|
1973
1990
|
const showRoutePicker = routeAssetDisplays.length > 0 && (model.selectedRoute === null || routeDisplays.length === 0);
|
|
1974
1991
|
const activeTutorialProvider = activeTutorial === null ? void 0 : routeDisplays.flatMap((route) => route.providers).find((provider) => provider.id === activeTutorial.providerId);
|
|
1975
1992
|
const swapAssetOptions = swapOptions.enabled ? swapOptions.options.filter((option) => option.provider.length > 0) : [];
|
|
@@ -2045,17 +2062,33 @@ function PaymentWizard(props) {
|
|
|
2045
2062
|
selectedPickerKey,
|
|
2046
2063
|
startingAsset: swapStartingAsset,
|
|
2047
2064
|
selectedSwapNetworks,
|
|
2065
|
+
// One resolver decides what a tile click MEANS, so the "ask the
|
|
2066
|
+
// network question only when it is a real question" rule is not
|
|
2067
|
+
// re-derived here: a single-network group comes back as start_swap
|
|
2068
|
+
// and the wizard starts it instead of opening a one-answer step.
|
|
2048
2069
|
onSelectPicker: (key, previousKey) => {
|
|
2070
|
+
const resolved = resolveWizardSelection({
|
|
2071
|
+
pickerKey: key,
|
|
2072
|
+
previousKey,
|
|
2073
|
+
entries: buildMethodGridEntries(paymentMethods, swapAssetOptions),
|
|
2074
|
+
selectedNetworks: selectedSwapNetworks
|
|
2075
|
+
});
|
|
2076
|
+
if (resolved.kind === "none") return;
|
|
2077
|
+
if (resolved.kind === "select_method") {
|
|
2078
|
+
setSelectedPickerKey(null);
|
|
2079
|
+
updateWizardSelection(
|
|
2080
|
+
(controller) => controller.selectMethod(resolved.methodId)
|
|
2081
|
+
);
|
|
2082
|
+
if (resolved.methodId === "bitcoin") void props.onRequestLightning?.();
|
|
2083
|
+
return;
|
|
2084
|
+
}
|
|
2085
|
+
if (resolved.kind === "start_swap") {
|
|
2086
|
+
setSelectedPickerKey(null);
|
|
2087
|
+
selectSwapAsset(resolved.payInAsset);
|
|
2088
|
+
return;
|
|
2089
|
+
}
|
|
2049
2090
|
setSelectedPickerKey(key);
|
|
2050
|
-
|
|
2051
|
-
setSelectedSwapNetworks(
|
|
2052
|
-
(current) => updateSelectedSwapNetworks({
|
|
2053
|
-
entries,
|
|
2054
|
-
nextKey: key,
|
|
2055
|
-
previousKey,
|
|
2056
|
-
selectedNetworks: current
|
|
2057
|
-
})
|
|
2058
|
-
);
|
|
2091
|
+
setSelectedSwapNetworks(resolved.selectedNetworks);
|
|
2059
2092
|
},
|
|
2060
2093
|
onSelectNetwork: (groupKey, payInAsset) => {
|
|
2061
2094
|
setSelectedSwapNetworks((current) => ({
|
|
@@ -2071,7 +2104,8 @@ function PaymentWizard(props) {
|
|
|
2071
2104
|
void props.onRequestLightning?.();
|
|
2072
2105
|
}
|
|
2073
2106
|
},
|
|
2074
|
-
onContinueSwap: selectSwapAsset
|
|
2107
|
+
onContinueSwap: selectSwapAsset,
|
|
2108
|
+
...resolveAssetUrl === void 0 ? {} : { resolveAssetUrl }
|
|
2075
2109
|
}) : null,
|
|
2076
2110
|
selection.selectedMethod === null ? null : React9.createElement(
|
|
2077
2111
|
"div",
|
|
@@ -2238,23 +2272,16 @@ function PaymentWizard(props) {
|
|
|
2238
2272
|
);
|
|
2239
2273
|
}
|
|
2240
2274
|
function renderCompactPaymentMethodSelector(options) {
|
|
2241
|
-
const
|
|
2275
|
+
const display = createMethodGridDisplay({
|
|
2276
|
+
entries: buildMethodGridEntries(paymentMethods, options.swapAssetOptions),
|
|
2277
|
+
selectedPickerKey: options.selectedPickerKey,
|
|
2278
|
+
selectedNetworks: options.selectedSwapNetworks,
|
|
2279
|
+
startingAsset: options.startingAsset,
|
|
2280
|
+
...options.checkout === void 0 ? {} : { checkout: options.checkout }
|
|
2281
|
+
});
|
|
2242
2282
|
const currenciesLoading = options.currenciesLoading === true && options.swapAssetOptions.length === 0;
|
|
2243
|
-
const
|
|
2244
|
-
const
|
|
2245
|
-
const networkRequired = selectedGroup !== void 0 && selectedGroup.options.length > 1;
|
|
2246
|
-
const selectedGroupKey = selectedGroup?.label.trim().toUpperCase();
|
|
2247
|
-
const selectedNetworkAsset = selectedGroupKey === void 0 ? void 0 : options.selectedSwapNetworks[selectedGroupKey];
|
|
2248
|
-
const selectedNetworkOption = selectedGroup === void 0 || selectedNetworkAsset === void 0 ? void 0 : selectedGroup.options.find((option) => option.pay_in_asset === selectedNetworkAsset);
|
|
2249
|
-
const continueTarget = selectedNetworkOption !== void 0 ? {
|
|
2250
|
-
payInAsset: selectedNetworkOption.pay_in_asset,
|
|
2251
|
-
disabled: selectedNetworkOption.available === false,
|
|
2252
|
-
limitMessage: swapOptionLimitMessage2(selectedNetworkOption, options.checkout)
|
|
2253
|
-
} : null;
|
|
2254
|
-
const startingAsset = options.startingAsset;
|
|
2255
|
-
const gridBusy = startingAsset !== null;
|
|
2256
|
-
const continueStarting = continueTarget !== null && continueTarget.payInAsset === startingAsset;
|
|
2257
|
-
const canContinue = continueTarget !== null && !continueTarget.disabled && selectedNetworkOption !== void 0 && !gridBusy;
|
|
2283
|
+
const { gridBusy, networkRequired, selectedGroup, continueTarget, canContinue } = display;
|
|
2284
|
+
const continueStarting = continueTarget?.starting === true;
|
|
2258
2285
|
const continueButton = (className) => React9.createElement(
|
|
2259
2286
|
"button",
|
|
2260
2287
|
{
|
|
@@ -2264,7 +2291,7 @@ function renderCompactPaymentMethodSelector(options) {
|
|
|
2264
2291
|
"aria-disabled": canContinue ? void 0 : "true",
|
|
2265
2292
|
"aria-busy": continueStarting ? "true" : void 0,
|
|
2266
2293
|
onClick: !canContinue ? void 0 : () => {
|
|
2267
|
-
if (continueTarget ===
|
|
2294
|
+
if (continueTarget === void 0) return;
|
|
2268
2295
|
options.onContinueSwap(continueTarget.payInAsset);
|
|
2269
2296
|
}
|
|
2270
2297
|
},
|
|
@@ -2276,14 +2303,10 @@ function renderCompactPaymentMethodSelector(options) {
|
|
|
2276
2303
|
"aria-hidden": "true"
|
|
2277
2304
|
}),
|
|
2278
2305
|
checkoutLabels5.preparingPayment
|
|
2279
|
-
) : continueTarget?.
|
|
2306
|
+
) : continueTarget?.label ?? checkoutLabels5.continue
|
|
2280
2307
|
);
|
|
2281
2308
|
const renderNetworkSelector = (group, mobile) => {
|
|
2282
|
-
const accent =
|
|
2283
|
-
const groupKey = group.label.trim().toUpperCase();
|
|
2284
|
-
const selectedAsset = options.selectedSwapNetworks[groupKey];
|
|
2285
|
-
const selectedOption = selectedAsset === void 0 ? void 0 : group.options.find((option) => option.pay_in_asset === selectedAsset);
|
|
2286
|
-
const { panelId, headingId } = wizardNetworkGroupIds(groupKey);
|
|
2309
|
+
const { accent, groupKey, panelId, headingId, selectedOption } = group;
|
|
2287
2310
|
return React9.createElement(
|
|
2288
2311
|
"div",
|
|
2289
2312
|
{
|
|
@@ -2304,7 +2327,7 @@ function renderCompactPaymentMethodSelector(options) {
|
|
|
2304
2327
|
id: headingId,
|
|
2305
2328
|
className: orClasses6.methodNetworkHeading
|
|
2306
2329
|
},
|
|
2307
|
-
|
|
2330
|
+
group.heading
|
|
2308
2331
|
),
|
|
2309
2332
|
React9.createElement(
|
|
2310
2333
|
"p",
|
|
@@ -2346,7 +2369,7 @@ function renderCompactPaymentMethodSelector(options) {
|
|
|
2346
2369
|
React9.createElement("img", {
|
|
2347
2370
|
alt: "",
|
|
2348
2371
|
className: orClasses6.methodNetworkIcon,
|
|
2349
|
-
src: getNetworkIcon(option.network_label)
|
|
2372
|
+
src: getNetworkIcon(option.network_label, options.resolveAssetUrl)
|
|
2350
2373
|
})
|
|
2351
2374
|
),
|
|
2352
2375
|
React9.createElement("span", { className: "truncate" }, option.network_label),
|
|
@@ -2418,23 +2441,22 @@ function renderCompactPaymentMethodSelector(options) {
|
|
|
2418
2441
|
"aria-label": checkoutLabels5.paymentMethod,
|
|
2419
2442
|
className: orClasses6.methodGrid
|
|
2420
2443
|
},
|
|
2421
|
-
...entries.map((entry) => {
|
|
2444
|
+
...display.entries.map((entry) => {
|
|
2422
2445
|
if (entry.kind === "method") {
|
|
2423
2446
|
const method = entry.method;
|
|
2424
|
-
const accent2 = paymentAccentId(method.id);
|
|
2425
2447
|
return React9.createElement(
|
|
2426
2448
|
"button",
|
|
2427
2449
|
{
|
|
2428
2450
|
key: method.id,
|
|
2429
2451
|
type: "button",
|
|
2430
2452
|
className: assetButtonClasses({
|
|
2431
|
-
accent:
|
|
2453
|
+
accent: entry.accent,
|
|
2432
2454
|
selected: false,
|
|
2433
|
-
disabled:
|
|
2455
|
+
disabled: entry.disabled
|
|
2434
2456
|
}),
|
|
2435
|
-
disabled:
|
|
2436
|
-
"aria-disabled":
|
|
2437
|
-
onClick:
|
|
2457
|
+
disabled: entry.disabled,
|
|
2458
|
+
"aria-disabled": entry.disabled ? "true" : void 0,
|
|
2459
|
+
onClick: entry.disabled ? void 0 : () => options.onContinueMethod(method.id)
|
|
2438
2460
|
},
|
|
2439
2461
|
React9.createElement(
|
|
2440
2462
|
"span",
|
|
@@ -2442,7 +2464,7 @@ function renderCompactPaymentMethodSelector(options) {
|
|
|
2442
2464
|
React9.createElement("img", {
|
|
2443
2465
|
alt: "",
|
|
2444
2466
|
className: orClasses6.methodIcon,
|
|
2445
|
-
src: getPaymentMethodIcon(method.id)
|
|
2467
|
+
src: getPaymentMethodIcon(method.id, options.resolveAssetUrl)
|
|
2446
2468
|
})
|
|
2447
2469
|
),
|
|
2448
2470
|
React9.createElement(
|
|
@@ -2453,21 +2475,18 @@ function renderCompactPaymentMethodSelector(options) {
|
|
|
2453
2475
|
);
|
|
2454
2476
|
}
|
|
2455
2477
|
const group = entry.group;
|
|
2456
|
-
const
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
const limitOption = disabled ? swapGroupLimitOption(group.options) ?? activeOption : activeOption;
|
|
2469
|
-
const limitMessage = swapOptionLimitMessage2(limitOption, options.checkout);
|
|
2470
|
-
const { panelId } = wizardNetworkGroupIds(groupKey);
|
|
2478
|
+
const {
|
|
2479
|
+
pickerKey,
|
|
2480
|
+
selected,
|
|
2481
|
+
multiNetwork,
|
|
2482
|
+
displayOption,
|
|
2483
|
+
selectedOption,
|
|
2484
|
+
starting,
|
|
2485
|
+
disabled,
|
|
2486
|
+
accent,
|
|
2487
|
+
limitMessage,
|
|
2488
|
+
panelId
|
|
2489
|
+
} = group;
|
|
2471
2490
|
return React9.createElement(
|
|
2472
2491
|
"div",
|
|
2473
2492
|
{ key: pickerKey, className: orClasses6.methodTile },
|
|
@@ -2486,7 +2505,14 @@ function renderCompactPaymentMethodSelector(options) {
|
|
|
2486
2505
|
selected: starting || multiNetwork && selected,
|
|
2487
2506
|
disabled: disabled || gridBusy && !starting
|
|
2488
2507
|
}),
|
|
2489
|
-
onClick: disabled || gridBusy ? void 0 :
|
|
2508
|
+
onClick: disabled || gridBusy ? void 0 : (
|
|
2509
|
+
// `needsNetworkStep` / `startPayInAsset` are the
|
|
2510
|
+
// options.length > 1 rule as DATA, so neither renderer
|
|
2511
|
+
// re-derives which of the two a tile click means.
|
|
2512
|
+
group.needsNetworkStep ? () => options.onSelectPicker(pickerKey, options.selectedPickerKey) : () => options.onContinueSwap(
|
|
2513
|
+
group.startPayInAsset ?? displayOption.pay_in_asset
|
|
2514
|
+
)
|
|
2515
|
+
)
|
|
2490
2516
|
},
|
|
2491
2517
|
React9.createElement(
|
|
2492
2518
|
"span",
|
|
@@ -2497,7 +2523,7 @@ function renderCompactPaymentMethodSelector(options) {
|
|
|
2497
2523
|
}) : React9.createElement("img", {
|
|
2498
2524
|
alt: "",
|
|
2499
2525
|
className: orClasses6.methodIcon,
|
|
2500
|
-
src: getSwapOptionIcon(displayOption)
|
|
2526
|
+
src: getSwapOptionIcon(displayOption, options.resolveAssetUrl)
|
|
2501
2527
|
})
|
|
2502
2528
|
),
|
|
2503
2529
|
React9.createElement(
|
|
@@ -2643,13 +2669,13 @@ function renderWizardBreadcrumbs(options) {
|
|
|
2643
2669
|
function swapOptionsForRoute(routeKey, options) {
|
|
2644
2670
|
return options.filter((option) => swapAssetMatchesRoute(routeKey, option.pay_in_asset));
|
|
2645
2671
|
}
|
|
2646
|
-
function
|
|
2647
|
-
const
|
|
2648
|
-
(invoice
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2672
|
+
function resolveAttemptPaymentHash(invoices, attemptId) {
|
|
2673
|
+
for (const invoice of invoices) {
|
|
2674
|
+
if (invoice == null) continue;
|
|
2675
|
+
if ((invoice.swap?.attempt_id ?? invoice.invoice_id) !== attemptId) continue;
|
|
2676
|
+
if (invoice.payment_hash !== void 0) return invoice.payment_hash;
|
|
2677
|
+
}
|
|
2678
|
+
throw new Error(`No swap attempt ${attemptId} in this checkout.`);
|
|
2653
2679
|
}
|
|
2654
2680
|
function renderRoutePicker(options) {
|
|
2655
2681
|
return React9.createElement(
|
|
@@ -2890,6 +2916,8 @@ function CheckoutView(props) {
|
|
|
2890
2916
|
components,
|
|
2891
2917
|
classNames,
|
|
2892
2918
|
children,
|
|
2919
|
+
resolveAssetUrl,
|
|
2920
|
+
assetBaseUrl,
|
|
2893
2921
|
className,
|
|
2894
2922
|
...sectionProps
|
|
2895
2923
|
} = props;
|
|
@@ -2960,6 +2988,21 @@ function CheckoutView(props) {
|
|
|
2960
2988
|
...ownsTheme ? theme.attributes : {}
|
|
2961
2989
|
},
|
|
2962
2990
|
customChildren === void 0 ? [
|
|
2991
|
+
// Above the amount and OUTSIDE the Lightning pane, which drops out on
|
|
2992
|
+
// the swap deposit panel, on expiry and on the receipt — the payer
|
|
2993
|
+
// needs to know what they are buying on all four screens.
|
|
2994
|
+
checkoutModel.checkout.description === void 0 || checkoutModel.checkout.description === "" ? null : React10.createElement(
|
|
2995
|
+
"p",
|
|
2996
|
+
{
|
|
2997
|
+
key: "order-description",
|
|
2998
|
+
className: joinClassNames(
|
|
2999
|
+
orClasses7.orderDescription,
|
|
3000
|
+
classNames?.orderDescription
|
|
3001
|
+
),
|
|
3002
|
+
[OPENRECEIVE_CHECKOUT_DATA_ATTRIBUTES3.orderDescription]: ""
|
|
3003
|
+
},
|
|
3004
|
+
checkoutModel.checkout.description
|
|
3005
|
+
),
|
|
2963
3006
|
ownsTheme ? React10.createElement(ThemeToggle, {
|
|
2964
3007
|
key: "theme",
|
|
2965
3008
|
className: classNames?.themeToggle,
|
|
@@ -3033,16 +3076,25 @@ function CheckoutView(props) {
|
|
|
3033
3076
|
className: classNames?.summary,
|
|
3034
3077
|
classNames
|
|
3035
3078
|
}) : null,
|
|
3036
|
-
settled ? React10.createElement(
|
|
3037
|
-
key: "
|
|
3038
|
-
// The model IS the checkout state, so the
|
|
3039
|
-
//
|
|
3040
|
-
//
|
|
3041
|
-
//
|
|
3079
|
+
settled ? React10.createElement(TransactionDetails, {
|
|
3080
|
+
key: "transaction-details",
|
|
3081
|
+
// The model IS the checkout state, so the panel reads
|
|
3082
|
+
// the same derivation the rest of the screen does. It
|
|
3083
|
+
// used to re-flatten the snapshot separately, which
|
|
3084
|
+
// reported the displayed ATTEMPT's transaction /
|
|
3042
3085
|
// workflow state on a checkout the state already knows
|
|
3043
3086
|
// is paid.
|
|
3044
|
-
|
|
3045
|
-
|
|
3087
|
+
//
|
|
3088
|
+
// The SAME panel the swap flow renders one screen
|
|
3089
|
+
// earlier. A payer's whole evidence that they paid is a
|
|
3090
|
+
// payment hash and, on a swap, a deposit txid — so the
|
|
3091
|
+
// most keep-worthy screen gets copy buttons and
|
|
3092
|
+
// explorer links, not un-copyable text. No
|
|
3093
|
+
// `decodeLinkUrl` is passed, so the bolt11 never
|
|
3094
|
+
// reaches a third party.
|
|
3095
|
+
state: checkoutModel,
|
|
3096
|
+
className: classNames?.details,
|
|
3097
|
+
onError
|
|
3046
3098
|
}) : expired ? React10.createElement(
|
|
3047
3099
|
"div",
|
|
3048
3100
|
{
|
|
@@ -3120,7 +3172,12 @@ function CheckoutView(props) {
|
|
|
3120
3172
|
onProviderCopy,
|
|
3121
3173
|
onCopy,
|
|
3122
3174
|
onRequestLightning,
|
|
3123
|
-
onSwapStarted
|
|
3175
|
+
onSwapStarted,
|
|
3176
|
+
resolveAssetUrl,
|
|
3177
|
+
assetBaseUrl,
|
|
3178
|
+
// The engine's staged refund address rides the controller this
|
|
3179
|
+
// model owns, so a poll cannot wipe a review in progress.
|
|
3180
|
+
swapRefund: checkoutModel
|
|
3124
3181
|
}) : null
|
|
3125
3182
|
] : customChildren
|
|
3126
3183
|
);
|
|
@@ -3153,7 +3210,6 @@ export {
|
|
|
3153
3210
|
CopyInvoiceButton,
|
|
3154
3211
|
InvoiceSummary,
|
|
3155
3212
|
OpenWalletButton,
|
|
3156
|
-
PaymentData,
|
|
3157
3213
|
PaymentState,
|
|
3158
3214
|
PaymentWizard,
|
|
3159
3215
|
QRCode,
|