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