@pollar/react 0.10.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 +47 -9
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +26 -3
- package/dist/index.d.ts +26 -3
- package/dist/index.js +291 -60
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +291 -60
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { pollarPaths, PollarClient, PollarClientConfig, PollarAdapters, OnStorageDegrade, WalletInfo, PollarLoginOptions, SessionsState, TransactionState, TxBuildBody, BuildOutcome, SubmitOutcome, SignOutcome, StellarNetwork, WalletBalanceState, EnabledAssetsState, TrustlineOutcome, TxHistoryState, SwapQuoteParams, SwapQuote, PollarAdapter, WalletId, KycStatus as KycStatus$1, RampQuote, AuthState, KycProvider, KycStartResponse, RampDirection, RampTxStatus, EnabledAssetRecord, WalletBalanceRecord, SwapProvider, DistributionRulesState, DistributionRule } from '@pollar/core';
|
|
2
|
+
import { pollarPaths, PollarClient, PollarClientConfig, PollarAdapters, OnStorageDegrade, WalletInfo, PollarLoginOptions, SessionsState, TransactionState, TxBuildBody, BuildOutcome, SubmitOutcome, SignOutcome, StellarNetwork, WalletBalanceState, EnabledAssetsState, TrustlineOutcome, TxHistoryState, SwapVenue, SwapToken, SwapQuoteParams, SwapQuote, PollarAdapter, WalletId, KycStatus as KycStatus$1, RampQuote, AuthState, KycProvider, KycStartResponse, RampDirection, RampCountry, RampTxStatus, EnabledAssetRecord, WalletBalanceRecord, SwapProvider, DistributionRulesState, DistributionRule } from '@pollar/core';
|
|
3
3
|
export { AuthProviderContext, PollarAuthProvider, SessionsState } from '@pollar/core';
|
|
4
4
|
import { ReactNode } from 'react';
|
|
5
5
|
|
|
@@ -91,6 +91,16 @@ interface PollarContextValue {
|
|
|
91
91
|
openWalletBalanceModal: () => void;
|
|
92
92
|
openSendModal: () => void;
|
|
93
93
|
openReceiveModal: () => void;
|
|
94
|
+
/**
|
|
95
|
+
* The swap venues this app exposes to end-users (empty = swap disabled, hide
|
|
96
|
+
* swap UI). Mirrors {@link PollarClient.getSwapConfig}.
|
|
97
|
+
*/
|
|
98
|
+
getSwapConfig: () => Promise<SwapVenue[]>;
|
|
99
|
+
/**
|
|
100
|
+
* The curated "buy" tokens this app opted into (admin catalog). Mirrors
|
|
101
|
+
* {@link PollarClient.getSwapTokens}.
|
|
102
|
+
*/
|
|
103
|
+
getSwapTokens: () => Promise<SwapToken[]>;
|
|
94
104
|
/**
|
|
95
105
|
* Quote an asset-to-asset swap across the requested venue(s). Read-only;
|
|
96
106
|
* returns quotes ranked best-first. Mirrors {@link PollarClient.getSwapQuote}.
|
|
@@ -307,6 +317,9 @@ interface RampWidgetTemplateProps {
|
|
|
307
317
|
amount: string;
|
|
308
318
|
currency: string;
|
|
309
319
|
country: string;
|
|
320
|
+
countries: RampCountry[];
|
|
321
|
+
countriesLoading: boolean;
|
|
322
|
+
refreshing: boolean;
|
|
310
323
|
quotes: RampQuote[];
|
|
311
324
|
isLoading: boolean;
|
|
312
325
|
provider: string;
|
|
@@ -325,9 +338,10 @@ interface RampWidgetTemplateProps {
|
|
|
325
338
|
onOpenKyc: () => void;
|
|
326
339
|
onCompleteWithdraw: () => void;
|
|
327
340
|
onRetry: () => void;
|
|
341
|
+
onRefresh: () => void;
|
|
328
342
|
onClose: () => void;
|
|
329
343
|
}
|
|
330
|
-
declare function RampWidgetTemplate({ theme, accentColor, step, direction, amount, currency, country, quotes, isLoading, provider, txStatus, kycUrl, stellarTxHash, canComplete, completing, errorMsg, onDirectionChange, onAmountChange, onCurrencyChange, onCountryChange, onFindRoute, onSelectQuote, onOpenKyc, onCompleteWithdraw, onRetry, onClose, }: RampWidgetTemplateProps): react_jsx_runtime.JSX.Element;
|
|
344
|
+
declare function RampWidgetTemplate({ theme, accentColor, step, direction, amount, currency, country, countries, countriesLoading, refreshing, quotes, isLoading, provider, txStatus, kycUrl, stellarTxHash, canComplete, completing, errorMsg, onDirectionChange, onAmountChange, onCurrencyChange, onCountryChange, onFindRoute, onSelectQuote, onOpenKyc, onCompleteWithdraw, onRetry, onRefresh, onClose, }: RampWidgetTemplateProps): react_jsx_runtime.JSX.Element;
|
|
331
345
|
|
|
332
346
|
interface TransactionModalTemplateProps {
|
|
333
347
|
theme: string;
|
|
@@ -454,6 +468,12 @@ interface SwapModalTemplateProps {
|
|
|
454
468
|
formError: string;
|
|
455
469
|
isLoadingData: boolean;
|
|
456
470
|
smartUnsupported: boolean;
|
|
471
|
+
/** Swap config is still loading. */
|
|
472
|
+
configLoading: boolean;
|
|
473
|
+
/** Config loaded and this app exposes no swap venues — swap is disabled. */
|
|
474
|
+
swapUnavailable: boolean;
|
|
475
|
+
/** Buying the selected asset will create a trustline first (~0.5 XLM reserve). */
|
|
476
|
+
buyNeedsTrustline: boolean;
|
|
457
477
|
transaction: TransactionState;
|
|
458
478
|
showXdr: boolean;
|
|
459
479
|
copied: boolean;
|
|
@@ -463,8 +483,11 @@ interface SwapModalTemplateProps {
|
|
|
463
483
|
isInProgress: boolean;
|
|
464
484
|
onClose: () => void;
|
|
465
485
|
onBack: () => void;
|
|
486
|
+
onRefresh: () => void;
|
|
466
487
|
onSelectSell: (o: SwapAssetOption) => void;
|
|
467
488
|
onSelectBuy: (o: SwapAssetOption) => void;
|
|
489
|
+
/** Add a user-pasted token (code + issuer) to the buy list. Returns an error or null. */
|
|
490
|
+
onAddCustomToken: (code: string, issuer: string) => string | null;
|
|
468
491
|
onAmountChange: (value: string) => void;
|
|
469
492
|
onProviderChange: (p: SwapProvider) => void;
|
|
470
493
|
onSwap: () => void;
|
|
@@ -473,7 +496,7 @@ interface SwapModalTemplateProps {
|
|
|
473
496
|
onRetry: () => void;
|
|
474
497
|
onDone: () => void;
|
|
475
498
|
}
|
|
476
|
-
declare function SwapModalTemplate({ theme, accentColor, step, txTitle, sellOptions, buyOptions, selectedSell, selectedBuy, amount, provider, providers, quote, quoteLoading, quoteError, formError, isLoadingData, smartUnsupported, transaction, showXdr, copied, explorerUrl, walletType, showBack, isInProgress, onClose, onBack, onSelectSell, onSelectBuy, onAmountChange, onProviderChange, onSwap, onToggleXdr, onCopyHash, onRetry, onDone, }: SwapModalTemplateProps): react_jsx_runtime.JSX.Element;
|
|
499
|
+
declare function SwapModalTemplate({ theme, accentColor, step, txTitle, sellOptions, buyOptions, selectedSell, selectedBuy, amount, provider, providers, quote, quoteLoading, quoteError, formError, isLoadingData, smartUnsupported, configLoading, swapUnavailable, buyNeedsTrustline, transaction, showXdr, copied, explorerUrl, walletType, showBack, isInProgress, onClose, onBack, onRefresh, onSelectSell, onSelectBuy, onAddCustomToken, onAmountChange, onProviderChange, onSwap, onToggleXdr, onCopyHash, onRetry, onDone, }: SwapModalTemplateProps): react_jsx_runtime.JSX.Element;
|
|
477
500
|
|
|
478
501
|
interface ReceiveModalTemplateProps {
|
|
479
502
|
theme: string;
|
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.
|
|
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
|
) });
|
|
@@ -3507,7 +3575,6 @@ var PROVIDER_LABELS = {
|
|
|
3507
3575
|
soroswap: "Soroswap",
|
|
3508
3576
|
sdex: "Stellar DEX"
|
|
3509
3577
|
};
|
|
3510
|
-
var IMPLEMENTED_PROVIDERS = ["auto", "aquarius"];
|
|
3511
3578
|
function formatAmount2(value) {
|
|
3512
3579
|
const n = parseFloat(value);
|
|
3513
3580
|
return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
|
|
@@ -3530,6 +3597,9 @@ function SwapModalTemplate({
|
|
|
3530
3597
|
formError,
|
|
3531
3598
|
isLoadingData,
|
|
3532
3599
|
smartUnsupported,
|
|
3600
|
+
configLoading,
|
|
3601
|
+
swapUnavailable,
|
|
3602
|
+
buyNeedsTrustline,
|
|
3533
3603
|
transaction,
|
|
3534
3604
|
showXdr,
|
|
3535
3605
|
copied,
|
|
@@ -3539,8 +3609,10 @@ function SwapModalTemplate({
|
|
|
3539
3609
|
isInProgress,
|
|
3540
3610
|
onClose,
|
|
3541
3611
|
onBack,
|
|
3612
|
+
onRefresh,
|
|
3542
3613
|
onSelectSell,
|
|
3543
3614
|
onSelectBuy,
|
|
3615
|
+
onAddCustomToken,
|
|
3544
3616
|
onAmountChange,
|
|
3545
3617
|
onProviderChange,
|
|
3546
3618
|
onSwap,
|
|
@@ -3550,6 +3622,21 @@ function SwapModalTemplate({
|
|
|
3550
3622
|
onDone
|
|
3551
3623
|
}) {
|
|
3552
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
|
+
};
|
|
3553
3640
|
const cssVars = {
|
|
3554
3641
|
"--pollar-accent": accentColor,
|
|
3555
3642
|
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
@@ -3577,9 +3664,34 @@ function SwapModalTemplate({
|
|
|
3577
3664
|
showBack && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onBack, "aria-label": "Back", 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: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
|
|
3578
3665
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: title })
|
|
3579
3666
|
] }),
|
|
3580
|
-
!isInProgress && /* @__PURE__ */ jsxRuntime.
|
|
3667
|
+
!isInProgress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
|
|
3668
|
+
step === "form" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3669
|
+
"button",
|
|
3670
|
+
{
|
|
3671
|
+
type: "button",
|
|
3672
|
+
className: "pollar-modal-close",
|
|
3673
|
+
onClick: onRefresh,
|
|
3674
|
+
disabled: configLoading || isLoadingData,
|
|
3675
|
+
"aria-label": "Refresh",
|
|
3676
|
+
title: "Refresh balances and options",
|
|
3677
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3678
|
+
"path",
|
|
3679
|
+
{
|
|
3680
|
+
d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2.5v3h-3",
|
|
3681
|
+
stroke: "currentColor",
|
|
3682
|
+
strokeWidth: "1.6",
|
|
3683
|
+
strokeLinecap: "round",
|
|
3684
|
+
strokeLinejoin: "round"
|
|
3685
|
+
}
|
|
3686
|
+
) })
|
|
3687
|
+
}
|
|
3688
|
+
),
|
|
3689
|
+
/* @__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" }) }) })
|
|
3690
|
+
] })
|
|
3581
3691
|
] }),
|
|
3582
|
-
step === "form" && /* @__PURE__ */ jsxRuntime.
|
|
3692
|
+
step === "form" && configLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "Loading swap options\u2026" }),
|
|
3693
|
+
step === "form" && !configLoading && swapUnavailable && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Swap is not available for this app." }),
|
|
3694
|
+
step === "form" && !configLoading && !swapUnavailable && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3583
3695
|
smartUnsupported && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Swaps are not yet available for smart (passkey) wallets." }),
|
|
3584
3696
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
3585
3697
|
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "You pay" }),
|
|
@@ -3643,7 +3755,45 @@ function SwapModalTemplate({
|
|
|
3643
3755
|
] }, assetOptionKey(o)))
|
|
3644
3756
|
]
|
|
3645
3757
|
}
|
|
3646
|
-
)
|
|
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" }))
|
|
3647
3797
|
] }),
|
|
3648
3798
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
3649
3799
|
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Route" }),
|
|
@@ -3653,13 +3803,7 @@ function SwapModalTemplate({
|
|
|
3653
3803
|
className: "pollar-input pollar-send-select",
|
|
3654
3804
|
value: provider,
|
|
3655
3805
|
onChange: (e) => onProviderChange(e.target.value),
|
|
3656
|
-
children: providers.map((p) => {
|
|
3657
|
-
const implemented = IMPLEMENTED_PROVIDERS.includes(p);
|
|
3658
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("option", { value: p, disabled: !implemented, children: [
|
|
3659
|
-
PROVIDER_LABELS[p],
|
|
3660
|
-
implemented ? "" : " (coming soon)"
|
|
3661
|
-
] }, p);
|
|
3662
|
-
})
|
|
3806
|
+
children: providers.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p, children: PROVIDER_LABELS[p] }, p))
|
|
3663
3807
|
}
|
|
3664
3808
|
)
|
|
3665
3809
|
] }),
|
|
@@ -3696,8 +3840,13 @@ function SwapModalTemplate({
|
|
|
3696
3840
|
] })
|
|
3697
3841
|
] }),
|
|
3698
3842
|
!quoteLoading && !quoteError && !quote && selectedSell && selectedBuy && !!amount && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "No route found for this pair." }),
|
|
3843
|
+
buyNeedsTrustline && selectedBuy && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-trustline-notice", children: [
|
|
3844
|
+
"To receive ",
|
|
3845
|
+
selectedBuy.code,
|
|
3846
|
+
" your wallet needs a trustline. Swapping will create it first (~0.5 XLM reserve, refundable if you later remove it)."
|
|
3847
|
+
] }),
|
|
3699
3848
|
formError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: formError }),
|
|
3700
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-btn-primary", onClick: onSwap, disabled: !canSwap, children: "Swap" }) })
|
|
3849
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-btn-primary", onClick: onSwap, disabled: !canSwap, children: buyNeedsTrustline ? "Create trustline & swap" : "Swap" }) })
|
|
3701
3850
|
] }),
|
|
3702
3851
|
step === "tx" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3703
3852
|
TxStatusView,
|
|
@@ -3719,14 +3868,18 @@ function SwapModalTemplate({
|
|
|
3719
3868
|
] });
|
|
3720
3869
|
}
|
|
3721
3870
|
var QUOTE_DEBOUNCE_MS = 400;
|
|
3722
|
-
var ALL_PROVIDERS = ["auto", "aquarius", "soroswap", "sdex"];
|
|
3723
3871
|
function toRef(a) {
|
|
3724
3872
|
if (a.type === "native") return { type: "native" };
|
|
3725
3873
|
if (a.type === "credit_alphanum4") return { type: "credit_alphanum4", code: a.code, issuer: a.issuer };
|
|
3726
3874
|
return { type: "credit_alphanum12", code: a.code, issuer: a.issuer };
|
|
3727
3875
|
}
|
|
3876
|
+
function catalogRef(code, issuer) {
|
|
3877
|
+
return code.length <= 4 ? { type: "credit_alphanum4", code, issuer } : { type: "credit_alphanum12", code, issuer };
|
|
3878
|
+
}
|
|
3728
3879
|
function SwapModal({ onClose }) {
|
|
3729
3880
|
const {
|
|
3881
|
+
getSwapConfig,
|
|
3882
|
+
getSwapTokens,
|
|
3730
3883
|
getSwapQuote,
|
|
3731
3884
|
swap,
|
|
3732
3885
|
walletBalance,
|
|
@@ -3746,6 +3899,9 @@ function SwapModal({ onClose }) {
|
|
|
3746
3899
|
const [selectedBuy, setSelectedBuy] = react.useState(null);
|
|
3747
3900
|
const [amount, setAmount] = react.useState("");
|
|
3748
3901
|
const [provider, setProvider] = react.useState("auto");
|
|
3902
|
+
const [venues, setVenues] = react.useState(null);
|
|
3903
|
+
const [catalogTokens, setCatalogTokens] = react.useState([]);
|
|
3904
|
+
const [customTokens, setCustomTokens] = react.useState([]);
|
|
3749
3905
|
const [quotes, setQuotes] = react.useState([]);
|
|
3750
3906
|
const [quoteLoading, setQuoteLoading] = react.useState(false);
|
|
3751
3907
|
const [quoteError, setQuoteError] = react.useState("");
|
|
@@ -3758,6 +3914,26 @@ function SwapModal({ onClose }) {
|
|
|
3758
3914
|
void refreshWalletBalance();
|
|
3759
3915
|
void refreshAssets();
|
|
3760
3916
|
}, [refreshWalletBalance, refreshAssets]);
|
|
3917
|
+
const loadConfig = react.useCallback(() => {
|
|
3918
|
+
setVenues(null);
|
|
3919
|
+
return getSwapConfig().then(setVenues).catch(() => setVenues([]));
|
|
3920
|
+
}, [getSwapConfig]);
|
|
3921
|
+
react.useEffect(() => {
|
|
3922
|
+
void loadConfig();
|
|
3923
|
+
}, [loadConfig]);
|
|
3924
|
+
const loadCatalog = react.useCallback(
|
|
3925
|
+
() => getSwapTokens().then(setCatalogTokens).catch(() => setCatalogTokens([])),
|
|
3926
|
+
[getSwapTokens]
|
|
3927
|
+
);
|
|
3928
|
+
react.useEffect(() => {
|
|
3929
|
+
void loadCatalog();
|
|
3930
|
+
}, [loadCatalog]);
|
|
3931
|
+
function handleRefresh() {
|
|
3932
|
+
void refreshWalletBalance();
|
|
3933
|
+
void refreshAssets();
|
|
3934
|
+
void loadConfig();
|
|
3935
|
+
void loadCatalog();
|
|
3936
|
+
}
|
|
3761
3937
|
react.useEffect(
|
|
3762
3938
|
() => () => {
|
|
3763
3939
|
if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
|
|
@@ -3769,11 +3945,47 @@ function SwapModal({ onClose }) {
|
|
|
3769
3945
|
const isLoadingData = walletBalance.step === "loading" || enabledAssets.step === "loading";
|
|
3770
3946
|
const sellOptions = balances.filter((b) => parseFloat(b.available) > 0).map((b) => ({ ref: toRef(b), code: b.code, issuer: b.issuer, available: b.available, enabledInApp: b.enabledInApp }));
|
|
3771
3947
|
const buyKeyOfSell = selectedSell ? `${selectedSell.code}:${selectedSell.issuer ?? "native"}` : "";
|
|
3772
|
-
const
|
|
3773
|
-
const
|
|
3948
|
+
const optKey = (o) => `${o.code}:${o.issuer ?? "native"}`;
|
|
3949
|
+
const enabledBuy = assetRecords.map((a) => ({
|
|
3950
|
+
ref: toRef(a),
|
|
3951
|
+
code: a.code,
|
|
3952
|
+
issuer: a.issuer,
|
|
3953
|
+
enabledInApp: a.enabledInApp
|
|
3954
|
+
}));
|
|
3955
|
+
const enabledKeys = new Set(enabledBuy.map(optKey));
|
|
3956
|
+
const catalogBuy = catalogTokens.map((tk) => ({
|
|
3957
|
+
ref: catalogRef(tk.code, tk.issuer),
|
|
3958
|
+
code: tk.code,
|
|
3959
|
+
issuer: tk.issuer,
|
|
3960
|
+
enabledInApp: false
|
|
3961
|
+
})).filter((o) => !enabledKeys.has(optKey(o)));
|
|
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
|
+
}
|
|
3977
|
+
const buyNeedsTrustline = (() => {
|
|
3978
|
+
if (!selectedBuy || smartUnsupported) return false;
|
|
3979
|
+
if (selectedBuy.ref.type === "native") return false;
|
|
3980
|
+
const rec = assetRecords.find((a) => a.code === selectedBuy.code && a.issuer === selectedBuy.issuer);
|
|
3981
|
+
return !rec?.trustlineEstablished;
|
|
3982
|
+
})();
|
|
3983
|
+
const configLoading = venues === null;
|
|
3984
|
+
const swapUnavailable = venues !== null && venues.length === 0;
|
|
3985
|
+
const providers = venues && venues.length > 0 ? ["auto", ...venues] : [];
|
|
3774
3986
|
const quote = quotes[0] ?? null;
|
|
3775
3987
|
react.useEffect(() => {
|
|
3776
|
-
if (step !== "form" || !selectedSell || !selectedBuy || !amount || parseFloat(amount) <= 0) {
|
|
3988
|
+
if (step !== "form" || swapUnavailable || configLoading || !selectedSell || !selectedBuy || !amount || parseFloat(amount) <= 0) {
|
|
3777
3989
|
setQuotes([]);
|
|
3778
3990
|
setQuoteError("");
|
|
3779
3991
|
setQuoteLoading(false);
|
|
@@ -3805,7 +4017,7 @@ function SwapModal({ onClose }) {
|
|
|
3805
4017
|
cancelled = true;
|
|
3806
4018
|
clearTimeout(t);
|
|
3807
4019
|
};
|
|
3808
|
-
}, [step, selectedSell, selectedBuy, amount, provider, getSwapQuote]);
|
|
4020
|
+
}, [step, swapUnavailable, configLoading, selectedSell, selectedBuy, amount, provider, getSwapQuote]);
|
|
3809
4021
|
const hash = transaction.step === "success" ? transaction.hash : null;
|
|
3810
4022
|
const buildData = "buildData" in transaction ? transaction.buildData : null;
|
|
3811
4023
|
const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
|
|
@@ -3886,6 +4098,9 @@ function SwapModal({ onClose }) {
|
|
|
3886
4098
|
formError,
|
|
3887
4099
|
isLoadingData,
|
|
3888
4100
|
smartUnsupported,
|
|
4101
|
+
configLoading,
|
|
4102
|
+
swapUnavailable,
|
|
4103
|
+
buyNeedsTrustline,
|
|
3889
4104
|
transaction,
|
|
3890
4105
|
showXdr,
|
|
3891
4106
|
copied,
|
|
@@ -3895,8 +4110,10 @@ function SwapModal({ onClose }) {
|
|
|
3895
4110
|
isInProgress,
|
|
3896
4111
|
onClose,
|
|
3897
4112
|
onBack: handleBack,
|
|
4113
|
+
onRefresh: handleRefresh,
|
|
3898
4114
|
onSelectSell: setSelectedSell,
|
|
3899
4115
|
onSelectBuy: setSelectedBuy,
|
|
4116
|
+
onAddCustomToken: addCustomToken,
|
|
3900
4117
|
onAmountChange: setAmount,
|
|
3901
4118
|
onProviderChange: setProvider,
|
|
3902
4119
|
onSwap: () => void handleSwap(),
|
|
@@ -4608,6 +4825,18 @@ function PollarProvider({
|
|
|
4608
4825
|
const [pollarClient] = react.useState(
|
|
4609
4826
|
() => client instanceof core.PollarClient ? client : new core.PollarClient({ passkey: browserPasskeyCeremony, passkeySign: browserPasskeySigner, ...client })
|
|
4610
4827
|
);
|
|
4828
|
+
const ownsClientRef = react.useRef(!(client instanceof core.PollarClient));
|
|
4829
|
+
const destroyTimerRef = react.useRef(null);
|
|
4830
|
+
react.useEffect(() => {
|
|
4831
|
+
if (!ownsClientRef.current) return;
|
|
4832
|
+
if (destroyTimerRef.current) {
|
|
4833
|
+
clearTimeout(destroyTimerRef.current);
|
|
4834
|
+
destroyTimerRef.current = null;
|
|
4835
|
+
}
|
|
4836
|
+
return () => {
|
|
4837
|
+
destroyTimerRef.current = setTimeout(() => pollarClient.destroy(), 0);
|
|
4838
|
+
};
|
|
4839
|
+
}, [pollarClient]);
|
|
4611
4840
|
const [networkState, setNetworkState] = react.useState(() => pollarClient.getNetworkState());
|
|
4612
4841
|
const [sessionState, setSessionState] = react.useState(null);
|
|
4613
4842
|
const [verified, setVerified] = react.useState(false);
|
|
@@ -4747,6 +4976,8 @@ function PollarProvider({
|
|
|
4747
4976
|
openSendModal: () => setSendModalOpen(true),
|
|
4748
4977
|
openReceiveModal: () => setReceiveModalOpen(true),
|
|
4749
4978
|
// swap
|
|
4979
|
+
getSwapConfig: () => pollarClient.getSwapConfig(),
|
|
4980
|
+
getSwapTokens: () => pollarClient.getSwapTokens(),
|
|
4750
4981
|
getSwapQuote: (params) => pollarClient.getSwapQuote(params),
|
|
4751
4982
|
swap: (quote, opts) => pollarClient.swap(quote, opts),
|
|
4752
4983
|
openSwapModal: () => setSwapModalOpen(true),
|