@pollar/react 0.11.3 → 0.11.4-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/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +68 -25
- package/dist/index.css +1375 -217
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +163 -33
- package/dist/index.d.ts +163 -33
- package/dist/index.js +2090 -570
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2088 -572
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -1027,19 +1027,77 @@ var ModalErrorBoundary = class extends react.Component {
|
|
|
1027
1027
|
return this.props.children;
|
|
1028
1028
|
}
|
|
1029
1029
|
};
|
|
1030
|
-
var PollarModalFooter = () => {
|
|
1030
|
+
var PollarModalFooter = ({ shield = false }) => {
|
|
1031
1031
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-footer", children: [
|
|
1032
1032
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-footer-protected", children: "Protected by" }),
|
|
1033
1033
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-footer-brand", children: [
|
|
1034
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1034
|
+
shield ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "pollar-footer-shield", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", "aria-hidden": true, children: [
|
|
1035
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 3.2 19 6v5.3c0 4.4-2.9 7.8-7 9.5-4.1-1.7-7-5.1-7-9.5V6l7-2.8Z", fill: "var(--pollar-accent)" }),
|
|
1036
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m8.5 12 2.2 2.2 4.8-5", stroke: "white", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
1037
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("img", { src: LOGO_POLLAR, alt: "Pollar", className: "pollar-footer-logo" }),
|
|
1035
1038
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
|
|
1036
1039
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-footer-version", children: [
|
|
1037
1040
|
"v",
|
|
1038
|
-
"0.11.
|
|
1041
|
+
"0.11.4-rc.2"
|
|
1039
1042
|
] })
|
|
1040
1043
|
] })
|
|
1041
1044
|
] });
|
|
1042
1045
|
};
|
|
1046
|
+
function RefreshIcon({ spinning = false, className = "" }) {
|
|
1047
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1048
|
+
"svg",
|
|
1049
|
+
{
|
|
1050
|
+
className: `${spinning ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon"}${className ? ` ${className}` : ""}`,
|
|
1051
|
+
width: "17",
|
|
1052
|
+
height: "17",
|
|
1053
|
+
viewBox: "0 0 17 17",
|
|
1054
|
+
fill: "none",
|
|
1055
|
+
"aria-hidden": true,
|
|
1056
|
+
children: [
|
|
1057
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1058
|
+
"path",
|
|
1059
|
+
{
|
|
1060
|
+
d: "M2.125 8.5C2.125 6.80924 2.79665 5.18774 3.99219 3.99219C5.18774 2.79665 6.80924 2.125 8.5 2.125C10.2822 2.1317 11.9928 2.82712 13.2742 4.06583L14.875 5.66667",
|
|
1061
|
+
stroke: "currentColor",
|
|
1062
|
+
strokeWidth: "2",
|
|
1063
|
+
strokeLinecap: "round",
|
|
1064
|
+
strokeLinejoin: "round"
|
|
1065
|
+
}
|
|
1066
|
+
),
|
|
1067
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1068
|
+
"path",
|
|
1069
|
+
{
|
|
1070
|
+
d: "M14.8747 2.125V5.66667H11.333",
|
|
1071
|
+
stroke: "currentColor",
|
|
1072
|
+
strokeWidth: "2",
|
|
1073
|
+
strokeLinecap: "round",
|
|
1074
|
+
strokeLinejoin: "round"
|
|
1075
|
+
}
|
|
1076
|
+
),
|
|
1077
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1078
|
+
"path",
|
|
1079
|
+
{
|
|
1080
|
+
d: "M14.875 8.5C14.875 10.1908 14.2033 11.8123 13.0078 13.0078C11.8123 14.2033 10.1908 14.875 8.5 14.875C6.7178 14.8683 5.00719 14.1729 3.72583 12.9342L2.125 11.3333",
|
|
1081
|
+
stroke: "currentColor",
|
|
1082
|
+
strokeWidth: "2",
|
|
1083
|
+
strokeLinecap: "round",
|
|
1084
|
+
strokeLinejoin: "round"
|
|
1085
|
+
}
|
|
1086
|
+
),
|
|
1087
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1088
|
+
"path",
|
|
1089
|
+
{
|
|
1090
|
+
d: "M2.125 14.875V11.3333H5.66667",
|
|
1091
|
+
stroke: "currentColor",
|
|
1092
|
+
strokeWidth: "2",
|
|
1093
|
+
strokeLinecap: "round",
|
|
1094
|
+
strokeLinejoin: "round"
|
|
1095
|
+
}
|
|
1096
|
+
)
|
|
1097
|
+
]
|
|
1098
|
+
}
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1043
1101
|
function CopyButton({ value, label = "Copy", className }) {
|
|
1044
1102
|
const [copied, setCopied] = react.useState(false);
|
|
1045
1103
|
const timerRef = react.useRef(null);
|
|
@@ -1827,9 +1885,10 @@ var STATUS_CONFIG = {
|
|
|
1827
1885
|
none: { label: "Not started", color: "#6b7280", dot: false },
|
|
1828
1886
|
pending: { label: "Pending review", color: "#f59e0b", dot: true },
|
|
1829
1887
|
approved: { label: "Verified", color: "#10b981", dot: false },
|
|
1830
|
-
rejected: { label: "Rejected", color: "#ef4444", dot: false }
|
|
1888
|
+
rejected: { label: "Rejected", color: "#ef4444", dot: false },
|
|
1889
|
+
expired: { label: "Expired", color: "#6b7280", dot: false }
|
|
1831
1890
|
};
|
|
1832
|
-
function KycStatus({ status, className }) {
|
|
1891
|
+
function KycStatus({ status, label, className }) {
|
|
1833
1892
|
const config = STATUS_CONFIG[status] ?? STATUS_CONFIG.none;
|
|
1834
1893
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1835
1894
|
"span",
|
|
@@ -1838,11 +1897,42 @@ function KycStatus({ status, className }) {
|
|
|
1838
1897
|
style: { "--pollar-kyc-color": config.color },
|
|
1839
1898
|
children: [
|
|
1840
1899
|
config.dot && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-kyc-badge-dot" }),
|
|
1841
|
-
config.label
|
|
1900
|
+
label ?? config.label
|
|
1842
1901
|
]
|
|
1843
1902
|
}
|
|
1844
1903
|
);
|
|
1845
1904
|
}
|
|
1905
|
+
|
|
1906
|
+
// src/components/kyc-modal/kyc-messages.ts
|
|
1907
|
+
function kycErrorMessage(error, phase) {
|
|
1908
|
+
const code = error?.code;
|
|
1909
|
+
switch (code) {
|
|
1910
|
+
case "SDK_KYC_NOT_CONFIGURED":
|
|
1911
|
+
return "Identity verification is not available for this app yet.";
|
|
1912
|
+
case "SDK_KYC_PROVIDER_ERROR":
|
|
1913
|
+
return "The verification service is not responding right now. Please try again in a moment.";
|
|
1914
|
+
case "SDK_KYC_SESSION_EXPIRED":
|
|
1915
|
+
return "Your previous verification session expired. Select the provider to start a new one.";
|
|
1916
|
+
case "SDK_KYC_PROVIDER_NOT_FOUND":
|
|
1917
|
+
case "SDK_KYC_PROVIDER_NOT_ENABLED":
|
|
1918
|
+
return "This verification option is no longer available. Refresh to see the current options.";
|
|
1919
|
+
case "SDK_RAMPS_PROVIDER_NOT_CONFIGURED":
|
|
1920
|
+
return "This route is not set up for identity verification yet.";
|
|
1921
|
+
case "VALIDATION_ERROR":
|
|
1922
|
+
return "This verification option is not available for your country.";
|
|
1923
|
+
default:
|
|
1924
|
+
return phase === "load" ? "Could not load verification options. Please refresh to try again." : "Could not start verification. Please try again.";
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
function kycReviewMessage(reviewReason) {
|
|
1928
|
+
if (reviewReason === "DUPLICATE_DOCUMENT") {
|
|
1929
|
+
return "This document is already linked to another account, so our team is reviewing it. You can check again later.";
|
|
1930
|
+
}
|
|
1931
|
+
return "Your verification is still being reviewed. You can check again shortly.";
|
|
1932
|
+
}
|
|
1933
|
+
function kycProcessingMessage() {
|
|
1934
|
+
return "Your verification was approved. We are finishing setting it up; check again in a minute.";
|
|
1935
|
+
}
|
|
1846
1936
|
function KycModalTemplate({
|
|
1847
1937
|
theme,
|
|
1848
1938
|
accentColor,
|
|
@@ -1852,151 +1942,274 @@ function KycModalTemplate({
|
|
|
1852
1942
|
selectedProvider,
|
|
1853
1943
|
session,
|
|
1854
1944
|
kycStatus,
|
|
1945
|
+
reviewReason,
|
|
1946
|
+
processing = false,
|
|
1855
1947
|
isLoading,
|
|
1948
|
+
error,
|
|
1856
1949
|
onSelectProvider,
|
|
1857
1950
|
onDoneVerifying,
|
|
1951
|
+
onStartAgain,
|
|
1858
1952
|
onRefresh,
|
|
1859
1953
|
onClose
|
|
1860
1954
|
}) {
|
|
1861
1955
|
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
|
|
1862
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
"
|
|
1956
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1957
|
+
"div",
|
|
1958
|
+
{
|
|
1959
|
+
className: `pollar-modal-card pollar-kyc-modal ${step === "verifying" ? "pollar-kyc-modal--verifying" : ""}`,
|
|
1960
|
+
role: "dialog",
|
|
1961
|
+
"aria-modal": "true",
|
|
1962
|
+
"aria-label": "Identity verification",
|
|
1963
|
+
style: cssVars,
|
|
1964
|
+
onClick: (e) => e.stopPropagation(),
|
|
1965
|
+
children: [
|
|
1966
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
1967
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-kyc-header-text", children: [
|
|
1968
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: "Identity verification" }),
|
|
1969
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-kyc-subtitle", children: [
|
|
1970
|
+
step === "select_provider" && "Choose your verification provider",
|
|
1971
|
+
step === "verifying" && `Complete the steps below with ${selectedProvider?.name}`,
|
|
1972
|
+
step === "polling" && "Waiting for verification result",
|
|
1973
|
+
step === "done" && (kycStatus === "approved" ? "You\u2019re ready to continue" : "Your verification status")
|
|
1974
|
+
] })
|
|
1975
|
+
] }),
|
|
1976
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
|
|
1977
|
+
step === "select_provider" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1978
|
+
"button",
|
|
1885
1979
|
{
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
"
|
|
1980
|
+
type: "button",
|
|
1981
|
+
className: "pollar-modal-close",
|
|
1982
|
+
onClick: onRefresh,
|
|
1983
|
+
disabled: isLoading,
|
|
1984
|
+
"aria-label": "Refresh",
|
|
1985
|
+
title: "Refresh providers",
|
|
1892
1986
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1893
|
-
"
|
|
1987
|
+
"svg",
|
|
1894
1988
|
{
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1989
|
+
className: isLoading ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
|
|
1990
|
+
width: "16",
|
|
1991
|
+
height: "16",
|
|
1992
|
+
viewBox: "0 0 16 16",
|
|
1993
|
+
fill: "none",
|
|
1994
|
+
"aria-hidden": true,
|
|
1995
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1996
|
+
"path",
|
|
1997
|
+
{
|
|
1998
|
+
d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
|
|
1999
|
+
stroke: "currentColor",
|
|
2000
|
+
strokeWidth: "1.6",
|
|
2001
|
+
strokeLinecap: "round",
|
|
2002
|
+
strokeLinejoin: "round"
|
|
2003
|
+
}
|
|
2004
|
+
)
|
|
1900
2005
|
}
|
|
1901
2006
|
)
|
|
1902
2007
|
}
|
|
1903
|
-
)
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
2008
|
+
),
|
|
2009
|
+
/* @__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" }) }) })
|
|
2010
|
+
] })
|
|
2011
|
+
] }),
|
|
2012
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-kyc-error", role: "alert", children: error }),
|
|
2013
|
+
step === "select_provider" && (isLoading && providers.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-loading-block", children: [
|
|
2014
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-spinner" }),
|
|
2015
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Loading providers\u2026" })
|
|
2016
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-kyc-providers", children: [
|
|
2017
|
+
providers.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "var(--pollar-muted)", textAlign: "center" }, children: "No providers available for your country." }),
|
|
2018
|
+
providers.map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2019
|
+
"button",
|
|
2020
|
+
{
|
|
2021
|
+
type: "button",
|
|
2022
|
+
className: "pollar-kyc-provider-btn",
|
|
2023
|
+
disabled: isLoading,
|
|
2024
|
+
onClick: () => onSelectProvider(p),
|
|
2025
|
+
children: [
|
|
2026
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-kyc-provider-name", children: p.name }),
|
|
2027
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-kyc-provider-flow", children: isLoading && selectedProvider?.id === p.id ? "Opening\u2026" : p.flow === "redirect" ? "Continue in a new tab" : "Continue here" })
|
|
2028
|
+
]
|
|
2029
|
+
},
|
|
2030
|
+
p.id
|
|
2031
|
+
))
|
|
2032
|
+
] })),
|
|
2033
|
+
step === "verifying" && selectedProvider && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2034
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-kyc-session-bar", children: [
|
|
2035
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-kyc-session-label", children: [
|
|
2036
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-kyc-session-dot" }),
|
|
2037
|
+
"Verification in progress"
|
|
2038
|
+
] }),
|
|
2039
|
+
session?.kycUrl && /* @__PURE__ */ jsxRuntime.jsx("a", { href: session.kycUrl, target: "_blank", rel: "noopener noreferrer", children: "Open in new tab \u2197" })
|
|
2040
|
+
] }),
|
|
2041
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-kyc-iframe-wrap", children: session?.kycUrl && selectedProvider.flow === "redirect" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-kyc-iframe-mock", children: [
|
|
2042
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Complete verification in a separate tab, then return here to check your status." }),
|
|
2043
|
+
/* @__PURE__ */ jsxRuntime.jsx("a", { className: "pollar-btn-primary", href: session.kycUrl, target: "_blank", rel: "noopener noreferrer", children: "Open verification" })
|
|
2044
|
+
] }) : session?.kycUrl ? /* @__PURE__ */ jsxRuntime.jsx("iframe", { className: "pollar-kyc-iframe", src: session.kycUrl, title: "KYC verification", allow: "camera; microphone" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-kyc-iframe-mock", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: selectedProvider.flow === "form" ? "The identity verification form will appear here." : "Identity verification will open here." }) }) }),
|
|
2045
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-kyc-footer", children: [
|
|
2046
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Finished the steps? Check your status to continue." }),
|
|
2047
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
|
|
2048
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Close" }),
|
|
2049
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onDoneVerifying, children: "Check status" })
|
|
2050
|
+
] })
|
|
2051
|
+
] })
|
|
2052
|
+
] }),
|
|
2053
|
+
step === "polling" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-kyc-polling", children: [
|
|
2054
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-spinner" }),
|
|
2055
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-kyc-polling-text", children: "Checking verification status\u2026" })
|
|
2056
|
+
] }),
|
|
2057
|
+
step === "done" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-kyc-result", children: [
|
|
2058
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `pollar-kyc-result-icon pollar-kyc-result-icon--${kycStatus}`, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2059
|
+
"svg",
|
|
2060
|
+
{
|
|
2061
|
+
width: "28",
|
|
2062
|
+
height: "28",
|
|
2063
|
+
viewBox: "0 0 24 24",
|
|
2064
|
+
fill: "none",
|
|
2065
|
+
stroke: "currentColor",
|
|
2066
|
+
strokeWidth: "1.5",
|
|
2067
|
+
strokeLinecap: "round",
|
|
2068
|
+
strokeLinejoin: "round",
|
|
2069
|
+
children: kycStatus === "approved" ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m5 12 4 4L19 6" }) : kycStatus === "rejected" ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m7 7 10 10M17 7 7 17" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2070
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "8" }),
|
|
2071
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 7v5l3 2" })
|
|
2072
|
+
] })
|
|
2073
|
+
}
|
|
2074
|
+
) }),
|
|
2075
|
+
/* @__PURE__ */ jsxRuntime.jsx(KycStatus, { status: kycStatus, ...processing ? { label: "Approved" } : {} }),
|
|
2076
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-kyc-result-text", children: kycStatus === "approved" ? "Your identity has been verified successfully." : kycStatus === "rejected" ? "Your verification was not approved. Contact support for the next steps." : kycStatus === "expired" ? "Your verification expired. Start again to verify your identity." : processing ? kycProcessingMessage() : kycReviewMessage(reviewReason) }),
|
|
2077
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
|
|
2078
|
+
kycStatus === "expired" && onStartAgain && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onStartAgain, disabled: isLoading, children: "Start again" }),
|
|
2079
|
+
kycStatus !== "approved" && kycStatus !== "rejected" && kycStatus !== "expired" && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onDoneVerifying, children: "Check again" }),
|
|
2080
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onClose, children: "Close" })
|
|
2081
|
+
] })
|
|
2082
|
+
] })
|
|
2083
|
+
]
|
|
2084
|
+
}
|
|
2085
|
+
);
|
|
1950
2086
|
}
|
|
1951
|
-
function
|
|
2087
|
+
function newIdempotencyKey() {
|
|
2088
|
+
const c = globalThis.crypto;
|
|
2089
|
+
if (c && typeof c.randomUUID === "function") return c.randomUUID();
|
|
2090
|
+
return `kyc-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
|
|
2091
|
+
}
|
|
2092
|
+
function KycModal({ onClose, country = "MX", level = "basic", onApproved, corridorId, providerId }) {
|
|
1952
2093
|
const { getClient, styles } = usePollar();
|
|
1953
2094
|
const [step, setStep] = react.useState("select_provider");
|
|
1954
2095
|
const [providers, setProviders] = react.useState([]);
|
|
1955
2096
|
const [selectedProvider, setSelectedProvider] = react.useState(null);
|
|
1956
2097
|
const [session, setSession] = react.useState(null);
|
|
1957
2098
|
const [kycStatus, setKycStatus] = react.useState("none");
|
|
2099
|
+
const [reviewReason, setReviewReason] = react.useState(null);
|
|
2100
|
+
const [processing, setProcessing] = react.useState(false);
|
|
1958
2101
|
const [isLoading, setIsLoading] = react.useState(false);
|
|
2102
|
+
const [error, setError] = react.useState(null);
|
|
2103
|
+
const idempotencyKeys = react.useRef({});
|
|
2104
|
+
const autoOpened = react.useRef(false);
|
|
1959
2105
|
const client = getClient();
|
|
1960
2106
|
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
}
|
|
1968
|
-
|
|
2107
|
+
function finish(status, reason = null, isProcessing = false) {
|
|
2108
|
+
setKycStatus(status);
|
|
2109
|
+
setReviewReason(reason);
|
|
2110
|
+
setProcessing(isProcessing);
|
|
2111
|
+
setStep("done");
|
|
2112
|
+
if (status === "approved") onApproved?.();
|
|
2113
|
+
}
|
|
2114
|
+
function finishWith(read) {
|
|
2115
|
+
if (read.status === "pending" && read.decisionStatus === "approved") finish("pending", null, true);
|
|
2116
|
+
else if (read.decisionStatus === "manual_review") finish("pending", read.reviewReason ?? null);
|
|
2117
|
+
else finish(read.decisionStatus === "expired" ? "expired" : read.status);
|
|
2118
|
+
}
|
|
2119
|
+
function readStatus(providerId2) {
|
|
2120
|
+
return corridorId ? client.getKycStatus(void 0, corridorId) : client.getKycStatus(providerId2);
|
|
2121
|
+
}
|
|
2122
|
+
const starting = react.useRef(false);
|
|
2123
|
+
async function handleSelectProvider(provider, listed = true) {
|
|
2124
|
+
var _a, _b;
|
|
2125
|
+
if (starting.current) return;
|
|
2126
|
+
starting.current = true;
|
|
1969
2127
|
setSelectedProvider(provider);
|
|
2128
|
+
setError(null);
|
|
1970
2129
|
setIsLoading(true);
|
|
2130
|
+
const key = (_a = idempotencyKeys.current)[_b = provider.id] ?? (_a[_b] = newIdempotencyKey());
|
|
1971
2131
|
try {
|
|
1972
|
-
const result = await client.resolveKyc(
|
|
2132
|
+
const result = await client.resolveKyc(
|
|
2133
|
+
provider.id,
|
|
2134
|
+
provider.levels?.[0] ?? level,
|
|
2135
|
+
listed ? country : void 0,
|
|
2136
|
+
corridorId,
|
|
2137
|
+
key
|
|
2138
|
+
);
|
|
1973
2139
|
if (result.alreadyApproved) {
|
|
1974
|
-
|
|
1975
|
-
setStep("done");
|
|
1976
|
-
onApproved?.();
|
|
2140
|
+
finish("approved");
|
|
1977
2141
|
return;
|
|
1978
2142
|
}
|
|
1979
2143
|
setSession(result);
|
|
1980
2144
|
setStep("verifying");
|
|
1981
|
-
} catch {
|
|
2145
|
+
} catch (e) {
|
|
2146
|
+
const code = core.isPollarApiError(e) ? e.code : void 0;
|
|
2147
|
+
if (code === "SDK_KYC_ALREADY_APPROVED") {
|
|
2148
|
+
finish("approved");
|
|
2149
|
+
return;
|
|
2150
|
+
}
|
|
2151
|
+
if (code === "SDK_KYC_UNDER_REVIEW") {
|
|
2152
|
+
await readStatus(provider.id).then(finishWith, () => finish("pending"));
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2155
|
+
if (code === "SDK_KYC_SESSION_EXPIRED") delete idempotencyKeys.current[provider.id];
|
|
2156
|
+
setError(kycErrorMessage(e, "start"));
|
|
1982
2157
|
setStep("select_provider");
|
|
1983
2158
|
} finally {
|
|
2159
|
+
starting.current = false;
|
|
1984
2160
|
setIsLoading(false);
|
|
1985
2161
|
}
|
|
1986
2162
|
}
|
|
2163
|
+
const loadProviders = react.useCallback(() => {
|
|
2164
|
+
setIsLoading(true);
|
|
2165
|
+
setError(null);
|
|
2166
|
+
return getClient().getKycProviders(country, corridorId).then((result) => {
|
|
2167
|
+
setProviders(result.providers);
|
|
2168
|
+
return result.providers;
|
|
2169
|
+
}).catch((e) => {
|
|
2170
|
+
setProviders([]);
|
|
2171
|
+
setError(kycErrorMessage(e, "load"));
|
|
2172
|
+
return [];
|
|
2173
|
+
}).finally(() => setIsLoading(false));
|
|
2174
|
+
}, [getClient, country, corridorId]);
|
|
2175
|
+
react.useEffect(() => {
|
|
2176
|
+
void loadProviders().then((list) => {
|
|
2177
|
+
if (!providerId || autoOpened.current) return;
|
|
2178
|
+
autoOpened.current = true;
|
|
2179
|
+
const target = list.find((p) => p.id === providerId);
|
|
2180
|
+
if (target) void handleSelectProvider(target);
|
|
2181
|
+
else
|
|
2182
|
+
void handleSelectProvider(
|
|
2183
|
+
{ id: providerId, name: "Identity verification", flow: "iframe", levels: [level] },
|
|
2184
|
+
false
|
|
2185
|
+
);
|
|
2186
|
+
});
|
|
2187
|
+
}, [loadProviders, providerId]);
|
|
1987
2188
|
async function handleDoneVerifying() {
|
|
1988
2189
|
if (!selectedProvider) return;
|
|
2190
|
+
setError(null);
|
|
1989
2191
|
setStep("polling");
|
|
1990
2192
|
try {
|
|
1991
|
-
const
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
2193
|
+
const read = await client.pollKycDecision(selectedProvider.id, {
|
|
2194
|
+
intervalMs: 3e3,
|
|
2195
|
+
timeoutMs: 12e4,
|
|
2196
|
+
...corridorId ? { corridorId } : {}
|
|
2197
|
+
});
|
|
2198
|
+
finishWith(read);
|
|
1995
2199
|
} catch {
|
|
1996
|
-
|
|
1997
|
-
setStep("
|
|
2200
|
+
setError("We could not confirm your result yet. Check again shortly; this does not mean your verification was rejected.");
|
|
2201
|
+
setStep("verifying");
|
|
1998
2202
|
}
|
|
1999
2203
|
}
|
|
2204
|
+
function handleStartAgain() {
|
|
2205
|
+
if (selectedProvider) delete idempotencyKeys.current[selectedProvider.id];
|
|
2206
|
+
setSession(null);
|
|
2207
|
+
setKycStatus("none");
|
|
2208
|
+
setReviewReason(null);
|
|
2209
|
+
setProcessing(false);
|
|
2210
|
+
if (selectedProvider) void handleSelectProvider(selectedProvider);
|
|
2211
|
+
else setStep("select_provider");
|
|
2212
|
+
}
|
|
2000
2213
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2001
2214
|
KycModalTemplate,
|
|
2002
2215
|
{
|
|
@@ -2008,91 +2221,477 @@ function KycModal({ onClose, country = "MX", level = "basic", onApproved }) {
|
|
|
2008
2221
|
selectedProvider,
|
|
2009
2222
|
session,
|
|
2010
2223
|
kycStatus,
|
|
2224
|
+
reviewReason,
|
|
2225
|
+
processing,
|
|
2011
2226
|
isLoading,
|
|
2227
|
+
error,
|
|
2012
2228
|
onSelectProvider: handleSelectProvider,
|
|
2013
2229
|
onDoneVerifying: handleDoneVerifying,
|
|
2230
|
+
onStartAgain: handleStartAgain,
|
|
2014
2231
|
onRefresh: () => void loadProviders(),
|
|
2015
2232
|
onClose
|
|
2016
2233
|
}
|
|
2017
2234
|
) });
|
|
2018
2235
|
}
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2236
|
+
|
|
2237
|
+
// src/components/requirement-form-modal/form-fields.ts
|
|
2238
|
+
function formLanguage() {
|
|
2239
|
+
const language = typeof navigator !== "undefined" ? navigator.language : "";
|
|
2240
|
+
return language.toLowerCase().startsWith("es") ? "es" : "en";
|
|
2241
|
+
}
|
|
2242
|
+
function localized(text, language) {
|
|
2243
|
+
return (language === "es" ? text?.es || text?.en : text?.en || text?.es) ?? "";
|
|
2244
|
+
}
|
|
2245
|
+
function initialValues(fields, answers) {
|
|
2246
|
+
const values = {};
|
|
2247
|
+
for (const field of fields) {
|
|
2248
|
+
const answer = answers[field.key];
|
|
2249
|
+
if (field.type === "checkbox") values[field.key] = answer === true;
|
|
2250
|
+
else if (field.type === "multiselect") values[field.key] = Array.isArray(answer) ? answer : [];
|
|
2251
|
+
else values[field.key] = answer === void 0 || answer === null ? "" : String(answer);
|
|
2024
2252
|
}
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2253
|
+
return values;
|
|
2254
|
+
}
|
|
2255
|
+
var DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
2256
|
+
function localFieldErrors(fields, values) {
|
|
2257
|
+
const errors = {};
|
|
2258
|
+
for (const field of fields) {
|
|
2259
|
+
const value = values[field.key];
|
|
2260
|
+
if (typeof value !== "string" || !value.trim()) continue;
|
|
2261
|
+
if (field.type === "number" && !Number.isFinite(Number(value))) errors[field.key] = "invalid_type";
|
|
2262
|
+
if (field.type === "date" && (!DATE.test(value.trim()) || Number.isNaN(Date.parse(`${value.trim()}T00:00:00Z`)))) {
|
|
2263
|
+
errors[field.key] = "invalid_format";
|
|
2264
|
+
}
|
|
2031
2265
|
}
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2266
|
+
return errors;
|
|
2267
|
+
}
|
|
2268
|
+
function answersOf(fields, values) {
|
|
2269
|
+
const answers = {};
|
|
2270
|
+
for (const field of fields) {
|
|
2271
|
+
const value = values[field.key];
|
|
2272
|
+
if (field.type === "checkbox") {
|
|
2273
|
+
answers[field.key] = value === true;
|
|
2274
|
+
} else if (field.type === "multiselect") {
|
|
2275
|
+
if (Array.isArray(value) && value.length) answers[field.key] = value;
|
|
2276
|
+
} else if (typeof value === "string" && value.trim()) {
|
|
2277
|
+
answers[field.key] = field.type === "number" ? Number(value) : value.trim();
|
|
2035
2278
|
}
|
|
2036
2279
|
}
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2280
|
+
return answers;
|
|
2281
|
+
}
|
|
2282
|
+
var MESSAGES = {
|
|
2283
|
+
en: {
|
|
2284
|
+
required: "This field is required.",
|
|
2285
|
+
invalid_type: "This value is not valid.",
|
|
2286
|
+
invalid_option: "Choose one of the options.",
|
|
2287
|
+
too_long: "This is too long.",
|
|
2288
|
+
too_small: "This value is too small.",
|
|
2289
|
+
too_large: "This value is too large.",
|
|
2290
|
+
pattern: "This does not have the expected format.",
|
|
2291
|
+
invalid_format: "This does not have the expected format."
|
|
2292
|
+
},
|
|
2293
|
+
es: {
|
|
2294
|
+
required: "Este campo es obligatorio.",
|
|
2295
|
+
invalid_type: "Este valor no es v\xE1lido.",
|
|
2296
|
+
invalid_option: "Elige una de las opciones.",
|
|
2297
|
+
too_long: "Es demasiado largo.",
|
|
2298
|
+
too_small: "Este valor es demasiado bajo.",
|
|
2299
|
+
too_large: "Este valor es demasiado alto.",
|
|
2300
|
+
pattern: "No tiene el formato esperado.",
|
|
2301
|
+
invalid_format: "No tiene el formato esperado."
|
|
2044
2302
|
}
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
email ? /* @__PURE__ */ jsxRuntime.jsx("strong", { children: email }) : "your email"
|
|
2049
|
-
] }),
|
|
2050
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-code-inputs", children: digits.map((digit, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2051
|
-
"input",
|
|
2052
|
-
{
|
|
2053
|
-
ref: (el) => {
|
|
2054
|
-
inputRefs.current[i] = el;
|
|
2055
|
-
},
|
|
2056
|
-
type: "text",
|
|
2057
|
-
inputMode: "numeric",
|
|
2058
|
-
maxLength: 2,
|
|
2059
|
-
value: digit,
|
|
2060
|
-
className: "pollar-code-input",
|
|
2061
|
-
onChange: (e) => handleChange(i, e.target.value),
|
|
2062
|
-
onKeyDown: (e) => handleKeyDown(i, e),
|
|
2063
|
-
onPaste: handlePaste
|
|
2064
|
-
},
|
|
2065
|
-
i
|
|
2066
|
-
)) })
|
|
2067
|
-
] });
|
|
2303
|
+
};
|
|
2304
|
+
function fieldErrorMessage(code, language) {
|
|
2305
|
+
return MESSAGES[language][code] ?? MESSAGES[language].invalid_type;
|
|
2068
2306
|
}
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2307
|
+
function fieldErrorsOf(error) {
|
|
2308
|
+
if (!error || typeof error !== "object") return null;
|
|
2309
|
+
const { code, body } = error;
|
|
2310
|
+
if (code !== "KYC_FORM_INVALID_ANSWERS" || !Array.isArray(body?.errors)) return null;
|
|
2311
|
+
const errors = {};
|
|
2312
|
+
for (const item of body.errors) {
|
|
2313
|
+
if (typeof item.key === "string" && typeof item.code === "string") errors[item.key] = item.code;
|
|
2314
|
+
}
|
|
2315
|
+
return Object.keys(errors).length ? errors : null;
|
|
2316
|
+
}
|
|
2317
|
+
var COPY = {
|
|
2318
|
+
en: {
|
|
2319
|
+
title: "A few more details",
|
|
2320
|
+
loading: "Loading the form\u2026",
|
|
2321
|
+
submit: "Continue",
|
|
2322
|
+
submitting: "Saving\u2026",
|
|
2323
|
+
close: "Close",
|
|
2324
|
+
loadError: "Could not load the form. Please try again.",
|
|
2325
|
+
submitError: "Could not save your answers. Please try again.",
|
|
2326
|
+
step: "Step {n} of {total}"
|
|
2327
|
+
},
|
|
2328
|
+
es: {
|
|
2329
|
+
title: "Unos datos m\xE1s",
|
|
2330
|
+
loading: "Cargando el formulario\u2026",
|
|
2331
|
+
submit: "Continuar",
|
|
2332
|
+
submitting: "Guardando\u2026",
|
|
2333
|
+
close: "Cerrar",
|
|
2334
|
+
loadError: "No se pudo cargar el formulario. Intenta de nuevo.",
|
|
2335
|
+
submitError: "No se pudieron guardar tus respuestas. Intenta de nuevo.",
|
|
2336
|
+
step: "Paso {n} de {total}"
|
|
2337
|
+
}
|
|
2081
2338
|
};
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2339
|
+
function FieldInput({
|
|
2340
|
+
field,
|
|
2341
|
+
value,
|
|
2342
|
+
language,
|
|
2343
|
+
disabled,
|
|
2344
|
+
onChange
|
|
2345
|
+
}) {
|
|
2346
|
+
const id = `pollar-form-${field.key}`;
|
|
2347
|
+
const text = typeof value === "string" ? value : "";
|
|
2348
|
+
switch (field.type) {
|
|
2349
|
+
case "select":
|
|
2350
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("select", { id, className: "pollar-input", value: text, disabled, onChange: (e) => onChange(e.target.value), children: [
|
|
2351
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "" }),
|
|
2352
|
+
(field.options ?? []).map((option) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: option.value, children: localized(option.label, language) }, option.value))
|
|
2353
|
+
] });
|
|
2354
|
+
case "multiselect": {
|
|
2355
|
+
const selected = Array.isArray(value) ? value : [];
|
|
2356
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-form-choices", children: (field.options ?? []).map((option) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-form-choice", children: [
|
|
2087
2357
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2088
|
-
"
|
|
2358
|
+
"input",
|
|
2089
2359
|
{
|
|
2090
|
-
|
|
2091
|
-
|
|
2360
|
+
type: "checkbox",
|
|
2361
|
+
checked: selected.includes(option.value),
|
|
2362
|
+
disabled,
|
|
2363
|
+
onChange: (e) => onChange(e.target.checked ? [...selected, option.value] : selected.filter((item) => item !== option.value))
|
|
2092
2364
|
}
|
|
2093
2365
|
),
|
|
2094
|
-
|
|
2095
|
-
|
|
2366
|
+
localized(option.label, language)
|
|
2367
|
+
] }, option.value)) });
|
|
2368
|
+
}
|
|
2369
|
+
case "textarea":
|
|
2370
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2371
|
+
"textarea",
|
|
2372
|
+
{
|
|
2373
|
+
id,
|
|
2374
|
+
className: "pollar-input pollar-form-textarea",
|
|
2375
|
+
value: text,
|
|
2376
|
+
disabled,
|
|
2377
|
+
maxLength: field.validation?.maxLength,
|
|
2378
|
+
onChange: (e) => onChange(e.target.value)
|
|
2379
|
+
}
|
|
2380
|
+
);
|
|
2381
|
+
default:
|
|
2382
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2383
|
+
"input",
|
|
2384
|
+
{
|
|
2385
|
+
id,
|
|
2386
|
+
className: "pollar-input",
|
|
2387
|
+
type: field.type === "phone" ? "tel" : field.type === "text" ? "text" : field.type,
|
|
2388
|
+
inputMode: field.type === "number" ? "decimal" : void 0,
|
|
2389
|
+
value: text,
|
|
2390
|
+
disabled,
|
|
2391
|
+
min: field.validation?.min,
|
|
2392
|
+
max: field.validation?.max,
|
|
2393
|
+
maxLength: field.validation?.maxLength,
|
|
2394
|
+
onChange: (e) => onChange(e.target.value)
|
|
2395
|
+
}
|
|
2396
|
+
);
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
function RequirementFormModal({ formId, progress, onClose, onSubmitted }) {
|
|
2400
|
+
const { getClient, styles } = usePollar();
|
|
2401
|
+
const client = getClient();
|
|
2402
|
+
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
2403
|
+
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
|
|
2404
|
+
const language = react.useMemo(formLanguage, []);
|
|
2405
|
+
const copy = COPY[language];
|
|
2406
|
+
const [form, setForm] = react.useState(null);
|
|
2407
|
+
const [values, setValues] = react.useState({});
|
|
2408
|
+
const [fieldErrors, setFieldErrors] = react.useState({});
|
|
2409
|
+
const [error, setError] = react.useState(null);
|
|
2410
|
+
const [submitting, setSubmitting] = react.useState(false);
|
|
2411
|
+
const mounted = react.useRef(true);
|
|
2412
|
+
react.useEffect(() => {
|
|
2413
|
+
mounted.current = true;
|
|
2414
|
+
return () => {
|
|
2415
|
+
mounted.current = false;
|
|
2416
|
+
};
|
|
2417
|
+
}, []);
|
|
2418
|
+
react.useEffect(() => {
|
|
2419
|
+
client.getRequirementForm(formId).then((loaded) => {
|
|
2420
|
+
if (!mounted.current) return;
|
|
2421
|
+
setForm(loaded);
|
|
2422
|
+
setValues(initialValues(loaded.fields, loaded.answers));
|
|
2423
|
+
}).catch(() => mounted.current && setError(copy.loadError));
|
|
2424
|
+
}, [formId]);
|
|
2425
|
+
async function submit() {
|
|
2426
|
+
if (!form) return;
|
|
2427
|
+
setError(null);
|
|
2428
|
+
const local = localFieldErrors(form.fields, values);
|
|
2429
|
+
if (Object.keys(local).length) return setFieldErrors(local);
|
|
2430
|
+
setSubmitting(true);
|
|
2431
|
+
setFieldErrors({});
|
|
2432
|
+
try {
|
|
2433
|
+
await client.submitRequirementForm(form.formId, answersOf(form.fields, values));
|
|
2434
|
+
if (mounted.current) onSubmitted();
|
|
2435
|
+
} catch (e) {
|
|
2436
|
+
if (!mounted.current) return;
|
|
2437
|
+
const byField = fieldErrorsOf(e);
|
|
2438
|
+
if (byField) setFieldErrors(byField);
|
|
2439
|
+
else setError(copy.submitError);
|
|
2440
|
+
} finally {
|
|
2441
|
+
if (mounted.current) setSubmitting(false);
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2444
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2445
|
+
"div",
|
|
2446
|
+
{
|
|
2447
|
+
className: "pollar-modal-card pollar-form-modal",
|
|
2448
|
+
role: "dialog",
|
|
2449
|
+
"aria-modal": "true",
|
|
2450
|
+
"aria-label": form?.name ?? copy.title,
|
|
2451
|
+
style: cssVars,
|
|
2452
|
+
onClick: (e) => e.stopPropagation(),
|
|
2453
|
+
children: [
|
|
2454
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
2455
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-form-header-text", children: [
|
|
2456
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: form?.name ?? copy.title }),
|
|
2457
|
+
progress && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-subtitle", children: copy.step.replace("{n}", String(progress.position)).replace("{total}", String(progress.total)) })
|
|
2458
|
+
] }),
|
|
2459
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": copy.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" }) }) })
|
|
2460
|
+
] }),
|
|
2461
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-error", role: "alert", children: error }),
|
|
2462
|
+
!form && !error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-loading-block", children: [
|
|
2463
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-spinner" }),
|
|
2464
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: copy.loading })
|
|
2465
|
+
] }),
|
|
2466
|
+
form && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2467
|
+
"form",
|
|
2468
|
+
{
|
|
2469
|
+
className: "pollar-form-body",
|
|
2470
|
+
onSubmit: (e) => {
|
|
2471
|
+
e.preventDefault();
|
|
2472
|
+
void submit();
|
|
2473
|
+
},
|
|
2474
|
+
children: [
|
|
2475
|
+
form.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-description", children: form.description }),
|
|
2476
|
+
form.fields.map((field) => {
|
|
2477
|
+
const fieldError = fieldErrors[field.key];
|
|
2478
|
+
const help = localized(field.help, language);
|
|
2479
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-form-field", children: [
|
|
2480
|
+
field.type === "checkbox" ? /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-form-choice", children: [
|
|
2481
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2482
|
+
"input",
|
|
2483
|
+
{
|
|
2484
|
+
type: "checkbox",
|
|
2485
|
+
checked: values[field.key] === true,
|
|
2486
|
+
disabled: submitting,
|
|
2487
|
+
onChange: (e) => setValues((v) => ({ ...v, [field.key]: e.target.checked }))
|
|
2488
|
+
}
|
|
2489
|
+
),
|
|
2490
|
+
localized(field.label, language),
|
|
2491
|
+
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-form-required", children: " *" })
|
|
2492
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2493
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: `pollar-form-${field.key}`, className: "pollar-form-label", children: [
|
|
2494
|
+
localized(field.label, language),
|
|
2495
|
+
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-form-required", children: " *" })
|
|
2496
|
+
] }),
|
|
2497
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2498
|
+
FieldInput,
|
|
2499
|
+
{
|
|
2500
|
+
field,
|
|
2501
|
+
value: values[field.key] ?? "",
|
|
2502
|
+
language,
|
|
2503
|
+
disabled: submitting,
|
|
2504
|
+
onChange: (value) => setValues((v) => ({ ...v, [field.key]: value }))
|
|
2505
|
+
}
|
|
2506
|
+
)
|
|
2507
|
+
] }),
|
|
2508
|
+
help && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-form-help", children: help }),
|
|
2509
|
+
fieldError && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-form-field-error", role: "alert", children: fieldErrorMessage(fieldError, language) })
|
|
2510
|
+
] }, field.key);
|
|
2511
|
+
}),
|
|
2512
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
|
|
2513
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, disabled: submitting, children: copy.close }),
|
|
2514
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", className: "pollar-btn-primary", disabled: submitting, children: submitting ? copy.submitting : copy.submit })
|
|
2515
|
+
] })
|
|
2516
|
+
]
|
|
2517
|
+
}
|
|
2518
|
+
)
|
|
2519
|
+
]
|
|
2520
|
+
}
|
|
2521
|
+
) });
|
|
2522
|
+
}
|
|
2523
|
+
function AppKycFlow({ onClose, country, level, onApproved }) {
|
|
2524
|
+
const { getClient } = usePollar();
|
|
2525
|
+
const client = getClient();
|
|
2526
|
+
const [state, setState] = react.useState({ kind: "loading" });
|
|
2527
|
+
const kycStepDone = react.useRef(false);
|
|
2528
|
+
const firstRead = react.useRef(true);
|
|
2529
|
+
const loading = react.useRef(false);
|
|
2530
|
+
const mounted = react.useRef(true);
|
|
2531
|
+
react.useEffect(() => {
|
|
2532
|
+
mounted.current = true;
|
|
2533
|
+
return () => {
|
|
2534
|
+
mounted.current = false;
|
|
2535
|
+
};
|
|
2536
|
+
}, []);
|
|
2537
|
+
async function approvedOption(steps) {
|
|
2538
|
+
for (const step2 of steps) {
|
|
2539
|
+
if (step2.type !== "KYC") continue;
|
|
2540
|
+
for (const optionId of step2.optionIds) {
|
|
2541
|
+
const status = await client.getKycStatus(optionId).catch(() => null);
|
|
2542
|
+
if (status?.status === "approved") return optionId;
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
return null;
|
|
2546
|
+
}
|
|
2547
|
+
const load = react.useCallback(async () => {
|
|
2548
|
+
if (loading.current) return;
|
|
2549
|
+
loading.current = true;
|
|
2550
|
+
kycStepDone.current = false;
|
|
2551
|
+
try {
|
|
2552
|
+
const requirements = await client.getAppRequirements();
|
|
2553
|
+
if (!mounted.current) return;
|
|
2554
|
+
if (!requirements.total) return setState({ kind: "options" });
|
|
2555
|
+
const first = firstRead.current;
|
|
2556
|
+
firstRead.current = false;
|
|
2557
|
+
if (requirements.next) return setState({ kind: "step", step: requirements.next });
|
|
2558
|
+
onApproved?.();
|
|
2559
|
+
const providerId = first ? await approvedOption(requirements.steps) : null;
|
|
2560
|
+
if (!mounted.current) return;
|
|
2561
|
+
if (providerId) setState({ kind: "done", providerId });
|
|
2562
|
+
else onClose();
|
|
2563
|
+
} catch {
|
|
2564
|
+
if (mounted.current) setState({ kind: "options" });
|
|
2565
|
+
} finally {
|
|
2566
|
+
loading.current = false;
|
|
2567
|
+
}
|
|
2568
|
+
}, []);
|
|
2569
|
+
react.useEffect(() => {
|
|
2570
|
+
void load();
|
|
2571
|
+
}, [load]);
|
|
2572
|
+
if (state.kind === "loading") return null;
|
|
2573
|
+
if (state.kind === "options") {
|
|
2574
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2575
|
+
KycModal,
|
|
2576
|
+
{
|
|
2577
|
+
onClose,
|
|
2578
|
+
...country !== void 0 && { country },
|
|
2579
|
+
...level !== void 0 && { level },
|
|
2580
|
+
...onApproved !== void 0 && { onApproved }
|
|
2581
|
+
}
|
|
2582
|
+
);
|
|
2583
|
+
}
|
|
2584
|
+
if (state.kind === "done") {
|
|
2585
|
+
return /* @__PURE__ */ jsxRuntime.jsx(KycModal, { onClose, providerId: state.providerId, ...country !== void 0 && { country } });
|
|
2586
|
+
}
|
|
2587
|
+
const { step } = state;
|
|
2588
|
+
const progress = { position: step.completed + 1, total: step.total };
|
|
2589
|
+
if (step.type === "FORM") {
|
|
2590
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2591
|
+
RequirementFormModal,
|
|
2592
|
+
{
|
|
2593
|
+
formId: step.optionId,
|
|
2594
|
+
progress,
|
|
2595
|
+
onClose,
|
|
2596
|
+
onSubmitted: () => void load()
|
|
2597
|
+
},
|
|
2598
|
+
step.optionId
|
|
2599
|
+
);
|
|
2600
|
+
}
|
|
2601
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2602
|
+
KycModal,
|
|
2603
|
+
{
|
|
2604
|
+
providerId: step.optionId,
|
|
2605
|
+
...country !== void 0 && { country },
|
|
2606
|
+
...level !== void 0 && { level },
|
|
2607
|
+
onApproved: () => {
|
|
2608
|
+
kycStepDone.current = true;
|
|
2609
|
+
},
|
|
2610
|
+
onClose: () => {
|
|
2611
|
+
if (kycStepDone.current) void load();
|
|
2612
|
+
else onClose();
|
|
2613
|
+
}
|
|
2614
|
+
},
|
|
2615
|
+
step.optionId
|
|
2616
|
+
);
|
|
2617
|
+
}
|
|
2618
|
+
function EmailCodeInput({ email, onSubmit }) {
|
|
2619
|
+
const [digits, setDigits] = react.useState(["", "", "", "", "", ""]);
|
|
2620
|
+
const inputRefs = react.useRef([]);
|
|
2621
|
+
function submit(next) {
|
|
2622
|
+
if (next.every(Boolean)) onSubmit(next.join(""));
|
|
2623
|
+
}
|
|
2624
|
+
function handleChange(index, value) {
|
|
2625
|
+
const cleaned = value.replace(/\D/g, "").slice(-1);
|
|
2626
|
+
const next = digits.map((d, i) => i === index ? cleaned : d);
|
|
2627
|
+
setDigits(next);
|
|
2628
|
+
if (cleaned && index < 5) inputRefs.current[index + 1]?.focus();
|
|
2629
|
+
submit(next);
|
|
2630
|
+
}
|
|
2631
|
+
function handleKeyDown(index, e) {
|
|
2632
|
+
if (e.key === "Backspace" && !digits[index] && index > 0) {
|
|
2633
|
+
inputRefs.current[index - 1]?.focus();
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
function handlePaste(e) {
|
|
2637
|
+
e.preventDefault();
|
|
2638
|
+
const text = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, 6);
|
|
2639
|
+
const next = Array.from({ length: 6 }, (_, i) => text[i] ?? "");
|
|
2640
|
+
setDigits(next);
|
|
2641
|
+
inputRefs.current[Math.min(text.length - 1, 5)]?.focus();
|
|
2642
|
+
submit(next);
|
|
2643
|
+
}
|
|
2644
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-code-section", children: [
|
|
2645
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-code-label", children: [
|
|
2646
|
+
"Enter the 6-digit code sent to ",
|
|
2647
|
+
email ? /* @__PURE__ */ jsxRuntime.jsx("strong", { children: email }) : "your email"
|
|
2648
|
+
] }),
|
|
2649
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-code-inputs", children: digits.map((digit, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2650
|
+
"input",
|
|
2651
|
+
{
|
|
2652
|
+
ref: (el) => {
|
|
2653
|
+
inputRefs.current[i] = el;
|
|
2654
|
+
},
|
|
2655
|
+
type: "text",
|
|
2656
|
+
inputMode: "numeric",
|
|
2657
|
+
maxLength: 2,
|
|
2658
|
+
value: digit,
|
|
2659
|
+
className: "pollar-code-input",
|
|
2660
|
+
onChange: (e) => handleChange(i, e.target.value),
|
|
2661
|
+
onKeyDown: (e) => handleKeyDown(i, e),
|
|
2662
|
+
onPaste: handlePaste
|
|
2663
|
+
},
|
|
2664
|
+
i
|
|
2665
|
+
)) })
|
|
2666
|
+
] });
|
|
2667
|
+
}
|
|
2668
|
+
var GithubButton = ({ disabled, onClick }) => {
|
|
2669
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "pollar-github-button", disabled, onClick, children: [
|
|
2670
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "pollar-github-button-icon", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2671
|
+
"path",
|
|
2672
|
+
{
|
|
2673
|
+
fillRule: "evenodd",
|
|
2674
|
+
d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z",
|
|
2675
|
+
clipRule: "evenodd"
|
|
2676
|
+
}
|
|
2677
|
+
) }),
|
|
2678
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-github-button-contents", children: "GitHub" })
|
|
2679
|
+
] });
|
|
2680
|
+
};
|
|
2681
|
+
var GoogleButton = ({ disabled, onClick }) => {
|
|
2682
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "pollar-gsi-material-button", disabled, onClick, children: [
|
|
2683
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-gsi-material-button-state" }),
|
|
2684
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-gsi-material-button-content-wrapper", children: [
|
|
2685
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-gsi-material-button-icon", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { version: "1.1", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 48 48", style: { display: "block" }, children: [
|
|
2686
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2687
|
+
"path",
|
|
2688
|
+
{
|
|
2689
|
+
fill: "#EA4335",
|
|
2690
|
+
d: "M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"
|
|
2691
|
+
}
|
|
2692
|
+
),
|
|
2693
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2694
|
+
"path",
|
|
2096
2695
|
{
|
|
2097
2696
|
fill: "#4285F4",
|
|
2098
2697
|
d: "M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"
|
|
@@ -2732,6 +3331,53 @@ function LoginModal({ onClose }) {
|
|
|
2732
3331
|
}
|
|
2733
3332
|
) });
|
|
2734
3333
|
}
|
|
3334
|
+
|
|
3335
|
+
// src/components/ramp-widget/ramp-kyc.ts
|
|
3336
|
+
var nonEmpty = (value) => typeof value === "string" && !!value.trim();
|
|
3337
|
+
function requiredRampKyc(error) {
|
|
3338
|
+
if (!error || typeof error !== "object") return null;
|
|
3339
|
+
const { code, body } = error;
|
|
3340
|
+
if (code !== "SDK_RAMPS_KYC_REQUIRED" || !body || typeof body !== "object") return null;
|
|
3341
|
+
const { rampProviderId, corridorId, requirementType, optionId, kycProviderId } = body;
|
|
3342
|
+
if (!nonEmpty(rampProviderId) || !nonEmpty(corridorId)) return null;
|
|
3343
|
+
if ((requirementType === "FORM" || requirementType === "REGISTRY_CHECK" || requirementType === "PROVIDER_REGISTRATION") && nonEmpty(optionId)) {
|
|
3344
|
+
return { rampProviderId, corridorId, type: requirementType, optionId };
|
|
3345
|
+
}
|
|
3346
|
+
const kyc = nonEmpty(optionId) && requirementType === "KYC" ? optionId : kycProviderId;
|
|
3347
|
+
return nonEmpty(kyc) ? { rampProviderId, corridorId, type: "KYC", optionId: kyc } : null;
|
|
3348
|
+
}
|
|
3349
|
+
function pendingFromQuote(requirement) {
|
|
3350
|
+
return {
|
|
3351
|
+
rampProviderId: requirement.rampProviderId,
|
|
3352
|
+
corridorId: requirement.corridorId,
|
|
3353
|
+
type: requirement.type,
|
|
3354
|
+
optionId: requirement.optionId,
|
|
3355
|
+
progress: { position: requirement.completed + 1, total: requirement.total }
|
|
3356
|
+
};
|
|
3357
|
+
}
|
|
3358
|
+
function lockedRouteCopy(requirement) {
|
|
3359
|
+
if (requirement.type === "FORM") return { message: "Answer a few questions to see this route", action: "Continue" };
|
|
3360
|
+
if (requirement.type === "PROVIDER_REGISTRATION") {
|
|
3361
|
+
return { message: "Register with the provider to see this route", action: "Continue" };
|
|
3362
|
+
}
|
|
3363
|
+
if (requirement.type === "REGISTRY_CHECK") {
|
|
3364
|
+
return requirement.status === "pending" ? { message: "Your details are under review", action: null } : { message: "Confirm your details to see this route", action: "Confirm" };
|
|
3365
|
+
}
|
|
3366
|
+
switch (requirement.status) {
|
|
3367
|
+
case "expired":
|
|
3368
|
+
return { message: "Your verification expired", action: "Verify again" };
|
|
3369
|
+
case "pending":
|
|
3370
|
+
if (!requirement.reviewReason) return { message: "Verification in progress", action: "Continue" };
|
|
3371
|
+
return {
|
|
3372
|
+
message: requirement.reviewReason === "DUPLICATE_DOCUMENT" ? kycReviewMessage(requirement.reviewReason) : "Your verification is under review",
|
|
3373
|
+
action: null
|
|
3374
|
+
};
|
|
3375
|
+
case "rejected":
|
|
3376
|
+
return { message: "Verification was not approved", action: null };
|
|
3377
|
+
default:
|
|
3378
|
+
return { message: "Verify your identity to see this route", action: "Verify" };
|
|
3379
|
+
}
|
|
3380
|
+
}
|
|
2735
3381
|
var RAIL_LABELS = {
|
|
2736
3382
|
SPEI: "SPEI (Mexico)",
|
|
2737
3383
|
PIX: "PIX (Brazil)",
|
|
@@ -2772,6 +3418,34 @@ function RouteDisplay({ quote, busy = false, disabled = false, onSelect }) {
|
|
|
2772
3418
|
}
|
|
2773
3419
|
);
|
|
2774
3420
|
}
|
|
3421
|
+
function LockedRouteDisplay({ requirement, disabled = false, onVerify }) {
|
|
3422
|
+
const { message, action } = lockedRouteCopy(requirement);
|
|
3423
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3424
|
+
"div",
|
|
3425
|
+
{
|
|
3426
|
+
className: "pollar-ramp-route-card",
|
|
3427
|
+
"data-locked": true,
|
|
3428
|
+
"data-kyc-status": requirement.status,
|
|
3429
|
+
"data-disabled": disabled || void 0,
|
|
3430
|
+
children: [
|
|
3431
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-route-left", children: [
|
|
3432
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-route-provider", children: requirement.provider }),
|
|
3433
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-route-meta", children: message })
|
|
3434
|
+
] }),
|
|
3435
|
+
action && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-route-right", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3436
|
+
"button",
|
|
3437
|
+
{
|
|
3438
|
+
type: "button",
|
|
3439
|
+
className: "pollar-btn-secondary pollar-ramp-route-verify",
|
|
3440
|
+
disabled,
|
|
3441
|
+
onClick: () => onVerify(requirement),
|
|
3442
|
+
children: action
|
|
3443
|
+
}
|
|
3444
|
+
) })
|
|
3445
|
+
]
|
|
3446
|
+
}
|
|
3447
|
+
);
|
|
3448
|
+
}
|
|
2775
3449
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2776
3450
|
function isFieldValid(spec, raw) {
|
|
2777
3451
|
const value = (raw ?? "").trim();
|
|
@@ -2779,6 +3453,9 @@ function isFieldValid(spec, raw) {
|
|
|
2779
3453
|
if (spec.type === "email") return EMAIL_RE.test(value);
|
|
2780
3454
|
return true;
|
|
2781
3455
|
}
|
|
3456
|
+
function scannableImageSrc(image) {
|
|
3457
|
+
return image.encoding === "base64" ? `data:${image.mediaType};base64,${image.data}` : `data:${image.mediaType};charset=utf-8,${encodeURIComponent(image.data)}`;
|
|
3458
|
+
}
|
|
2782
3459
|
function listOf(items) {
|
|
2783
3460
|
const last = items[items.length - 1];
|
|
2784
3461
|
if (last === void 0) return "a few details";
|
|
@@ -2829,12 +3506,14 @@ function RampWidgetTemplate({
|
|
|
2829
3506
|
countriesLoading,
|
|
2830
3507
|
refreshing,
|
|
2831
3508
|
quotes,
|
|
3509
|
+
kycRequired,
|
|
2832
3510
|
isLoading,
|
|
2833
3511
|
provider,
|
|
2834
3512
|
txStatus,
|
|
2835
3513
|
kycUrl,
|
|
2836
3514
|
tosUrl,
|
|
2837
3515
|
kycBlocking,
|
|
3516
|
+
onboardingStatus,
|
|
2838
3517
|
kycJustApproved,
|
|
2839
3518
|
stellarTxHash,
|
|
2840
3519
|
explorerUrl,
|
|
@@ -2842,12 +3521,14 @@ function RampWidgetTemplate({
|
|
|
2842
3521
|
canComplete,
|
|
2843
3522
|
completing,
|
|
2844
3523
|
errorMsg,
|
|
3524
|
+
noticeMsg,
|
|
2845
3525
|
onDirectionChange,
|
|
2846
3526
|
onAmountChange,
|
|
2847
3527
|
onFieldChange,
|
|
2848
3528
|
onCountryChange,
|
|
2849
3529
|
onFindRoute,
|
|
2850
3530
|
onSelectQuote,
|
|
3531
|
+
onVerifyRoute,
|
|
2851
3532
|
onContactContinue,
|
|
2852
3533
|
onOpenKyc,
|
|
2853
3534
|
onOpenTos,
|
|
@@ -3004,16 +3685,28 @@ function RampWidgetTemplate({
|
|
|
3004
3685
|
] }, i))
|
|
3005
3686
|
] }),
|
|
3006
3687
|
step === "select_route" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3007
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3688
|
+
noticeMsg && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-ramp-payment-note", children: noticeMsg }),
|
|
3689
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-route-list", children: [
|
|
3690
|
+
quotes.map((q, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3691
|
+
RouteDisplay,
|
|
3692
|
+
{
|
|
3693
|
+
quote: q,
|
|
3694
|
+
busy: startingQuoteId != null && q.quoteId === startingQuoteId,
|
|
3695
|
+
disabled: startingQuoteId != null && q.quoteId !== startingQuoteId,
|
|
3696
|
+
onSelect: onSelectQuote
|
|
3697
|
+
},
|
|
3698
|
+
i
|
|
3699
|
+
)),
|
|
3700
|
+
kycRequired.map((r) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3701
|
+
LockedRouteDisplay,
|
|
3702
|
+
{
|
|
3703
|
+
requirement: r,
|
|
3704
|
+
disabled: startingQuoteId != null,
|
|
3705
|
+
onVerify: onVerifyRoute
|
|
3706
|
+
},
|
|
3707
|
+
`${r.rampProviderId}:${r.corridorId}`
|
|
3708
|
+
))
|
|
3709
|
+
] }),
|
|
3017
3710
|
errorMsg && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-ramp-payment-note", style: { color: "var(--pollar-error-text)" }, children: errorMsg }),
|
|
3018
3711
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: errorMsg ? "pollar-btn-primary" : "pollar-btn-secondary", onClick: onBack, children: "Back" })
|
|
3019
3712
|
] }),
|
|
@@ -3133,7 +3826,7 @@ function RampWidgetTemplate({
|
|
|
3133
3826
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3134
3827
|
"img",
|
|
3135
3828
|
{
|
|
3136
|
-
src:
|
|
3829
|
+
src: scannableImageSrc(depositInstructions.scannable.image),
|
|
3137
3830
|
alt: "Payment QR",
|
|
3138
3831
|
style: { width: "100%", maxWidth: 220, height: "auto", display: "block", margin: "0 auto" }
|
|
3139
3832
|
}
|
|
@@ -3167,15 +3860,24 @@ function RampWidgetTemplate({
|
|
|
3167
3860
|
"Continue at ",
|
|
3168
3861
|
provider
|
|
3169
3862
|
] }),
|
|
3170
|
-
kycBlocking && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-ramp-payment-note", children: [
|
|
3863
|
+
kycBlocking && onboardingStatus === "awaiting_provider" && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-ramp-payment-note", children: [
|
|
3864
|
+
provider,
|
|
3865
|
+
" is still setting up your account for this payment method. Your verification is complete and there is nothing left for you to do \u2014 nothing has been sent, and this will update on its own once ",
|
|
3866
|
+
provider,
|
|
3867
|
+
" is ready."
|
|
3868
|
+
] }),
|
|
3869
|
+
kycBlocking && onboardingStatus !== "awaiting_provider" && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-ramp-payment-note", children: [
|
|
3171
3870
|
provider,
|
|
3172
3871
|
" needs to verify your identity before this payout. Nothing has been sent yet \u2014 complete verification with ",
|
|
3173
3872
|
provider,
|
|
3174
3873
|
", and this will update on its own."
|
|
3175
3874
|
] }),
|
|
3176
|
-
kycJustApproved && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3177
|
-
|
|
3178
|
-
|
|
3875
|
+
kycJustApproved && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3876
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-ramp-payment-note", children: [
|
|
3877
|
+
provider,
|
|
3878
|
+
" approved your verification. Request a new quote to continue \u2014 the previous one was consumed."
|
|
3879
|
+
] }),
|
|
3880
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onRetry, children: "Request a new quote" })
|
|
3179
3881
|
] }),
|
|
3180
3882
|
canComplete && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", disabled: completing, onClick: onCompleteWithdraw, children: completing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3181
3883
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
@@ -3193,6 +3895,383 @@ function RampWidgetTemplate({
|
|
|
3193
3895
|
] })
|
|
3194
3896
|
] });
|
|
3195
3897
|
}
|
|
3898
|
+
|
|
3899
|
+
// src/components/registry-check-modal/registry-copy.ts
|
|
3900
|
+
var REGISTRY_COPY = {
|
|
3901
|
+
en: {
|
|
3902
|
+
title: "Confirm your details",
|
|
3903
|
+
intro: "We check these details with SEGIP, Bolivia's civil registry. They come from your verified document: you can only adjust how your surnames are split and your ID complement.",
|
|
3904
|
+
givenNames: "Names",
|
|
3905
|
+
surname1: "First surname",
|
|
3906
|
+
surname2: "Second surname",
|
|
3907
|
+
birthdate: "Date of birth",
|
|
3908
|
+
documentNumber: "ID number",
|
|
3909
|
+
complement: "Complement (if your ID has one)",
|
|
3910
|
+
submit: "Confirm",
|
|
3911
|
+
submitting: "Checking\u2026",
|
|
3912
|
+
close: "Close",
|
|
3913
|
+
approved: "Your details were confirmed.",
|
|
3914
|
+
review: "Your details are being reviewed. You can continue once they are confirmed.",
|
|
3915
|
+
notApplicable: "This check is only for Bolivian ID cards (CI). Your verified document is not one, so this route is not available.",
|
|
3916
|
+
identityRequired: "Verify your identity first.",
|
|
3917
|
+
nameMismatch: "Both surnames together must read as on your document: {full}.",
|
|
3918
|
+
rejected: "The registry did not confirm: {fields}. Check how they are written and try again.",
|
|
3919
|
+
loadError: "Could not load your details. Please try again.",
|
|
3920
|
+
submitError: "Could not check your details. Please try again.",
|
|
3921
|
+
step: "Step {n} of {total}"
|
|
3922
|
+
},
|
|
3923
|
+
es: {
|
|
3924
|
+
title: "Confirma tus datos",
|
|
3925
|
+
intro: "Validamos estos datos con el SEGIP, el registro civil de Bolivia. Vienen de tu documento verificado: solo puedes ajustar c\xF3mo se separan tus apellidos y el complemento de tu CI.",
|
|
3926
|
+
givenNames: "Nombres",
|
|
3927
|
+
surname1: "Primer apellido",
|
|
3928
|
+
surname2: "Segundo apellido",
|
|
3929
|
+
birthdate: "Fecha de nacimiento",
|
|
3930
|
+
documentNumber: "N\xFAmero de CI",
|
|
3931
|
+
complement: "Complemento (si tu CI lo tiene)",
|
|
3932
|
+
submit: "Confirmar",
|
|
3933
|
+
submitting: "Validando\u2026",
|
|
3934
|
+
close: "Cerrar",
|
|
3935
|
+
approved: "Tus datos fueron confirmados.",
|
|
3936
|
+
review: "Tus datos est\xE1n en revisi\xF3n. Podr\xE1s continuar cuando se confirmen.",
|
|
3937
|
+
notApplicable: "Esta validaci\xF3n es solo para c\xE9dulas bolivianas (CI). Tu documento verificado no lo es, as\xED que esta ruta no est\xE1 disponible.",
|
|
3938
|
+
identityRequired: "Primero verifica tu identidad.",
|
|
3939
|
+
nameMismatch: "Los dos apellidos juntos deben leerse como en tu documento: {full}.",
|
|
3940
|
+
rejected: "El registro no confirm\xF3: {fields}. Revisa c\xF3mo est\xE1n escritos e intenta de nuevo.",
|
|
3941
|
+
loadError: "No se pudieron cargar tus datos. Intenta de nuevo.",
|
|
3942
|
+
submitError: "No se pudieron validar tus datos. Intenta de nuevo.",
|
|
3943
|
+
step: "Paso {n} de {total}"
|
|
3944
|
+
}
|
|
3945
|
+
};
|
|
3946
|
+
var REGISTRATION_COPY = {
|
|
3947
|
+
en: {
|
|
3948
|
+
title: "Register with the payment provider",
|
|
3949
|
+
intro: "To use this route, the provider registers you as its customer. These details will be sent to it:",
|
|
3950
|
+
consent: "I agree to share these details with the provider.",
|
|
3951
|
+
submit: "Register",
|
|
3952
|
+
submitting: "Registering\u2026",
|
|
3953
|
+
close: "Close",
|
|
3954
|
+
notReady: "Complete the previous steps first.",
|
|
3955
|
+
missing: "Some details are missing: {fields}.",
|
|
3956
|
+
loadError: "Could not load the registration. Please try again.",
|
|
3957
|
+
submitError: "Could not register you. Please try again.",
|
|
3958
|
+
step: "Step {n} of {total}"
|
|
3959
|
+
},
|
|
3960
|
+
es: {
|
|
3961
|
+
title: "Registro con el proveedor de pagos",
|
|
3962
|
+
intro: "Para usar esta ruta, el proveedor te registra como su cliente. Se le enviar\xE1n estos datos:",
|
|
3963
|
+
consent: "Acepto compartir estos datos con el proveedor.",
|
|
3964
|
+
submit: "Registrarme",
|
|
3965
|
+
submitting: "Registrando\u2026",
|
|
3966
|
+
close: "Cerrar",
|
|
3967
|
+
notReady: "Primero completa los pasos anteriores.",
|
|
3968
|
+
missing: "Faltan algunos datos: {fields}.",
|
|
3969
|
+
loadError: "No se pudo cargar el registro. Intenta de nuevo.",
|
|
3970
|
+
submitError: "No se pudo completar el registro. Intenta de nuevo.",
|
|
3971
|
+
step: "Paso {n} de {total}"
|
|
3972
|
+
}
|
|
3973
|
+
};
|
|
3974
|
+
var SHARED_FIELD_LABELS = {
|
|
3975
|
+
en: {
|
|
3976
|
+
name: "Names",
|
|
3977
|
+
lastname: "Surnames",
|
|
3978
|
+
document_type: "Document type",
|
|
3979
|
+
document_number: "Document number",
|
|
3980
|
+
country: "Country",
|
|
3981
|
+
state_of_residence: "Department of residence",
|
|
3982
|
+
economic_activity: "Economic activity",
|
|
3983
|
+
source_of_funds: "Source of funds",
|
|
3984
|
+
destination_of_funds: "Use of funds",
|
|
3985
|
+
income_level: "Income level",
|
|
3986
|
+
doc_provider_id: "SEGIP validation"
|
|
3987
|
+
},
|
|
3988
|
+
es: {
|
|
3989
|
+
name: "Nombres",
|
|
3990
|
+
lastname: "Apellidos",
|
|
3991
|
+
document_type: "Tipo de documento",
|
|
3992
|
+
document_number: "N\xFAmero de documento",
|
|
3993
|
+
country: "Pa\xEDs",
|
|
3994
|
+
state_of_residence: "Departamento de residencia",
|
|
3995
|
+
economic_activity: "Actividad econ\xF3mica",
|
|
3996
|
+
source_of_funds: "Origen de los fondos",
|
|
3997
|
+
destination_of_funds: "Destino de los fondos",
|
|
3998
|
+
income_level: "Nivel de ingresos",
|
|
3999
|
+
doc_provider_id: "Validaci\xF3n SEGIP"
|
|
4000
|
+
}
|
|
4001
|
+
};
|
|
4002
|
+
var errorCode = (error) => error && typeof error === "object" && typeof error.code === "string" ? error.code : null;
|
|
4003
|
+
function missingFieldsOf(error) {
|
|
4004
|
+
const body = error && typeof error === "object" ? error.body : void 0;
|
|
4005
|
+
return Array.isArray(body?.missing) ? body.missing.filter((item) => typeof item === "string") : [];
|
|
4006
|
+
}
|
|
4007
|
+
function RegistryCheckModal({ optionId, progress, onClose, onApproved }) {
|
|
4008
|
+
const { getClient, styles } = usePollar();
|
|
4009
|
+
const client = getClient();
|
|
4010
|
+
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
4011
|
+
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
|
|
4012
|
+
const language = react.useMemo(formLanguage, []);
|
|
4013
|
+
const copy = REGISTRY_COPY[language];
|
|
4014
|
+
const [check, setCheck] = react.useState(null);
|
|
4015
|
+
const [surname1, setSurname1] = react.useState("");
|
|
4016
|
+
const [surname2, setSurname2] = react.useState("");
|
|
4017
|
+
const [complement, setComplement] = react.useState("");
|
|
4018
|
+
const [error, setError] = react.useState(null);
|
|
4019
|
+
const [review, setReview] = react.useState(false);
|
|
4020
|
+
const [submitting, setSubmitting] = react.useState(false);
|
|
4021
|
+
const mounted = react.useRef(true);
|
|
4022
|
+
react.useEffect(() => {
|
|
4023
|
+
mounted.current = true;
|
|
4024
|
+
return () => {
|
|
4025
|
+
mounted.current = false;
|
|
4026
|
+
};
|
|
4027
|
+
}, []);
|
|
4028
|
+
react.useEffect(() => {
|
|
4029
|
+
client.getRegistryCheck(optionId).then((loaded) => {
|
|
4030
|
+
if (!mounted.current) return;
|
|
4031
|
+
if (loaded.status === "approved") return onApproved();
|
|
4032
|
+
setCheck(loaded);
|
|
4033
|
+
if (loaded.status === "pending") setReview(true);
|
|
4034
|
+
if (loaded.status === "rejected") setError(rejectedMessage(loaded.rejectedFields));
|
|
4035
|
+
if (loaded.prefill.applies) {
|
|
4036
|
+
setSurname1(loaded.prefill.surname1);
|
|
4037
|
+
setSurname2(loaded.prefill.surname2 ?? "");
|
|
4038
|
+
setComplement(loaded.prefill.complementNumber ?? "");
|
|
4039
|
+
}
|
|
4040
|
+
}).catch((e) => {
|
|
4041
|
+
if (!mounted.current) return;
|
|
4042
|
+
setError(errorCode(e) === "KYC_REGISTRY_IDENTITY_REQUIRED" ? copy.identityRequired : copy.loadError);
|
|
4043
|
+
});
|
|
4044
|
+
}, [optionId]);
|
|
4045
|
+
const prefill = check?.prefill.applies ? check.prefill : null;
|
|
4046
|
+
function rejectedMessage(fields) {
|
|
4047
|
+
const labels = { surname1: copy.surname1, surname2: copy.surname2, complementNumber: copy.complement };
|
|
4048
|
+
const named = (fields ?? []).map((field) => labels[field] ?? field);
|
|
4049
|
+
return copy.rejected.replace("{fields}", named.length ? named.join(", ") : copy.surname2);
|
|
4050
|
+
}
|
|
4051
|
+
async function submit() {
|
|
4052
|
+
if (!prefill) return;
|
|
4053
|
+
setSubmitting(true);
|
|
4054
|
+
setError(null);
|
|
4055
|
+
try {
|
|
4056
|
+
const result = await client.submitRegistryCheck(optionId, {
|
|
4057
|
+
surname1: surname1.trim(),
|
|
4058
|
+
...surname2.trim() ? { surname2: surname2.trim() } : {},
|
|
4059
|
+
...complement.trim() ? { complementNumber: complement.trim() } : {}
|
|
4060
|
+
});
|
|
4061
|
+
if (!mounted.current) return;
|
|
4062
|
+
if (result.status === "approved") onApproved();
|
|
4063
|
+
else if (result.status === "rejected") setError(rejectedMessage(result.rejectedFields));
|
|
4064
|
+
else setReview(true);
|
|
4065
|
+
} catch (e) {
|
|
4066
|
+
if (!mounted.current) return;
|
|
4067
|
+
const code = errorCode(e);
|
|
4068
|
+
if (code === "SDK_KYC_ALREADY_APPROVED") return onApproved();
|
|
4069
|
+
if (code === "KYC_REGISTRY_NAME_MISMATCH") {
|
|
4070
|
+
setError(copy.nameMismatch.replace("{full}", [prefill.surname1, prefill.surname2].filter(Boolean).join(" ")));
|
|
4071
|
+
} else if (code === "SDK_KYC_UNDER_REVIEW") setReview(true);
|
|
4072
|
+
else setError(copy.submitError);
|
|
4073
|
+
} finally {
|
|
4074
|
+
if (mounted.current) setSubmitting(false);
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
4077
|
+
const readOnly = (label, value) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-form-field", children: [
|
|
4078
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-form-label", children: label }),
|
|
4079
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { className: "pollar-input", value, readOnly: true, disabled: true })
|
|
4080
|
+
] });
|
|
4081
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4082
|
+
"div",
|
|
4083
|
+
{
|
|
4084
|
+
className: "pollar-modal-card pollar-form-modal",
|
|
4085
|
+
role: "dialog",
|
|
4086
|
+
"aria-modal": "true",
|
|
4087
|
+
"aria-label": copy.title,
|
|
4088
|
+
style: cssVars,
|
|
4089
|
+
onClick: (e) => e.stopPropagation(),
|
|
4090
|
+
children: [
|
|
4091
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
4092
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-form-header-text", children: [
|
|
4093
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: copy.title }),
|
|
4094
|
+
progress && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-subtitle", children: copy.step.replace("{n}", String(progress.position)).replace("{total}", String(progress.total)) })
|
|
4095
|
+
] }),
|
|
4096
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": copy.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" }) }) })
|
|
4097
|
+
] }),
|
|
4098
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-error", role: "alert", children: error }),
|
|
4099
|
+
!check && !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-loading-block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-spinner" }) }),
|
|
4100
|
+
check && (review || !prefill) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-form-body", children: [
|
|
4101
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-error", role: "status", children: review ? copy.review : copy.notApplicable }),
|
|
4102
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: copy.close }) })
|
|
4103
|
+
] }),
|
|
4104
|
+
prefill && !review && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4105
|
+
"form",
|
|
4106
|
+
{
|
|
4107
|
+
className: "pollar-form-body",
|
|
4108
|
+
onSubmit: (e) => {
|
|
4109
|
+
e.preventDefault();
|
|
4110
|
+
void submit();
|
|
4111
|
+
},
|
|
4112
|
+
children: [
|
|
4113
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-description", children: copy.intro }),
|
|
4114
|
+
readOnly(copy.givenNames, prefill.givenNames),
|
|
4115
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-form-field", children: [
|
|
4116
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: "pollar-registry-surname1", className: "pollar-form-label", children: [
|
|
4117
|
+
copy.surname1,
|
|
4118
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-form-required", children: " *" })
|
|
4119
|
+
] }),
|
|
4120
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4121
|
+
"input",
|
|
4122
|
+
{
|
|
4123
|
+
id: "pollar-registry-surname1",
|
|
4124
|
+
className: "pollar-input",
|
|
4125
|
+
value: surname1,
|
|
4126
|
+
required: true,
|
|
4127
|
+
disabled: submitting,
|
|
4128
|
+
onChange: (e) => setSurname1(e.target.value)
|
|
4129
|
+
}
|
|
4130
|
+
)
|
|
4131
|
+
] }),
|
|
4132
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-form-field", children: [
|
|
4133
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "pollar-registry-surname2", className: "pollar-form-label", children: copy.surname2 }),
|
|
4134
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4135
|
+
"input",
|
|
4136
|
+
{
|
|
4137
|
+
id: "pollar-registry-surname2",
|
|
4138
|
+
className: "pollar-input",
|
|
4139
|
+
value: surname2,
|
|
4140
|
+
disabled: submitting,
|
|
4141
|
+
onChange: (e) => setSurname2(e.target.value)
|
|
4142
|
+
}
|
|
4143
|
+
)
|
|
4144
|
+
] }),
|
|
4145
|
+
readOnly(copy.birthdate, prefill.birthdate),
|
|
4146
|
+
readOnly(copy.documentNumber, prefill.documentNumber),
|
|
4147
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-form-field", children: [
|
|
4148
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "pollar-registry-complement", className: "pollar-form-label", children: copy.complement }),
|
|
4149
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4150
|
+
"input",
|
|
4151
|
+
{
|
|
4152
|
+
id: "pollar-registry-complement",
|
|
4153
|
+
className: "pollar-input",
|
|
4154
|
+
value: complement,
|
|
4155
|
+
maxLength: 3,
|
|
4156
|
+
disabled: submitting,
|
|
4157
|
+
onChange: (e) => setComplement(e.target.value.toUpperCase().replace(/[^0-9A-Z]/g, ""))
|
|
4158
|
+
}
|
|
4159
|
+
)
|
|
4160
|
+
] }),
|
|
4161
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
|
|
4162
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, disabled: submitting, children: copy.close }),
|
|
4163
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", className: "pollar-btn-primary", disabled: submitting || !surname1.trim(), children: submitting ? copy.submitting : copy.submit })
|
|
4164
|
+
] })
|
|
4165
|
+
]
|
|
4166
|
+
}
|
|
4167
|
+
)
|
|
4168
|
+
]
|
|
4169
|
+
}
|
|
4170
|
+
) });
|
|
4171
|
+
}
|
|
4172
|
+
function ProviderRegistrationModal({ corridorId, progress, onClose, onRegistered }) {
|
|
4173
|
+
const { getClient, styles } = usePollar();
|
|
4174
|
+
const client = getClient();
|
|
4175
|
+
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
4176
|
+
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
|
|
4177
|
+
const language = react.useMemo(formLanguage, []);
|
|
4178
|
+
const copy = REGISTRATION_COPY[language];
|
|
4179
|
+
const labels = SHARED_FIELD_LABELS[language];
|
|
4180
|
+
const [registration, setRegistration] = react.useState(null);
|
|
4181
|
+
const [consent, setConsent] = react.useState(false);
|
|
4182
|
+
const [error, setError] = react.useState(null);
|
|
4183
|
+
const [submitting, setSubmitting] = react.useState(false);
|
|
4184
|
+
const mounted = react.useRef(true);
|
|
4185
|
+
react.useEffect(() => {
|
|
4186
|
+
mounted.current = true;
|
|
4187
|
+
return () => {
|
|
4188
|
+
mounted.current = false;
|
|
4189
|
+
};
|
|
4190
|
+
}, []);
|
|
4191
|
+
react.useEffect(() => {
|
|
4192
|
+
client.getProviderRegistration(corridorId).then((loaded) => {
|
|
4193
|
+
if (!mounted.current) return;
|
|
4194
|
+
if (loaded.status === "registered") onRegistered();
|
|
4195
|
+
else setRegistration(loaded);
|
|
4196
|
+
}).catch(() => mounted.current && setError(copy.loadError));
|
|
4197
|
+
}, [corridorId]);
|
|
4198
|
+
async function submit() {
|
|
4199
|
+
setSubmitting(true);
|
|
4200
|
+
setError(null);
|
|
4201
|
+
try {
|
|
4202
|
+
await client.submitProviderRegistration(corridorId);
|
|
4203
|
+
if (mounted.current) onRegistered();
|
|
4204
|
+
} catch (e) {
|
|
4205
|
+
if (!mounted.current) return;
|
|
4206
|
+
const code = errorCode(e);
|
|
4207
|
+
if (code === "KYC_REGISTRATION_MISSING_DATA") {
|
|
4208
|
+
setError(
|
|
4209
|
+
copy.missing.replace(
|
|
4210
|
+
"{fields}",
|
|
4211
|
+
missingFieldsOf(e).map((key) => labels[key] ?? key).join(", ")
|
|
4212
|
+
)
|
|
4213
|
+
);
|
|
4214
|
+
} else if (code === "KYC_REGISTRATION_STEPS_PENDING") setError(copy.notReady);
|
|
4215
|
+
else setError(copy.submitError);
|
|
4216
|
+
} finally {
|
|
4217
|
+
if (mounted.current) setSubmitting(false);
|
|
4218
|
+
}
|
|
4219
|
+
}
|
|
4220
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4221
|
+
"div",
|
|
4222
|
+
{
|
|
4223
|
+
className: "pollar-modal-card pollar-form-modal",
|
|
4224
|
+
role: "dialog",
|
|
4225
|
+
"aria-modal": "true",
|
|
4226
|
+
"aria-label": copy.title,
|
|
4227
|
+
style: cssVars,
|
|
4228
|
+
onClick: (e) => e.stopPropagation(),
|
|
4229
|
+
children: [
|
|
4230
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
4231
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-form-header-text", children: [
|
|
4232
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: copy.title }),
|
|
4233
|
+
progress && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-subtitle", children: copy.step.replace("{n}", String(progress.position)).replace("{total}", String(progress.total)) })
|
|
4234
|
+
] }),
|
|
4235
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": copy.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" }) }) })
|
|
4236
|
+
] }),
|
|
4237
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-error", role: "alert", children: error }),
|
|
4238
|
+
!registration && !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-loading-block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-spinner" }) }),
|
|
4239
|
+
registration && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4240
|
+
"form",
|
|
4241
|
+
{
|
|
4242
|
+
className: "pollar-form-body",
|
|
4243
|
+
onSubmit: (e) => {
|
|
4244
|
+
e.preventDefault();
|
|
4245
|
+
void submit();
|
|
4246
|
+
},
|
|
4247
|
+
children: [
|
|
4248
|
+
registration.ready ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4249
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-description", children: copy.intro }),
|
|
4250
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "pollar-form-description", children: registration.fields.map((key) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: labels[key] ?? key }, key)) }),
|
|
4251
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-form-choice", children: [
|
|
4252
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4253
|
+
"input",
|
|
4254
|
+
{
|
|
4255
|
+
type: "checkbox",
|
|
4256
|
+
checked: consent,
|
|
4257
|
+
disabled: submitting,
|
|
4258
|
+
onChange: (e) => setConsent(e.target.checked)
|
|
4259
|
+
}
|
|
4260
|
+
),
|
|
4261
|
+
copy.consent
|
|
4262
|
+
] })
|
|
4263
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-error", role: "status", children: copy.notReady }),
|
|
4264
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
|
|
4265
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, disabled: submitting, children: copy.close }),
|
|
4266
|
+
registration.ready && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", className: "pollar-btn-primary", disabled: submitting || !consent, children: submitting ? copy.submitting : copy.submit })
|
|
4267
|
+
] })
|
|
4268
|
+
]
|
|
4269
|
+
}
|
|
4270
|
+
)
|
|
4271
|
+
]
|
|
4272
|
+
}
|
|
4273
|
+
) });
|
|
4274
|
+
}
|
|
3196
4275
|
var TERMINAL = ["completed", "failed"];
|
|
3197
4276
|
function requiredFieldsOf(quote) {
|
|
3198
4277
|
return quote.requiredFields ?? [];
|
|
@@ -3225,7 +4304,12 @@ var RAMP_ERROR_MESSAGES = {
|
|
|
3225
4304
|
SDK_RAMPS_WALLET_UNSUPPORTED: "This wallet type cannot be used for this ramp.",
|
|
3226
4305
|
SDK_RAMPS_PROVIDER_NOT_CONFIGURED: "This ramp provider is not configured for this app yet.",
|
|
3227
4306
|
SDK_RAMPS_ANCHOR_ERROR: "The provider rejected the request. Please try again in a moment.",
|
|
3228
|
-
SDK_RAMPS_BRIDGE_ERROR: "The provider rejected the request. Please try again in a moment."
|
|
4307
|
+
SDK_RAMPS_BRIDGE_ERROR: "The provider rejected the request. Please try again in a moment.",
|
|
4308
|
+
SDK_RAMPS_ETHERFUSE_ERROR: "The provider rejected the request. Please try again in a moment.",
|
|
4309
|
+
SDK_RAMPS_INSUFFICIENT_BALANCE: "This wallet does not hold enough to cover that amount. Try a smaller one.",
|
|
4310
|
+
// Nothing moved on-chain, so the balance is untouched. Almost always no XLM
|
|
4311
|
+
// for the network fee on a wallet the app does not sponsor.
|
|
4312
|
+
SDK_RAMPS_ONCHAIN_SUBMIT_FAILED: "The network rejected the transaction, so nothing was sent. The wallet may need XLM for the fee."
|
|
3229
4313
|
};
|
|
3230
4314
|
function rampErrorMessage(e, fallback) {
|
|
3231
4315
|
const body = e?.body;
|
|
@@ -3255,14 +4339,25 @@ function RampWidget({ onClose }) {
|
|
|
3255
4339
|
const [countriesLoading, setCountriesLoading] = react.useState(true);
|
|
3256
4340
|
const [refreshing, setRefreshing] = react.useState(false);
|
|
3257
4341
|
const [quotes, setQuotes] = react.useState([]);
|
|
4342
|
+
const [requirementsRequired, setRequirementsRequired] = react.useState([]);
|
|
3258
4343
|
const [selectedQuote, setSelectedQuote] = react.useState(null);
|
|
3259
4344
|
const [isLoading, setIsLoading] = react.useState(false);
|
|
4345
|
+
const [pendingKyc, setPendingKyc] = react.useState(null);
|
|
4346
|
+
const [noticeMsg, setNoticeMsg] = react.useState(null);
|
|
4347
|
+
const kycAttempt = react.useRef(null);
|
|
4348
|
+
react.useEffect(
|
|
4349
|
+
() => () => {
|
|
4350
|
+
kycAttempt.current = null;
|
|
4351
|
+
},
|
|
4352
|
+
[]
|
|
4353
|
+
);
|
|
3260
4354
|
const [txId, setTxId] = react.useState(null);
|
|
3261
4355
|
const [provider, setProvider] = react.useState("");
|
|
3262
4356
|
const [kycUrl, setKycUrl] = react.useState(null);
|
|
3263
4357
|
const [tosUrl, setTosUrl] = react.useState(null);
|
|
3264
4358
|
const [kycPending, setKycPending] = react.useState(false);
|
|
3265
4359
|
const [kycApproved, setKycApproved] = react.useState(false);
|
|
4360
|
+
const [onboardingStatus, setOnboardingStatus] = react.useState(void 0);
|
|
3266
4361
|
const [txStatus, setTxStatus] = react.useState(null);
|
|
3267
4362
|
const [stellarTxHash, setStellarTxHash] = react.useState(null);
|
|
3268
4363
|
const [depositInstructions, setDepositInstructions] = react.useState(null);
|
|
@@ -3293,6 +4388,7 @@ function RampWidget({ onClose }) {
|
|
|
3293
4388
|
}, [step, txId, txStatus, client]);
|
|
3294
4389
|
react.useEffect(() => {
|
|
3295
4390
|
if (step !== "status" || !kycPending || kycApproved) return;
|
|
4391
|
+
if (onboardingStatus === "awaiting_provider") return;
|
|
3296
4392
|
let active = true;
|
|
3297
4393
|
const check = async () => {
|
|
3298
4394
|
try {
|
|
@@ -3307,7 +4403,7 @@ function RampWidget({ onClose }) {
|
|
|
3307
4403
|
active = false;
|
|
3308
4404
|
clearInterval(id);
|
|
3309
4405
|
};
|
|
3310
|
-
}, [step, kycPending, kycApproved, client]);
|
|
4406
|
+
}, [step, kycPending, kycApproved, onboardingStatus, client]);
|
|
3311
4407
|
async function loadCountries(resetSelection) {
|
|
3312
4408
|
setCountriesLoading(true);
|
|
3313
4409
|
try {
|
|
@@ -3341,6 +4437,7 @@ function RampWidget({ onClose }) {
|
|
|
3341
4437
|
if (step === "select_route") {
|
|
3342
4438
|
const result = await client.getRampsQuote({ country, amount: Number(amount), currency, direction });
|
|
3343
4439
|
setQuotes(result.quotes ?? []);
|
|
4440
|
+
setRequirementsRequired(result.requirementsRequired ?? []);
|
|
3344
4441
|
} else if (step === "status" && txId) {
|
|
3345
4442
|
const tx = await client.getRampTransaction(txId);
|
|
3346
4443
|
setTxStatus(tx.status);
|
|
@@ -3356,6 +4453,7 @@ function RampWidget({ onClose }) {
|
|
|
3356
4453
|
function resetToInput({ keepMessage = false } = {}) {
|
|
3357
4454
|
setStep("input");
|
|
3358
4455
|
setQuotes([]);
|
|
4456
|
+
setRequirementsRequired([]);
|
|
3359
4457
|
setSelectedQuote(null);
|
|
3360
4458
|
setFieldValues({});
|
|
3361
4459
|
setTxId(null);
|
|
@@ -3365,6 +4463,9 @@ function RampWidget({ onClose }) {
|
|
|
3365
4463
|
setTxStatus(null);
|
|
3366
4464
|
setStellarTxHash(null);
|
|
3367
4465
|
setDepositInstructions(null);
|
|
4466
|
+
setKycPending(false);
|
|
4467
|
+
setKycApproved(false);
|
|
4468
|
+
setNoticeMsg(null);
|
|
3368
4469
|
if (!keepMessage) setErrorMsg(null);
|
|
3369
4470
|
}
|
|
3370
4471
|
async function resumeWithSignature(id, ps) {
|
|
@@ -3389,6 +4490,7 @@ function RampWidget({ onClose }) {
|
|
|
3389
4490
|
}
|
|
3390
4491
|
setKycUrl(result.kycUrl ?? null);
|
|
3391
4492
|
setTosUrl(result.tosUrl ?? null);
|
|
4493
|
+
setOnboardingStatus(result.onboardingStatus);
|
|
3392
4494
|
setKycPending(result.kycRequired === true);
|
|
3393
4495
|
if (result.kycRequired) setKycApproved(false);
|
|
3394
4496
|
setTxStatus(result.status);
|
|
@@ -3396,19 +4498,28 @@ function RampWidget({ onClose }) {
|
|
|
3396
4498
|
setDepositInstructions(result.depositInstructions ?? null);
|
|
3397
4499
|
setStep("status");
|
|
3398
4500
|
}
|
|
4501
|
+
async function loadQuotes() {
|
|
4502
|
+
const result = await client.getRampsQuote({ country, amount: Number(amount), currency, direction });
|
|
4503
|
+
const list = result.quotes ?? [];
|
|
4504
|
+
const locked = result.requirementsRequired ?? [];
|
|
4505
|
+
if (list.length === 0 && locked.length === 0) {
|
|
4506
|
+
const down = (result.unavailable ?? []).map((u) => u.provider);
|
|
4507
|
+
setErrorMsg(
|
|
4508
|
+
down.length > 0 ? `${down.join(", ")} ${down.length === 1 ? "is" : "are"} temporarily unavailable. Please try again later.` : `No ramp providers available for ${country} yet.`
|
|
4509
|
+
);
|
|
4510
|
+
setStep("error");
|
|
4511
|
+
return false;
|
|
4512
|
+
}
|
|
4513
|
+
setQuotes(list);
|
|
4514
|
+
setRequirementsRequired(locked);
|
|
4515
|
+
return true;
|
|
4516
|
+
}
|
|
3399
4517
|
async function handleFindRoute() {
|
|
3400
4518
|
setStep("loading_quote");
|
|
3401
4519
|
setIsLoading(true);
|
|
3402
4520
|
setErrorMsg(null);
|
|
3403
4521
|
try {
|
|
3404
|
-
|
|
3405
|
-
const list = result.quotes ?? [];
|
|
3406
|
-
if (list.length === 0) {
|
|
3407
|
-
setErrorMsg(`No ramp providers available for ${country} yet.`);
|
|
3408
|
-
setStep("error");
|
|
3409
|
-
return;
|
|
3410
|
-
}
|
|
3411
|
-
setQuotes(list);
|
|
4522
|
+
if (!await loadQuotes()) return;
|
|
3412
4523
|
setStep("select_route");
|
|
3413
4524
|
} catch (e) {
|
|
3414
4525
|
setErrorMsg(rampErrorMessage(e, "Failed to fetch quotes."));
|
|
@@ -3420,6 +4531,7 @@ function RampWidget({ onClose }) {
|
|
|
3420
4531
|
function handleSelectQuote(quote) {
|
|
3421
4532
|
setSelectedQuote(quote);
|
|
3422
4533
|
setErrorMsg(null);
|
|
4534
|
+
setNoticeMsg(null);
|
|
3423
4535
|
const broken = brokenLimitOf(Number(amount), quote);
|
|
3424
4536
|
if (broken) {
|
|
3425
4537
|
setErrorMsg(limitMessage(broken.limit, broken.value, currency));
|
|
@@ -3455,12 +4567,47 @@ function RampWidget({ onClose }) {
|
|
|
3455
4567
|
const result = direction === "onramp" ? await client.createOnRamp(base) : await client.createOffRamp(base);
|
|
3456
4568
|
await applyResult(result);
|
|
3457
4569
|
} catch (e) {
|
|
4570
|
+
const requirement = requiredRampKyc(e);
|
|
4571
|
+
if (requirement) {
|
|
4572
|
+
setStep(requiredFieldsOf(quote).length ? "contact" : "select_route");
|
|
4573
|
+
setErrorMsg(
|
|
4574
|
+
requirement.type === "KYC" ? "Identity verification is required before continuing." : "A few more details are required before continuing."
|
|
4575
|
+
);
|
|
4576
|
+
kycAttempt.current = requirement;
|
|
4577
|
+
setPendingKyc(requirement);
|
|
4578
|
+
return;
|
|
4579
|
+
}
|
|
3458
4580
|
setErrorMsg(rampErrorMessage(e, "Failed to start the ramp."));
|
|
3459
4581
|
setStep("error");
|
|
3460
4582
|
} finally {
|
|
3461
4583
|
setIsLoading(false);
|
|
3462
4584
|
}
|
|
3463
4585
|
}
|
|
4586
|
+
async function requoteAfterKyc(completed = "KYC") {
|
|
4587
|
+
setStep("loading_quote");
|
|
4588
|
+
setIsLoading(true);
|
|
4589
|
+
setErrorMsg(null);
|
|
4590
|
+
setSelectedQuote(null);
|
|
4591
|
+
try {
|
|
4592
|
+
if (!await loadQuotes()) return;
|
|
4593
|
+
setNoticeMsg(
|
|
4594
|
+
completed === "KYC" ? "Your identity is verified. Prices may have changed, so choose a route to continue." : "Thanks, your details are saved. Prices may have changed, so choose a route to continue."
|
|
4595
|
+
);
|
|
4596
|
+
setStep("select_route");
|
|
4597
|
+
} catch (e) {
|
|
4598
|
+
setErrorMsg(rampErrorMessage(e, "Failed to fetch quotes."));
|
|
4599
|
+
setStep("error");
|
|
4600
|
+
} finally {
|
|
4601
|
+
setIsLoading(false);
|
|
4602
|
+
}
|
|
4603
|
+
}
|
|
4604
|
+
function handleVerifyRoute(requirement) {
|
|
4605
|
+
const attempt = pendingFromQuote(requirement);
|
|
4606
|
+
setErrorMsg(null);
|
|
4607
|
+
setNoticeMsg(null);
|
|
4608
|
+
kycAttempt.current = attempt;
|
|
4609
|
+
setPendingKyc(attempt);
|
|
4610
|
+
}
|
|
3464
4611
|
function handleOpenKyc() {
|
|
3465
4612
|
if (kycUrl) window.open(kycUrl, "_blank", "noopener,noreferrer");
|
|
3466
4613
|
}
|
|
@@ -3489,9 +4636,61 @@ function RampWidget({ onClose }) {
|
|
|
3489
4636
|
}
|
|
3490
4637
|
}
|
|
3491
4638
|
const kycBlocking = kycPending && !kycApproved;
|
|
3492
|
-
const canComplete = direction === "offramp" && step === "status" && txStatus !== "completed" && !stellarTxHash && !
|
|
4639
|
+
const canComplete = direction === "offramp" && step === "status" && txStatus !== "completed" && !stellarTxHash && !kycPending;
|
|
3493
4640
|
const flowSteps = flowStepsOf(quotes, selectedQuote);
|
|
3494
4641
|
const flowStepIndex = flowSteps.indexOf(STEP_LABEL[step] ?? "");
|
|
4642
|
+
if (pendingKyc?.type === "FORM") {
|
|
4643
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4644
|
+
RequirementFormModal,
|
|
4645
|
+
{
|
|
4646
|
+
formId: pendingKyc.optionId,
|
|
4647
|
+
...pendingKyc.progress ? { progress: pendingKyc.progress } : {},
|
|
4648
|
+
onClose: () => {
|
|
4649
|
+
kycAttempt.current = null;
|
|
4650
|
+
setPendingKyc(null);
|
|
4651
|
+
},
|
|
4652
|
+
onSubmitted: () => {
|
|
4653
|
+
if (kycAttempt.current !== pendingKyc) return;
|
|
4654
|
+
kycAttempt.current = null;
|
|
4655
|
+
setPendingKyc(null);
|
|
4656
|
+
void requoteAfterKyc("FORM");
|
|
4657
|
+
}
|
|
4658
|
+
}
|
|
4659
|
+
);
|
|
4660
|
+
}
|
|
4661
|
+
if (pendingKyc?.type === "REGISTRY_CHECK" || pendingKyc?.type === "PROVIDER_REGISTRATION") {
|
|
4662
|
+
const close = () => {
|
|
4663
|
+
kycAttempt.current = null;
|
|
4664
|
+
setPendingKyc(null);
|
|
4665
|
+
};
|
|
4666
|
+
const done = () => {
|
|
4667
|
+
if (kycAttempt.current !== pendingKyc) return;
|
|
4668
|
+
close();
|
|
4669
|
+
void requoteAfterKyc(pendingKyc.type);
|
|
4670
|
+
};
|
|
4671
|
+
const progress = pendingKyc.progress ? { progress: pendingKyc.progress } : {};
|
|
4672
|
+
return pendingKyc.type === "REGISTRY_CHECK" ? /* @__PURE__ */ jsxRuntime.jsx(RegistryCheckModal, { optionId: pendingKyc.optionId, ...progress, onClose: close, onApproved: done }) : /* @__PURE__ */ jsxRuntime.jsx(ProviderRegistrationModal, { corridorId: pendingKyc.corridorId, ...progress, onClose: close, onRegistered: done });
|
|
4673
|
+
}
|
|
4674
|
+
if (pendingKyc) {
|
|
4675
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4676
|
+
KycModal,
|
|
4677
|
+
{
|
|
4678
|
+
country,
|
|
4679
|
+
corridorId: pendingKyc.corridorId,
|
|
4680
|
+
providerId: pendingKyc.optionId,
|
|
4681
|
+
onClose: () => {
|
|
4682
|
+
kycAttempt.current = null;
|
|
4683
|
+
setPendingKyc(null);
|
|
4684
|
+
},
|
|
4685
|
+
onApproved: () => {
|
|
4686
|
+
if (kycAttempt.current !== pendingKyc) return;
|
|
4687
|
+
kycAttempt.current = null;
|
|
4688
|
+
setPendingKyc(null);
|
|
4689
|
+
void requoteAfterKyc();
|
|
4690
|
+
}
|
|
4691
|
+
}
|
|
4692
|
+
);
|
|
4693
|
+
}
|
|
3495
4694
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3496
4695
|
RampWidgetTemplate,
|
|
3497
4696
|
{
|
|
@@ -3512,12 +4711,14 @@ function RampWidget({ onClose }) {
|
|
|
3512
4711
|
countriesLoading,
|
|
3513
4712
|
refreshing,
|
|
3514
4713
|
quotes,
|
|
4714
|
+
kycRequired: requirementsRequired,
|
|
3515
4715
|
isLoading,
|
|
3516
4716
|
provider,
|
|
3517
4717
|
txStatus,
|
|
3518
4718
|
kycUrl,
|
|
3519
4719
|
tosUrl,
|
|
3520
4720
|
kycBlocking,
|
|
4721
|
+
onboardingStatus: onboardingStatus ?? null,
|
|
3521
4722
|
kycJustApproved: kycPending && kycApproved,
|
|
3522
4723
|
stellarTxHash,
|
|
3523
4724
|
explorerUrl: stellarTxHash ? `https://stellar.expert/explorer/${network === "mainnet" ? "public" : "testnet"}/tx/${stellarTxHash}` : null,
|
|
@@ -3525,6 +4726,7 @@ function RampWidget({ onClose }) {
|
|
|
3525
4726
|
canComplete,
|
|
3526
4727
|
completing,
|
|
3527
4728
|
errorMsg,
|
|
4729
|
+
noticeMsg,
|
|
3528
4730
|
onDirectionChange: setDirection,
|
|
3529
4731
|
onAmountChange: (next) => {
|
|
3530
4732
|
setAmount(next);
|
|
@@ -3534,6 +4736,7 @@ function RampWidget({ onClose }) {
|
|
|
3534
4736
|
onCountryChange: handleCountryChange,
|
|
3535
4737
|
onFindRoute: handleFindRoute,
|
|
3536
4738
|
onSelectQuote: handleSelectQuote,
|
|
4739
|
+
onVerifyRoute: handleVerifyRoute,
|
|
3537
4740
|
onContactContinue: handleContactContinue,
|
|
3538
4741
|
onOpenKyc: handleOpenKyc,
|
|
3539
4742
|
onOpenTos: handleOpenTos,
|
|
@@ -3546,6 +4749,18 @@ function RampWidget({ onClose }) {
|
|
|
3546
4749
|
) });
|
|
3547
4750
|
}
|
|
3548
4751
|
|
|
4752
|
+
// src/lib/wallet-provisioning.ts
|
|
4753
|
+
function walletNotReadyReason(wallet, chain) {
|
|
4754
|
+
if (chain !== "STELLAR") return null;
|
|
4755
|
+
if (wallet?.provisioning === "CREATING") {
|
|
4756
|
+
return "Your wallet is still being prepared on the network. This usually takes a few seconds.";
|
|
4757
|
+
}
|
|
4758
|
+
if (wallet?.provisioning === "FAILED") {
|
|
4759
|
+
return "Your wallet could not be created on the network. Sign in again to retry.";
|
|
4760
|
+
}
|
|
4761
|
+
return null;
|
|
4762
|
+
}
|
|
4763
|
+
|
|
3549
4764
|
// src/lib/qr-code/index.tsx
|
|
3550
4765
|
var import_ErrorCorrectLevel = __toESM(require_ErrorCorrectLevel());
|
|
3551
4766
|
var import_QRCode = __toESM(require_QRCode());
|
|
@@ -3588,6 +4803,31 @@ var QRCode = react.forwardRef(function QRCode2({ bgColor = "#FFFFFF", fgColor =
|
|
|
3588
4803
|
}
|
|
3589
4804
|
);
|
|
3590
4805
|
});
|
|
4806
|
+
function PollarLogo(props) {
|
|
4807
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "45", height: "48", viewBox: "0 0 45 48", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: [
|
|
4808
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4809
|
+
"path",
|
|
4810
|
+
{
|
|
4811
|
+
d: "M27.2476 11.7526L23.3926 10.0529L24.6679 9.14844L26.8168 9.19868L27.7248 10.3873L27.2476 11.7526Z",
|
|
4812
|
+
fill: "#005DB4"
|
|
4813
|
+
}
|
|
4814
|
+
),
|
|
4815
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4816
|
+
"path",
|
|
4817
|
+
{
|
|
4818
|
+
d: "M27.2307 33.2204L35.6034 28.6687L35.5931 25.9484L35.5707 20.0746L37.96 20.0989C37.96 20.0989 35.8728 18.3558 34.958 17.571C34.0431 16.7861 29.1016 12.8772 29.1016 12.8772L29.7315 11.2883L29.723 9.3148L27.3303 7.45046L23.7464 7.40887C23.7464 7.40887 20.5179 8.96827 20.4115 9.12248C20.2227 9.12248 15.4579 9.17619 14.5568 9.17619C12.3907 10.5103 8.21642 13.1527 8.21642 13.1527L8.22672 15.1002L2.54028 18.4858L5.60406 18.8704L5.99368 19.9568L4.93466 21.7276C4.93466 21.7276 3.61131 22.4796 3.43624 22.5264C3.76248 23.1143 4.12596 23.6803 4.52444 24.2209C4.72869 24.4773 5.01362 24.5259 5.26421 24.5969C5.66242 24.7078 6.09152 24.6991 6.50517 24.7563C6.71629 24.784 6.92226 24.8585 7.13509 24.8863C7.34792 24.914 10.6966 25.4061 11.1566 25.4424C11.5767 25.519 11.9895 25.6315 12.3907 25.7786C13.1476 26.1719 13.8685 26.6449 14.622 27.0226C15.4236 27.4298 16.1668 27.9184 16.9426 28.3689C17.5519 28.7258 18.7397 29.5281 18.7397 29.5281L19.4366 30.3372C19.4366 30.3372 17.7819 30.4135 17.219 30.5261C16.9117 30.5885 16.6302 30.63 16.4534 31.0286C16.2286 31.5345 6.69054 47.5703 6.43136 48C6.36442 47.9134 6.38845 28.6687 6.38845 28.6687L8.60776 27.2513L3.81385 26.0662L0.53552 20.818L0 18.3662L6.45368 14.414L6.36957 0H28.8304C28.8304 0 30.5468 0.223514 31.0618 0.377721C31.5767 0.531928 31.98 0.609898 33.7205 1.8938C35.3373 3.30592 39.7502 7.82125 42.3214 10.4098C42.6028 10.694 43.4422 11.7735 43.6087 12.47C43.7752 13.1665 44 14.2442 44 15.0586C43.9708 19.1148 44.0172 23.2853 43.9571 27.3397C43.9382 28.615 43.516 29.8226 42.8449 30.9506C42.5531 31.4427 41.3276 32.8201 40.3595 33.8233C39.9109 34.2848 39.3577 34.6291 38.7478 34.8266L27.2307 38.5847V33.2204Z",
|
|
4819
|
+
fill: "#005DB4"
|
|
4820
|
+
}
|
|
4821
|
+
),
|
|
4822
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4823
|
+
"path",
|
|
4824
|
+
{
|
|
4825
|
+
d: "M14.2192 17.0897C13.6705 17.1694 11.7754 15.6937 11.7754 15.6937L13.4741 14.3999H16.5112L18.0217 15.7182C18.0217 15.7182 16.6853 15.708 16.2399 15.708C15.6669 16.3927 14.7679 17.0181 14.2152 17.0999",
|
|
4826
|
+
fill: "#005DB4"
|
|
4827
|
+
}
|
|
4828
|
+
)
|
|
4829
|
+
] });
|
|
4830
|
+
}
|
|
3591
4831
|
var CHAIN_NAME = {
|
|
3592
4832
|
STELLAR: "Stellar",
|
|
3593
4833
|
POLYGON: "Polygon",
|
|
@@ -3602,10 +4842,10 @@ function ReceiveModalTemplate({
|
|
|
3602
4842
|
selectedChain,
|
|
3603
4843
|
onSelectChain,
|
|
3604
4844
|
copied,
|
|
4845
|
+
notReadyReason,
|
|
3605
4846
|
onCopy,
|
|
3606
4847
|
onClose
|
|
3607
4848
|
}) {
|
|
3608
|
-
const isDark = theme === "dark";
|
|
3609
4849
|
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
|
|
3610
4850
|
const chainName = selectedChain ? CHAIN_NAME[selectedChain] ?? selectedChain : "wallet";
|
|
3611
4851
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3620,18 +4860,32 @@ function ReceiveModalTemplate({
|
|
|
3620
4860
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: "Receive" }),
|
|
3621
4861
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-header-actions", children: /* @__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" }) }) }) })
|
|
3622
4862
|
] }),
|
|
3623
|
-
/* @__PURE__ */ jsxRuntime.jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain }),
|
|
4863
|
+
chains && onSelectChain && /* @__PURE__ */ jsxRuntime.jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain }),
|
|
3624
4864
|
walletAddress ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3625
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
4865
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-receive-qr", children: [
|
|
4866
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-receive-network-badge", children: [
|
|
4867
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-receive-network-dot", "aria-hidden": true }),
|
|
4868
|
+
chainName,
|
|
4869
|
+
" network"
|
|
4870
|
+
] }),
|
|
4871
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-receive-qr-frame", children: [
|
|
4872
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4873
|
+
QRCode,
|
|
4874
|
+
{
|
|
4875
|
+
value: walletAddress,
|
|
4876
|
+
size: 220,
|
|
4877
|
+
level: "H",
|
|
4878
|
+
fgColor: "#111827",
|
|
4879
|
+
bgColor: "#ffffff",
|
|
4880
|
+
title: `${chainName} wallet QR code`
|
|
4881
|
+
}
|
|
4882
|
+
),
|
|
4883
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-receive-qr-mark", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(PollarLogo, { width: "22", height: "24" }) })
|
|
4884
|
+
] })
|
|
3632
4885
|
] }),
|
|
3633
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3634
|
-
|
|
4886
|
+
notReadyReason && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-receive-notice", children: notReadyReason }),
|
|
4887
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-receive-address-actions", children: [
|
|
4888
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-receive-address-row", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-receive-address", children: walletAddress }) }),
|
|
3635
4889
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-receive-copy-btn", onClick: onCopy, "aria-label": "Copy address", children: copied ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3636
4890
|
/* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
|
|
3637
4891
|
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
|
|
@@ -3646,7 +4900,7 @@ function ReceiveModalTemplate({
|
|
|
3646
4900
|
}
|
|
3647
4901
|
)
|
|
3648
4902
|
] }),
|
|
3649
|
-
"Copied
|
|
4903
|
+
"Copied"
|
|
3650
4904
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3651
4905
|
/* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
|
|
3652
4906
|
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
@@ -3660,17 +4914,28 @@ function ReceiveModalTemplate({
|
|
|
3660
4914
|
}
|
|
3661
4915
|
)
|
|
3662
4916
|
] }),
|
|
3663
|
-
"Copy
|
|
4917
|
+
"Copy"
|
|
3664
4918
|
] }) })
|
|
4919
|
+
] }),
|
|
4920
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-receive-warning", children: [
|
|
4921
|
+
/* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
|
|
4922
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "7", cy: "7", r: "5.5", stroke: "currentColor", strokeWidth: "1.25" }),
|
|
4923
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 6.25V9.25M7 4.5V4.75", stroke: "currentColor", strokeWidth: "1.25", strokeLinecap: "round" })
|
|
4924
|
+
] }),
|
|
4925
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
4926
|
+
"Only send ",
|
|
4927
|
+
chainName,
|
|
4928
|
+
" assets to this address"
|
|
4929
|
+
] })
|
|
3665
4930
|
] })
|
|
3666
4931
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "No wallet connected." }),
|
|
3667
|
-
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
4932
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, { shield: true })
|
|
3668
4933
|
]
|
|
3669
4934
|
}
|
|
3670
4935
|
);
|
|
3671
4936
|
}
|
|
3672
4937
|
function ReceiveModal({ onClose }) {
|
|
3673
|
-
const { wallets, styles } = usePollar();
|
|
4938
|
+
const { wallet, wallets, styles } = usePollar();
|
|
3674
4939
|
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
3675
4940
|
const [copied, setCopied] = react.useState(false);
|
|
3676
4941
|
const copyTimerRef = react.useRef(null);
|
|
@@ -3680,6 +4945,7 @@ function ReceiveModal({ onClose }) {
|
|
|
3680
4945
|
if (selectedChain === null && chains.length > 0) setSelectedChain(chains[0]);
|
|
3681
4946
|
}, [chains, selectedChain]);
|
|
3682
4947
|
const walletAddress = addressForChain(wallets, selectedChain);
|
|
4948
|
+
const notReadyReason = walletNotReadyReason(wallet, selectedChain);
|
|
3683
4949
|
react.useEffect(
|
|
3684
4950
|
() => () => {
|
|
3685
4951
|
if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
|
|
@@ -3710,53 +4976,13 @@ function ReceiveModal({ onClose }) {
|
|
|
3710
4976
|
setCopied(false);
|
|
3711
4977
|
setSelectedChain(chain);
|
|
3712
4978
|
},
|
|
4979
|
+
notReadyReason,
|
|
3713
4980
|
copied,
|
|
3714
4981
|
onCopy: handleCopy,
|
|
3715
4982
|
onClose
|
|
3716
4983
|
}
|
|
3717
4984
|
) });
|
|
3718
4985
|
}
|
|
3719
|
-
function formatAmount2(value) {
|
|
3720
|
-
const n = parseFloat(value);
|
|
3721
|
-
return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
|
|
3722
|
-
}
|
|
3723
|
-
var optionLabel = (o) => o.available !== void 0 ? `${o.code} \u2014 ${formatAmount2(o.available)} available` : o.code;
|
|
3724
|
-
function AssetSelect({
|
|
3725
|
-
label,
|
|
3726
|
-
value,
|
|
3727
|
-
options,
|
|
3728
|
-
onChange,
|
|
3729
|
-
loading = false,
|
|
3730
|
-
loadingLabel,
|
|
3731
|
-
disabled = false,
|
|
3732
|
-
appGroupLabel = "App assets",
|
|
3733
|
-
otherGroupLabel = "Other assets",
|
|
3734
|
-
children
|
|
3735
|
-
}) {
|
|
3736
|
-
const appAssets = options.filter((o) => o.enabledInApp);
|
|
3737
|
-
const otherAssets = options.filter((o) => !o.enabledInApp);
|
|
3738
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
3739
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: label }),
|
|
3740
|
-
loading ? loadingLabel ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-input pollar-select-loading", children: [
|
|
3741
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
3742
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: loadingLabel })
|
|
3743
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3744
|
-
"select",
|
|
3745
|
-
{
|
|
3746
|
-
className: "pollar-input pollar-send-select",
|
|
3747
|
-
value,
|
|
3748
|
-
disabled,
|
|
3749
|
-
onChange: (e) => onChange(e.target.value),
|
|
3750
|
-
children: [
|
|
3751
|
-
value === "" && /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, hidden: true }),
|
|
3752
|
-
appAssets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("optgroup", { label: appGroupLabel, children: appAssets.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.key, children: optionLabel(o) }, o.key)) }),
|
|
3753
|
-
otherAssets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("optgroup", { label: otherGroupLabel, children: otherAssets.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.key, children: optionLabel(o) }, o.key)) })
|
|
3754
|
-
]
|
|
3755
|
-
}
|
|
3756
|
-
),
|
|
3757
|
-
!loading && children
|
|
3758
|
-
] });
|
|
3759
|
-
}
|
|
3760
4986
|
var STATUS_MESSAGES = {
|
|
3761
4987
|
idle: "",
|
|
3762
4988
|
building: "Building transaction\u2026",
|
|
@@ -3962,6 +5188,97 @@ function formatBalance(balance) {
|
|
|
3962
5188
|
function assetKey3(record) {
|
|
3963
5189
|
return `${record.code}:${record.issuer ?? "native"}`;
|
|
3964
5190
|
}
|
|
5191
|
+
function chainLabel(chain) {
|
|
5192
|
+
if (chain === "STELLAR") return "Stellar";
|
|
5193
|
+
if (chain === "SOLANA") return "Solana";
|
|
5194
|
+
if (chain === "POLYGON") return "Polygon";
|
|
5195
|
+
return "network";
|
|
5196
|
+
}
|
|
5197
|
+
function AssetIcon({ code }) {
|
|
5198
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-asset-icon", "aria-hidden": true, children: code.slice(0, 2).toUpperCase() });
|
|
5199
|
+
}
|
|
5200
|
+
function SendAssetSelector({ assets, selectedAsset, loading, onSelectAsset }) {
|
|
5201
|
+
const [open, setOpen] = react.useState(false);
|
|
5202
|
+
const triggerRef = react.useRef(null);
|
|
5203
|
+
react.useEffect(() => {
|
|
5204
|
+
if (!open) return;
|
|
5205
|
+
const closeOnOutsideClick = (event) => {
|
|
5206
|
+
if (!(event.target instanceof Node) || !triggerRef.current?.parentElement?.contains(event.target)) setOpen(false);
|
|
5207
|
+
};
|
|
5208
|
+
document.addEventListener("mousedown", closeOnOutsideClick);
|
|
5209
|
+
return () => document.removeEventListener("mousedown", closeOnOutsideClick);
|
|
5210
|
+
}, [open]);
|
|
5211
|
+
function handleTriggerKeyDown(event) {
|
|
5212
|
+
if (event.key === "ArrowDown" || event.key === "Enter" || event.key === " ") {
|
|
5213
|
+
event.preventDefault();
|
|
5214
|
+
setOpen(true);
|
|
5215
|
+
}
|
|
5216
|
+
}
|
|
5217
|
+
if (loading) {
|
|
5218
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
5219
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-label", children: "Asset" }),
|
|
5220
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-asset-selector pollar-send-asset-selector-loading", "aria-label": "Loading assets", children: [
|
|
5221
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
5222
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Loading assets\u2026" })
|
|
5223
|
+
] })
|
|
5224
|
+
] });
|
|
5225
|
+
}
|
|
5226
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
5227
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", id: "pollar-send-asset-label", children: "Asset" }),
|
|
5228
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-asset-picker", children: [
|
|
5229
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5230
|
+
"button",
|
|
5231
|
+
{
|
|
5232
|
+
ref: triggerRef,
|
|
5233
|
+
type: "button",
|
|
5234
|
+
className: "pollar-send-asset-selector",
|
|
5235
|
+
"aria-labelledby": "pollar-send-asset-label",
|
|
5236
|
+
"aria-haspopup": "listbox",
|
|
5237
|
+
"aria-expanded": open,
|
|
5238
|
+
disabled: !selectedAsset,
|
|
5239
|
+
onClick: () => setOpen((value) => !value),
|
|
5240
|
+
onKeyDown: handleTriggerKeyDown,
|
|
5241
|
+
children: [
|
|
5242
|
+
selectedAsset ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5243
|
+
/* @__PURE__ */ jsxRuntime.jsx(AssetIcon, { code: selectedAsset.code }),
|
|
5244
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-send-asset-copy", children: [
|
|
5245
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: selectedAsset.code }),
|
|
5246
|
+
/* @__PURE__ */ jsxRuntime.jsx("small", { children: selectedAsset.available === null ? "Balance unavailable" : `${formatBalance(selectedAsset.available)} available` })
|
|
5247
|
+
] })
|
|
5248
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-asset-copy", children: /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "No assets available" }) }),
|
|
5249
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "pollar-send-chevron", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m4 6 4 4 4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
5250
|
+
]
|
|
5251
|
+
}
|
|
5252
|
+
),
|
|
5253
|
+
open && assets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-asset-menu", role: "listbox", "aria-label": "Assets", children: assets.map((asset) => {
|
|
5254
|
+
const key = assetKey3(asset);
|
|
5255
|
+
const selected = selectedAsset ? key === assetKey3(selectedAsset) : false;
|
|
5256
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5257
|
+
"button",
|
|
5258
|
+
{
|
|
5259
|
+
type: "button",
|
|
5260
|
+
role: "option",
|
|
5261
|
+
"aria-selected": selected,
|
|
5262
|
+
className: `pollar-send-asset-option${selected ? " is-selected" : ""}`,
|
|
5263
|
+
onClick: () => {
|
|
5264
|
+
onSelectAsset(asset);
|
|
5265
|
+
setOpen(false);
|
|
5266
|
+
triggerRef.current?.focus();
|
|
5267
|
+
},
|
|
5268
|
+
children: [
|
|
5269
|
+
/* @__PURE__ */ jsxRuntime.jsx(AssetIcon, { code: asset.code }),
|
|
5270
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-send-asset-copy", children: [
|
|
5271
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: asset.code }),
|
|
5272
|
+
/* @__PURE__ */ jsxRuntime.jsx("small", { children: asset.available === null ? "Balance unavailable" : `${formatBalance(asset.available)} available` })
|
|
5273
|
+
] })
|
|
5274
|
+
]
|
|
5275
|
+
},
|
|
5276
|
+
key
|
|
5277
|
+
);
|
|
5278
|
+
}) })
|
|
5279
|
+
] })
|
|
5280
|
+
] });
|
|
5281
|
+
}
|
|
3965
5282
|
function SendModalTemplate({
|
|
3966
5283
|
theme,
|
|
3967
5284
|
accentColor,
|
|
@@ -3970,10 +5287,10 @@ function SendModalTemplate({
|
|
|
3970
5287
|
txTitle,
|
|
3971
5288
|
assets,
|
|
3972
5289
|
selectedAsset,
|
|
3973
|
-
chains,
|
|
3974
5290
|
selectedChain,
|
|
3975
|
-
walletAddress,
|
|
3976
5291
|
canSendOnChain,
|
|
5292
|
+
notReadyReason,
|
|
5293
|
+
chains,
|
|
3977
5294
|
onSelectChain,
|
|
3978
5295
|
amount,
|
|
3979
5296
|
destination,
|
|
@@ -3991,6 +5308,8 @@ function SendModalTemplate({
|
|
|
3991
5308
|
onRefresh,
|
|
3992
5309
|
onSelectAsset,
|
|
3993
5310
|
onAmountChange,
|
|
5311
|
+
onMax,
|
|
5312
|
+
onPaste,
|
|
3994
5313
|
onDestinationChange,
|
|
3995
5314
|
onSubmit,
|
|
3996
5315
|
onSignAndSend,
|
|
@@ -4000,8 +5319,9 @@ function SendModalTemplate({
|
|
|
4000
5319
|
onDone
|
|
4001
5320
|
}) {
|
|
4002
5321
|
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
|
|
4003
|
-
const
|
|
4004
|
-
const
|
|
5322
|
+
const parsedAmount = amount ? Number(amount) : 0;
|
|
5323
|
+
const availableAmount = selectedAsset?.available === null || selectedAsset?.available === void 0 ? 0 : Number(selectedAsset.available);
|
|
5324
|
+
const canSubmit = canSendOnChain && !notReadyReason && !!selectedAsset && Number.isFinite(parsedAmount) && parsedAmount > 0 && parsedAmount <= availableAmount && !!destination.trim() && !isLoadingBalance;
|
|
4005
5325
|
const title = step === "form" ? "Send" : txTitle;
|
|
4006
5326
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4007
5327
|
"div",
|
|
@@ -4014,7 +5334,14 @@ function SendModalTemplate({
|
|
|
4014
5334
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
4015
5335
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-header-left", children: [
|
|
4016
5336
|
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" }) }) }),
|
|
4017
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5337
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-title-copy", children: [
|
|
5338
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: title }),
|
|
5339
|
+
step === "form" && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-send-subtitle", children: [
|
|
5340
|
+
"Transfer assets to another ",
|
|
5341
|
+
chainLabel(selectedChain),
|
|
5342
|
+
" wallet"
|
|
5343
|
+
] })
|
|
5344
|
+
] })
|
|
4018
5345
|
] }),
|
|
4019
5346
|
!isInProgress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
|
|
4020
5347
|
step === "form" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4026,58 +5353,23 @@ function SendModalTemplate({
|
|
|
4026
5353
|
disabled: isLoadingBalance,
|
|
4027
5354
|
"aria-label": "Refresh",
|
|
4028
5355
|
title: "Refresh balances",
|
|
4029
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4030
|
-
"svg",
|
|
4031
|
-
{
|
|
4032
|
-
className: isLoadingBalance ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
|
|
4033
|
-
width: "16",
|
|
4034
|
-
height: "16",
|
|
4035
|
-
viewBox: "0 0 16 16",
|
|
4036
|
-
fill: "none",
|
|
4037
|
-
"aria-hidden": true,
|
|
4038
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4039
|
-
"path",
|
|
4040
|
-
{
|
|
4041
|
-
d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
|
|
4042
|
-
stroke: "currentColor",
|
|
4043
|
-
strokeWidth: "1.6",
|
|
4044
|
-
strokeLinecap: "round",
|
|
4045
|
-
strokeLinejoin: "round"
|
|
4046
|
-
}
|
|
4047
|
-
)
|
|
4048
|
-
}
|
|
4049
|
-
)
|
|
5356
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(RefreshIcon, { spinning: isLoadingBalance })
|
|
4050
5357
|
}
|
|
4051
5358
|
),
|
|
4052
5359
|
/* @__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" }) }) })
|
|
4053
5360
|
] })
|
|
4054
5361
|
] }),
|
|
4055
5362
|
step === "form" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4056
|
-
/* @__PURE__ */ jsxRuntime.jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain, disabled: isLoadingBalance }),
|
|
4057
|
-
walletAddress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-address-row", children: [
|
|
4058
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-address", children: cropAddress(walletAddress) }),
|
|
4059
|
-
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: walletAddress, label: "Copy wallet address" })
|
|
4060
|
-
] }),
|
|
5363
|
+
chains && onSelectChain && /* @__PURE__ */ jsxRuntime.jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain, disabled: isLoadingBalance }),
|
|
4061
5364
|
!canSendOnChain && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "Sending is not available on this network yet." }),
|
|
5365
|
+
canSendOnChain && notReadyReason && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: notReadyReason }),
|
|
4062
5366
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4063
|
-
|
|
5367
|
+
SendAssetSelector,
|
|
4064
5368
|
{
|
|
4065
|
-
|
|
4066
|
-
|
|
5369
|
+
assets,
|
|
5370
|
+
selectedAsset,
|
|
4067
5371
|
loading: isLoadingBalance,
|
|
4068
|
-
|
|
4069
|
-
options: assets.map((a) => ({
|
|
4070
|
-
key: assetKey3(a),
|
|
4071
|
-
code: a.code,
|
|
4072
|
-
// Unreadable (null) drops the "- X available" suffix instead of
|
|
4073
|
-
// claiming a zero balance.
|
|
4074
|
-
available: a.available ?? void 0,
|
|
4075
|
-
enabledInApp: a.enabledInApp
|
|
4076
|
-
})),
|
|
4077
|
-
onChange: (key) => {
|
|
4078
|
-
const found = assets.find((a) => assetKey3(a) === key);
|
|
4079
|
-
if (found) onSelectAsset(found);
|
|
4080
|
-
}
|
|
5372
|
+
onSelectAsset
|
|
4081
5373
|
}
|
|
4082
5374
|
),
|
|
4083
5375
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
@@ -4090,30 +5382,50 @@ function SendModalTemplate({
|
|
|
4090
5382
|
selectedAsset.code
|
|
4091
5383
|
] })
|
|
4092
5384
|
] }),
|
|
4093
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
5385
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-input-shell", children: [
|
|
5386
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5387
|
+
"input",
|
|
5388
|
+
{
|
|
5389
|
+
className: "pollar-input pollar-send-amount-input",
|
|
5390
|
+
type: "text",
|
|
5391
|
+
inputMode: "decimal",
|
|
5392
|
+
placeholder: "0.00",
|
|
5393
|
+
value: amount,
|
|
5394
|
+
onChange: (e) => onAmountChange(e.target.value),
|
|
5395
|
+
"aria-label": "Amount"
|
|
5396
|
+
}
|
|
5397
|
+
),
|
|
5398
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-input-suffix", children: [
|
|
5399
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5400
|
+
"button",
|
|
5401
|
+
{
|
|
5402
|
+
type: "button",
|
|
5403
|
+
className: "pollar-send-inline-action",
|
|
5404
|
+
onClick: onMax,
|
|
5405
|
+
disabled: !selectedAsset?.available,
|
|
5406
|
+
children: "Max"
|
|
5407
|
+
}
|
|
5408
|
+
),
|
|
5409
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: selectedAsset?.code ?? "" })
|
|
5410
|
+
] })
|
|
5411
|
+
] })
|
|
4104
5412
|
] }),
|
|
4105
5413
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
4106
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Destination wallet" }),
|
|
4107
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
5414
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Destination wallet" }),
|
|
5415
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-input-shell", children: [
|
|
5416
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5417
|
+
"input",
|
|
5418
|
+
{
|
|
5419
|
+
className: "pollar-input pollar-send-destination-input",
|
|
5420
|
+
type: "text",
|
|
5421
|
+
placeholder: "G\u2026",
|
|
5422
|
+
value: destination,
|
|
5423
|
+
onChange: (e) => onDestinationChange(e.target.value),
|
|
5424
|
+
"aria-label": "Destination wallet"
|
|
5425
|
+
}
|
|
5426
|
+
),
|
|
5427
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-send-inline-action", onClick: onPaste, children: "Paste" })
|
|
5428
|
+
] })
|
|
4117
5429
|
] }),
|
|
4118
5430
|
formError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: formError }),
|
|
4119
5431
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-btn-primary", onClick: onSubmit, disabled: !canSubmit, children: "Continue" }) })
|
|
@@ -4154,7 +5466,6 @@ function SendModal({ onClose }) {
|
|
|
4154
5466
|
signAndSubmitTx,
|
|
4155
5467
|
tx: transaction,
|
|
4156
5468
|
wallet,
|
|
4157
|
-
wallets,
|
|
4158
5469
|
network,
|
|
4159
5470
|
styles
|
|
4160
5471
|
} = usePollar();
|
|
@@ -4173,8 +5484,8 @@ function SendModal({ onClose }) {
|
|
|
4173
5484
|
react.useEffect(() => {
|
|
4174
5485
|
if (selectedChain === null && chains.length > 0) setSelectedChain(chains[0]);
|
|
4175
5486
|
}, [chains, selectedChain]);
|
|
4176
|
-
const walletAddress = addressForChain(wallets, selectedChain);
|
|
4177
5487
|
const canSendOnChain = selectedChain === "STELLAR" || selectedChain === "SOLANA";
|
|
5488
|
+
const notReadyReason = walletNotReadyReason(wallet, selectedChain);
|
|
4178
5489
|
const isBaseUnitChain = selectedChain === "SOLANA";
|
|
4179
5490
|
react.useEffect(() => {
|
|
4180
5491
|
void refreshWalletBalance();
|
|
@@ -4221,6 +5532,10 @@ function SendModal({ onClose }) {
|
|
|
4221
5532
|
setFormError("Sending is not available on this network yet.");
|
|
4222
5533
|
return;
|
|
4223
5534
|
}
|
|
5535
|
+
if (notReadyReason) {
|
|
5536
|
+
setFormError(notReadyReason);
|
|
5537
|
+
return;
|
|
5538
|
+
}
|
|
4224
5539
|
if (!selectedAsset) {
|
|
4225
5540
|
setFormError("Select an asset");
|
|
4226
5541
|
return;
|
|
@@ -4271,6 +5586,29 @@ function SendModal({ onClose }) {
|
|
|
4271
5586
|
void signAndSubmitTx(transaction.buildData.unsignedXdr);
|
|
4272
5587
|
}
|
|
4273
5588
|
}
|
|
5589
|
+
function handleMax() {
|
|
5590
|
+
if (selectedAsset?.available !== null && selectedAsset?.available !== void 0) {
|
|
5591
|
+
setAmount(selectedAsset.available);
|
|
5592
|
+
setFormError("");
|
|
5593
|
+
}
|
|
5594
|
+
}
|
|
5595
|
+
async function handlePaste() {
|
|
5596
|
+
if (!navigator.clipboard?.readText) {
|
|
5597
|
+
setFormError("Clipboard access is not available. Paste the address manually.");
|
|
5598
|
+
return;
|
|
5599
|
+
}
|
|
5600
|
+
try {
|
|
5601
|
+
const value = (await navigator.clipboard.readText()).trim();
|
|
5602
|
+
if (!value) {
|
|
5603
|
+
setFormError("The clipboard is empty.");
|
|
5604
|
+
return;
|
|
5605
|
+
}
|
|
5606
|
+
setDestination(value);
|
|
5607
|
+
setFormError("");
|
|
5608
|
+
} catch {
|
|
5609
|
+
setFormError("Could not read the clipboard. Paste the address manually.");
|
|
5610
|
+
}
|
|
5611
|
+
}
|
|
4274
5612
|
function handleCopyHash() {
|
|
4275
5613
|
if (!hash) return;
|
|
4276
5614
|
navigator.clipboard.writeText(hash).then(() => {
|
|
@@ -4304,8 +5642,8 @@ function SendModal({ onClose }) {
|
|
|
4304
5642
|
selectedAsset,
|
|
4305
5643
|
chains,
|
|
4306
5644
|
selectedChain,
|
|
4307
|
-
walletAddress,
|
|
4308
5645
|
canSendOnChain,
|
|
5646
|
+
notReadyReason,
|
|
4309
5647
|
onSelectChain: setSelectedChain,
|
|
4310
5648
|
amount,
|
|
4311
5649
|
destination,
|
|
@@ -4323,6 +5661,8 @@ function SendModal({ onClose }) {
|
|
|
4323
5661
|
onRefresh: () => void refreshWalletBalance(),
|
|
4324
5662
|
onSelectAsset: setSelectedAsset,
|
|
4325
5663
|
onAmountChange: setAmount,
|
|
5664
|
+
onMax: handleMax,
|
|
5665
|
+
onPaste: handlePaste,
|
|
4326
5666
|
onDestinationChange: setDestination,
|
|
4327
5667
|
onSubmit: () => void handleSubmit(),
|
|
4328
5668
|
onSignAndSend: handleSignAndSend,
|
|
@@ -4337,15 +5677,77 @@ function assetOptionKey(o) {
|
|
|
4337
5677
|
return `${o.code}:${o.issuer ?? "native"}`;
|
|
4338
5678
|
}
|
|
4339
5679
|
var PROVIDER_LABELS = {
|
|
4340
|
-
auto: "Best price
|
|
5680
|
+
auto: "Best price",
|
|
4341
5681
|
aquarius: "Aquarius",
|
|
4342
5682
|
soroswap: "Soroswap",
|
|
4343
5683
|
sdex: "Stellar DEX"
|
|
4344
5684
|
};
|
|
4345
|
-
function
|
|
5685
|
+
function formatAmount2(value) {
|
|
5686
|
+
if (value === void 0) return "\u2014";
|
|
4346
5687
|
const n = parseFloat(value);
|
|
4347
5688
|
return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
|
|
4348
5689
|
}
|
|
5690
|
+
function formatRate(numerator, denominator) {
|
|
5691
|
+
const parse = (value) => {
|
|
5692
|
+
const trimmed = value.trim();
|
|
5693
|
+
if (!/^\d+(\.\d+)?$/.test(trimmed)) return null;
|
|
5694
|
+
const [whole2 = "0", fraction2 = ""] = trimmed.split(".");
|
|
5695
|
+
return { digits: BigInt(`${whole2}${fraction2}`), scale: fraction2.length };
|
|
5696
|
+
};
|
|
5697
|
+
const top = parse(numerator);
|
|
5698
|
+
const bottom = parse(denominator);
|
|
5699
|
+
if (!top || !bottom || bottom.digits === 0n || top.digits === 0n) return null;
|
|
5700
|
+
const precision = 8;
|
|
5701
|
+
const scaledNumerator = top.digits * 10n ** BigInt(bottom.scale + precision);
|
|
5702
|
+
const scaledDenominator = bottom.digits * 10n ** BigInt(top.scale);
|
|
5703
|
+
const scaled = scaledNumerator / scaledDenominator;
|
|
5704
|
+
const whole = scaled / 10n ** BigInt(precision);
|
|
5705
|
+
const fraction = (scaled % 10n ** BigInt(precision)).toString().padStart(precision, "0").replace(/0+$/, "");
|
|
5706
|
+
return fraction ? `${whole}.${fraction}` : whole.toString();
|
|
5707
|
+
}
|
|
5708
|
+
function AssetIcon2({ code }) {
|
|
5709
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-swap-asset-icon", "aria-hidden": true, children: code.slice(0, 2).toUpperCase() });
|
|
5710
|
+
}
|
|
5711
|
+
function AssetPill({
|
|
5712
|
+
label,
|
|
5713
|
+
value,
|
|
5714
|
+
options,
|
|
5715
|
+
disabled,
|
|
5716
|
+
onChange
|
|
5717
|
+
}) {
|
|
5718
|
+
const selected = options.find((option) => assetOptionKey(option) === value);
|
|
5719
|
+
const appAssets = options.filter((option) => option.enabledInApp);
|
|
5720
|
+
const otherAssets = options.filter((option) => !option.enabledInApp);
|
|
5721
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-swap-asset-pill-wrap", children: [
|
|
5722
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: label }),
|
|
5723
|
+
/* @__PURE__ */ jsxRuntime.jsx(AssetIcon2, { code: selected?.code ?? "\u2014" }),
|
|
5724
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5725
|
+
"select",
|
|
5726
|
+
{
|
|
5727
|
+
className: "pollar-swap-asset-pill",
|
|
5728
|
+
"aria-label": label,
|
|
5729
|
+
value,
|
|
5730
|
+
disabled,
|
|
5731
|
+
onChange: (event) => onChange(event.target.value),
|
|
5732
|
+
children: [
|
|
5733
|
+
value === "" && /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, hidden: true }),
|
|
5734
|
+
appAssets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("optgroup", { label: "App assets", children: appAssets.map((option) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: assetOptionKey(option), children: option.code }, assetOptionKey(option))) }),
|
|
5735
|
+
otherAssets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("optgroup", { label: "Other assets", children: otherAssets.map((option) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: assetOptionKey(option), children: option.code }, assetOptionKey(option))) })
|
|
5736
|
+
]
|
|
5737
|
+
}
|
|
5738
|
+
),
|
|
5739
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "pollar-swap-chevron", width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5740
|
+
"path",
|
|
5741
|
+
{
|
|
5742
|
+
d: "m3.5 5.25 3.5 3.5 3.5-3.5",
|
|
5743
|
+
stroke: "currentColor",
|
|
5744
|
+
strokeWidth: "1.5",
|
|
5745
|
+
strokeLinecap: "round",
|
|
5746
|
+
strokeLinejoin: "round"
|
|
5747
|
+
}
|
|
5748
|
+
) })
|
|
5749
|
+
] });
|
|
5750
|
+
}
|
|
4349
5751
|
function SwapModalTemplate({
|
|
4350
5752
|
theme,
|
|
4351
5753
|
accentColor,
|
|
@@ -4381,6 +5783,8 @@ function SwapModalTemplate({
|
|
|
4381
5783
|
onSelectSell,
|
|
4382
5784
|
onSelectBuy,
|
|
4383
5785
|
onAddCustomToken,
|
|
5786
|
+
onReverse,
|
|
5787
|
+
onMax,
|
|
4384
5788
|
onAmountChange,
|
|
4385
5789
|
onProviderChange,
|
|
4386
5790
|
onSwap,
|
|
@@ -4407,19 +5811,29 @@ function SwapModalTemplate({
|
|
|
4407
5811
|
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
|
|
4408
5812
|
const sellKey = selectedSell ? assetOptionKey(selectedSell) : "";
|
|
4409
5813
|
const buyKey = selectedBuy ? assetOptionKey(selectedBuy) : "";
|
|
4410
|
-
const
|
|
5814
|
+
const sameAsset = !!selectedSell && !!selectedBuy && sellKey === buyKey;
|
|
5815
|
+
const canSwap = !smartUnsupported && !sameAsset && !!selectedSell && !!selectedBuy && !!amount && !!quote && !quoteLoading && !isLoadingData;
|
|
5816
|
+
const rate = quote && amount ? formatRate(quote.amountOut, amount) : null;
|
|
4411
5817
|
const title = step === "form" ? "Swap" : txTitle;
|
|
5818
|
+
const selectSell = (key) => {
|
|
5819
|
+
const found = sellOptions.find((option) => assetOptionKey(option) === key);
|
|
5820
|
+
if (found) onSelectSell(found);
|
|
5821
|
+
};
|
|
5822
|
+
const selectBuy = (key) => {
|
|
5823
|
+
const found = buyOptions.find((option) => assetOptionKey(option) === key);
|
|
5824
|
+
if (found) onSelectBuy(found);
|
|
5825
|
+
};
|
|
4412
5826
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4413
5827
|
"div",
|
|
4414
5828
|
{
|
|
4415
|
-
className: "pollar-modal-card pollar-
|
|
5829
|
+
className: "pollar-modal-card pollar-swap-modal",
|
|
4416
5830
|
"data-theme": theme,
|
|
4417
5831
|
style: cssVars,
|
|
4418
|
-
onClick: (
|
|
5832
|
+
onClick: (event) => event.stopPropagation(),
|
|
4419
5833
|
children: [
|
|
4420
5834
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
4421
5835
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-header-left", children: [
|
|
4422
|
-
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
|
|
5836
|
+
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 3 5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
|
|
4423
5837
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: title })
|
|
4424
5838
|
] }),
|
|
4425
5839
|
!isInProgress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
|
|
@@ -4432,16 +5846,7 @@ function SwapModalTemplate({
|
|
|
4432
5846
|
disabled: configLoading || isLoadingData,
|
|
4433
5847
|
"aria-label": "Refresh",
|
|
4434
5848
|
title: "Refresh balances and options",
|
|
4435
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4436
|
-
"path",
|
|
4437
|
-
{
|
|
4438
|
-
d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2.5v3h-3",
|
|
4439
|
-
stroke: "currentColor",
|
|
4440
|
-
strokeWidth: "1.6",
|
|
4441
|
-
strokeLinecap: "round",
|
|
4442
|
-
strokeLinejoin: "round"
|
|
4443
|
-
}
|
|
4444
|
-
) })
|
|
5849
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(RefreshIcon, { spinning: configLoading || isLoadingData })
|
|
4445
5850
|
}
|
|
4446
5851
|
),
|
|
4447
5852
|
/* @__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" }) }) })
|
|
@@ -4450,174 +5855,205 @@ function SwapModalTemplate({
|
|
|
4450
5855
|
step === "form" && !configLoading && swapUnavailable && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Swap is not available for this app." }),
|
|
4451
5856
|
step === "form" && !swapUnavailable && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4452
5857
|
smartUnsupported && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Swaps are not yet available for smart (passkey) wallets." }),
|
|
4453
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
code: o.code,
|
|
4464
|
-
available: o.available,
|
|
4465
|
-
enabledInApp: o.enabledInApp
|
|
4466
|
-
})),
|
|
4467
|
-
onChange: (key) => {
|
|
4468
|
-
const found = sellOptions.find((o) => assetOptionKey(o) === key);
|
|
4469
|
-
if (found) onSelectSell(found);
|
|
4470
|
-
}
|
|
4471
|
-
}
|
|
4472
|
-
),
|
|
4473
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-field", children: [
|
|
4474
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-label-row", children: [
|
|
4475
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: "Amount" }),
|
|
4476
|
-
selectedSell?.available !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-send-hint", children: [
|
|
4477
|
-
"Available: ",
|
|
4478
|
-
formatAmount3(selectedSell.available),
|
|
4479
|
-
" ",
|
|
4480
|
-
selectedSell.code
|
|
4481
|
-
] })
|
|
4482
|
-
] }),
|
|
4483
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4484
|
-
"input",
|
|
4485
|
-
{
|
|
4486
|
-
className: "pollar-input",
|
|
4487
|
-
type: "text",
|
|
4488
|
-
inputMode: "decimal",
|
|
4489
|
-
placeholder: "0.00",
|
|
4490
|
-
value: amount,
|
|
4491
|
-
disabled: configLoading,
|
|
4492
|
-
onChange: (e) => onAmountChange(e.target.value)
|
|
4493
|
-
}
|
|
4494
|
-
)
|
|
4495
|
-
] }),
|
|
4496
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4497
|
-
AssetSelect,
|
|
4498
|
-
{
|
|
4499
|
-
label: "You receive",
|
|
4500
|
-
value: buyKey,
|
|
4501
|
-
loading: isLoadingData || configLoading,
|
|
4502
|
-
loadingLabel: "Loading assets\u2026",
|
|
4503
|
-
disabled: configLoading,
|
|
4504
|
-
options: buyOptions.map((o) => ({
|
|
4505
|
-
key: assetOptionKey(o),
|
|
4506
|
-
code: o.code,
|
|
4507
|
-
enabledInApp: o.enabledInApp
|
|
4508
|
-
})),
|
|
4509
|
-
onChange: (key) => {
|
|
4510
|
-
const found = buyOptions.find((o) => assetOptionKey(o) === key);
|
|
4511
|
-
if (found) onSelectBuy(found);
|
|
4512
|
-
},
|
|
4513
|
-
children: customOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-custom", children: [
|
|
4514
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4515
|
-
"input",
|
|
4516
|
-
{
|
|
4517
|
-
className: "pollar-input",
|
|
4518
|
-
type: "text",
|
|
4519
|
-
placeholder: "Code (e.g. USDC)",
|
|
4520
|
-
value: customCode,
|
|
4521
|
-
onChange: (e) => setCustomCode(e.target.value)
|
|
4522
|
-
}
|
|
4523
|
-
),
|
|
5858
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-panels", children: [
|
|
5859
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "pollar-swap-panel", "aria-labelledby": "pollar-swap-pay-label", children: [
|
|
5860
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-panel-heading", children: [
|
|
5861
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { id: "pollar-swap-pay-label", className: "pollar-swap-panel-label", children: "You pay" }),
|
|
5862
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-swap-balance", children: [
|
|
5863
|
+
"Balance: ",
|
|
5864
|
+
formatAmount2(selectedSell?.available)
|
|
5865
|
+
] })
|
|
5866
|
+
] }),
|
|
5867
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-panel-main", children: [
|
|
4524
5868
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4525
5869
|
"input",
|
|
4526
5870
|
{
|
|
4527
|
-
className: "pollar-
|
|
5871
|
+
className: "pollar-swap-amount",
|
|
4528
5872
|
type: "text",
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
5873
|
+
inputMode: "decimal",
|
|
5874
|
+
"aria-label": "Amount to pay",
|
|
5875
|
+
placeholder: "0.00",
|
|
5876
|
+
value: amount,
|
|
5877
|
+
disabled: configLoading || isLoadingData,
|
|
5878
|
+
onChange: (event) => onAmountChange(event.target.value)
|
|
4532
5879
|
}
|
|
4533
5880
|
),
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
5881
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-panel-selector", children: [
|
|
5882
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5883
|
+
AssetPill,
|
|
5884
|
+
{
|
|
5885
|
+
label: "Asset to pay",
|
|
5886
|
+
value: sellKey,
|
|
5887
|
+
options: sellOptions,
|
|
5888
|
+
disabled: configLoading || isLoadingData,
|
|
5889
|
+
onChange: selectSell
|
|
5890
|
+
}
|
|
5891
|
+
),
|
|
4537
5892
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4538
5893
|
"button",
|
|
4539
5894
|
{
|
|
4540
5895
|
type: "button",
|
|
4541
|
-
className: "pollar-swap-
|
|
4542
|
-
onClick:
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
},
|
|
4546
|
-
children: "Cancel"
|
|
5896
|
+
className: "pollar-swap-max",
|
|
5897
|
+
onClick: onMax,
|
|
5898
|
+
disabled: !selectedSell?.available || configLoading || isLoadingData,
|
|
5899
|
+
children: "Max"
|
|
4547
5900
|
}
|
|
4548
5901
|
)
|
|
4549
5902
|
] })
|
|
4550
|
-
] })
|
|
5903
|
+
] })
|
|
5904
|
+
] }),
|
|
5905
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5906
|
+
"button",
|
|
5907
|
+
{
|
|
5908
|
+
type: "button",
|
|
5909
|
+
className: "pollar-swap-reverse",
|
|
5910
|
+
onClick: onReverse,
|
|
5911
|
+
disabled: !selectedSell || !selectedBuy,
|
|
5912
|
+
"aria-label": "Swap pay and receive assets",
|
|
5913
|
+
title: "Swap pay and receive assets",
|
|
5914
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "17", height: "17", viewBox: "0 0 17 17", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5915
|
+
"path",
|
|
5916
|
+
{
|
|
5917
|
+
d: "M5 3v10M5 3 2.5 5.5M5 3l2.5 2.5M12 14V4M12 14l2.5-2.5M12 14 9.5 11.5",
|
|
5918
|
+
stroke: "currentColor",
|
|
5919
|
+
strokeWidth: "1.6",
|
|
5920
|
+
strokeLinecap: "round",
|
|
5921
|
+
strokeLinejoin: "round"
|
|
5922
|
+
}
|
|
5923
|
+
) })
|
|
5924
|
+
}
|
|
5925
|
+
),
|
|
5926
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { className: "pollar-swap-panel", "aria-labelledby": "pollar-swap-receive-label", children: [
|
|
5927
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-panel-heading", children: [
|
|
5928
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { id: "pollar-swap-receive-label", className: "pollar-swap-panel-label", children: "You receive" }),
|
|
5929
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-swap-balance", children: [
|
|
5930
|
+
"Balance: ",
|
|
5931
|
+
formatAmount2(selectedBuy?.available)
|
|
5932
|
+
] })
|
|
5933
|
+
] }),
|
|
5934
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-panel-main", children: [
|
|
5935
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `pollar-swap-output${quoteLoading ? " is-loading" : ""}`, "aria-live": "polite", children: quoteLoading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-spinner pollar-spinner-sm" }) : formatAmount2(quote?.amountOut) }),
|
|
5936
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-panel-selector", children: [
|
|
5937
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5938
|
+
AssetPill,
|
|
5939
|
+
{
|
|
5940
|
+
label: "Asset to receive",
|
|
5941
|
+
value: buyKey,
|
|
5942
|
+
options: buyOptions,
|
|
5943
|
+
disabled: configLoading || isLoadingData,
|
|
5944
|
+
onChange: selectBuy
|
|
5945
|
+
}
|
|
5946
|
+
),
|
|
5947
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-swap-panel-note", children: "Quoted amount" })
|
|
5948
|
+
] })
|
|
5949
|
+
] })
|
|
5950
|
+
] })
|
|
5951
|
+
] }),
|
|
5952
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-swap-custom-area", children: customOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-custom", children: [
|
|
5953
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5954
|
+
"input",
|
|
5955
|
+
{
|
|
5956
|
+
className: "pollar-input",
|
|
5957
|
+
type: "text",
|
|
5958
|
+
placeholder: "Code (e.g. USDC)",
|
|
5959
|
+
value: customCode,
|
|
5960
|
+
onChange: (e) => setCustomCode(e.target.value)
|
|
5961
|
+
}
|
|
5962
|
+
),
|
|
5963
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5964
|
+
"input",
|
|
5965
|
+
{
|
|
5966
|
+
className: "pollar-input",
|
|
5967
|
+
type: "text",
|
|
5968
|
+
placeholder: "Issuer (G...)",
|
|
5969
|
+
value: customIssuer,
|
|
5970
|
+
onChange: (e) => setCustomIssuer(e.target.value)
|
|
5971
|
+
}
|
|
5972
|
+
),
|
|
5973
|
+
customError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: customError }),
|
|
5974
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-custom-actions", children: [
|
|
5975
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: submitCustomToken, children: "Add token" }),
|
|
5976
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4551
5977
|
"button",
|
|
4552
5978
|
{
|
|
4553
5979
|
type: "button",
|
|
4554
|
-
className: "pollar-swap-custom-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
5980
|
+
className: "pollar-swap-custom-cancel",
|
|
5981
|
+
onClick: () => {
|
|
5982
|
+
setCustomOpen(false);
|
|
5983
|
+
setCustomError("");
|
|
5984
|
+
},
|
|
5985
|
+
children: "Cancel"
|
|
4558
5986
|
}
|
|
4559
5987
|
)
|
|
5988
|
+
] })
|
|
5989
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
5990
|
+
"button",
|
|
5991
|
+
{
|
|
5992
|
+
type: "button",
|
|
5993
|
+
className: "pollar-swap-custom-toggle",
|
|
5994
|
+
disabled: configLoading,
|
|
5995
|
+
onClick: () => setCustomOpen(true),
|
|
5996
|
+
children: "+ Add a token by code / issuer"
|
|
4560
5997
|
}
|
|
4561
|
-
),
|
|
4562
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-
|
|
4563
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
4564
|
-
|
|
5998
|
+
) }),
|
|
5999
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-rate-row", children: [
|
|
6000
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-swap-rate", "aria-live": "polite", children: rate && selectedSell && selectedBuy ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6001
|
+
"1 ",
|
|
6002
|
+
selectedSell.code,
|
|
6003
|
+
" \u2248 ",
|
|
6004
|
+
rate,
|
|
6005
|
+
" ",
|
|
6006
|
+
selectedBuy.code
|
|
6007
|
+
] }) : quoteLoading ? "Updating rate\u2026" : "Exchange rate unavailable" }),
|
|
6008
|
+
configLoading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-route-pill", children: [
|
|
4565
6009
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
4566
|
-
|
|
4567
|
-
] }) : /* @__PURE__ */ jsxRuntime.
|
|
4568
|
-
"
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
6010
|
+
" Loading"
|
|
6011
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-swap-route-wrap", children: [
|
|
6012
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Route" }),
|
|
6013
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6014
|
+
"select",
|
|
6015
|
+
{
|
|
6016
|
+
className: "pollar-swap-route-pill",
|
|
6017
|
+
"aria-label": "Route",
|
|
6018
|
+
value: provider,
|
|
6019
|
+
disabled: providers.length === 0,
|
|
6020
|
+
onChange: (event) => onProviderChange(event.target.value),
|
|
6021
|
+
children: providers.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: provider, children: PROVIDER_LABELS[provider] }) : providers.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p, children: PROVIDER_LABELS[p] }, p))
|
|
6022
|
+
}
|
|
6023
|
+
)
|
|
6024
|
+
] })
|
|
4581
6025
|
] }),
|
|
4582
6026
|
!quoteLoading && quoteError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: quoteError }),
|
|
4583
|
-
!quoteLoading && !quoteError && quote && selectedBuy && /* @__PURE__ */ jsxRuntime.
|
|
4584
|
-
|
|
4585
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "You receive" }),
|
|
4586
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
4587
|
-
"~ ",
|
|
4588
|
-
formatAmount3(quote.amountOut),
|
|
4589
|
-
" ",
|
|
4590
|
-
selectedBuy.code
|
|
4591
|
-
] })
|
|
4592
|
-
] }),
|
|
6027
|
+
!quoteLoading && !quoteError && !quote && selectedSell && selectedBuy && !!amount && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "No route found for this pair." }),
|
|
6028
|
+
quote && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote", children: [
|
|
4593
6029
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
4594
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
4595
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
4596
|
-
|
|
6030
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Minimum received" }),
|
|
6031
|
+
/* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
|
|
6032
|
+
formatAmount2(quote.minReceived),
|
|
4597
6033
|
" ",
|
|
4598
|
-
selectedBuy
|
|
6034
|
+
selectedBuy?.code
|
|
4599
6035
|
] })
|
|
4600
6036
|
] }),
|
|
4601
6037
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
4602
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
4603
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
6038
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Price impact" }),
|
|
6039
|
+
/* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
|
|
4604
6040
|
quote.priceImpactPct,
|
|
4605
6041
|
"%"
|
|
4606
6042
|
] })
|
|
4607
6043
|
] }),
|
|
4608
6044
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
4609
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
4610
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
6045
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Route" }),
|
|
6046
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: PROVIDER_LABELS[quote.provider] })
|
|
4611
6047
|
] })
|
|
4612
6048
|
] }),
|
|
4613
|
-
!quoteLoading && !quoteError && !quote && selectedSell && selectedBuy && !!amount && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-send-hint", children: "No route found for this pair." }),
|
|
4614
6049
|
buyNeedsTrustline && selectedBuy && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-trustline-notice", children: [
|
|
4615
6050
|
"To receive ",
|
|
4616
6051
|
selectedBuy.code,
|
|
4617
6052
|
" your wallet needs a trustline. Swapping will create it first (~0.5 XLM reserve, refundable if you later remove it)."
|
|
4618
6053
|
] }),
|
|
6054
|
+
sameAsset && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Choose two different assets to swap." }),
|
|
4619
6055
|
formError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: formError }),
|
|
4620
|
-
/* @__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" }) })
|
|
6056
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onSwap, disabled: !canSwap, children: buyNeedsTrustline ? "Create trustline & swap" : "Swap" }) })
|
|
4621
6057
|
] }),
|
|
4622
6058
|
step === "tx" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4623
6059
|
TxStatusView,
|
|
@@ -4635,7 +6071,7 @@ function SwapModalTemplate({
|
|
|
4635
6071
|
onDone
|
|
4636
6072
|
}
|
|
4637
6073
|
),
|
|
4638
|
-
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
6074
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, { shield: true })
|
|
4639
6075
|
]
|
|
4640
6076
|
}
|
|
4641
6077
|
);
|
|
@@ -4716,6 +6152,7 @@ function SwapModal({ onClose }) {
|
|
|
4716
6152
|
const balances = walletBalance.step === "loaded" ? walletBalance.data.balances : [];
|
|
4717
6153
|
const assetRecords = enabledAssets.step === "loaded" ? enabledAssets.data.assets : [];
|
|
4718
6154
|
const isLoadingData = walletBalance.step === "loading" || enabledAssets.step === "loading";
|
|
6155
|
+
const availableFor = (code, issuer) => balances.find((b) => b.code === code && (b.issuer ?? "") === (issuer ?? ""))?.available ?? void 0;
|
|
4719
6156
|
const sellOptions = balances.filter(
|
|
4720
6157
|
(b) => (b.chain === void 0 || b.chain === "STELLAR") && (b.type === "native" || (b.type === "credit_alphanum4" || b.type === "credit_alphanum12") && !b.trustlineRemoved)
|
|
4721
6158
|
).map((b) => ({
|
|
@@ -4733,6 +6170,7 @@ function SwapModal({ onClose }) {
|
|
|
4733
6170
|
ref: toRef(a),
|
|
4734
6171
|
code: a.code,
|
|
4735
6172
|
issuer: a.issuer,
|
|
6173
|
+
available: availableFor(a.code, a.issuer),
|
|
4736
6174
|
enabledInApp: a.enabledInApp
|
|
4737
6175
|
}));
|
|
4738
6176
|
const enabledKeys = new Set(enabledBuy.map(optKey));
|
|
@@ -4740,11 +6178,14 @@ function SwapModal({ onClose }) {
|
|
|
4740
6178
|
ref: catalogRef(tk.code, tk.issuer),
|
|
4741
6179
|
code: tk.code,
|
|
4742
6180
|
issuer: tk.issuer,
|
|
6181
|
+
available: availableFor(tk.code, tk.issuer),
|
|
4743
6182
|
enabledInApp: false
|
|
4744
6183
|
})).filter((o) => !enabledKeys.has(optKey(o)));
|
|
4745
6184
|
const knownKeys = /* @__PURE__ */ new Set([...enabledKeys, ...catalogBuy.map(optKey)]);
|
|
4746
|
-
const customBuy = customTokens.filter((o) => !knownKeys.has(optKey(o)));
|
|
4747
|
-
const buyOptions = [...enabledBuy, ...catalogBuy, ...customBuy].filter(
|
|
6185
|
+
const customBuy = customTokens.filter((o) => !knownKeys.has(optKey(o))).map((o) => ({ ...o, available: availableFor(o.code, o.issuer) }));
|
|
6186
|
+
const buyOptions = [...enabledBuy, ...catalogBuy, ...customBuy].filter(
|
|
6187
|
+
(o) => optKey(o) !== buyKeyOfSell || optKey(o) === (selectedBuy ? optKey(selectedBuy) : "")
|
|
6188
|
+
);
|
|
4748
6189
|
react.useEffect(() => {
|
|
4749
6190
|
if (sellOptions.length === 0) return;
|
|
4750
6191
|
if (!selectedSell || !sellOptions.some((o) => optKey(o) === optKey(selectedSell))) {
|
|
@@ -4855,6 +6296,15 @@ function SwapModal({ onClose }) {
|
|
|
4855
6296
|
async function handleRetry() {
|
|
4856
6297
|
if (transaction.step === "error" && quote) await swap(quote);
|
|
4857
6298
|
}
|
|
6299
|
+
function handleMax() {
|
|
6300
|
+
if (selectedSell?.available !== void 0) setAmount(selectedSell.available);
|
|
6301
|
+
}
|
|
6302
|
+
function handleReverse() {
|
|
6303
|
+
if (!selectedSell || !selectedBuy) return;
|
|
6304
|
+
const previousSell = selectedSell;
|
|
6305
|
+
setSelectedSell(selectedBuy);
|
|
6306
|
+
setSelectedBuy(previousSell);
|
|
6307
|
+
}
|
|
4858
6308
|
function handleCopyHash() {
|
|
4859
6309
|
if (!hash) return;
|
|
4860
6310
|
navigator.clipboard.writeText(hash).then(() => {
|
|
@@ -4907,6 +6357,8 @@ function SwapModal({ onClose }) {
|
|
|
4907
6357
|
onRefresh: handleRefresh,
|
|
4908
6358
|
onSelectSell: setSelectedSell,
|
|
4909
6359
|
onSelectBuy: setSelectedBuy,
|
|
6360
|
+
onReverse: handleReverse,
|
|
6361
|
+
onMax: handleMax,
|
|
4910
6362
|
onAddCustomToken: addCustomToken,
|
|
4911
6363
|
onAmountChange: setAmount,
|
|
4912
6364
|
onProviderChange: setProvider,
|
|
@@ -4931,7 +6383,7 @@ var IN_FLIGHT_STEPS2 = [
|
|
|
4931
6383
|
"signing-submitting",
|
|
4932
6384
|
"building-signing-submitting"
|
|
4933
6385
|
];
|
|
4934
|
-
function
|
|
6386
|
+
function formatAmount3(value) {
|
|
4935
6387
|
const n = parseFloat(value);
|
|
4936
6388
|
return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
|
|
4937
6389
|
}
|
|
@@ -5245,7 +6697,7 @@ function EarnModal({ onClose }) {
|
|
|
5245
6697
|
tab === "deposit" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
5246
6698
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "In your wallet" }),
|
|
5247
6699
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
5248
|
-
walletAvailable != null ?
|
|
6700
|
+
walletAvailable != null ? formatAmount3(walletAvailable) : "\u2026",
|
|
5249
6701
|
" ",
|
|
5250
6702
|
assetCode
|
|
5251
6703
|
] })
|
|
@@ -5253,7 +6705,7 @@ function EarnModal({ onClose }) {
|
|
|
5253
6705
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
5254
6706
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-hint", children: "Your position" }),
|
|
5255
6707
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
5256
|
-
position ?
|
|
6708
|
+
position ? formatAmount3(position.balance) : "\u2026",
|
|
5257
6709
|
" ",
|
|
5258
6710
|
assetCode
|
|
5259
6711
|
] })
|
|
@@ -5271,13 +6723,13 @@ function EarnModal({ onClose }) {
|
|
|
5271
6723
|
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-send-label", children: tab === "deposit" ? "Amount" : "Withdraw amount" }),
|
|
5272
6724
|
tab === "deposit" && walletAvailable != null && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "pollar-swap-custom-toggle", onClick: () => setAmount(walletAvailable), children: [
|
|
5273
6725
|
"Max: ",
|
|
5274
|
-
|
|
6726
|
+
formatAmount3(walletAvailable),
|
|
5275
6727
|
" ",
|
|
5276
6728
|
amountUnitLabel
|
|
5277
6729
|
] }),
|
|
5278
6730
|
tab === "withdraw" && position && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "pollar-swap-custom-toggle", onClick: () => setAmount(position.withdrawable), children: [
|
|
5279
6731
|
"Max: ",
|
|
5280
|
-
|
|
6732
|
+
formatAmount3(position.withdrawable),
|
|
5281
6733
|
" ",
|
|
5282
6734
|
amountUnitLabel
|
|
5283
6735
|
] })
|
|
@@ -5327,10 +6779,15 @@ function EarnModal({ onClose }) {
|
|
|
5327
6779
|
) });
|
|
5328
6780
|
}
|
|
5329
6781
|
function describeDevice(s) {
|
|
5330
|
-
if (s.deviceLabel) return s.deviceLabel;
|
|
6782
|
+
if (s.deviceLabel) return normalizeDeviceLabel(s.deviceLabel);
|
|
5331
6783
|
if (!s.userAgent) return "Unknown device";
|
|
5332
6784
|
return parseUserAgent(s.userAgent);
|
|
5333
6785
|
}
|
|
6786
|
+
function normalizeDeviceLabel(label) {
|
|
6787
|
+
const parts = label.replace(/\s+/g, " ").split(/ (?:[—–-]|·) /);
|
|
6788
|
+
if (parts.length === 2 && parts[1] !== void 0) return `${parts[0]} \xB7 ${parts[1].toLowerCase()}`;
|
|
6789
|
+
return label;
|
|
6790
|
+
}
|
|
5334
6791
|
function detectBrowser(ua) {
|
|
5335
6792
|
if (/Edg\//.test(ua)) return "Edge";
|
|
5336
6793
|
if (/OPR\//.test(ua)) return "Opera";
|
|
@@ -5350,7 +6807,7 @@ function detectOS(ua) {
|
|
|
5350
6807
|
function parseUserAgent(ua) {
|
|
5351
6808
|
const browser = detectBrowser(ua);
|
|
5352
6809
|
const os = detectOS(ua);
|
|
5353
|
-
if (browser && os) return `${os} \
|
|
6810
|
+
if (browser && os) return `${os} \xB7 ${browser.toLowerCase()}`;
|
|
5354
6811
|
if (os) return os;
|
|
5355
6812
|
if (browser) return browser;
|
|
5356
6813
|
return ua.slice(0, 48);
|
|
@@ -5374,6 +6831,37 @@ function shortIp(hash) {
|
|
|
5374
6831
|
if (!hash) return "";
|
|
5375
6832
|
return hash.slice(0, 8);
|
|
5376
6833
|
}
|
|
6834
|
+
function deviceKind(session) {
|
|
6835
|
+
const value = `${session.deviceLabel ?? ""} ${session.userAgent ?? ""}`.toLowerCase();
|
|
6836
|
+
if (/ipad|tablet/.test(value)) return "tablet";
|
|
6837
|
+
if (/android|iphone|ipod|mobile|phone/.test(value)) return "phone";
|
|
6838
|
+
return "desktop";
|
|
6839
|
+
}
|
|
6840
|
+
function DeviceIcon({ kind, size = "small" }) {
|
|
6841
|
+
const dimensions = size === "large" ? 30 : 18;
|
|
6842
|
+
if (kind === "phone") {
|
|
6843
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: dimensions, height: dimensions, viewBox: "0 0 24 24", fill: "none", "aria-hidden": true, children: [
|
|
6844
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "7", y: "2.5", width: "10", height: "19", rx: "2.5", stroke: "currentColor", strokeWidth: "1.8" }),
|
|
6845
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10.5 5h3M11 18.5h2", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" })
|
|
6846
|
+
] });
|
|
6847
|
+
}
|
|
6848
|
+
if (kind === "tablet") {
|
|
6849
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: dimensions, height: dimensions, viewBox: "0 0 24 24", fill: "none", "aria-hidden": true, children: [
|
|
6850
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4.5", y: "2.5", width: "15", height: "19", rx: "2", stroke: "currentColor", strokeWidth: "1.8" }),
|
|
6851
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M11 18.5h2", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" })
|
|
6852
|
+
] });
|
|
6853
|
+
}
|
|
6854
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: dimensions, height: dimensions, viewBox: "0 0 24 24", fill: "none", "aria-hidden": true, children: [
|
|
6855
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3.5", width: "18", height: "12", rx: "1.8", stroke: "currentColor", strokeWidth: "1.8" }),
|
|
6856
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 20.5h8M12 15.5v5", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })
|
|
6857
|
+
] });
|
|
6858
|
+
}
|
|
6859
|
+
function CheckIcon() {
|
|
6860
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m2.5 6.2 2.1 2.1L9.6 3.6", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
6861
|
+
}
|
|
6862
|
+
function CloseIcon() {
|
|
6863
|
+
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m3 3 8 8M11 3l-8 8", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round" }) });
|
|
6864
|
+
}
|
|
5377
6865
|
function SessionsModalTemplate({
|
|
5378
6866
|
theme,
|
|
5379
6867
|
accentColor,
|
|
@@ -5381,6 +6869,7 @@ function SessionsModalTemplate({
|
|
|
5381
6869
|
state,
|
|
5382
6870
|
revokingFamilyId,
|
|
5383
6871
|
signingOutEverywhere,
|
|
6872
|
+
revokeError,
|
|
5384
6873
|
onRefresh,
|
|
5385
6874
|
onRevoke,
|
|
5386
6875
|
onLogoutEverywhere,
|
|
@@ -5389,7 +6878,9 @@ function SessionsModalTemplate({
|
|
|
5389
6878
|
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
|
|
5390
6879
|
const isLoading = state.step === "loading";
|
|
5391
6880
|
const sessions = state.step === "loaded" ? state.sessions : [];
|
|
5392
|
-
const
|
|
6881
|
+
const currentSession = sessions.find((s) => s.current);
|
|
6882
|
+
const otherSessions = sessions.filter((s) => !s.current);
|
|
6883
|
+
const otherCount = otherSessions.length;
|
|
5393
6884
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5394
6885
|
"div",
|
|
5395
6886
|
{
|
|
@@ -5410,30 +6901,10 @@ function SessionsModalTemplate({
|
|
|
5410
6901
|
disabled: isLoading,
|
|
5411
6902
|
"aria-label": "Refresh",
|
|
5412
6903
|
title: "Refresh",
|
|
5413
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5414
|
-
"svg",
|
|
5415
|
-
{
|
|
5416
|
-
className: isLoading ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
|
|
5417
|
-
width: "16",
|
|
5418
|
-
height: "16",
|
|
5419
|
-
viewBox: "0 0 16 16",
|
|
5420
|
-
fill: "none",
|
|
5421
|
-
"aria-hidden": true,
|
|
5422
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5423
|
-
"path",
|
|
5424
|
-
{
|
|
5425
|
-
d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
|
|
5426
|
-
stroke: "currentColor",
|
|
5427
|
-
strokeWidth: "1.6",
|
|
5428
|
-
strokeLinecap: "round",
|
|
5429
|
-
strokeLinejoin: "round"
|
|
5430
|
-
}
|
|
5431
|
-
)
|
|
5432
|
-
}
|
|
5433
|
-
)
|
|
6904
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(RefreshIcon, { spinning: isLoading })
|
|
5434
6905
|
}
|
|
5435
6906
|
),
|
|
5436
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close",
|
|
6907
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", title: "Close", children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {}) })
|
|
5437
6908
|
] })
|
|
5438
6909
|
] }),
|
|
5439
6910
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-sessions-list", children: [
|
|
@@ -5443,40 +6914,54 @@ function SessionsModalTemplate({
|
|
|
5443
6914
|
] }),
|
|
5444
6915
|
state.step === "error" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: state.message }),
|
|
5445
6916
|
state.step === "loaded" && sessions.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "No active sessions." }),
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
"ip ",
|
|
5462
|
-
shortIp(s.ipHash)
|
|
5463
|
-
] })
|
|
6917
|
+
state.step === "loaded" && currentSession && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-sessions-current-card", children: [
|
|
6918
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-sessions-current-icon-wrap", children: [
|
|
6919
|
+
/* @__PURE__ */ jsxRuntime.jsx(DeviceIcon, { kind: deviceKind(currentSession), size: "large" }),
|
|
6920
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-sessions-current-check", children: /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) })
|
|
6921
|
+
] }),
|
|
6922
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-sessions-current-label", children: "This device" }),
|
|
6923
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { className: "pollar-sessions-current-device", children: describeDevice(currentSession) }),
|
|
6924
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-sessions-current-status", children: [
|
|
6925
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-sessions-status-dot" }),
|
|
6926
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Active now" }),
|
|
6927
|
+
currentSession.ipHash && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6928
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "\xB7" }),
|
|
6929
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { title: `ip-hash ${currentSession.ipHash}`, children: [
|
|
6930
|
+
"IP ",
|
|
6931
|
+
shortIp(currentSession.ipHash)
|
|
5464
6932
|
] })
|
|
5465
|
-
] })
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
6933
|
+
] })
|
|
6934
|
+
] })
|
|
6935
|
+
] }),
|
|
6936
|
+
state.step === "loaded" && otherSessions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "pollar-sessions-other-section", "aria-labelledby": "pollar-other-devices-heading", children: [
|
|
6937
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h3", { id: "pollar-other-devices-heading", className: "pollar-sessions-section-title", children: [
|
|
6938
|
+
"Other devices ",
|
|
6939
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: otherCount })
|
|
6940
|
+
] }),
|
|
6941
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-sessions-grid", children: otherSessions.map((s) => {
|
|
6942
|
+
const isRevoking = revokingFamilyId === s.familyId;
|
|
6943
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-sessions-item", children: [
|
|
6944
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-sessions-item-top", children: [
|
|
6945
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-sessions-item-icon", children: /* @__PURE__ */ jsxRuntime.jsx(DeviceIcon, { kind: deviceKind(s) }) }),
|
|
6946
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6947
|
+
"button",
|
|
6948
|
+
{
|
|
6949
|
+
type: "button",
|
|
6950
|
+
className: "pollar-sessions-item-revoke",
|
|
6951
|
+
onClick: () => onRevoke(s.familyId),
|
|
6952
|
+
disabled: isRevoking || signingOutEverywhere,
|
|
6953
|
+
"aria-label": `Sign out ${describeDevice(s)}`,
|
|
6954
|
+
title: isRevoking ? "Signing out\u2026" : "Sign out this device",
|
|
6955
|
+
children: isRevoking ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-spinner pollar-spinner-sm" }) : /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {})
|
|
6956
|
+
}
|
|
6957
|
+
)
|
|
6958
|
+
] }),
|
|
6959
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { className: "pollar-sessions-item-device", children: describeDevice(s) }),
|
|
6960
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-sessions-item-meta", children: formatRelative(s.lastUsedAt ?? s.createdAt) })
|
|
6961
|
+
] }, s.familyId);
|
|
6962
|
+
}) })
|
|
6963
|
+
] }),
|
|
6964
|
+
revokeError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-sessions-action-error", role: "alert", children: revokeError })
|
|
5480
6965
|
] }),
|
|
5481
6966
|
state.step === "loaded" && sessions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-sessions-actions", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5482
6967
|
"button",
|
|
@@ -5501,6 +6986,7 @@ function SessionsModal({ onClose }) {
|
|
|
5501
6986
|
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
5502
6987
|
const [revokingFamilyId, setRevokingFamilyId] = react.useState(null);
|
|
5503
6988
|
const [signingOutEverywhere, setSigningOutEverywhere] = react.useState(false);
|
|
6989
|
+
const [revokeError, setRevokeError] = react.useState(null);
|
|
5504
6990
|
const load = react.useCallback(() => {
|
|
5505
6991
|
void getClient().fetchSessions();
|
|
5506
6992
|
}, [getClient]);
|
|
@@ -5517,9 +7003,11 @@ function SessionsModal({ onClose }) {
|
|
|
5517
7003
|
const handleRevoke = react.useCallback(
|
|
5518
7004
|
async (familyId) => {
|
|
5519
7005
|
setRevokingFamilyId(familyId);
|
|
7006
|
+
setRevokeError(null);
|
|
5520
7007
|
try {
|
|
5521
7008
|
await getClient().revokeSession(familyId);
|
|
5522
7009
|
} catch {
|
|
7010
|
+
setRevokeError("Could not sign out that device. Please try again.");
|
|
5523
7011
|
} finally {
|
|
5524
7012
|
setRevokingFamilyId(null);
|
|
5525
7013
|
load();
|
|
@@ -5545,6 +7033,7 @@ function SessionsModal({ onClose }) {
|
|
|
5545
7033
|
state: sessions,
|
|
5546
7034
|
revokingFamilyId,
|
|
5547
7035
|
signingOutEverywhere,
|
|
7036
|
+
revokeError,
|
|
5548
7037
|
onRefresh: () => load(),
|
|
5549
7038
|
onRevoke: (familyId) => void handleRevoke(familyId),
|
|
5550
7039
|
onLogoutEverywhere: () => void handleLogoutEverywhere(),
|
|
@@ -5939,14 +7428,32 @@ function faucetFor(record) {
|
|
|
5939
7428
|
if (record.code === "USDC") return { url: "https://faucet.circle.com/", label: "Get test USDC" };
|
|
5940
7429
|
return null;
|
|
5941
7430
|
}
|
|
5942
|
-
function
|
|
7431
|
+
function assetMetadataFor(record, metadata) {
|
|
7432
|
+
return metadata.find(
|
|
7433
|
+
(asset) => resolveChain(asset.chain) === resolveChain(record.chain) && asset.code === record.code && (asset.issuer ?? "") === (record.issuer ?? "")
|
|
7434
|
+
);
|
|
7435
|
+
}
|
|
7436
|
+
function AssetIcon3({ code }) {
|
|
7437
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-bal-asset-icon", "aria-hidden": true, children: code.slice(0, 2).toUpperCase() });
|
|
7438
|
+
}
|
|
7439
|
+
function BalanceItem({
|
|
7440
|
+
record,
|
|
7441
|
+
faucet,
|
|
7442
|
+
metadata
|
|
7443
|
+
}) {
|
|
5943
7444
|
const balanceDiffers = record.balance !== record.available;
|
|
7445
|
+
const secondary = metadata?.name ?? (record.issuer ? cropAddress(record.issuer) : "Native asset");
|
|
5944
7446
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-bal-item", children: [
|
|
5945
7447
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-bal-asset-info", children: [
|
|
5946
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5947
|
-
|
|
5948
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5949
|
-
|
|
7448
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-bal-asset-leading", children: [
|
|
7449
|
+
/* @__PURE__ */ jsxRuntime.jsx(AssetIcon3, { code: record.code }),
|
|
7450
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-bal-asset-copy", children: [
|
|
7451
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-bal-asset", children: record.code }),
|
|
7452
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-bal-asset-secondary", children: [
|
|
7453
|
+
secondary,
|
|
7454
|
+
record.issuer && /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: record.issuer, label: "Copy issuer address", className: "pollar-copy-btn-sm" })
|
|
7455
|
+
] })
|
|
7456
|
+
] })
|
|
5950
7457
|
] }),
|
|
5951
7458
|
faucet && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-bal-faucet-hint", children: [
|
|
5952
7459
|
"Need more?",
|
|
@@ -5970,6 +7477,7 @@ function WalletBalanceModalTemplate({
|
|
|
5970
7477
|
styleOverrides,
|
|
5971
7478
|
walletBalance,
|
|
5972
7479
|
walletAddress,
|
|
7480
|
+
assetMetadata = [],
|
|
5973
7481
|
chains,
|
|
5974
7482
|
selectedChain,
|
|
5975
7483
|
network,
|
|
@@ -5996,33 +7504,13 @@ function WalletBalanceModalTemplate({
|
|
|
5996
7504
|
disabled: isLoading,
|
|
5997
7505
|
"aria-label": "Refresh",
|
|
5998
7506
|
title: "Refresh",
|
|
5999
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6000
|
-
"svg",
|
|
6001
|
-
{
|
|
6002
|
-
className: isLoading ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
|
|
6003
|
-
width: "16",
|
|
6004
|
-
height: "16",
|
|
6005
|
-
viewBox: "0 0 16 16",
|
|
6006
|
-
fill: "none",
|
|
6007
|
-
"aria-hidden": true,
|
|
6008
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6009
|
-
"path",
|
|
6010
|
-
{
|
|
6011
|
-
d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
|
|
6012
|
-
stroke: "currentColor",
|
|
6013
|
-
strokeWidth: "1.6",
|
|
6014
|
-
strokeLinecap: "round",
|
|
6015
|
-
strokeLinejoin: "round"
|
|
6016
|
-
}
|
|
6017
|
-
)
|
|
6018
|
-
}
|
|
6019
|
-
)
|
|
7507
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(RefreshIcon, { spinning: isLoading })
|
|
6020
7508
|
}
|
|
6021
7509
|
),
|
|
6022
|
-
/* @__PURE__ */ jsxRuntime.jsx("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" }) }) })
|
|
7510
|
+
/* @__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" }) }) })
|
|
6023
7511
|
] })
|
|
6024
7512
|
] }),
|
|
6025
|
-
/* @__PURE__ */ jsxRuntime.jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain, disabled: isLoading }),
|
|
7513
|
+
chains && onSelectChain && /* @__PURE__ */ jsxRuntime.jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain, disabled: isLoading }),
|
|
6026
7514
|
walletAddress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-address-row", children: [
|
|
6027
7515
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-address", children: cropAddress(walletAddress) }),
|
|
6028
7516
|
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: walletAddress, label: "Copy wallet address" })
|
|
@@ -6042,6 +7530,7 @@ function WalletBalanceModalTemplate({
|
|
|
6042
7530
|
BalanceItem,
|
|
6043
7531
|
{
|
|
6044
7532
|
record: b,
|
|
7533
|
+
metadata: assetMetadataFor(b, assetMetadata),
|
|
6045
7534
|
faucet: showFaucets ? faucetFor(b) : null
|
|
6046
7535
|
},
|
|
6047
7536
|
(b.chain ?? "") + b.code + (b.issuer ?? "")
|
|
@@ -6050,7 +7539,7 @@ function WalletBalanceModalTemplate({
|
|
|
6050
7539
|
] });
|
|
6051
7540
|
}
|
|
6052
7541
|
function WalletBalanceModal({ onClose }) {
|
|
6053
|
-
const { walletBalance, refreshWalletBalance, wallets, network, styles } = usePollar();
|
|
7542
|
+
const { walletBalance, refreshWalletBalance, wallets, network, styles, enabledAssets } = usePollar();
|
|
6054
7543
|
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
6055
7544
|
const { chains } = useChains();
|
|
6056
7545
|
const [selectedChain, setSelectedChain] = react.useState(null);
|
|
@@ -6069,6 +7558,7 @@ function WalletBalanceModal({ onClose }) {
|
|
|
6069
7558
|
styleOverrides,
|
|
6070
7559
|
walletBalance,
|
|
6071
7560
|
walletAddress,
|
|
7561
|
+
assetMetadata: enabledAssets.step === "loaded" ? enabledAssets.data.assets : [],
|
|
6072
7562
|
chains,
|
|
6073
7563
|
selectedChain,
|
|
6074
7564
|
network,
|
|
@@ -6138,7 +7628,11 @@ var DEFAULT_APP_CONFIG = {
|
|
|
6138
7628
|
function sessionsEqual(a, b) {
|
|
6139
7629
|
if (a === b) return true;
|
|
6140
7630
|
if (!a || !b) return false;
|
|
6141
|
-
return a.clientSessionId === b.clientSessionId && a.userId === b.userId && a.status === b.status && a.token?.accessToken === b.token?.accessToken && a.token?.refreshToken === b.token?.refreshToken && a.token?.expiresAt === b.token?.expiresAt && a.wallet?.address === b.wallet?.address
|
|
7631
|
+
return a.clientSessionId === b.clientSessionId && a.userId === b.userId && a.status === b.status && a.token?.accessToken === b.token?.accessToken && a.token?.refreshToken === b.token?.refreshToken && a.token?.expiresAt === b.token?.expiresAt && a.wallet?.address === b.wallet?.address && // The wallet's on-chain account can move from CREATING to READY without any
|
|
7632
|
+
// other field changing. Leaving it out of the comparison is what would make
|
|
7633
|
+
// the whole provisioning UI dead: the short-circuit below would swallow the
|
|
7634
|
+
// one emission that says the wait is over.
|
|
7635
|
+
a.wallet?.provisioning === b.wallet?.provisioning;
|
|
6142
7636
|
}
|
|
6143
7637
|
var PollarContext = react.createContext(null);
|
|
6144
7638
|
var clientByConfig = /* @__PURE__ */ new WeakMap();
|
|
@@ -6304,6 +7798,7 @@ function PollarProvider({
|
|
|
6304
7798
|
const [sessionsModalOpen, setSessionsModalOpen] = react.useState(false);
|
|
6305
7799
|
const [distributionRulesModalOpen, setDistributionRulesModalOpen] = react.useState(false);
|
|
6306
7800
|
const walletAddress = sessionState?.wallet?.address || "";
|
|
7801
|
+
const walletProvisioning = sessionState?.wallet?.provisioning;
|
|
6307
7802
|
const getClient = react.useCallback(() => pollarClient, [pollarClient]);
|
|
6308
7803
|
const refreshWalletBalance = react.useCallback(() => pollarClient.refreshBalance(), [pollarClient, walletAddress]);
|
|
6309
7804
|
const refreshAssets = react.useCallback(() => pollarClient.refreshAssets(), [pollarClient, walletAddress]);
|
|
@@ -6395,6 +7890,7 @@ function PollarProvider({
|
|
|
6395
7890
|
};
|
|
6396
7891
|
}, [
|
|
6397
7892
|
walletAddress,
|
|
7893
|
+
walletProvisioning,
|
|
6398
7894
|
verified,
|
|
6399
7895
|
pollarClient,
|
|
6400
7896
|
getClient,
|
|
@@ -6415,11 +7911,24 @@ function PollarProvider({
|
|
|
6415
7911
|
children,
|
|
6416
7912
|
loginModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setLoginModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(LoginModal, { onClose: () => setLoginModalOpen(false) }) }),
|
|
6417
7913
|
transactionModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setTransactionModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(TransactionModal, { onClose: () => setTransactionModalOpen(false) }) }),
|
|
6418
|
-
kycModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setKycModalOpen(false), children:
|
|
7914
|
+
kycModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setKycModalOpen(false), children: kycModalOptions.corridorId === void 0 && kycModalOptions.providerId === void 0 ? (
|
|
7915
|
+
// The app's own KYC: its configured steps, in order.
|
|
7916
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7917
|
+
AppKycFlow,
|
|
7918
|
+
{
|
|
7919
|
+
onClose: () => setKycModalOpen(false),
|
|
7920
|
+
...kycModalOptions.country !== void 0 && { country: kycModalOptions.country },
|
|
7921
|
+
...kycModalOptions.level !== void 0 && { level: kycModalOptions.level },
|
|
7922
|
+
...kycModalOptions.onApproved !== void 0 && { onApproved: kycModalOptions.onApproved }
|
|
7923
|
+
}
|
|
7924
|
+
)
|
|
7925
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
6419
7926
|
KycModal,
|
|
6420
7927
|
{
|
|
6421
7928
|
onClose: () => setKycModalOpen(false),
|
|
6422
7929
|
...kycModalOptions.country !== void 0 && { country: kycModalOptions.country },
|
|
7930
|
+
...kycModalOptions.corridorId !== void 0 && { corridorId: kycModalOptions.corridorId },
|
|
7931
|
+
...kycModalOptions.providerId !== void 0 && { providerId: kycModalOptions.providerId },
|
|
6423
7932
|
...kycModalOptions.level !== void 0 && { level: kycModalOptions.level },
|
|
6424
7933
|
...kycModalOptions.onApproved !== void 0 && { onApproved: kycModalOptions.onApproved }
|
|
6425
7934
|
}
|
|
@@ -6481,6 +7990,7 @@ function WalletButtonTemplate({
|
|
|
6481
7990
|
wrapperRef,
|
|
6482
7991
|
isInProgress,
|
|
6483
7992
|
showCreateAccount,
|
|
7993
|
+
notReadyReason,
|
|
6484
7994
|
creatingAccount,
|
|
6485
7995
|
onToggleOpen,
|
|
6486
7996
|
onCreateAccount,
|
|
@@ -6545,6 +8055,10 @@ function WalletButtonTemplate({
|
|
|
6545
8055
|
}
|
|
6546
8056
|
),
|
|
6547
8057
|
open && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-wallet-dropdown", style: { backgroundColor: dropdownBg, borderColor: dropdownBorder }, children: [
|
|
8058
|
+
notReadyReason && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8059
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-wallet-dropdown-notice", style: { color: itemColor }, role: "status", children: notReadyReason }),
|
|
8060
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-wallet-dropdown-divider" })
|
|
8061
|
+
] }),
|
|
6548
8062
|
showCreateAccount && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6549
8063
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6550
8064
|
"button",
|
|
@@ -6814,7 +8328,7 @@ function WalletButton() {
|
|
|
6814
8328
|
openDistributionRulesModal,
|
|
6815
8329
|
tx: transaction
|
|
6816
8330
|
} = usePollar();
|
|
6817
|
-
const { primaryAddress } = useChains();
|
|
8331
|
+
const { primaryChain, primaryAddress } = useChains();
|
|
6818
8332
|
const walletAddress = primaryAddress || (wallet?.address ?? "");
|
|
6819
8333
|
const [open, setOpen] = react.useState(false);
|
|
6820
8334
|
const [copied, setCopied] = react.useState(false);
|
|
@@ -6824,6 +8338,7 @@ function WalletButton() {
|
|
|
6824
8338
|
const copyTimerRef = react.useRef(null);
|
|
6825
8339
|
const isInProgress = transaction.step === "building" || transaction.step === "signing";
|
|
6826
8340
|
const canCreateAccount = !created && wallet?.custody === "external" && wallet.existsOnStellar === false && wallet.fundingMode === "IMMEDIATE";
|
|
8341
|
+
const notReadyReason = walletNotReadyReason(wallet, primaryChain);
|
|
6827
8342
|
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
6828
8343
|
const isDark = theme === "dark";
|
|
6829
8344
|
const dropdownBg = isDark ? "#18181b" : "#fff";
|
|
@@ -6917,6 +8432,7 @@ function WalletButton() {
|
|
|
6917
8432
|
wrapperRef,
|
|
6918
8433
|
isInProgress,
|
|
6919
8434
|
showCreateAccount: canCreateAccount,
|
|
8435
|
+
notReadyReason,
|
|
6920
8436
|
creatingAccount: creating,
|
|
6921
8437
|
onToggleOpen: () => setOpen((v) => !v),
|
|
6922
8438
|
onCreateAccount: handleCreateAccount,
|
|
@@ -6946,10 +8462,13 @@ exports.KycModalTemplate = KycModalTemplate;
|
|
|
6946
8462
|
exports.KycStatus = KycStatus;
|
|
6947
8463
|
exports.LoginModalTemplate = LoginModalTemplate;
|
|
6948
8464
|
exports.PollarProvider = PollarProvider;
|
|
8465
|
+
exports.ProviderRegistrationModal = ProviderRegistrationModal;
|
|
6949
8466
|
exports.RampWidget = RampWidget;
|
|
6950
8467
|
exports.RampWidgetTemplate = RampWidgetTemplate;
|
|
6951
8468
|
exports.ReceiveModal = ReceiveModal;
|
|
6952
8469
|
exports.ReceiveModalTemplate = ReceiveModalTemplate;
|
|
8470
|
+
exports.RegistryCheckModal = RegistryCheckModal;
|
|
8471
|
+
exports.RequirementFormModal = RequirementFormModal;
|
|
6953
8472
|
exports.RouteDisplay = RouteDisplay;
|
|
6954
8473
|
exports.SendModal = SendModal;
|
|
6955
8474
|
exports.SendModalTemplate = SendModalTemplate;
|
|
@@ -6975,5 +8494,6 @@ exports.readableTextOn = readableTextOn;
|
|
|
6975
8494
|
exports.resolveChain = resolveChain;
|
|
6976
8495
|
exports.useChains = useChains;
|
|
6977
8496
|
exports.usePollar = usePollar;
|
|
8497
|
+
exports.walletNotReadyReason = walletNotReadyReason;
|
|
6978
8498
|
//# sourceMappingURL=index.js.map
|
|
6979
8499
|
//# sourceMappingURL=index.js.map
|