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