@pollar/react 0.10.1-rc.1 → 0.10.1-rc.3

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.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.1"
1036
+ "0.10.1-rc.3"
1037
1037
  ] })
1038
1038
  ] })
1039
1039
  ] });
@@ -2469,6 +2469,33 @@ var STATUS_LABEL = {
2469
2469
  completed: "Completed",
2470
2470
  failed: "Failed"
2471
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
+ }
2472
2499
  function RampWidgetTemplate({
2473
2500
  theme,
2474
2501
  accentColor,
@@ -2477,6 +2504,8 @@ function RampWidgetTemplate({
2477
2504
  amount,
2478
2505
  currency,
2479
2506
  country,
2507
+ requiredFields,
2508
+ fieldValues,
2480
2509
  countries,
2481
2510
  countriesLoading,
2482
2511
  refreshing,
@@ -2486,15 +2515,17 @@ function RampWidgetTemplate({
2486
2515
  txStatus,
2487
2516
  kycUrl,
2488
2517
  stellarTxHash,
2518
+ depositInstructions,
2489
2519
  canComplete,
2490
2520
  completing,
2491
2521
  errorMsg,
2492
2522
  onDirectionChange,
2493
2523
  onAmountChange,
2494
- onCurrencyChange,
2524
+ onFieldChange,
2495
2525
  onCountryChange,
2496
2526
  onFindRoute,
2497
2527
  onSelectQuote,
2528
+ onContactContinue,
2498
2529
  onOpenKyc,
2499
2530
  onCompleteWithdraw,
2500
2531
  onRetry,
@@ -2526,6 +2557,7 @@ function RampWidgetTemplate({
2526
2557
  input: direction === "onramp" ? "Buy crypto" : "Sell crypto",
2527
2558
  loading_quote: "Finding best route",
2528
2559
  select_route: "Select provider",
2560
+ contact: "Your details",
2529
2561
  status: direction === "onramp" ? "Complete your deposit" : "Complete your withdrawal",
2530
2562
  error: "Something went wrong"
2531
2563
  };
@@ -2533,6 +2565,7 @@ function RampWidgetTemplate({
2533
2565
  input: direction === "onramp" ? "Enter the amount you want to deposit" : "Enter the amount you want to withdraw",
2534
2566
  loading_quote: "Comparing providers in real time\u2026",
2535
2567
  select_route: "All prices include fees",
2568
+ contact: `${provider || "This provider"} needs your name and email to verify you`,
2536
2569
  status: `Finish the flow at ${provider || "the provider"} to continue`,
2537
2570
  error: "Please try again"
2538
2571
  };
@@ -2590,36 +2623,6 @@ function RampWidgetTemplate({
2590
2623
  }
2591
2624
  )
2592
2625
  ] }),
2593
- /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-input-row", children: [
2594
- /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
2595
- /* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", children: "Amount" }),
2596
- /* @__PURE__ */ jsx(
2597
- "input",
2598
- {
2599
- type: "number",
2600
- className: "pollar-ramp-input",
2601
- placeholder: "0.00",
2602
- value: amount,
2603
- min: "0",
2604
- onChange: (e) => onAmountChange(e.target.value)
2605
- }
2606
- )
2607
- ] }),
2608
- /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", style: { maxWidth: 90 }, children: [
2609
- /* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", children: "Currency" }),
2610
- /* @__PURE__ */ jsx(
2611
- "input",
2612
- {
2613
- type: "text",
2614
- className: "pollar-ramp-input",
2615
- placeholder: "MXN",
2616
- value: currency,
2617
- maxLength: 5,
2618
- onChange: (e) => onCurrencyChange(e.target.value.toUpperCase())
2619
- }
2620
- )
2621
- ] })
2622
- ] }),
2623
2626
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
2624
2627
  /* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", children: "Country" }),
2625
2628
  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: [
@@ -2629,6 +2632,23 @@ function RampWidgetTemplate({
2629
2632
  c.currency ? ` \u2014 ${c.currency}` : ""
2630
2633
  ] }, c.code)) })
2631
2634
  ] }),
2635
+ /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
2636
+ /* @__PURE__ */ jsxs("label", { className: "pollar-ramp-label", children: [
2637
+ "Amount",
2638
+ currency ? ` (${currency})` : ""
2639
+ ] }),
2640
+ /* @__PURE__ */ jsx(
2641
+ "input",
2642
+ {
2643
+ type: "number",
2644
+ className: "pollar-ramp-input",
2645
+ placeholder: "0.00",
2646
+ value: amount,
2647
+ min: "0",
2648
+ onChange: (e) => onAmountChange(e.target.value)
2649
+ }
2650
+ )
2651
+ ] }),
2632
2652
  /* @__PURE__ */ jsxs("div", { className: "pollar-modal-actions", children: [
2633
2653
  /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" }),
2634
2654
  /* @__PURE__ */ jsx(
@@ -2651,6 +2671,34 @@ function RampWidgetTemplate({
2651
2671
  /* @__PURE__ */ jsx("div", { className: "pollar-ramp-route-list", children: quotes.map((q, i) => /* @__PURE__ */ jsx(RouteDisplay, { quote: q, onSelect: onSelectQuote }, i)) }),
2652
2672
  /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" })
2653
2673
  ] }),
2674
+ step === "contact" && /* @__PURE__ */ jsxs(Fragment, { children: [
2675
+ requiredFields.map((f) => /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
2676
+ /* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", children: f.label }),
2677
+ /* @__PURE__ */ jsx(
2678
+ "input",
2679
+ {
2680
+ type: f.type,
2681
+ className: "pollar-ramp-input",
2682
+ value: fieldValues[f.key] ?? "",
2683
+ autoComplete: f.type === "email" ? "email" : "off",
2684
+ onChange: (e) => onFieldChange(f.key, e.target.value)
2685
+ }
2686
+ )
2687
+ ] }, f.key)),
2688
+ /* @__PURE__ */ jsxs("div", { className: "pollar-modal-actions", children: [
2689
+ /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onRetry, children: "Back" }),
2690
+ /* @__PURE__ */ jsx(
2691
+ "button",
2692
+ {
2693
+ type: "button",
2694
+ className: "pollar-btn-primary",
2695
+ disabled: requiredFields.some((f) => !(fieldValues[f.key] ?? "").trim()) || isLoading,
2696
+ onClick: onContactContinue,
2697
+ children: isLoading ? "Starting\u2026" : "Continue"
2698
+ }
2699
+ )
2700
+ ] })
2701
+ ] }),
2654
2702
  step === "status" && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment", children: [
