@pollar/react 0.10.1-rc.0 → 0.10.1-rc.1
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.css +37 -9
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +183 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +183 -45
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1033,7 +1033,7 @@ var PollarModalFooter = () => {
|
|
|
1033
1033
|
/* @__PURE__ */ jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
|
|
1034
1034
|
/* @__PURE__ */ jsxs("span", { className: "pollar-footer-version", children: [
|
|
1035
1035
|
"v",
|
|
1036
|
-
"0.10.1-rc.
|
|
1036
|
+
"0.10.1-rc.1"
|
|
1037
1037
|
] })
|
|
1038
1038
|
] })
|
|
1039
1039
|
] });
|
|
@@ -2457,14 +2457,12 @@ function RouteDisplay({ quote, onSelect }) {
|
|
|
2457
2457
|
);
|
|
2458
2458
|
}
|
|
2459
2459
|
var LOADING_STEPS = ["Detecting your country\u2026", "Consulting providers\u2026", "Route found!"];
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
AR: "ARS"
|
|
2467
|
-
};
|
|
2460
|
+
function flagEmoji(code) {
|
|
2461
|
+
const cc = code.trim().toUpperCase();
|
|
2462
|
+
if (!/^[A-Z]{2}$/.test(cc)) return "";
|
|
2463
|
+
const base = 127462;
|
|
2464
|
+
return String.fromCodePoint(base + (cc.charCodeAt(0) - 65), base + (cc.charCodeAt(1) - 65));
|
|
2465
|
+
}
|
|
2468
2466
|
var STATUS_LABEL = {
|
|
2469
2467
|
pending: "Pending",
|
|
2470
2468
|
processing: "Processing",
|
|
@@ -2479,6 +2477,9 @@ function RampWidgetTemplate({
|
|
|
2479
2477
|
amount,
|
|
2480
2478
|
currency,
|
|
2481
2479
|
country,
|
|
2480
|
+
countries,
|
|
2481
|
+
countriesLoading,
|
|
2482
|
+
refreshing,
|
|
2482
2483
|
quotes,
|
|
2483
2484
|
isLoading,
|
|
2484
2485
|
provider,
|
|
@@ -2497,6 +2498,7 @@ function RampWidgetTemplate({
|
|
|
2497
2498
|
onOpenKyc,
|
|
2498
2499
|
onCompleteWithdraw,
|
|
2499
2500
|
onRetry,
|
|
2501
|
+
onRefresh,
|
|
2500
2502
|
onClose
|
|
2501
2503
|
}) {
|
|
2502
2504
|
const isDark = theme === "dark";
|
|
@@ -2535,9 +2537,35 @@ function RampWidgetTemplate({
|
|
|
2535
2537
|
error: "Please try again"
|
|
2536
2538
|
};
|
|
2537
2539
|
return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-ramp-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
|
|
2538
|
-
/* @__PURE__ */ jsxs("div", { className: "pollar-
|
|
2539
|
-
/* @__PURE__ */
|
|
2540
|
-
|
|
2540
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
|
|
2541
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-header-text", children: [
|
|
2542
|
+
/* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: stepTitle[step] }),
|
|
2543
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-ramp-subtitle", children: stepSubtitle[step] })
|
|
2544
|
+
] }),
|
|
2545
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-modal-header-actions", children: [
|
|
2546
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onRefresh, disabled: refreshing, "aria-label": "Refresh", children: /* @__PURE__ */ jsx(
|
|
2547
|
+
"svg",
|
|
2548
|
+
{
|
|
2549
|
+
className: refreshing ? "pollar-modal-refresh-icon spinning" : "pollar-modal-refresh-icon",
|
|
2550
|
+
width: "16",
|
|
2551
|
+
height: "16",
|
|
2552
|
+
viewBox: "0 0 16 16",
|
|
2553
|
+
fill: "none",
|
|
2554
|
+
"aria-hidden": true,
|
|
2555
|
+
children: /* @__PURE__ */ jsx(
|
|
2556
|
+
"path",
|
|
2557
|
+
{
|
|
2558
|
+
d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
|
|
2559
|
+
stroke: "currentColor",
|
|
2560
|
+
strokeWidth: "1.6",
|
|
2561
|
+
strokeLinecap: "round",
|
|
2562
|
+
strokeLinejoin: "round"
|
|
2563
|
+
}
|
|
2564
|
+
)
|
|
2565
|
+
}
|
|
2566
|
+
) }),
|
|
2567
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
|
|
2568
|
+
] })
|
|
2541
2569
|
] }),
|
|
2542
2570
|
step === "input" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2543
2571
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-tabs", children: [
|
|
@@ -2594,30 +2622,25 @@ function RampWidgetTemplate({
|
|
|
2594
2622
|
] }),
|
|
2595
2623
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
|
|
2596
2624
|
/* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", children: "Country" }),
|
|
2597
|
-
/* @__PURE__ */ jsxs(
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
const c = e.target.value;
|
|
2604
|
-
onCountryChange(c);
|
|
2605
|
-
if (COUNTRY_CURRENCIES[c]) onCurrencyChange(COUNTRY_CURRENCIES[c]);
|
|
2606
|
-
},
|
|
2607
|
-
children: [
|
|
2608
|
-
/* @__PURE__ */ jsx("option", { value: "MX", children: "\u{1F1F2}\u{1F1FD} Mexico" }),
|
|
2609
|
-
/* @__PURE__ */ jsx("option", { value: "BR", children: "\u{1F1E7}\u{1F1F7} Brazil" }),
|
|
2610
|
-
/* @__PURE__ */ jsx("option", { value: "CO", children: "\u{1F1E8}\u{1F1F4} Colombia" }),
|
|
2611
|
-
/* @__PURE__ */ jsx("option", { value: "CL", children: "\u{1F1E8}\u{1F1F1} Chile" }),
|
|
2612
|
-
/* @__PURE__ */ jsx("option", { value: "PE", children: "\u{1F1F5}\u{1F1EA} Peru" }),
|
|
2613
|
-
/* @__PURE__ */ jsx("option", { value: "AR", children: "\u{1F1E6}\u{1F1F7} Argentina" })
|
|
2614
|
-
]
|
|
2615
|
-
}
|
|
2616
|
-
)
|
|
2625
|
+
countriesLoading ? /* @__PURE__ */ jsx("div", { className: "pollar-ramp-input pollar-ramp-input-loading", children: "Loading countries\u2026" }) : countries.length === 0 ? /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: "No ramp providers available on this network yet." }) : /* @__PURE__ */ jsx("select", { className: "pollar-ramp-input", value: country, onChange: (e) => onCountryChange(e.target.value), children: countries.map((c) => /* @__PURE__ */ jsxs("option", { value: c.code, children: [
|
|
2626
|
+
flagEmoji(c.code),
|
|
2627
|
+
" ",
|
|
2628
|
+
c.code,
|
|
2629
|
+
c.currency ? ` \u2014 ${c.currency}` : ""
|
|
2630
|
+
] }, c.code)) })
|
|
2617
2631
|
] }),
|
|
2618
2632
|
/* @__PURE__ */ jsxs("div", { className: "pollar-modal-actions", children: [
|
|
2619
2633
|
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" }),
|
|
2620
|
-
/* @__PURE__ */ jsx(
|
|
2634
|
+
/* @__PURE__ */ jsx(
|
|
2635
|
+
"button",
|
|
2636
|
+
{
|
|
2637
|
+
type: "button",
|
|
2638
|
+
className: "pollar-btn-primary",
|
|
2639
|
+
disabled: !amount || isLoading || countriesLoading || countries.length === 0,
|
|
2640
|
+
onClick: onFindRoute,
|
|
2641
|
+
children: "Find best route"
|
|
2642
|
+
}
|
|
2643
|
+
)
|
|
2621
2644
|
] })
|
|
2622
2645
|
] }),
|
|
2623
2646
|
step === "loading_quote" && /* @__PURE__ */ jsx("div", { className: "pollar-ramp-loading", children: LOADING_STEPS.map((text, i) => /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-loading-row", children: [
|
|
@@ -2635,13 +2658,7 @@ function RampWidgetTemplate({
|
|
|
2635
2658
|
] }),
|
|
2636
2659
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2637
2660
|
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Status" }),
|
|
2638
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsx(
|
|
2639
|
-
"code",
|
|
2640
|
-
{
|
|
2641
|
-
style: { color: txStatus === "completed" ? "var(--pollar-success-text)" : void 0 },
|
|
2642
|
-
children: txStatus ? STATUS_LABEL[txStatus] : "Processing"
|
|
2643
|
-
}
|
|
2644
|
-
) })
|
|
2661
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsx("code", { style: { color: txStatus === "completed" ? "var(--pollar-success-text)" : void 0 }, children: txStatus ? STATUS_LABEL[txStatus] : "Processing" }) })
|
|
2645
2662
|
] }),
|
|
2646
2663
|
stellarTxHash && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2647
2664
|
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Stellar tx" }),
|
|
@@ -2677,8 +2694,11 @@ function RampWidget({ onClose }) {
|
|
|
2677
2694
|
const [step, setStep] = useState("input");
|
|
2678
2695
|
const [direction, setDirection] = useState("onramp");
|
|
2679
2696
|
const [amount, setAmount] = useState("");
|
|
2680
|
-
const [currency, setCurrency] = useState("
|
|
2681
|
-
const [country, setCountry] = useState("
|
|
2697
|
+
const [currency, setCurrency] = useState("");
|
|
2698
|
+
const [country, setCountry] = useState("");
|
|
2699
|
+
const [countries, setCountries] = useState([]);
|
|
2700
|
+
const [countriesLoading, setCountriesLoading] = useState(true);
|
|
2701
|
+
const [refreshing, setRefreshing] = useState(false);
|
|
2682
2702
|
const [quotes, setQuotes] = useState([]);
|
|
2683
2703
|
const [isLoading, setIsLoading] = useState(false);
|
|
2684
2704
|
const [txId, setTxId] = useState(null);
|
|
@@ -2710,6 +2730,50 @@ function RampWidget({ onClose }) {
|
|
|
2710
2730
|
clearInterval(id);
|
|
2711
2731
|
};
|
|
2712
2732
|
}, [step, txId, txStatus, client]);
|
|
2733
|
+
async function loadCountries(resetSelection) {
|
|
2734
|
+
setCountriesLoading(true);
|
|
2735
|
+
try {
|
|
2736
|
+
const { countries: list } = await client.getRampCountries();
|
|
2737
|
+
setCountries(list);
|
|
2738
|
+
const first = list[0];
|
|
2739
|
+
const stillValid = list.some((c) => c.code === country);
|
|
2740
|
+
if (first && (resetSelection || !stillValid)) {
|
|
2741
|
+
setCountry(first.code);
|
|
2742
|
+
if (first.currency) setCurrency(first.currency);
|
|
2743
|
+
}
|
|
2744
|
+
} catch {
|
|
2745
|
+
setCountries([]);
|
|
2746
|
+
} finally {
|
|
2747
|
+
setCountriesLoading(false);
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
useEffect(() => {
|
|
2751
|
+
loadCountries(true);
|
|
2752
|
+
}, []);
|
|
2753
|
+
function handleCountryChange(code) {
|
|
2754
|
+
setCountry(code);
|
|
2755
|
+
const match = countries.find((c) => c.code === code);
|
|
2756
|
+
if (match?.currency) setCurrency(match.currency);
|
|
2757
|
+
}
|
|
2758
|
+
async function handleRefresh() {
|
|
2759
|
+
if (refreshing) return;
|
|
2760
|
+
setRefreshing(true);
|
|
2761
|
+
try {
|
|
2762
|
+
await loadCountries(false);
|
|
2763
|
+
if (step === "select_route") {
|
|
2764
|
+
const result = await client.getRampsQuote({ country, amount: Number(amount), currency, direction });
|
|
2765
|
+
setQuotes(result.quotes ?? []);
|
|
2766
|
+
} else if (step === "status" && txId) {
|
|
2767
|
+
const tx = await client.getRampTransaction(txId);
|
|
2768
|
+
setTxStatus(tx.status);
|
|
2769
|
+
if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
|
|
2770
|
+
if (tx.kycUrl) setKycUrl(tx.kycUrl);
|
|
2771
|
+
}
|
|
2772
|
+
} catch {
|
|
2773
|
+
} finally {
|
|
2774
|
+
setRefreshing(false);
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2713
2777
|
function resetToInput() {
|
|
2714
2778
|
setStep("input");
|
|
2715
2779
|
setQuotes([]);
|
|
@@ -2815,6 +2879,9 @@ function RampWidget({ onClose }) {
|
|
|
2815
2879
|
amount,
|
|
2816
2880
|
currency,
|
|
2817
2881
|
country,
|
|
2882
|
+
countries,
|
|
2883
|
+
countriesLoading,
|
|
2884
|
+
refreshing,
|
|
2818
2885
|
quotes,
|
|
2819
2886
|
isLoading,
|
|
2820
2887
|
provider,
|
|
@@ -2827,12 +2894,13 @@ function RampWidget({ onClose }) {
|
|
|
2827
2894
|
onDirectionChange: setDirection,
|
|
2828
2895
|
onAmountChange: setAmount,
|
|
2829
2896
|
onCurrencyChange: setCurrency,
|
|
2830
|
-
onCountryChange:
|
|
2897
|
+
onCountryChange: handleCountryChange,
|
|
2831
2898
|
onFindRoute: handleFindRoute,
|
|
2832
2899
|
onSelectQuote: handleSelectQuote,
|
|
2833
2900
|
onOpenKyc: handleOpenKyc,
|
|
2834
2901
|
onCompleteWithdraw: handleCompleteWithdraw,
|
|
2835
2902
|
onRetry: resetToInput,
|
|
2903
|
+
onRefresh: handleRefresh,
|
|
2836
2904
|
onClose
|
|
2837
2905
|
}
|
|
2838
2906
|
) });
|
|
@@ -3542,6 +3610,7 @@ function SwapModalTemplate({
|
|
|
3542
3610
|
onRefresh,
|
|
3543
3611
|
onSelectSell,
|
|
3544
3612
|
onSelectBuy,
|
|
3613
|
+
onAddCustomToken,
|
|
3545
3614
|
onAmountChange,
|
|
3546
3615
|
onProviderChange,
|
|
3547
3616
|
onSwap,
|
|
@@ -3551,6 +3620,21 @@ function SwapModalTemplate({
|
|
|
3551
3620
|
onDone
|
|
3552
3621
|
}) {
|
|
3553
3622
|
const isDark = theme === "dark";
|
|
3623
|
+
const [customOpen, setCustomOpen] = useState(false);
|
|
3624
|
+
const [customCode, setCustomCode] = useState("");
|
|
3625
|
+
const [customIssuer, setCustomIssuer] = useState("");
|
|
3626
|
+
const [customError, setCustomError] = useState("");
|
|
3627
|
+
const submitCustomToken = () => {
|
|
3628
|
+
const err = onAddCustomToken(customCode, customIssuer);
|
|
3629
|
+
if (err) {
|
|
3630
|
+
setCustomError(err);
|
|
3631
|
+
return;
|
|
3632
|
+
}
|
|
3633
|
+
setCustomCode("");
|
|
3634
|
+
setCustomIssuer("");
|
|
3635
|
+
setCustomError("");
|
|
3636
|
+
setCustomOpen(false);
|
|
3637
|
+
};
|
|
3554
3638
|
const cssVars = {
|
|
3555
3639
|
"--pollar-accent": accentColor,
|
|
3556
3640
|
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
@@ -3669,7 +3753,45 @@ function SwapModalTemplate({
|
|
|
3669
3753
|
] }, assetOptionKey(o)))
|
|
3670
3754
|
]
|
|
3671
3755
|
}
|
|
3672
|
-
)
|
|
3756
|
+
),
|
|
3757
|
+
!isLoadingData && (customOpen ? /* @__PURE__ */ jsxs("div", { className: "pollar-swap-custom", children: [
|
|
3758
|
+
/* @__PURE__ */ jsx(
|
|
3759
|
+
"input",
|
|
3760
|
+
{
|
|
3761
|
+
className: "pollar-input",
|
|
3762
|
+
type: "text",
|
|
3763
|
+
placeholder: "Code (e.g. USDC)",
|
|
3764
|
+
value: customCode,
|
|
3765
|
+
onChange: (e) => setCustomCode(e.target.value)
|
|
3766
|
+
}
|
|
3767
|
+
),
|
|
3768
|
+
/* @__PURE__ */ jsx(
|
|
3769
|
+
"input",
|
|
3770
|
+
{
|
|
3771
|
+
className: "pollar-input",
|
|
3772
|
+
type: "text",
|
|
3773
|
+
placeholder: "Issuer (G...)",
|
|
3774
|
+
value: customIssuer,
|
|
3775
|
+
onChange: (e) => setCustomIssuer(e.target.value)
|
|
3776
|
+
}
|
|
3777
|
+
),
|
|
3778
|
+
customError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: customError }),
|
|
3779
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-swap-custom-actions", children: [
|
|
3780
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", onClick: submitCustomToken, children: "Add token" }),
|
|
3781
|
+
/* @__PURE__ */ jsx(
|
|
3782
|
+
"button",
|
|
3783
|
+
{
|
|
3784
|
+
type: "button",
|
|
3785
|
+
className: "pollar-swap-custom-cancel",
|
|
3786
|
+
onClick: () => {
|
|
3787
|
+
setCustomOpen(false);
|
|
3788
|
+
setCustomError("");
|
|
3789
|
+
},
|
|
3790
|
+
children: "Cancel"
|
|
3791
|
+
}
|
|
3792
|
+
)
|
|
3793
|
+
] })
|
|
3794
|
+
] }) : /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-swap-custom-toggle", onClick: () => setCustomOpen(true), children: "+ Add a token by code / issuer" }))
|
|
3673
3795
|
] }),
|
|
3674
3796
|
/* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
|
|
3675
3797
|
/* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Route" }),
|
|
@@ -3777,6 +3899,7 @@ function SwapModal({ onClose }) {
|
|
|
3777
3899
|
const [provider, setProvider] = useState("auto");
|
|
3778
3900
|
const [venues, setVenues] = useState(null);
|
|
3779
3901
|
const [catalogTokens, setCatalogTokens] = useState([]);
|
|
3902
|
+
const [customTokens, setCustomTokens] = useState([]);
|
|
3780
3903
|
const [quotes, setQuotes] = useState([]);
|
|
3781
3904
|
const [quoteLoading, setQuoteLoading] = useState(false);
|
|
3782
3905
|
const [quoteError, setQuoteError] = useState("");
|
|
@@ -3834,7 +3957,21 @@ function SwapModal({ onClose }) {
|
|
|
3834
3957
|
issuer: tk.issuer,
|
|
3835
3958
|
enabledInApp: false
|
|
3836
3959
|
})).filter((o) => !enabledKeys.has(optKey(o)));
|
|
3837
|
-
const
|
|
3960
|
+
const knownKeys = /* @__PURE__ */ new Set([...enabledKeys, ...catalogBuy.map(optKey)]);
|
|
3961
|
+
const customBuy = customTokens.filter((o) => !knownKeys.has(optKey(o)));
|
|
3962
|
+
const buyOptions = [...enabledBuy, ...catalogBuy, ...customBuy].filter(
|
|
3963
|
+
(o) => optKey(o) !== buyKeyOfSell
|
|
3964
|
+
);
|
|
3965
|
+
function addCustomToken(code, issuer) {
|
|
3966
|
+
const c = code.trim().toUpperCase();
|
|
3967
|
+
const i = issuer.trim();
|
|
3968
|
+
if (c.length < 1 || c.length > 12) return "Code must be 1-12 characters";
|
|
3969
|
+
if (i.length !== 56 || !i.startsWith("G")) return "Issuer must be a Stellar address (G..., 56 chars)";
|
|
3970
|
+
const opt = { ref: catalogRef(c, i), code: c, issuer: i, enabledInApp: false };
|
|
3971
|
+
setCustomTokens((prev) => prev.some((o) => optKey(o) === optKey(opt)) ? prev : [...prev, opt]);
|
|
3972
|
+
setSelectedBuy(opt);
|
|
3973
|
+
return null;
|
|
3974
|
+
}
|
|
3838
3975
|
const buyNeedsTrustline = (() => {
|
|
3839
3976
|
if (!selectedBuy || smartUnsupported) return false;
|
|
3840
3977
|
if (selectedBuy.ref.type === "native") return false;
|
|
@@ -3974,6 +4111,7 @@ function SwapModal({ onClose }) {
|
|
|
3974
4111
|
onRefresh: handleRefresh,
|
|
3975
4112
|
onSelectSell: setSelectedSell,
|
|
3976
4113
|
onSelectBuy: setSelectedBuy,
|
|
4114
|
+
onAddCustomToken: addCustomToken,
|
|
3977
4115
|
onAmountChange: setAmount,
|
|
3978
4116
|
onProviderChange: setProvider,
|
|
3979
4117
|
onSwap: () => void handleSwap(),
|