@pollar/react 0.10.1-rc.0 → 0.10.1-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +37 -9
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +16 -5
- package/dist/index.d.ts +16 -5
- package/dist/index.js +322 -76
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +322 -76
- 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.2"
|
|
1039
1039
|
] })
|
|
1040
1040
|
] })
|
|
1041
1041
|
] });
|
|
@@ -2459,20 +2459,45 @@ 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",
|
|
2473
2471
|
completed: "Completed",
|
|
2474
2472
|
failed: "Failed"
|
|
2475
2473
|
};
|
|
2474
|
+
var INSTRUCTION_LABELS = {
|
|
2475
|
+
br_code: "Pix code",
|
|
2476
|
+
account_holder_name: "Account holder",
|
|
2477
|
+
bank_name: "Bank",
|
|
2478
|
+
bank_address: "Bank address",
|
|
2479
|
+
bank_account_number: "Account number",
|
|
2480
|
+
bank_routing_number: "Routing number",
|
|
2481
|
+
iban: "IBAN",
|
|
2482
|
+
bic: "BIC",
|
|
2483
|
+
clabe: "CLABE",
|
|
2484
|
+
amount: "Amount",
|
|
2485
|
+
currency: "Currency",
|
|
2486
|
+
payment_rails: "Rails"
|
|
2487
|
+
};
|
|
2488
|
+
function flattenInstructions(instr) {
|
|
2489
|
+
const out = [];
|
|
2490
|
+
for (const [k, v] of Object.entries(instr)) {
|
|
2491
|
+
let value = "";
|
|
2492
|
+
if (typeof v === "string" || typeof v === "number") value = String(v);
|
|
2493
|
+
else if (Array.isArray(v))
|
|
2494
|
+
value = v.filter((x) => typeof x === "string" || typeof x === "number").join(", ");
|
|
2495
|
+
else continue;
|
|
2496
|
+
if (!value) continue;
|
|
2497
|
+
out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? k, value });
|
|
2498
|
+
}
|
|
2499
|
+
return out;
|
|
2500
|
+
}
|
|
2476
2501
|
function RampWidgetTemplate({
|
|
2477
2502
|
theme,
|
|
2478
2503
|
accentColor,
|
|
@@ -2481,24 +2506,33 @@ function RampWidgetTemplate({
|
|
|
2481
2506
|
amount,
|
|
2482
2507
|
currency,
|
|
2483
2508
|
country,
|
|
2509
|
+
email,
|
|
2510
|
+
fullName,
|
|
2511
|
+
countries,
|
|
2512
|
+
countriesLoading,
|
|
2513
|
+
refreshing,
|
|
2484
2514
|
quotes,
|
|
2485
2515
|
isLoading,
|
|
2486
2516
|
provider,
|
|
2487
2517
|
txStatus,
|
|
2488
2518
|
kycUrl,
|
|
2489
2519
|
stellarTxHash,
|
|
2520
|
+
depositInstructions,
|
|
2490
2521
|
canComplete,
|
|
2491
2522
|
completing,
|
|
2492
2523
|
errorMsg,
|
|
2493
2524
|
onDirectionChange,
|
|
2494
2525
|
onAmountChange,
|
|
2495
|
-
|
|
2526
|
+
onEmailChange,
|
|
2527
|
+
onFullNameChange,
|
|
2496
2528
|
onCountryChange,
|
|
2497
2529
|
onFindRoute,
|
|
2498
2530
|
onSelectQuote,
|
|
2531
|
+
onContactContinue,
|
|
2499
2532
|
onOpenKyc,
|
|
2500
2533
|
onCompleteWithdraw,
|
|
2501
2534
|
onRetry,
|
|
2535
|
+
onRefresh,
|
|
2502
2536
|
onClose
|
|
2503
2537
|
}) {
|
|
2504
2538
|
const isDark = theme === "dark";
|
|
@@ -2526,6 +2560,7 @@ function RampWidgetTemplate({
|
|
|
2526
2560
|
input: direction === "onramp" ? "Buy crypto" : "Sell crypto",
|
|
2527
2561
|
loading_quote: "Finding best route",
|
|
2528
2562
|
select_route: "Select provider",
|
|
2563
|
+
contact: "Your details",
|
|
2529
2564
|
status: direction === "onramp" ? "Complete your deposit" : "Complete your withdrawal",
|
|
2530
2565
|
error: "Something went wrong"
|
|
2531
2566
|
};
|
|
@@ -2533,13 +2568,40 @@ function RampWidgetTemplate({
|
|
|
2533
2568
|
input: direction === "onramp" ? "Enter the amount you want to deposit" : "Enter the amount you want to withdraw",
|
|
2534
2569
|
loading_quote: "Comparing providers in real time\u2026",
|
|
2535
2570
|
select_route: "All prices include fees",
|
|
2571
|
+
contact: `${provider || "This provider"} needs your name and email to verify you`,
|
|
2536
2572
|
status: `Finish the flow at ${provider || "the provider"} to continue`,
|
|
2537
2573
|
error: "Please try again"
|
|
2538
2574
|
};
|
|
2539
2575
|
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
|
-
|
|
2576
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
2577
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-header-text", children: [
|
|
2578
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: stepTitle[step] }),
|
|
2579
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-ramp-subtitle", children: stepSubtitle[step] })
|
|
2580
|
+
] }),
|
|
2581
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
|
|
2582
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onRefresh, disabled: refreshing, "aria-label": "Refresh", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2583
|
+
"svg",
|
|
2584
|
+
{
|
|
2585
|
+
className: refreshing ? "pollar-modal-refresh-icon spinning" : "pollar-modal-refresh-icon",
|
|
2586
|
+
width: "16",
|
|
2587
|
+
height: "16",
|
|
2588
|
+
viewBox: "0 0 16 16",
|
|
2589
|
+
fill: "none",
|
|
2590
|
+
"aria-hidden": true,
|
|
2591
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2592
|
+
"path",
|
|
2593
|
+
{
|
|
2594
|
+
d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
|
|
2595
|
+
stroke: "currentColor",
|
|
2596
|
+
strokeWidth: "1.6",
|
|
2597
|
+
strokeLinecap: "round",
|
|
2598
|
+
strokeLinejoin: "round"
|
|
2599
|
+
}
|
|
2600
|
+
)
|
|
2601
|
+
}
|
|
2602
|
+
) }),
|
|
2603
|
+
/* @__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" }) }) })
|
|
2604
|
+
] })
|
|
2543
2605
|
] }),
|
|
2544
2606
|
step === "input" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2545
2607
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-tabs", children: [
|
|
@@ -2564,62 +2626,44 @@ function RampWidgetTemplate({
|
|
|
2564
2626
|
}
|
|
2565
2627
|
)
|
|
2566
2628
|
] }),
|
|
2567
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-input-row", children: [
|
|
2568
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-field", children: [
|
|
2569
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-ramp-label", children: "Amount" }),
|
|
2570
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2571
|
-
"input",
|
|
2572
|
-
{
|
|
2573
|
-
type: "number",
|
|
2574
|
-
className: "pollar-ramp-input",
|
|
2575
|
-
placeholder: "0.00",
|
|
2576
|
-
value: amount,
|
|
2577
|
-
min: "0",
|
|
2578
|
-
onChange: (e) => onAmountChange(e.target.value)
|
|
2579
|
-
}
|
|
2580
|
-
)
|
|
2581
|
-
] }),
|
|
2582
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-field", style: { maxWidth: 90 }, children: [
|
|
2583
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-ramp-label", children: "Currency" }),
|
|
2584
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2585
|
-
"input",
|
|
2586
|
-
{
|
|
2587
|
-
type: "text",
|
|
2588
|
-
className: "pollar-ramp-input",
|
|
2589
|
-
placeholder: "MXN",
|
|
2590
|
-
value: currency,
|
|
2591
|
-
maxLength: 5,
|
|
2592
|
-
onChange: (e) => onCurrencyChange(e.target.value.toUpperCase())
|
|
2593
|
-
}
|
|
2594
|
-
)
|
|
2595
|
-
] })
|
|
2596
|
-
] }),
|
|
2597
2629
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-field", children: [
|
|
2598
2630
|
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-ramp-label", children: "Country" }),
|
|
2599
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2600
|
-
|
|
2631
|
+
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: [
|
|
2632
|
+
flagEmoji(c.code),
|
|
2633
|
+
" ",
|
|
2634
|
+
c.code,
|
|
2635
|
+
c.currency ? ` \u2014 ${c.currency}` : ""
|
|
2636
|
+
] }, c.code)) })
|
|
2637
|
+
] }),
|
|
2638
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-field", children: [
|
|
2639
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-ramp-label", children: [
|
|
2640
|
+
"Amount",
|
|
2641
|
+
currency ? ` (${currency})` : ""
|
|
2642
|
+
] }),
|
|
2643
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2644
|
+
"input",
|
|
2601
2645
|
{
|
|
2646
|
+
type: "number",
|
|
2602
2647
|
className: "pollar-ramp-input",
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
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
|
-
]
|
|
2648
|
+
placeholder: "0.00",
|
|
2649
|
+
value: amount,
|
|
2650
|
+
min: "0",
|
|
2651
|
+
onChange: (e) => onAmountChange(e.target.value)
|
|
2617
2652
|
}
|
|
2618
2653
|
)
|
|
2619
2654
|
] }),
|
|
2620
2655
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
|
|
2621
2656
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" }),
|
|
2622
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2657
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2658
|
+
"button",
|
|
2659
|
+
{
|
|
2660
|
+
type: "button",
|
|
2661
|
+
className: "pollar-btn-primary",
|
|
2662
|
+
disabled: !amount || isLoading || countriesLoading || countries.length === 0,
|
|
2663
|
+
onClick: onFindRoute,
|
|
2664
|
+
children: "Find best route"
|
|
2665
|
+
}
|
|
2666
|
+
)
|
|
2623
2667
|
] })
|
|
2624
2668
|
] }),
|
|
2625
2669
|
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: [
|
|
@@ -2630,6 +2674,48 @@ function RampWidgetTemplate({
|
|
|
2630
2674
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-route-list", children: quotes.map((q, i) => /* @__PURE__ */ jsxRuntime.jsx(RouteDisplay, { quote: q, onSelect: onSelectQuote }, i)) }),
|
|
2631
2675
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" })
|
|
2632
2676
|
] }),
|
|
2677
|
+
step === "contact" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2678
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-field", children: [
|
|
2679
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-ramp-label", children: "Full name" }),
|
|
2680
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2681
|
+
"input",
|
|
2682
|
+
{
|
|
2683
|
+
type: "text",
|
|
2684
|
+
className: "pollar-ramp-input",
|
|
2685
|
+
placeholder: "Jane Doe",
|
|
2686
|
+
value: fullName,
|
|
2687
|
+
onChange: (e) => onFullNameChange(e.target.value)
|
|
2688
|
+
}
|
|
2689
|
+
)
|
|
2690
|
+
] }),
|
|
2691
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-field", children: [
|
|
2692
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-ramp-label", children: "Email" }),
|
|
2693
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2694
|
+
"input",
|
|
2695
|
+
{
|
|
2696
|
+
type: "email",
|
|
2697
|
+
className: "pollar-ramp-input",
|
|
2698
|
+
placeholder: "jane@example.com",
|
|
2699
|
+
value: email,
|
|
2700
|
+
autoComplete: "email",
|
|
2701
|
+
onChange: (e) => onEmailChange(e.target.value)
|
|
2702
|
+
}
|
|
2703
|
+
)
|
|
2704
|
+
] }),
|
|
2705
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
|
|
2706
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onRetry, children: "Back" }),
|
|
2707
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2708
|
+
"button",
|
|
2709
|
+
{
|
|
2710
|
+
type: "button",
|
|
2711
|
+
className: "pollar-btn-primary",
|
|
2712
|
+
disabled: !fullName.trim() || !email.trim() || isLoading,
|
|
2713
|
+
onClick: onContactContinue,
|
|
2714
|
+
children: isLoading ? "Starting\u2026" : "Continue"
|
|
2715
|
+
}
|
|
2716
|
+
)
|
|
2717
|
+
] })
|
|
2718
|
+
] }),
|
|
2633
2719
|
step === "status" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment", children: [
|
|
2634
2720
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2635
2721
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: "Provider" }),
|
|
@@ -2637,13 +2723,7 @@ function RampWidgetTemplate({
|
|
|
2637
2723
|
] }),
|
|
2638
2724
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2639
2725
|
/* @__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
|
-
) })
|
|
2726
|
+
/* @__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
2727
|
] }),
|
|
2648
2728
|
stellarTxHash && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2649
2729
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: "Stellar tx" }),
|
|
@@ -2653,6 +2733,10 @@ function RampWidgetTemplate({
|
|
|
2653
2733
|
stellarTxHash.slice(-8)
|
|
2654
2734
|
] }) })
|
|
2655
2735
|
] }),
|
|
2736
|
+
depositInstructions && txStatus !== "completed" && flattenInstructions(depositInstructions).map(({ key, label, value }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2737
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: label }),
|
|
2738
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsxRuntime.jsx("code", { style: { wordBreak: "break-all" }, children: value }) })
|
|
2739
|
+
] }, key)),
|
|
2656
2740
|
kycUrl && txStatus !== "completed" && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenKyc, children: [
|
|
2657
2741
|
"Continue at ",
|
|
2658
2742
|
provider
|
|
@@ -2679,15 +2763,22 @@ function RampWidget({ onClose }) {
|
|
|
2679
2763
|
const [step, setStep] = react.useState("input");
|
|
2680
2764
|
const [direction, setDirection] = react.useState("onramp");
|
|
2681
2765
|
const [amount, setAmount] = react.useState("");
|
|
2682
|
-
const [currency, setCurrency] = react.useState("
|
|
2683
|
-
const [country, setCountry] = react.useState("
|
|
2766
|
+
const [currency, setCurrency] = react.useState("");
|
|
2767
|
+
const [country, setCountry] = react.useState("");
|
|
2768
|
+
const [email, setEmail] = react.useState("");
|
|
2769
|
+
const [fullName, setFullName] = react.useState("");
|
|
2770
|
+
const [countries, setCountries] = react.useState([]);
|
|
2771
|
+
const [countriesLoading, setCountriesLoading] = react.useState(true);
|
|
2772
|
+
const [refreshing, setRefreshing] = react.useState(false);
|
|
2684
2773
|
const [quotes, setQuotes] = react.useState([]);
|
|
2774
|
+
const [selectedQuote, setSelectedQuote] = react.useState(null);
|
|
2685
2775
|
const [isLoading, setIsLoading] = react.useState(false);
|
|
2686
2776
|
const [txId, setTxId] = react.useState(null);
|
|
2687
2777
|
const [provider, setProvider] = react.useState("");
|
|
2688
2778
|
const [kycUrl, setKycUrl] = react.useState(null);
|
|
2689
2779
|
const [txStatus, setTxStatus] = react.useState(null);
|
|
2690
2780
|
const [stellarTxHash, setStellarTxHash] = react.useState(null);
|
|
2781
|
+
const [depositInstructions, setDepositInstructions] = react.useState(null);
|
|
2691
2782
|
const [completing, setCompleting] = react.useState(false);
|
|
2692
2783
|
const [errorMsg, setErrorMsg] = react.useState(null);
|
|
2693
2784
|
const directionRef = react.useRef(direction);
|
|
@@ -2703,6 +2794,8 @@ function RampWidget({ onClose }) {
|
|
|
2703
2794
|
setTxStatus(tx.status);
|
|
2704
2795
|
if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
|
|
2705
2796
|
if (tx.kycUrl) setKycUrl(tx.kycUrl);
|
|
2797
|
+
const di = tx.depositInstructions;
|
|
2798
|
+
if (di) setDepositInstructions(di);
|
|
2706
2799
|
if (TERMINAL.includes(tx.status)) clearInterval(id);
|
|
2707
2800
|
} catch {
|
|
2708
2801
|
}
|
|
@@ -2712,14 +2805,62 @@ function RampWidget({ onClose }) {
|
|
|
2712
2805
|
clearInterval(id);
|
|
2713
2806
|
};
|
|
2714
2807
|
}, [step, txId, txStatus, client]);
|
|
2808
|
+
async function loadCountries(resetSelection) {
|
|
2809
|
+
setCountriesLoading(true);
|
|
2810
|
+
try {
|
|
2811
|
+
const { countries: list } = await client.getRampCountries();
|
|
2812
|
+
setCountries(list);
|
|
2813
|
+
const first = list[0];
|
|
2814
|
+
const stillValid = list.some((c) => c.code === country);
|
|
2815
|
+
if (first && (resetSelection || !stillValid)) {
|
|
2816
|
+
setCountry(first.code);
|
|
2817
|
+
if (first.currency) setCurrency(first.currency);
|
|
2818
|
+
}
|
|
2819
|
+
} catch {
|
|
2820
|
+
setCountries([]);
|
|
2821
|
+
} finally {
|
|
2822
|
+
setCountriesLoading(false);
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
react.useEffect(() => {
|
|
2826
|
+
loadCountries(true);
|
|
2827
|
+
}, []);
|
|
2828
|
+
function handleCountryChange(code) {
|
|
2829
|
+
setCountry(code);
|
|
2830
|
+
const match = countries.find((c) => c.code === code);
|
|
2831
|
+
if (match?.currency) setCurrency(match.currency);
|
|
2832
|
+
}
|
|
2833
|
+
async function handleRefresh() {
|
|
2834
|
+
if (refreshing) return;
|
|
2835
|
+
setRefreshing(true);
|
|
2836
|
+
try {
|
|
2837
|
+
await loadCountries(false);
|
|
2838
|
+
if (step === "select_route") {
|
|
2839
|
+
const result = await client.getRampsQuote({ country, amount: Number(amount), currency, direction });
|
|
2840
|
+
setQuotes(result.quotes ?? []);
|
|
2841
|
+
} else if (step === "status" && txId) {
|
|
2842
|
+
const tx = await client.getRampTransaction(txId);
|
|
2843
|
+
setTxStatus(tx.status);
|
|
2844
|
+
if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
|
|
2845
|
+
if (tx.kycUrl) setKycUrl(tx.kycUrl);
|
|
2846
|
+
const di = tx.depositInstructions;
|
|
2847
|
+
if (di) setDepositInstructions(di);
|
|
2848
|
+
}
|
|
2849
|
+
} catch {
|
|
2850
|
+
} finally {
|
|
2851
|
+
setRefreshing(false);
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2715
2854
|
function resetToInput() {
|
|
2716
2855
|
setStep("input");
|
|
2717
2856
|
setQuotes([]);
|
|
2857
|
+
setSelectedQuote(null);
|
|
2718
2858
|
setTxId(null);
|
|
2719
2859
|
setProvider("");
|
|
2720
2860
|
setKycUrl(null);
|
|
2721
2861
|
setTxStatus(null);
|
|
2722
2862
|
setStellarTxHash(null);
|
|
2863
|
+
setDepositInstructions(null);
|
|
2723
2864
|
setErrorMsg(null);
|
|
2724
2865
|
}
|
|
2725
2866
|
async function resumeWithSignature(id, ps) {
|
|
@@ -2745,6 +2886,7 @@ function RampWidget({ onClose }) {
|
|
|
2745
2886
|
setKycUrl(result.kycUrl ?? null);
|
|
2746
2887
|
setTxStatus(result.status);
|
|
2747
2888
|
setStellarTxHash(result.stellarTxHash ?? null);
|
|
2889
|
+
setDepositInstructions(result.depositInstructions ?? null);
|
|
2748
2890
|
setStep("status");
|
|
2749
2891
|
}
|
|
2750
2892
|
async function handleFindRoute() {
|
|
@@ -2768,12 +2910,33 @@ function RampWidget({ onClose }) {
|
|
|
2768
2910
|
setIsLoading(false);
|
|
2769
2911
|
}
|
|
2770
2912
|
}
|
|
2771
|
-
|
|
2913
|
+
function handleSelectQuote(quote) {
|
|
2914
|
+
setSelectedQuote(quote);
|
|
2915
|
+
setErrorMsg(null);
|
|
2916
|
+
const requiresContact = quote.requiresContact ?? false;
|
|
2917
|
+
if (requiresContact && (!email.trim() || !fullName.trim())) {
|
|
2918
|
+
setStep("contact");
|
|
2919
|
+
return;
|
|
2920
|
+
}
|
|
2921
|
+
void startRamp(quote);
|
|
2922
|
+
}
|
|
2923
|
+
function handleContactContinue() {
|
|
2924
|
+
if (selectedQuote) void startRamp(selectedQuote);
|
|
2925
|
+
}
|
|
2926
|
+
async function startRamp(quote) {
|
|
2772
2927
|
setIsLoading(true);
|
|
2773
2928
|
setErrorMsg(null);
|
|
2774
2929
|
try {
|
|
2775
|
-
const base = {
|
|
2776
|
-
|
|
2930
|
+
const base = {
|
|
2931
|
+
quoteId: quote.quoteId,
|
|
2932
|
+
amount: Number(amount),
|
|
2933
|
+
currency,
|
|
2934
|
+
country,
|
|
2935
|
+
...email.trim() ? { email: email.trim() } : {},
|
|
2936
|
+
...fullName.trim() ? { fullName: fullName.trim() } : {},
|
|
2937
|
+
...walletAddress ? { walletAddress } : {}
|
|
2938
|
+
};
|
|
2939
|
+
const result = direction === "onramp" ? await client.createOnRamp(base) : await client.createOffRamp(base);
|
|
2777
2940
|
await applyResult(result);
|
|
2778
2941
|
} catch (e) {
|
|
2779
2942
|
setErrorMsg(e instanceof Error ? e.message : "Failed to start the ramp.");
|
|
@@ -2817,24 +2980,33 @@ function RampWidget({ onClose }) {
|
|
|
2817
2980
|
amount,
|
|
2818
2981
|
currency,
|
|
2819
2982
|
country,
|
|
2983
|
+
email,
|
|
2984
|
+
fullName,
|
|
2985
|
+
countries,
|
|
2986
|
+
countriesLoading,
|
|
2987
|
+
refreshing,
|
|
2820
2988
|
quotes,
|
|
2821
2989
|
isLoading,
|
|
2822
2990
|
provider,
|
|
2823
2991
|
txStatus,
|
|
2824
2992
|
kycUrl,
|
|
2825
2993
|
stellarTxHash,
|
|
2994
|
+
depositInstructions,
|
|
2826
2995
|
canComplete,
|
|
2827
2996
|
completing,
|
|
2828
2997
|
errorMsg,
|
|
2829
2998
|
onDirectionChange: setDirection,
|
|
2830
2999
|
onAmountChange: setAmount,
|
|
2831
|
-
|
|
2832
|
-
|
|
3000
|
+
onEmailChange: setEmail,
|
|
3001
|
+
onFullNameChange: setFullName,
|
|
3002
|
+
onCountryChange: handleCountryChange,
|
|
2833
3003
|
onFindRoute: handleFindRoute,
|
|
2834
3004
|
onSelectQuote: handleSelectQuote,
|
|
3005
|
+
onContactContinue: handleContactContinue,
|
|
2835
3006
|
onOpenKyc: handleOpenKyc,
|
|
2836
3007
|
onCompleteWithdraw: handleCompleteWithdraw,
|
|
2837
3008
|
onRetry: resetToInput,
|
|
3009
|
+
onRefresh: handleRefresh,
|
|
2838
3010
|
onClose
|
|
2839
3011
|
}
|
|
2840
3012
|
) });
|
|
@@ -3544,6 +3716,7 @@ function SwapModalTemplate({
|
|
|
3544
3716
|
onRefresh,
|
|
3545
3717
|
onSelectSell,
|
|
3546
3718
|
onSelectBuy,
|
|
3719
|
+
onAddCustomToken,
|
|
3547
3720
|
onAmountChange,
|
|
3548
3721
|
onProviderChange,
|
|
3549
3722
|
onSwap,
|
|
@@ -3553,6 +3726,21 @@ function SwapModalTemplate({
|
|
|
3553
3726
|
onDone
|
|
3554
3727
|
}) {
|
|
3555
3728
|
const isDark = theme === "dark";
|
|
3729
|
+
const [customOpen, setCustomOpen] = react.useState(false);
|
|
3730
|
+
const [customCode, setCustomCode] = react.useState("");
|
|
3731
|
+
const [customIssuer, setCustomIssuer] = react.useState("");
|
|
3732
|
+
const [customError, setCustomError] = react.useState("");
|
|
3733
|
+
const submitCustomToken = () => {
|
|
3734
|
+
const err = onAddCustomToken(customCode, customIssuer);
|
|
3735
|
+
if (err) {
|
|
3736
|
+
setCustomError(err);
|
|
3737
|
+
return;
|
|
3738
|
+
}
|
|
3739
|
+
setCustomCode("");
|
|
3740
|
+
setCustomIssuer("");
|
|
3741
|
+
setCustomError("");
|
|
3742
|
+
setCustomOpen(false);
|
|
3743
|
+
};
|
|
3556
3744
|
const cssVars = {
|
|
3557
3745
|
"--pollar-accent": accentColor,
|
|
3558
3746
|
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
@@ -3671,7 +3859,45 @@ function SwapModalTemplate({
|
|
|
3671
3859
|
] }, assetOptionKey(o)))
|
|
3672
3860
|
]
|
|
3673
3861
|
}
|
|
3674
|
-
)
|
|
3862
|
+
),
|
|
3863
|
+
!isLoadingData && (customOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-custom", children: [
|
|
3864
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3865
|
+
"input",
|
|
3866
|
+
{
|
|
3867
|
+
className: "pollar-input",
|
|
3868
|
+
type: "text",
|
|
3869
|
+
placeholder: "Code (e.g. USDC)",
|
|
3870
|
+
value: customCode,
|
|
3871
|
+
onChange: (e) => setCustomCode(e.target.value)
|
|
3872
|
+
}
|
|
3873
|
+
),
|
|
3874
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3875
|
+
"input",
|
|
3876
|
+
{
|
|
3877
|
+
className: "pollar-input",
|
|
3878
|
+
type: "text",
|
|
3879
|
+
placeholder: "Issuer (G...)",
|
|
3880
|
+
value: customIssuer,
|
|
3881
|
+
onChange: (e) => setCustomIssuer(e.target.value)
|
|
3882
|
+
}
|
|
3883
|
+
),
|
|
3884
|
+
customError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: customError }),
|
|
3885
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-custom-actions", children: [
|
|
3886
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: submitCustomToken, children: "Add token" }),
|
|
3887
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3888
|
+
"button",
|
|
3889
|
+
{
|
|
3890
|
+
type: "button",
|
|
3891
|
+
className: "pollar-swap-custom-cancel",
|
|
3892
|
+
onClick: () => {
|
|
3893
|
+
setCustomOpen(false);
|
|
3894
|
+
setCustomError("");
|
|
3895
|
+
},
|
|
3896
|
+
children: "Cancel"
|
|
3897
|
+
}
|
|
3898
|
+
)
|
|
3899
|
+
] })
|
|
3900
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-swap-custom-toggle", onClick: () => setCustomOpen(true), children: "+ Add a token by code / issuer" }))
|
|
3675
3901
|
] }),
|
|
3676
3902
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
3677
3903
|
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Route" }),
|
|
@@ -3779,6 +4005,7 @@ function SwapModal({ onClose }) {
|
|
|
3779
4005
|
const [provider, setProvider] = react.useState("auto");
|
|
3780
4006
|
const [venues, setVenues] = react.useState(null);
|
|
3781
4007
|
const [catalogTokens, setCatalogTokens] = react.useState([]);
|
|
4008
|
+
const [customTokens, setCustomTokens] = react.useState([]);
|
|
3782
4009
|
const [quotes, setQuotes] = react.useState([]);
|
|
3783
4010
|
const [quoteLoading, setQuoteLoading] = react.useState(false);
|
|
3784
4011
|
const [quoteError, setQuoteError] = react.useState("");
|
|
@@ -3836,7 +4063,21 @@ function SwapModal({ onClose }) {
|
|
|
3836
4063
|
issuer: tk.issuer,
|
|
3837
4064
|
enabledInApp: false
|
|
3838
4065
|
})).filter((o) => !enabledKeys.has(optKey(o)));
|
|
3839
|
-
const
|
|
4066
|
+
const knownKeys = /* @__PURE__ */ new Set([...enabledKeys, ...catalogBuy.map(optKey)]);
|
|
4067
|
+
const customBuy = customTokens.filter((o) => !knownKeys.has(optKey(o)));
|
|
4068
|
+
const buyOptions = [...enabledBuy, ...catalogBuy, ...customBuy].filter(
|
|
4069
|
+
(o) => optKey(o) !== buyKeyOfSell
|
|
4070
|
+
);
|
|
4071
|
+
function addCustomToken(code, issuer) {
|
|
4072
|
+
const c = code.trim().toUpperCase();
|
|
4073
|
+
const i = issuer.trim();
|
|
4074
|
+
if (c.length < 1 || c.length > 12) return "Code must be 1-12 characters";
|
|
4075
|
+
if (i.length !== 56 || !i.startsWith("G")) return "Issuer must be a Stellar address (G..., 56 chars)";
|
|
4076
|
+
const opt = { ref: catalogRef(c, i), code: c, issuer: i, enabledInApp: false };
|
|
4077
|
+
setCustomTokens((prev) => prev.some((o) => optKey(o) === optKey(opt)) ? prev : [...prev, opt]);
|
|
4078
|
+
setSelectedBuy(opt);
|
|
4079
|
+
return null;
|
|
4080
|
+
}
|
|
3840
4081
|
const buyNeedsTrustline = (() => {
|
|
3841
4082
|
if (!selectedBuy || smartUnsupported) return false;
|
|
3842
4083
|
if (selectedBuy.ref.type === "native") return false;
|
|
@@ -3976,6 +4217,7 @@ function SwapModal({ onClose }) {
|
|
|
3976
4217
|
onRefresh: handleRefresh,
|
|
3977
4218
|
onSelectSell: setSelectedSell,
|
|
3978
4219
|
onSelectBuy: setSelectedBuy,
|
|
4220
|
+
onAddCustomToken: addCustomToken,
|
|
3979
4221
|
onAmountChange: setAmount,
|
|
3980
4222
|
onProviderChange: setProvider,
|
|
3981
4223
|
onSwap: () => void handleSwap(),
|
|
@@ -4413,6 +4655,10 @@ function TxHistoryModalTemplate({
|
|
|
4413
4655
|
/* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: record.status }),
|
|
4414
4656
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-hist-item-meta", children: [
|
|
4415
4657
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: record.operation }),
|
|
4658
|
+
typeof record.details?.sponsored === "boolean" && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
4659
|
+
"\xB7 ",
|
|
4660
|
+
record.details.sponsored ? "Sponsored" : "Self-paid"
|
|
4661
|
+
] }),
|
|
4416
4662
|
record.feeXlm && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
4417
4663
|
"\xB7 ",
|
|
4418
4664
|
record.feeXlm,
|