2655
2703
  /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
2656
2704
  /* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Provider" }),
@@ -2668,6 +2716,10 @@ function RampWidgetTemplate({
2668
2716
  stellarTxHash.slice(-8)
2669
2717
  ] }) })
2670
2718
  ] }),
2719
+ depositInstructions && txStatus !== "completed" && flattenInstructions(depositInstructions).map(({ key, label, value }) => /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
2720
+ /* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: label }),
2721
+ /* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsx("code", { style: { wordBreak: "break-all" }, children: value }) })
2722
+ ] }, key)),
2671
2723
  kycUrl && txStatus !== "completed" && /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenKyc, children: [
2672
2724
  "Continue at ",
2673
2725
  provider
@@ -2686,6 +2738,9 @@ function RampWidgetTemplate({
2686
2738
  ] });
2687
2739
  }
2688
2740
  var TERMINAL = ["completed", "failed"];
2741
+ function requiredFieldsOf(quote) {
2742
+ return quote.requiredFields ?? [];
2743
+ }
2689
2744
  function RampWidget({ onClose }) {
2690
2745
  const { getClient, signTx, wallet, styles } = usePollar();
2691
2746
  const walletAddress = wallet?.address ?? "";
@@ -2696,16 +2751,20 @@ function RampWidget({ onClose }) {
2696
2751
  const [amount, setAmount] = useState("");
2697
2752
  const [currency, setCurrency] = useState("");
2698
2753
  const [country, setCountry] = useState("");
2754
+ const [fieldValues, setFieldValues] = useState({});
2755
+ const setFieldValue = (key, value) => setFieldValues((v) => ({ ...v, [key]: value }));
2699
2756
  const [countries, setCountries] = useState([]);
2700
2757
  const [countriesLoading, setCountriesLoading] = useState(true);
2701
2758
  const [refreshing, setRefreshing] = useState(false);
2702
2759
  const [quotes, setQuotes] = useState([]);
2760
+ const [selectedQuote, setSelectedQuote] = useState(null);
2703
2761
  const [isLoading, setIsLoading] = useState(false);
2704
2762
  const [txId, setTxId] = useState(null);
2705
2763
  const [provider, setProvider] = useState("");
2706
2764
  const [kycUrl, setKycUrl] = useState(null);
2707
2765
  const [txStatus, setTxStatus] = useState(null);
2708
2766
  const [stellarTxHash, setStellarTxHash] = useState(null);
2767
+ const [depositInstructions, setDepositInstructions] = useState(null);
2709
2768
  const [completing, setCompleting] = useState(false);
2710
2769
  const [errorMsg, setErrorMsg] = useState(null);
2711
2770
  const directionRef = useRef(direction);
@@ -2721,6 +2780,8 @@ function RampWidget({ onClose }) {
2721
2780
  setTxStatus(tx.status);
2722
2781
  if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
2723
2782
  if (tx.kycUrl) setKycUrl(tx.kycUrl);
2783
+ const di = tx.depositInstructions;
2784
+ if (di) setDepositInstructions(di);
2724
2785
  if (TERMINAL.includes(tx.status)) clearInterval(id);
2725
2786
  } catch {
2726
2787
  }
@@ -2768,6 +2829,8 @@ function RampWidget({ onClose }) {
2768
2829
  setTxStatus(tx.status);
2769
2830
  if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
2770
2831
  if (tx.kycUrl) setKycUrl(tx.kycUrl);
2832
+ const di = tx.depositInstructions;
2833
+ if (di) setDepositInstructions(di);
2771
2834
  }
2772
2835
  } catch {
2773
2836
  } finally {
@@ -2777,11 +2840,13 @@ function RampWidget({ onClose }) {
2777
2840
  function resetToInput() {
2778
2841
  setStep("input");
2779
2842
  setQuotes([]);
2843
+ setSelectedQuote(null);
2780
2844
  setTxId(null);
2781
2845
  setProvider("");
2782
2846
  setKycUrl(null);
2783
2847
  setTxStatus(null);
2784
2848
  setStellarTxHash(null);
2849
+ setDepositInstructions(null);
2785
2850
  setErrorMsg(null);
2786
2851
  }
2787
2852
  async function resumeWithSignature(id, ps) {
@@ -2807,6 +2872,7 @@ function RampWidget({ onClose }) {
2807
2872
  setKycUrl(result.kycUrl ?? null);
2808
2873
  setTxStatus(result.status);
2809
2874
  setStellarTxHash(result.stellarTxHash ?? null);
2875
+ setDepositInstructions(result.depositInstructions ?? null);
2810
2876
  setStep("status");
2811
2877
  }
2812
2878
  async function handleFindRoute() {
@@ -2830,12 +2896,33 @@ function RampWidget({ onClose }) {
2830
2896
  setIsLoading(false);
2831
2897
  }
2832
2898
  }
2833
- async function handleSelectQuote(quote) {
2899
+ function handleSelectQuote(quote) {
2900
+ setSelectedQuote(quote);
2901
+ setErrorMsg(null);
2902
+ const fields = requiredFieldsOf(quote);
2903
+ const missing = fields.some((f) => !(fieldValues[f.key] ?? "").trim());
2904
+ if (fields.length > 0 && missing) {
2905
+ setStep("contact");
2906
+ return;
2907
+ }
2908
+ void startRamp(quote);
2909
+ }
2910
+ function handleContactContinue() {
2911
+ if (selectedQuote) void startRamp(selectedQuote);
2912
+ }
2913
+ async function startRamp(quote) {
2834
2914
  setIsLoading(true);
2835
2915
  setErrorMsg(null);
2836
2916
  try {
2837
2917
  const base = { quoteId: quote.quoteId, amount: Number(amount), currency, country };
2838
- const result = direction === "onramp" ? await client.createOnRamp({ ...base, ...walletAddress ? { walletAddress } : {} }) : await client.createOffRamp({ ...base, ...walletAddress ? { walletAddress } : {} });
2918
+ if (walletAddress) base.walletAddress = walletAddress;
2919
+ for (const f of requiredFieldsOf(quote)) {
2920
+ const val = (fieldValues[f.key] ?? "").trim();
2921
+ if (!val) continue;
2922
+ if (f.bankType) base.bankDetails = { type: f.bankType, value: val };
2923
+ else base[f.key] = val;
2924
+ }
2925
+ const result = direction === "onramp" ? await client.createOnRamp(base) : await client.createOffRamp(base);
2839
2926
  await applyResult(result);
2840
2927
  } catch (e) {
2841
2928
  setErrorMsg(e instanceof Error ? e.message : "Failed to start the ramp.");
@@ -2879,6 +2966,8 @@ function RampWidget({ onClose }) {
2879
2966
  amount,
2880
2967
  currency,
2881
2968
  country,
2969
+ requiredFields: selectedQuote ? requiredFieldsOf(selectedQuote) : [],
2970
+ fieldValues,
2882
2971
  countries,
2883
2972
  countriesLoading,
2884
2973
  refreshing,
@@ -2888,15 +2977,17 @@ function RampWidget({ onClose }) {
2888
2977
  txStatus,
2889
2978
  kycUrl,
2890
2979
  stellarTxHash,
2980
+ depositInstructions,
2891
2981
  canComplete,
2892
2982
  completing,
2893
2983
  errorMsg,
2894
2984
  onDirectionChange: setDirection,
2895
2985
  onAmountChange: setAmount,
2896
- onCurrencyChange: setCurrency,
2986
+ onFieldChange: setFieldValue,
2897
2987
  onCountryChange: handleCountryChange,
2898
2988
  onFindRoute: handleFindRoute,
2899
2989
  onSelectQuote: handleSelectQuote,
2990
+ onContactContinue: handleContactContinue,
2900
2991
  onOpenKyc: handleOpenKyc,
2901
2992
  onCompleteWithdraw: handleCompleteWithdraw,
2902
2993
  onRetry: resetToInput,
@@ -4549,6 +4640,10 @@ function TxHistoryModalTemplate({
4549
4640
  /* @__PURE__ */ jsx(StatusBadge, { status: record.status }),
4550
4641
  /* @__PURE__ */ jsxs("span", { className: "pollar-hist-item-meta", children: [
4551
4642
  /* @__PURE__ */ jsx("span", { children: record.operation }),
4643
+ typeof record.details?.sponsored === "boolean" && /* @__PURE__ */ jsxs("span", { children: [
4644
+ "\xB7 ",
4645
+ record.details.sponsored ? "Sponsored" : "Self-paid"
4646
+ ] }),
4552
4647
  record.feeXlm && /* @__PURE__ */ jsxs("span", { children: [
4553
4648
  "\xB7 ",
4554
4649
  record.feeXlm,