@pollar/react 0.10.0-rc.0 → 0.10.0-rc.10
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/README.md +23 -47
- package/dist/index.css +40 -11
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +92 -64
- package/dist/index.d.ts +92 -64
- package/dist/index.js +869 -243
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +869 -245
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { AUTH_ERROR_CODES, WalletType, PollarClient } from '@pollar/core';
|
|
2
|
+
import { AUTH_ERROR_CODES, WalletType, PollarClient, isInteractiveAuthAdapter } from '@pollar/core';
|
|
3
3
|
import { forwardRef, createContext, useState, useCallback, useEffect, useRef, useMemo, useContext, Component } from 'react';
|
|
4
4
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { startAuthentication, startRegistration } from '@simplewebauthn/browser';
|
|
@@ -1033,7 +1033,7 @@ var PollarModalFooter = () => {
|
|
|
1033
1033
|
/* @__PURE__ */ jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
|
|
1034
1034
|
/* @__PURE__ */ jsxs("span", { className: "pollar-footer-version", children: [
|
|
1035
1035
|
"v",
|
|
1036
|
-
"0.10.0-rc.
|
|
1036
|
+
"0.10.0-rc.10"
|
|
1037
1037
|
] })
|
|
1038
1038
|
] })
|
|
1039
1039
|
] });
|
|
@@ -1850,35 +1850,42 @@ var GoogleButton = ({ disabled, onClick }) => {
|
|
|
1850
1850
|
] })
|
|
1851
1851
|
] });
|
|
1852
1852
|
};
|
|
1853
|
-
function
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
onClick: () => onConnect(WalletType.FREIGHTER),
|
|
1862
|
-
children: [
|
|
1863
|
-
/* @__PURE__ */ jsx("img", { src: LOGO_FREIGHTER, alt: "Freighter", className: "pollar-wallet-list-icon" }),
|
|
1864
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-wallet-list-name", children: "Freighter" })
|
|
1865
|
-
]
|
|
1866
|
-
}
|
|
1867
|
-
),
|
|
1868
|
-
/* @__PURE__ */ jsxs(
|
|
1853
|
+
function WalletAdapterButtons({
|
|
1854
|
+
walletAdapters,
|
|
1855
|
+
onConnect,
|
|
1856
|
+
isLoading,
|
|
1857
|
+
variant = "list"
|
|
1858
|
+
}) {
|
|
1859
|
+
if (variant === "entry") {
|
|
1860
|
+
return /* @__PURE__ */ jsx(Fragment, { children: walletAdapters.map((a) => /* @__PURE__ */ jsxs(
|
|
1869
1861
|
"button",
|
|
1870
1862
|
{
|
|
1871
1863
|
type: "button",
|
|
1872
1864
|
disabled: isLoading,
|
|
1873
|
-
className: "pollar-wallet-
|
|
1874
|
-
onClick: () => onConnect(
|
|
1865
|
+
className: "pollar-wallet-entry-btn",
|
|
1866
|
+
onClick: () => onConnect(a.id),
|
|
1875
1867
|
children: [
|
|
1876
|
-
/* @__PURE__ */ jsx("img", { src:
|
|
1877
|
-
|
|
1868
|
+
a.meta.iconUrl && /* @__PURE__ */ jsx("img", { src: a.meta.iconUrl, alt: a.meta.label, className: "pollar-wallet-icon" }),
|
|
1869
|
+
a.meta.label
|
|
1878
1870
|
]
|
|
1879
|
-
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1871
|
+
},
|
|
1872
|
+
a.id
|
|
1873
|
+
)) });
|
|
1874
|
+
}
|
|
1875
|
+
return /* @__PURE__ */ jsx("div", { className: "pollar-wallet-list", children: walletAdapters.map((a) => /* @__PURE__ */ jsxs(
|
|
1876
|
+
"button",
|
|
1877
|
+
{
|
|
1878
|
+
type: "button",
|
|
1879
|
+
disabled: isLoading,
|
|
1880
|
+
className: "pollar-wallet-list-btn",
|
|
1881
|
+
onClick: () => onConnect(a.id),
|
|
1882
|
+
children: [
|
|
1883
|
+
a.meta.iconUrl && /* @__PURE__ */ jsx("img", { src: a.meta.iconUrl, alt: a.meta.label, className: "pollar-wallet-list-icon" }),
|
|
1884
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-wallet-list-name", children: a.meta.label })
|
|
1885
|
+
]
|
|
1886
|
+
},
|
|
1887
|
+
a.id
|
|
1888
|
+
)) });
|
|
1882
1889
|
}
|
|
1883
1890
|
var AUTH_STATE_MESSAGES = {
|
|
1884
1891
|
idle: "",
|
|
@@ -1926,17 +1933,15 @@ function LoginModalTemplate({
|
|
|
1926
1933
|
embeddedWallets,
|
|
1927
1934
|
smartWallet = false,
|
|
1928
1935
|
providers,
|
|
1929
|
-
|
|
1936
|
+
walletAdapters,
|
|
1930
1937
|
appName,
|
|
1931
1938
|
email = "",
|
|
1932
1939
|
onEmailChange,
|
|
1933
1940
|
onEmailSubmit,
|
|
1934
1941
|
onSocialLogin,
|
|
1935
|
-
onCustomLogin,
|
|
1936
1942
|
onWalletConnect,
|
|
1937
1943
|
onLoginSmartWallet,
|
|
1938
1944
|
onCreateSmartWallet,
|
|
1939
|
-
renderWallets,
|
|
1940
1945
|
authState,
|
|
1941
1946
|
codeInputKey,
|
|
1942
1947
|
onCodeSubmit,
|
|
@@ -1944,10 +1949,19 @@ function LoginModalTemplate({
|
|
|
1944
1949
|
onCancel,
|
|
1945
1950
|
onRetry
|
|
1946
1951
|
}) {
|
|
1947
|
-
const [showWalletPicker, setShowWalletPicker] = useState(false);
|
|
1948
1952
|
const [showPasskeyChooser, setShowPasskeyChooser] = useState(false);
|
|
1953
|
+
const [activeGroup, setActiveGroup] = useState(null);
|
|
1949
1954
|
const isDark = theme === "dark";
|
|
1950
1955
|
const enabledSocial = Object.entries(providers).filter(([, enabled]) => enabled);
|
|
1956
|
+
const rootAdapters = walletAdapters.filter((a) => !a.meta.group);
|
|
1957
|
+
const walletGroups = walletAdapters.filter((a) => a.meta.group).reduce((acc, a) => {
|
|
1958
|
+
const label = a.meta.group;
|
|
1959
|
+
const existing = acc.find((g) => g.label === label);
|
|
1960
|
+
if (existing) existing.adapters.push(a);
|
|
1961
|
+
else acc.push({ label, adapters: [a] });
|
|
1962
|
+
return acc;
|
|
1963
|
+
}, []);
|
|
1964
|
+
const activeGroupAdapters = walletGroups.find((g) => g.label === activeGroup)?.adapters ?? [];
|
|
1951
1965
|
const cssVars = {
|
|
1952
1966
|
"--pollar-accent": accentColor,
|
|
1953
1967
|
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
@@ -2011,11 +2025,17 @@ function LoginModalTemplate({
|
|
|
2011
2025
|
/* @__PURE__ */ jsx(BackButton, { onClick: onBack }),
|
|
2012
2026
|
/* @__PURE__ */ jsx(EmailCodeInput, { email, onSubmit: onCodeSubmit ?? (() => {
|
|
2013
2027
|
}) }, codeInputKey)
|
|
2014
|
-
] }) :
|
|
2015
|
-
/* @__PURE__ */ jsx(BackButton, { onClick: () =>
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2028
|
+
] }) : activeGroup ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2029
|
+
/* @__PURE__ */ jsx(BackButton, { onClick: () => setActiveGroup(null) }),
|
|
2030
|
+
/* @__PURE__ */ jsx(
|
|
2031
|
+
WalletAdapterButtons,
|
|
2032
|
+
{
|
|
2033
|
+
walletAdapters: activeGroupAdapters,
|
|
2034
|
+
onConnect: onWalletConnect ?? (() => {
|
|
2035
|
+
}),
|
|
2036
|
+
isLoading
|
|
2037
|
+
}
|
|
2038
|
+
)
|
|
2019
2039
|
] }) : showPasskeyChooser ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2020
2040
|
/* @__PURE__ */ jsx(BackButton, { onClick: () => setShowPasskeyChooser(false) }),
|
|
2021
2041
|
/* @__PURE__ */ jsxs("div", { className: "pollar-wallet-section", children: [
|
|
@@ -2048,7 +2068,7 @@ function LoginModalTemplate({
|
|
|
2048
2068
|
}
|
|
2049
2069
|
)
|
|
2050
2070
|
] }),
|
|
2051
|
-
emailEnabled &&
|
|
2071
|
+
emailEnabled && enabledSocial.length > 0 && /* @__PURE__ */ jsxs("div", { className: "pollar-divider", children: [
|
|
2052
2072
|
/* @__PURE__ */ jsx("div", { className: "pollar-divider-line" }),
|
|
2053
2073
|
/* @__PURE__ */ jsx("div", { className: "pollar-divider-label", children: /* @__PURE__ */ jsx("span", { className: "pollar-divider-text", children: "or continue with" }) })
|
|
2054
2074
|
] }),
|
|
@@ -2056,47 +2076,46 @@ function LoginModalTemplate({
|
|
|
2056
2076
|
enabledSocial.some(([key]) => key === "google") && /* @__PURE__ */ jsx(GoogleButton, { disabled: isLoading, onClick: () => onSocialLogin?.("google") }),
|
|
2057
2077
|
enabledSocial.some(([key]) => key === "github") && /* @__PURE__ */ jsx(GithubButton, { disabled: isLoading, onClick: () => onSocialLogin?.("github") })
|
|
2058
2078
|
] }),
|
|
2059
|
-
customProviders.length > 0 && /* @__PURE__ */ jsx("div", { className: "pollar-social-list", children: customProviders.map((p) => /* @__PURE__ */ jsxs(
|
|
2060
|
-
"button",
|
|
2061
|
-
{
|
|
2062
|
-
type: "button",
|
|
2063
|
-
disabled: isLoading,
|
|
2064
|
-
className: "pollar-wallet-entry-btn",
|
|
2065
|
-
onClick: () => onCustomLogin?.(p.id),
|
|
2066
|
-
children: [
|
|
2067
|
-
p.iconUrl && /* @__PURE__ */ jsx("img", { src: p.iconUrl, alt: "", className: "pollar-wallet-list-icon" }),
|
|
2068
|
-
p.label
|
|
2069
|
-
]
|
|
2070
|
-
},
|
|
2071
|
-
p.id
|
|
2072
|
-
)) }),
|
|
2073
2079
|
(embeddedWallets || smartWallet) && /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-section", children: [
|
|
2074
|
-
embeddedWallets && /* @__PURE__ */ jsxs(
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2080
|
+
embeddedWallets && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2081
|
+
walletGroups.map((g) => /* @__PURE__ */ jsxs(
|
|
2082
|
+
"button",
|
|
2083
|
+
{
|
|
2084
|
+
type: "button",
|
|
2085
|
+
disabled: isLoading,
|
|
2086
|
+
className: "pollar-wallet-entry-btn",
|
|
2087
|
+
onClick: () => setActiveGroup(g.label),
|
|
2088
|
+
children: [
|
|
2089
|
+
/* @__PURE__ */ jsx(
|
|
2090
|
+
"svg",
|
|
2091
|
+
{
|
|
2092
|
+
width: "18",
|
|
2093
|
+
height: "20",
|
|
2094
|
+
viewBox: "0 0 24 24",
|
|
2095
|
+
fill: "none",
|
|
2096
|
+
stroke: "currentColor",
|
|
2097
|
+
strokeWidth: "2",
|
|
2098
|
+
strokeLinecap: "round",
|
|
2099
|
+
strokeLinejoin: "round",
|
|
2100
|
+
children: /* @__PURE__ */ jsx("path", { d: "M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" })
|
|
2101
|
+
}
|
|
2102
|
+
),
|
|
2103
|
+
g.label
|
|
2104
|
+
]
|
|
2105
|
+
},
|
|
2106
|
+
g.label
|
|
2107
|
+
)),
|
|
2108
|
+
rootAdapters.length > 0 && /* @__PURE__ */ jsx(
|
|
2109
|
+
WalletAdapterButtons,
|
|
2110
|
+
{
|
|
2111
|
+
walletAdapters: rootAdapters,
|
|
2112
|
+
onConnect: onWalletConnect ?? (() => {
|
|
2113
|
+
}),
|
|
2114
|
+
isLoading,
|
|
2115
|
+
variant: "entry"
|
|
2116
|
+
}
|
|
2117
|
+
)
|
|
2118
|
+
] }),
|
|
2100
2119
|
smartWallet && /* @__PURE__ */ jsxs(
|
|
2101
2120
|
"button",
|
|
2102
2121
|
{
|
|
@@ -2137,12 +2156,142 @@ function LoginModalTemplate({
|
|
|
2137
2156
|
/* @__PURE__ */ jsx(PollarModalFooter, {})
|
|
2138
2157
|
] });
|
|
2139
2158
|
}
|
|
2159
|
+
function PrivyLoginSubmodal({
|
|
2160
|
+
adapter,
|
|
2161
|
+
theme,
|
|
2162
|
+
accentColor,
|
|
2163
|
+
logoUrl,
|
|
2164
|
+
appName,
|
|
2165
|
+
onBack,
|
|
2166
|
+
onCancel,
|
|
2167
|
+
onAuthenticated
|
|
2168
|
+
}) {
|
|
2169
|
+
const options = useMemo(() => adapter.getAuthOptions(), [adapter]);
|
|
2170
|
+
const [email, setEmail] = useState("");
|
|
2171
|
+
const [view, setView] = useState("root");
|
|
2172
|
+
const [status, setStatus] = useState("NONE");
|
|
2173
|
+
const [message, setMessage] = useState("");
|
|
2174
|
+
const isDark = theme === "dark";
|
|
2175
|
+
const isLoading = status === "LOADING";
|
|
2176
|
+
const cssVars = {
|
|
2177
|
+
"--pollar-accent": accentColor,
|
|
2178
|
+
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
2179
|
+
"--pollar-border": isDark ? "#374151" : "#e5e7eb",
|
|
2180
|
+
"--pollar-text": isDark ? "#ffffff" : "#111827",
|
|
2181
|
+
"--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
|
|
2182
|
+
"--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
|
|
2183
|
+
"--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
|
|
2184
|
+
"--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
|
|
2185
|
+
"--pollar-error-text": isDark ? "#f87171" : "#dc2626",
|
|
2186
|
+
"--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
|
|
2187
|
+
"--pollar-buttons-border-radius": "6px",
|
|
2188
|
+
"--pollar-buttons-height": "44px",
|
|
2189
|
+
"--pollar-input-height": "44px",
|
|
2190
|
+
"--pollar-input-border-radius": "0.5rem",
|
|
2191
|
+
"--pollar-card-border-radius": "10px",
|
|
2192
|
+
"--pollar-modal-padding": "2rem",
|
|
2193
|
+
"--pollar-modal-heading-size": "1.375rem",
|
|
2194
|
+
"--pollar-modal-subtitle-size": "0.9rem"
|
|
2195
|
+
};
|
|
2196
|
+
function fail(error) {
|
|
2197
|
+
setStatus("ERROR");
|
|
2198
|
+
setMessage(error instanceof Error ? error.message : "Something went wrong. Please try again.");
|
|
2199
|
+
}
|
|
2200
|
+
async function handleEmailSubmit() {
|
|
2201
|
+
if (!email) return;
|
|
2202
|
+
setStatus("LOADING");
|
|
2203
|
+
setMessage("");
|
|
2204
|
+
try {
|
|
2205
|
+
await adapter.sendEmailCode(email);
|
|
2206
|
+
setStatus("SUCCESS");
|
|
2207
|
+
setMessage("Code sent \u2014 check your inbox");
|
|
2208
|
+
setView("email-code");
|
|
2209
|
+
} catch (error) {
|
|
2210
|
+
fail(error);
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
async function handleCodeSubmit(code) {
|
|
2214
|
+
setStatus("LOADING");
|
|
2215
|
+
setMessage("Verifying\u2026");
|
|
2216
|
+
try {
|
|
2217
|
+
await adapter.verifyEmailCode(code);
|
|
2218
|
+
onAuthenticated();
|
|
2219
|
+
} catch (error) {
|
|
2220
|
+
fail(error);
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
async function handleOAuth(provider) {
|
|
2224
|
+
setStatus("LOADING");
|
|
2225
|
+
setMessage("");
|
|
2226
|
+
try {
|
|
2227
|
+
await adapter.loginWithOAuth(provider);
|
|
2228
|
+
onAuthenticated();
|
|
2229
|
+
} catch (error) {
|
|
2230
|
+
fail(error);
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
const BackButton = ({ onClick }) => /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-back-btn", onClick, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M15 19l-7-7 7-7" }) }) });
|
|
2234
|
+
const showEmail = options.includes("email");
|
|
2235
|
+
const showGoogle = options.includes("google");
|
|
2236
|
+
const showGithub = options.includes("github");
|
|
2237
|
+
return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
|
|
2238
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-close-btn", onClick: onCancel, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" }) }) }),
|
|
2239
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-header", children: [
|
|
2240
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsx("img", { src: logoUrl ?? LOGO_POLLAR, alt: "Logo", className: "pollar-logo" }) }),
|
|
2241
|
+
/* @__PURE__ */ jsx("h2", { className: "pollar-title", children: appName }),
|
|
2242
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-subtitle", children: adapter.meta.label })
|
|
2243
|
+
] }),
|
|
2244
|
+
view === "email-code" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2245
|
+
/* @__PURE__ */ jsx(BackButton, { onClick: () => setView("root") }),
|
|
2246
|
+
/* @__PURE__ */ jsx(EmailCodeInput, { email, onSubmit: handleCodeSubmit })
|
|
2247
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2248
|
+
/* @__PURE__ */ jsx(BackButton, { onClick: onBack }),
|
|
2249
|
+
showEmail && /* @__PURE__ */ jsxs("div", { className: "pollar-email-section", children: [
|
|
2250
|
+
/* @__PURE__ */ jsx(
|
|
2251
|
+
"input",
|
|
2252
|
+
{
|
|
2253
|
+
type: "email",
|
|
2254
|
+
placeholder: "you@email.com",
|
|
2255
|
+
value: email,
|
|
2256
|
+
disabled: isLoading,
|
|
2257
|
+
className: "pollar-email-input",
|
|
2258
|
+
onChange: (e) => setEmail(e.target.value),
|
|
2259
|
+
onKeyDown: (e) => e.key === "Enter" && handleEmailSubmit()
|
|
2260
|
+
}
|
|
2261
|
+
),
|
|
2262
|
+
/* @__PURE__ */ jsx(
|
|
2263
|
+
"button",
|
|
2264
|
+
{
|
|
2265
|
+
type: "button",
|
|
2266
|
+
disabled: isLoading || !email,
|
|
2267
|
+
className: "pollar-btn-primary",
|
|
2268
|
+
style: { marginTop: "0.75rem" },
|
|
2269
|
+
onClick: handleEmailSubmit,
|
|
2270
|
+
children: "Submit"
|
|
2271
|
+
}
|
|
2272
|
+
)
|
|
2273
|
+
] }),
|
|
2274
|
+
showEmail && (showGoogle || showGithub) && /* @__PURE__ */ jsxs("div", { className: "pollar-divider", children: [
|
|
2275
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-divider-line" }),
|
|
2276
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-divider-label", children: /* @__PURE__ */ jsx("span", { className: "pollar-divider-text", children: "or continue with" }) })
|
|
2277
|
+
] }),
|
|
2278
|
+
(showGoogle || showGithub) && /* @__PURE__ */ jsxs("div", { className: "pollar-social-list", children: [
|
|
2279
|
+
showGoogle && /* @__PURE__ */ jsx(GoogleButton, { disabled: isLoading, onClick: () => handleOAuth("google") }),
|
|
2280
|
+
showGithub && /* @__PURE__ */ jsx(GithubButton, { disabled: isLoading, onClick: () => handleOAuth("github") })
|
|
2281
|
+
] })
|
|
2282
|
+
] }),
|
|
2283
|
+
/* @__PURE__ */ jsx(ModalStatusBanner, { message, status, onCancel, onRetry: void 0 }),
|
|
2284
|
+
/* @__PURE__ */ jsx(PollarModalFooter, {})
|
|
2285
|
+
] });
|
|
2286
|
+
}
|
|
2140
2287
|
function LoginModal({ onClose }) {
|
|
2141
2288
|
const [email, setEmail] = useState("");
|
|
2142
|
-
const { getClient, styles, appConfig: config
|
|
2289
|
+
const { getClient, styles, appConfig: config } = usePollar();
|
|
2143
2290
|
const [authState, setAuthState] = useState(() => getClient().getAuthState());
|
|
2291
|
+
const walletAdapters = useMemo(() => getClient().listWalletAdapters(), [getClient]);
|
|
2144
2292
|
const [codeInputKey, setCodeInputKey] = useState(0);
|
|
2145
2293
|
const pendingEmail = useRef(null);
|
|
2294
|
+
const [interactiveAdapter, setInteractiveAdapter] = useState(null);
|
|
2146
2295
|
const onCloseRef = useRef(onClose);
|
|
2147
2296
|
onCloseRef.current = onClose;
|
|
2148
2297
|
const autoCloseTimer = useRef(null);
|
|
@@ -2189,11 +2338,13 @@ function LoginModal({ onClose }) {
|
|
|
2189
2338
|
function handleSocialLogin(provider) {
|
|
2190
2339
|
getClient().login({ provider });
|
|
2191
2340
|
}
|
|
2192
|
-
function handleCustomLogin(id) {
|
|
2193
|
-
getClient().login({ provider: id });
|
|
2194
|
-
}
|
|
2195
2341
|
function handleWalletConnect(type) {
|
|
2196
|
-
getClient().
|
|
2342
|
+
const adapter = getClient().getWalletAdapter(type);
|
|
2343
|
+
if (isInteractiveAuthAdapter(adapter)) {
|
|
2344
|
+
setInteractiveAdapter(adapter);
|
|
2345
|
+
return;
|
|
2346
|
+
}
|
|
2347
|
+
getClient().login({ provider: type });
|
|
2197
2348
|
}
|
|
2198
2349
|
function handleLoginSmartWallet() {
|
|
2199
2350
|
getClient().loginSmartWallet();
|
|
@@ -2214,7 +2365,26 @@ function LoginModal({ onClose }) {
|
|
|
2214
2365
|
getClient().beginEmailLogin();
|
|
2215
2366
|
}
|
|
2216
2367
|
}
|
|
2217
|
-
|
|
2368
|
+
function handleInteractiveAuthenticated() {
|
|
2369
|
+
const provider = interactiveAdapter?.type;
|
|
2370
|
+
setInteractiveAdapter(null);
|
|
2371
|
+
if (provider) {
|
|
2372
|
+
getClient().login({ provider });
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: handleClose, children: interactiveAdapter ? /* @__PURE__ */ jsx(
|
|
2376
|
+
PrivyLoginSubmodal,
|
|
2377
|
+
{
|
|
2378
|
+
adapter: interactiveAdapter,
|
|
2379
|
+
theme,
|
|
2380
|
+
accentColor,
|
|
2381
|
+
logoUrl: logoUrl ?? null,
|
|
2382
|
+
appName: config.application?.name ?? "Pollar",
|
|
2383
|
+
onBack: () => setInteractiveAdapter(null),
|
|
2384
|
+
onCancel: handleClose,
|
|
2385
|
+
onAuthenticated: handleInteractiveAuthenticated
|
|
2386
|
+
}
|
|
2387
|
+
) : /* @__PURE__ */ jsx(
|
|
2218
2388
|
LoginModalTemplate,
|
|
2219
2389
|
{
|
|
2220
2390
|
theme,
|
|
@@ -2230,17 +2400,15 @@ function LoginModal({ onClose }) {
|
|
|
2230
2400
|
github: !!providers?.github,
|
|
2231
2401
|
apple: !!providers?.apple
|
|
2232
2402
|
},
|
|
2233
|
-
|
|
2403
|
+
walletAdapters,
|
|
2234
2404
|
appName: config.application?.name ?? "Pollar",
|
|
2235
2405
|
email,
|
|
2236
2406
|
onEmailChange: setEmail,
|
|
2237
2407
|
onEmailSubmit: handleEmailSubmit,
|
|
2238
2408
|
onSocialLogin: handleSocialLogin,
|
|
2239
|
-
onCustomLogin: handleCustomLogin,
|
|
2240
2409
|
onWalletConnect: handleWalletConnect,
|
|
2241
2410
|
onLoginSmartWallet: handleLoginSmartWallet,
|
|
2242
2411
|
onCreateSmartWallet: handleCreateSmartWallet,
|
|
2243
|
-
...renderWallets !== void 0 && { renderWallets },
|
|
2244
2412
|
authState,
|
|
2245
2413
|
codeInputKey,
|
|
2246
2414
|
onCodeSubmit: handleVerifyCode,
|
|
@@ -2297,6 +2465,12 @@ var COUNTRY_CURRENCIES = {
|
|
|
2297
2465
|
PE: "PEN",
|
|
2298
2466
|
AR: "ARS"
|
|
2299
2467
|
};
|
|
2468
|
+
var STATUS_LABEL = {
|
|
2469
|
+
pending: "Pending",
|
|
2470
|
+
processing: "Processing",
|
|
2471
|
+
completed: "Completed",
|
|
2472
|
+
failed: "Failed"
|
|
2473
|
+
};
|
|
2300
2474
|
function RampWidgetTemplate({
|
|
2301
2475
|
theme,
|
|
2302
2476
|
accentColor,
|
|
@@ -2306,15 +2480,23 @@ function RampWidgetTemplate({
|
|
|
2306
2480
|
currency,
|
|
2307
2481
|
country,
|
|
2308
2482
|
quotes,
|
|
2309
|
-
paymentInstructions,
|
|
2310
2483
|
isLoading,
|
|
2484
|
+
provider,
|
|
2485
|
+
txStatus,
|
|
2486
|
+
kycUrl,
|
|
2487
|
+
stellarTxHash,
|
|
2488
|
+
canComplete,
|
|
2489
|
+
completing,
|
|
2490
|
+
errorMsg,
|
|
2311
2491
|
onDirectionChange,
|
|
2312
2492
|
onAmountChange,
|
|
2313
2493
|
onCurrencyChange,
|
|
2314
2494
|
onCountryChange,
|
|
2315
2495
|
onFindRoute,
|
|
2316
2496
|
onSelectQuote,
|
|
2317
|
-
|
|
2497
|
+
onOpenKyc,
|
|
2498
|
+
onCompleteWithdraw,
|
|
2499
|
+
onRetry,
|
|
2318
2500
|
onClose
|
|
2319
2501
|
}) {
|
|
2320
2502
|
const isDark = theme === "dark";
|
|
@@ -2342,13 +2524,15 @@ function RampWidgetTemplate({
|
|
|
2342
2524
|
input: direction === "onramp" ? "Buy crypto" : "Sell crypto",
|
|
2343
2525
|
loading_quote: "Finding best route",
|
|
2344
2526
|
select_route: "Select provider",
|
|
2345
|
-
|
|
2527
|
+
status: direction === "onramp" ? "Complete your deposit" : "Complete your withdrawal",
|
|
2528
|
+
error: "Something went wrong"
|
|
2346
2529
|
};
|
|
2347
2530
|
const stepSubtitle = {
|
|
2348
2531
|
input: direction === "onramp" ? "Enter the amount you want to deposit" : "Enter the amount you want to withdraw",
|
|
2349
2532
|
loading_quote: "Comparing providers in real time\u2026",
|
|
2350
2533
|
select_route: "All prices include fees",
|
|
2351
|
-
|
|
2534
|
+
status: `Finish the flow at ${provider || "the provider"} to continue`,
|
|
2535
|
+
error: "Please try again"
|
|
2352
2536
|
};
|
|
2353
2537
|
return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-ramp-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
|
|
2354
2538
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-header", children: [
|
|
@@ -2444,183 +2628,183 @@ function RampWidgetTemplate({
|
|
|
2444
2628
|
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-route-list", children: quotes.map((q, i) => /* @__PURE__ */ jsx(RouteDisplay, { quote: q, onSelect: onSelectQuote }, i)) }),
|
|
2445
2629
|
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" })
|
|
2446
2630
|
] }),
|
|
2447
|
-
step === "
|
|
2448
|
-
/* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-title", children: paymentInstructions.type }),
|
|
2631
|
+
step === "status" && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment", children: [
|
|
2449
2632
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2450
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children:
|
|
2451
|
-
/* @__PURE__ */
|
|
2452
|
-
/* @__PURE__ */ jsx("code", { children: paymentInstructions.value }),
|
|
2453
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-ramp-copy-btn", onClick: () => onCopy(paymentInstructions.value), children: "Copy" })
|
|
2454
|
-
] })
|
|
2633
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Provider" }),
|
|
2634
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsx("code", { children: provider }) })
|
|
2455
2635
|
] }),
|
|
2456
2636
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2457
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "
|
|
2458
|
-
/* @__PURE__ */
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
" ",
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
"button",
|
|
2466
|
-
{
|
|
2467
|
-
type: "button",
|
|
2468
|
-
className: "pollar-ramp-copy-btn",
|
|
2469
|
-
onClick: () => onCopy(`${paymentInstructions.amount} ${paymentInstructions.currency}`),
|
|
2470
|
-
children: "Copy"
|
|
2471
|
-
}
|
|
2472
|
-
)
|
|
2473
|
-
] })
|
|
2637
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Status" }),
|
|
2638
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsx(
|
|
2639
|
+
"code",
|
|
2640
|
+
{
|
|
2641
|
+
style: { color: txStatus === "completed" ? "var(--pollar-success-text)" : void 0 },
|
|
2642
|
+
children: txStatus ? STATUS_LABEL[txStatus] : "Processing"
|
|
2643
|
+
}
|
|
2644
|
+
) })
|
|
2474
2645
|
] }),
|
|
2475
|
-
|
|
2476
|
-
"
|
|
2477
|
-
|
|
2646
|
+
stellarTxHash && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2647
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Stellar tx" }),
|
|
2648
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsxs("code", { children: [
|
|
2649
|
+
stellarTxHash.slice(0, 8),
|
|
2650
|
+
"\u2026",
|
|
2651
|
+
stellarTxHash.slice(-8)
|
|
2652
|
+
] }) })
|
|
2478
2653
|
] }),
|
|
2479
|
-
/* @__PURE__ */
|
|
2654
|
+
kycUrl && txStatus !== "completed" && /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenKyc, children: [
|
|
2655
|
+
"Continue at ",
|
|
2656
|
+
provider
|
|
2657
|
+
] }),
|
|
2658
|
+
canComplete && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", disabled: completing, onClick: onCompleteWithdraw, children: completing ? "Submitting\u2026" : "I've completed KYC \u2014 withdraw" }),
|
|
2659
|
+
errorMsg && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", style: { color: "var(--pollar-error-text)" }, children: errorMsg }),
|
|
2660
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: txStatus === "completed" ? "Done" : "Close" })
|
|
2661
|
+
] }),
|
|
2662
|
+
step === "error" && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment", children: [
|
|
2663
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", style: { color: "var(--pollar-error-text)" }, children: errorMsg ?? "Unexpected error." }),
|
|
2664
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-modal-actions", children: [
|
|
2665
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Close" }),
|
|
2666
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onRetry, children: "Try again" })
|
|
2667
|
+
] })
|
|
2480
2668
|
] })
|
|
2481
2669
|
] });
|
|
2482
2670
|
}
|
|
2483
|
-
var
|
|
2484
|
-
{
|
|
2485
|
-
quoteId: "meld-default",
|
|
2486
|
-
provider: "Meld",
|
|
2487
|
-
fee: 1.2,
|
|
2488
|
-
feeCurrency: "USD",
|
|
2489
|
-
rate: 1,
|
|
2490
|
-
rail: "ACH",
|
|
2491
|
-
protocol: "REST",
|
|
2492
|
-
estimatedTime: "~20 min",
|
|
2493
|
-
recommended: true
|
|
2494
|
-
}
|
|
2495
|
-
];
|
|
2496
|
-
var MOCK_QUOTES = {
|
|
2497
|
-
MX: [
|
|
2498
|
-
{
|
|
2499
|
-
quoteId: "etherfuse-mx",
|
|
2500
|
-
provider: "Etherfuse",
|
|
2501
|
-
fee: 0.5,
|
|
2502
|
-
feeCurrency: "MXN",
|
|
2503
|
-
rate: 17.2,
|
|
2504
|
-
rail: "SPEI",
|
|
2505
|
-
protocol: "SEP-24",
|
|
2506
|
-
estimatedTime: "~10 min",
|
|
2507
|
-
recommended: true
|
|
2508
|
-
},
|
|
2509
|
-
{
|
|
2510
|
-
quoteId: "alfredpay-mx",
|
|
2511
|
-
provider: "AlfredPay",
|
|
2512
|
-
fee: 0.8,
|
|
2513
|
-
feeCurrency: "MXN",
|
|
2514
|
-
rate: 17.1,
|
|
2515
|
-
rail: "SPEI",
|
|
2516
|
-
protocol: "REST",
|
|
2517
|
-
estimatedTime: "~15 min",
|
|
2518
|
-
recommended: false
|
|
2519
|
-
}
|
|
2520
|
-
],
|
|
2521
|
-
BR: [
|
|
2522
|
-
{
|
|
2523
|
-
quoteId: "abroad-br",
|
|
2524
|
-
provider: "Abroad",
|
|
2525
|
-
fee: 0.6,
|
|
2526
|
-
feeCurrency: "BRL",
|
|
2527
|
-
rate: 5.1,
|
|
2528
|
-
rail: "PIX",
|
|
2529
|
-
protocol: "REST",
|
|
2530
|
-
estimatedTime: "~5 min",
|
|
2531
|
-
recommended: true
|
|
2532
|
-
}
|
|
2533
|
-
],
|
|
2534
|
-
CO: [
|
|
2535
|
-
{
|
|
2536
|
-
quoteId: "abroad-co",
|
|
2537
|
-
provider: "Abroad",
|
|
2538
|
-
fee: 0.7,
|
|
2539
|
-
feeCurrency: "COP",
|
|
2540
|
-
rate: 4100,
|
|
2541
|
-
rail: "PSE",
|
|
2542
|
-
protocol: "REST",
|
|
2543
|
-
estimatedTime: "~10 min",
|
|
2544
|
-
recommended: true
|
|
2545
|
-
},
|
|
2546
|
-
{
|
|
2547
|
-
quoteId: "koywe-co",
|
|
2548
|
-
provider: "Koywe",
|
|
2549
|
-
fee: 0.9,
|
|
2550
|
-
feeCurrency: "COP",
|
|
2551
|
-
rate: 4095,
|
|
2552
|
-
rail: "PSE",
|
|
2553
|
-
protocol: "REST",
|
|
2554
|
-
estimatedTime: "~15 min",
|
|
2555
|
-
recommended: false
|
|
2556
|
-
}
|
|
2557
|
-
],
|
|
2558
|
-
DEFAULT: MOCK_DEFAULT_QUOTES
|
|
2559
|
-
};
|
|
2560
|
-
var MOCK_PAYMENT = {
|
|
2561
|
-
type: "CLABE",
|
|
2562
|
-
value: "646180157088723456",
|
|
2563
|
-
amount: 1e3,
|
|
2564
|
-
currency: "MXN",
|
|
2565
|
-
expiresAt: new Date(Date.now() + 30 * 60 * 1e3).toISOString()
|
|
2566
|
-
};
|
|
2671
|
+
var TERMINAL = ["completed", "failed"];
|
|
2567
2672
|
function RampWidget({ onClose }) {
|
|
2568
|
-
const { getClient, wallet, styles } = usePollar();
|
|
2673
|
+
const { getClient, signTx, wallet, styles } = usePollar();
|
|
2569
2674
|
const walletAddress = wallet?.address ?? "";
|
|
2675
|
+
const client = getClient();
|
|
2676
|
+
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
2570
2677
|
const [step, setStep] = useState("input");
|
|
2571
2678
|
const [direction, setDirection] = useState("onramp");
|
|
2572
2679
|
const [amount, setAmount] = useState("");
|
|
2573
|
-
const [currency, setCurrency] = useState("
|
|
2574
|
-
const [country, setCountry] = useState("
|
|
2680
|
+
const [currency, setCurrency] = useState("ARS");
|
|
2681
|
+
const [country, setCountry] = useState("AR");
|
|
2575
2682
|
const [quotes, setQuotes] = useState([]);
|
|
2576
|
-
const [paymentInstructions, setPaymentInstructions] = useState(null);
|
|
2577
2683
|
const [isLoading, setIsLoading] = useState(false);
|
|
2578
|
-
const
|
|
2579
|
-
const
|
|
2684
|
+
const [txId, setTxId] = useState(null);
|
|
2685
|
+
const [provider, setProvider] = useState("");
|
|
2686
|
+
const [kycUrl, setKycUrl] = useState(null);
|
|
2687
|
+
const [txStatus, setTxStatus] = useState(null);
|
|
2688
|
+
const [stellarTxHash, setStellarTxHash] = useState(null);
|
|
2689
|
+
const [completing, setCompleting] = useState(false);
|
|
2690
|
+
const [errorMsg, setErrorMsg] = useState(null);
|
|
2691
|
+
const directionRef = useRef(direction);
|
|
2692
|
+
directionRef.current = direction;
|
|
2693
|
+
useEffect(() => {
|
|
2694
|
+
if (step !== "status" || !txId) return;
|
|
2695
|
+
if (txStatus && TERMINAL.includes(txStatus)) return;
|
|
2696
|
+
let active = true;
|
|
2697
|
+
const id = setInterval(async () => {
|
|
2698
|
+
try {
|
|
2699
|
+
const tx = await client.getRampTransaction(txId);
|
|
2700
|
+
if (!active) return;
|
|
2701
|
+
setTxStatus(tx.status);
|
|
2702
|
+
if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
|
|
2703
|
+
if (tx.kycUrl) setKycUrl(tx.kycUrl);
|
|
2704
|
+
if (TERMINAL.includes(tx.status)) clearInterval(id);
|
|
2705
|
+
} catch {
|
|
2706
|
+
}
|
|
2707
|
+
}, 5e3);
|
|
2708
|
+
return () => {
|
|
2709
|
+
active = false;
|
|
2710
|
+
clearInterval(id);
|
|
2711
|
+
};
|
|
2712
|
+
}, [step, txId, txStatus, client]);
|
|
2713
|
+
function resetToInput() {
|
|
2714
|
+
setStep("input");
|
|
2715
|
+
setQuotes([]);
|
|
2716
|
+
setTxId(null);
|
|
2717
|
+
setProvider("");
|
|
2718
|
+
setKycUrl(null);
|
|
2719
|
+
setTxStatus(null);
|
|
2720
|
+
setStellarTxHash(null);
|
|
2721
|
+
setErrorMsg(null);
|
|
2722
|
+
}
|
|
2723
|
+
async function resumeWithSignature(id, ps) {
|
|
2724
|
+
const outcome = await signTx(ps.unsignedXdr);
|
|
2725
|
+
if (outcome.status !== "signed") {
|
|
2726
|
+
setErrorMsg(outcome.message ?? outcome.details ?? "Signing was cancelled.");
|
|
2727
|
+
setStep("error");
|
|
2728
|
+
return;
|
|
2729
|
+
}
|
|
2730
|
+
const result = await client.submitRampSignature(id, {
|
|
2731
|
+
signedXdr: outcome.signedXdr,
|
|
2732
|
+
action: ps.action
|
|
2733
|
+
});
|
|
2734
|
+
await applyResult(result);
|
|
2735
|
+
}
|
|
2736
|
+
async function applyResult(result) {
|
|
2737
|
+
setTxId(result.txId);
|
|
2738
|
+
setProvider(result.provider);
|
|
2739
|
+
if (result.pendingSignature) {
|
|
2740
|
+
await resumeWithSignature(result.txId, result.pendingSignature);
|
|
2741
|
+
return;
|
|
2742
|
+
}
|
|
2743
|
+
setKycUrl(result.kycUrl ?? null);
|
|
2744
|
+
setTxStatus(result.status);
|
|
2745
|
+
setStellarTxHash(result.stellarTxHash ?? null);
|
|
2746
|
+
setStep("status");
|
|
2747
|
+
}
|
|
2580
2748
|
async function handleFindRoute() {
|
|
2581
2749
|
setStep("loading_quote");
|
|
2582
2750
|
setIsLoading(true);
|
|
2751
|
+
setErrorMsg(null);
|
|
2583
2752
|
try {
|
|
2584
|
-
const result = await client.getRampsQuote({
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2753
|
+
const result = await client.getRampsQuote({ country, amount: Number(amount), currency, direction });
|
|
2754
|
+
const list = result.quotes ?? [];
|
|
2755
|
+
if (list.length === 0) {
|
|
2756
|
+
setErrorMsg(`No ramp providers available for ${country} yet.`);
|
|
2757
|
+
setStep("error");
|
|
2758
|
+
return;
|
|
2759
|
+
}
|
|
2760
|
+
setQuotes(list);
|
|
2761
|
+
setStep("select_route");
|
|
2762
|
+
} catch (e) {
|
|
2763
|
+
setErrorMsg(e instanceof Error ? e.message : "Failed to fetch quotes.");
|
|
2764
|
+
setStep("error");
|
|
2594
2765
|
} finally {
|
|
2595
2766
|
setIsLoading(false);
|
|
2596
|
-
setStep("select_route");
|
|
2597
2767
|
}
|
|
2598
2768
|
}
|
|
2599
2769
|
async function handleSelectQuote(quote) {
|
|
2600
|
-
if (!walletAddress) return;
|
|
2601
2770
|
setIsLoading(true);
|
|
2602
|
-
|
|
2603
|
-
quoteId: `${quote.provider}-${Date.now()}`,
|
|
2604
|
-
amount: Number(amount),
|
|
2605
|
-
currency,
|
|
2606
|
-
country,
|
|
2607
|
-
walletAddress
|
|
2608
|
-
};
|
|
2771
|
+
setErrorMsg(null);
|
|
2609
2772
|
try {
|
|
2610
|
-
const
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2773
|
+
const base = { quoteId: quote.quoteId, amount: Number(amount), currency, country };
|
|
2774
|
+
const result = direction === "onramp" ? await client.createOnRamp({ ...base, ...walletAddress ? { walletAddress } : {} }) : await client.createOffRamp({ ...base, ...walletAddress ? { walletAddress } : {} });
|
|
2775
|
+
await applyResult(result);
|
|
2776
|
+
} catch (e) {
|
|
2777
|
+
setErrorMsg(e instanceof Error ? e.message : "Failed to start the ramp.");
|
|
2778
|
+
setStep("error");
|
|
2615
2779
|
} finally {
|
|
2616
2780
|
setIsLoading(false);
|
|
2617
|
-
setStep("payment_instructions");
|
|
2618
2781
|
}
|
|
2619
2782
|
}
|
|
2620
|
-
function
|
|
2621
|
-
|
|
2622
|
-
|
|
2783
|
+
function handleOpenKyc() {
|
|
2784
|
+
if (kycUrl) window.open(kycUrl, "_blank", "noopener,noreferrer");
|
|
2785
|
+
}
|
|
2786
|
+
async function handleCompleteWithdraw() {
|
|
2787
|
+
if (!txId) return;
|
|
2788
|
+
setCompleting(true);
|
|
2789
|
+
setErrorMsg(null);
|
|
2790
|
+
try {
|
|
2791
|
+
const result = await client.completeWithdraw(txId);
|
|
2792
|
+
if (result.pendingSignature) {
|
|
2793
|
+
await resumeWithSignature(txId, result.pendingSignature);
|
|
2794
|
+
return;
|
|
2795
|
+
}
|
|
2796
|
+
setTxStatus(result.status);
|
|
2797
|
+
setStellarTxHash(result.stellarTxHash ?? null);
|
|
2798
|
+
} catch (e) {
|
|
2799
|
+
const msg = e instanceof Error ? e.message : "";
|
|
2800
|
+
setErrorMsg(
|
|
2801
|
+
msg.includes("KYC") ? "Finish KYC at the provider first, then try again." : msg || "Failed to complete the withdrawal."
|
|
2802
|
+
);
|
|
2803
|
+
} finally {
|
|
2804
|
+
setCompleting(false);
|
|
2805
|
+
}
|
|
2623
2806
|
}
|
|
2807
|
+
const canComplete = direction === "offramp" && step === "status" && txStatus !== "completed" && !stellarTxHash;
|
|
2624
2808
|
return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsx(
|
|
2625
2809
|
RampWidgetTemplate,
|
|
2626
2810
|
{
|
|
@@ -2632,15 +2816,23 @@ function RampWidget({ onClose }) {
|
|
|
2632
2816
|
currency,
|
|
2633
2817
|
country,
|
|
2634
2818
|
quotes,
|
|
2635
|
-
paymentInstructions,
|
|
2636
2819
|
isLoading,
|
|
2820
|
+
provider,
|
|
2821
|
+
txStatus,
|
|
2822
|
+
kycUrl,
|
|
2823
|
+
stellarTxHash,
|
|
2824
|
+
canComplete,
|
|
2825
|
+
completing,
|
|
2826
|
+
errorMsg,
|
|
2637
2827
|
onDirectionChange: setDirection,
|
|
2638
2828
|
onAmountChange: setAmount,
|
|
2639
2829
|
onCurrencyChange: setCurrency,
|
|
2640
2830
|
onCountryChange: setCountry,
|
|
2641
2831
|
onFindRoute: handleFindRoute,
|
|
2642
2832
|
onSelectQuote: handleSelectQuote,
|
|
2643
|
-
|
|
2833
|
+
onOpenKyc: handleOpenKyc,
|
|
2834
|
+
onCompleteWithdraw: handleCompleteWithdraw,
|
|
2835
|
+
onRetry: resetToInput,
|
|
2644
2836
|
onClose
|
|
2645
2837
|
}
|
|
2646
2838
|
) });
|
|
@@ -3304,6 +3496,415 @@ function SendModal({ onClose }) {
|
|
|
3304
3496
|
}
|
|
3305
3497
|
) });
|
|
3306
3498
|
}
|
|
3499
|
+
function assetOptionKey(o) {
|
|
3500
|
+
return `${o.code}:${o.issuer ?? "native"}`;
|
|
3501
|
+
}
|
|
3502
|
+
var PROVIDER_LABELS = {
|
|
3503
|
+
auto: "Best price (auto)",
|
|
3504
|
+
aquarius: "Aquarius",
|
|
3505
|
+
soroswap: "Soroswap",
|
|
3506
|
+
sdex: "Stellar DEX"
|
|
3507
|
+
};
|
|
3508
|
+
var IMPLEMENTED_PROVIDERS = ["auto", "aquarius"];
|
|
3509
|
+
function formatAmount2(value) {
|
|
3510
|
+
const n = parseFloat(value);
|
|
3511
|
+
return isNaN(n) ? value : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
|
|
3512
|
+
}
|
|
3513
|
+
function SwapModalTemplate({
|
|
3514
|
+
theme,
|
|
3515
|
+
accentColor,
|
|
3516
|
+
step,
|
|
3517
|
+
txTitle,
|
|
3518
|
+
sellOptions,
|
|
3519
|
+
buyOptions,
|
|
3520
|
+
selectedSell,
|
|
3521
|
+
selectedBuy,
|
|
3522
|
+
amount,
|
|
3523
|
+
provider,
|
|
3524
|
+
providers,
|
|
3525
|
+
quote,
|
|
3526
|
+
quoteLoading,
|
|
3527
|
+
quoteError,
|
|
3528
|
+
formError,
|
|
3529
|
+
isLoadingData,
|
|
3530
|
+
smartUnsupported,
|
|
3531
|
+
transaction,
|
|
3532
|
+
showXdr,
|
|
3533
|
+
copied,
|
|
3534
|
+
explorerUrl,
|
|
3535
|
+
walletType,
|
|
3536
|
+
showBack,
|
|
3537
|
+
isInProgress,
|
|
3538
|
+
onClose,
|
|
3539
|
+
onBack,
|
|
3540
|
+
onSelectSell,
|
|
3541
|
+
onSelectBuy,
|
|
3542
|
+
onAmountChange,
|
|
3543
|
+
onProviderChange,
|
|
3544
|
+
onSwap,
|
|
3545
|
+
onToggleXdr,
|
|
3546
|
+
onCopyHash,
|
|
3547
|
+
onRetry,
|
|
3548
|
+
onDone
|
|
3549
|
+
}) {
|
|
3550
|
+
const isDark = theme === "dark";
|
|
3551
|
+
const cssVars = {
|
|
3552
|
+
"--pollar-accent": accentColor,
|
|
3553
|
+
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
3554
|
+
"--pollar-border": isDark ? "#374151" : "#e5e7eb",
|
|
3555
|
+
"--pollar-text": isDark ? "#ffffff" : "#111827",
|
|
3556
|
+
"--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
|
|
3557
|
+
"--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
|
|
3558
|
+
"--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
|
|
3559
|
+
"--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
|
|
3560
|
+
"--pollar-error-text": isDark ? "#f87171" : "#dc2626",
|
|
3561
|
+
"--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
|
|
3562
|
+
"--pollar-buttons-border-radius": "6px",
|
|
3563
|
+
"--pollar-buttons-height": "44px",
|
|
3564
|
+
"--pollar-input-height": "44px",
|
|
3565
|
+
"--pollar-input-border-radius": "0.5rem",
|
|
3566
|
+
"--pollar-card-border-radius": "10px"
|
|
3567
|
+
};
|
|
3568
|
+
const sellKey = selectedSell ? assetOptionKey(selectedSell) : "";
|
|
3569
|
+
const buyKey = selectedBuy ? assetOptionKey(selectedBuy) : "";
|
|
3570
|
+
const canSwap = !smartUnsupported && !!selectedSell && !!selectedBuy && !!amount && !!quote && !quoteLoading && !isLoadingData;
|
|
3571
|
+
const title = step === "form" ? "Swap" : txTitle;
|
|
3572
|
+
return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-send-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
|
|
3573
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-modal-header", children: [
|
|
3574
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-header-left", children: [
|
|
3575
|
+
showBack && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onBack, "aria-label": "Back", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
|
|
3576
|
+
/* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: title })
|
|
3577
|
+
] }),
|
|
3578
|
+
!isInProgress && /* @__PURE__ */ jsx("div", { className: "pollar-modal-header-actions", children: /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) }) })
|
|
3579
|
+
] }),
|
|
3580
|
+
step === "form" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3581
|
+
smartUnsupported && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: "Swaps are not yet available for smart (passkey) wallets." }),
|
|
3582
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
|
|
3583
|
+
/* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "You pay" }),
|
|
3584
|
+
isLoadingData ? /* @__PURE__ */ jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxs(
|
|
3585
|
+
"select",
|
|
3586
|
+
{
|
|
3587
|
+
className: "pollar-input pollar-send-select",
|
|
3588
|
+
value: sellKey,
|
|
3589
|
+
onChange: (e) => {
|
|
3590
|
+
const found = sellOptions.find((o) => assetOptionKey(o) === e.target.value);
|
|
3591
|
+
if (found) onSelectSell(found);
|
|
3592
|
+
},
|
|
3593
|
+
children: [
|
|
3594
|
+
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select asset to sell" }),
|
|
3595
|
+
sellOptions.map((o) => /* @__PURE__ */ jsxs("option", { value: assetOptionKey(o), children: [
|
|
3596
|
+
o.code,
|
|
3597
|
+
o.available !== void 0 ? ` \u2014 ${formatAmount2(o.available)} available` : ""
|
|
3598
|
+
] }, assetOptionKey(o)))
|
|
3599
|
+
]
|
|
3600
|
+
}
|
|
3601
|
+
)
|
|
3602
|
+
] }),
|
|
3603
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
|
|
3604
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-label-row", children: [
|
|
3605
|
+
/* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Amount" }),
|
|
3606
|
+
selectedSell?.available !== void 0 && /* @__PURE__ */ jsxs("span", { className: "pollar-send-hint", children: [
|
|
3607
|
+
"Available: ",
|
|
3608
|
+
formatAmount2(selectedSell.available),
|
|
3609
|
+
" ",
|
|
3610
|
+
selectedSell.code
|
|
3611
|
+
] })
|
|
3612
|
+
] }),
|
|
3613
|
+
/* @__PURE__ */ jsx(
|
|
3614
|
+
"input",
|
|
3615
|
+
{
|
|
3616
|
+
className: "pollar-input",
|
|
3617
|
+
type: "text",
|
|
3618
|
+
inputMode: "decimal",
|
|
3619
|
+
placeholder: "0.00",
|
|
3620
|
+
value: amount,
|
|
3621
|
+
onChange: (e) => onAmountChange(e.target.value)
|
|
3622
|
+
}
|
|
3623
|
+
)
|
|
3624
|
+
] }),
|
|
3625
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
|
|
3626
|
+
/* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "You receive" }),
|
|
3627
|
+
isLoadingData ? /* @__PURE__ */ jsx("div", { className: "pollar-send-skeleton" }) : /* @__PURE__ */ jsxs(
|
|
3628
|
+
"select",
|
|
3629
|
+
{
|
|
3630
|
+
className: "pollar-input pollar-send-select",
|
|
3631
|
+
value: buyKey,
|
|
3632
|
+
onChange: (e) => {
|
|
3633
|
+
const found = buyOptions.find((o) => assetOptionKey(o) === e.target.value);
|
|
3634
|
+
if (found) onSelectBuy(found);
|
|
3635
|
+
},
|
|
3636
|
+
children: [
|
|
3637
|
+
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select asset to buy" }),
|
|
3638
|
+
buyOptions.map((o) => /* @__PURE__ */ jsxs("option", { value: assetOptionKey(o), children: [
|
|
3639
|
+
o.code,
|
|
3640
|
+
o.enabledInApp ? "" : " (external)"
|
|
3641
|
+
] }, assetOptionKey(o)))
|
|
3642
|
+
]
|
|
3643
|
+
}
|
|
3644
|
+
)
|
|
3645
|
+
] }),
|
|
3646
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
|
|
3647
|
+
/* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Route" }),
|
|
3648
|
+
/* @__PURE__ */ jsx(
|
|
3649
|
+
"select",
|
|
3650
|
+
{
|
|
3651
|
+
className: "pollar-input pollar-send-select",
|
|
3652
|
+
value: provider,
|
|
3653
|
+
onChange: (e) => onProviderChange(e.target.value),
|
|
3654
|
+
children: providers.map((p) => {
|
|
3655
|
+
const implemented = IMPLEMENTED_PROVIDERS.includes(p);
|
|
3656
|
+
return /* @__PURE__ */ jsxs("option", { value: p, disabled: !implemented, children: [
|
|
3657
|
+
PROVIDER_LABELS[p],
|
|
3658
|
+
implemented ? "" : " (coming soon)"
|
|
3659
|
+
] }, p);
|
|
3660
|
+
})
|
|
3661
|
+
}
|
|
3662
|
+
)
|
|
3663
|
+
] }),
|
|
3664
|
+
quoteLoading && /* @__PURE__ */ jsx("div", { className: "pollar-send-hint", children: "Fetching best price\u2026" }),
|
|
3665
|
+
!quoteLoading && quoteError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: quoteError }),
|
|
3666
|
+
!quoteLoading && !quoteError && quote && selectedBuy && /* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote", children: [
|
|
3667
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
3668
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "You receive" }),
|
|
3669
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
3670
|
+
"~ ",
|
|
3671
|
+
formatAmount2(quote.amountOut),
|
|
3672
|
+
" ",
|
|
3673
|
+
selectedBuy.code
|
|
3674
|
+
] })
|
|
3675
|
+
] }),
|
|
3676
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
3677
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "Minimum received" }),
|
|
3678
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
3679
|
+
formatAmount2(quote.minReceived),
|
|
3680
|
+
" ",
|
|
3681
|
+
selectedBuy.code
|
|
3682
|
+
] })
|
|
3683
|
+
] }),
|
|
3684
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
3685
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "Price impact" }),
|
|
3686
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
3687
|
+
quote.priceImpactPct,
|
|
3688
|
+
"%"
|
|
3689
|
+
] })
|
|
3690
|
+
] }),
|
|
3691
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-swap-quote-row", children: [
|
|
3692
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-send-hint", children: "Route" }),
|
|
3693
|
+
/* @__PURE__ */ jsx("span", { children: PROVIDER_LABELS[quote.provider] })
|
|
3694
|
+
] })
|
|
3695
|
+
] }),
|
|
3696
|
+
!quoteLoading && !quoteError && !quote && selectedSell && selectedBuy && !!amount && /* @__PURE__ */ jsx("div", { className: "pollar-send-hint", children: "No route found for this pair." }),
|
|
3697
|
+
formError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: formError }),
|
|
3698
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsx("button", { className: "pollar-btn-primary", onClick: onSwap, disabled: !canSwap, children: "Swap" }) })
|
|
3699
|
+
] }),
|
|
3700
|
+
step === "tx" && /* @__PURE__ */ jsx(
|
|
3701
|
+
TxStatusView,
|
|
3702
|
+
{
|
|
3703
|
+
transaction,
|
|
3704
|
+
showXdr,
|
|
3705
|
+
copied,
|
|
3706
|
+
explorerUrl,
|
|
3707
|
+
walletType,
|
|
3708
|
+
onSignAndSend: () => {
|
|
3709
|
+
},
|
|
3710
|
+
onToggleXdr,
|
|
3711
|
+
onCopyHash,
|
|
3712
|
+
onRetry,
|
|
3713
|
+
onDone
|
|
3714
|
+
}
|
|
3715
|
+
),
|
|
3716
|
+
/* @__PURE__ */ jsx(PollarModalFooter, {})
|
|
3717
|
+
] });
|
|
3718
|
+
}
|
|
3719
|
+
var QUOTE_DEBOUNCE_MS = 400;
|
|
3720
|
+
var ALL_PROVIDERS = ["auto", "aquarius", "soroswap", "sdex"];
|
|
3721
|
+
function toRef(a) {
|
|
3722
|
+
if (a.type === "native") return { type: "native" };
|
|
3723
|
+
if (a.type === "credit_alphanum4") return { type: "credit_alphanum4", code: a.code, issuer: a.issuer };
|
|
3724
|
+
return { type: "credit_alphanum12", code: a.code, issuer: a.issuer };
|
|
3725
|
+
}
|
|
3726
|
+
function SwapModal({ onClose }) {
|
|
3727
|
+
const {
|
|
3728
|
+
getSwapQuote,
|
|
3729
|
+
swap,
|
|
3730
|
+
walletBalance,
|
|
3731
|
+
refreshWalletBalance,
|
|
3732
|
+
enabledAssets,
|
|
3733
|
+
refreshAssets,
|
|
3734
|
+
tx: transaction,
|
|
3735
|
+
wallet,
|
|
3736
|
+
network,
|
|
3737
|
+
styles
|
|
3738
|
+
} = usePollar();
|
|
3739
|
+
const walletType = wallet?.custody === "external" ? wallet.provider : null;
|
|
3740
|
+
const smartUnsupported = wallet?.custody === "smart";
|
|
3741
|
+
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
3742
|
+
const [step, setStep] = useState("form");
|
|
3743
|
+
const [selectedSell, setSelectedSell] = useState(null);
|
|
3744
|
+
const [selectedBuy, setSelectedBuy] = useState(null);
|
|
3745
|
+
const [amount, setAmount] = useState("");
|
|
3746
|
+
const [provider, setProvider] = useState("auto");
|
|
3747
|
+
const [quotes, setQuotes] = useState([]);
|
|
3748
|
+
const [quoteLoading, setQuoteLoading] = useState(false);
|
|
3749
|
+
const [quoteError, setQuoteError] = useState("");
|
|
3750
|
+
const [formError, setFormError] = useState("");
|
|
3751
|
+
const [showXdr, setShowXdr] = useState(false);
|
|
3752
|
+
const [copied, setCopied] = useState(false);
|
|
3753
|
+
const copyTimerRef = useRef(null);
|
|
3754
|
+
const slippageBps = 50;
|
|
3755
|
+
useEffect(() => {
|
|
3756
|
+
void refreshWalletBalance();
|
|
3757
|
+
void refreshAssets();
|
|
3758
|
+
}, [refreshWalletBalance, refreshAssets]);
|
|
3759
|
+
useEffect(
|
|
3760
|
+
() => () => {
|
|
3761
|
+
if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
|
|
3762
|
+
},
|
|
3763
|
+
[]
|
|
3764
|
+
);
|
|
3765
|
+
const balances = walletBalance.step === "loaded" ? walletBalance.data.balances : [];
|
|
3766
|
+
const assetRecords = enabledAssets.step === "loaded" ? enabledAssets.data.assets : [];
|
|
3767
|
+
const isLoadingData = walletBalance.step === "loading" || enabledAssets.step === "loading";
|
|
3768
|
+
const sellOptions = balances.filter((b) => parseFloat(b.available) > 0).map((b) => ({ ref: toRef(b), code: b.code, issuer: b.issuer, available: b.available, enabledInApp: b.enabledInApp }));
|
|
3769
|
+
const buyKeyOfSell = selectedSell ? `${selectedSell.code}:${selectedSell.issuer ?? "native"}` : "";
|
|
3770
|
+
const buyOptions = assetRecords.map((a) => ({ ref: toRef(a), code: a.code, issuer: a.issuer, enabledInApp: a.enabledInApp })).filter((o) => `${o.code}:${o.issuer ?? "native"}` !== buyKeyOfSell);
|
|
3771
|
+
const providers = smartUnsupported ? ALL_PROVIDERS.filter((p) => p !== "sdex") : ALL_PROVIDERS;
|
|
3772
|
+
const quote = quotes[0] ?? null;
|
|
3773
|
+
useEffect(() => {
|
|
3774
|
+
if (step !== "form" || !selectedSell || !selectedBuy || !amount || parseFloat(amount) <= 0) {
|
|
3775
|
+
setQuotes([]);
|
|
3776
|
+
setQuoteError("");
|
|
3777
|
+
setQuoteLoading(false);
|
|
3778
|
+
return;
|
|
3779
|
+
}
|
|
3780
|
+
let cancelled = false;
|
|
3781
|
+
setQuoteLoading(true);
|
|
3782
|
+
setQuoteError("");
|
|
3783
|
+
const t = setTimeout(async () => {
|
|
3784
|
+
try {
|
|
3785
|
+
const qs = await getSwapQuote({
|
|
3786
|
+
sellAsset: selectedSell.ref,
|
|
3787
|
+
buyAsset: selectedBuy.ref,
|
|
3788
|
+
amount,
|
|
3789
|
+
provider,
|
|
3790
|
+
slippageBps
|
|
3791
|
+
});
|
|
3792
|
+
if (!cancelled) setQuotes(qs);
|
|
3793
|
+
} catch (e) {
|
|
3794
|
+
if (!cancelled) {
|
|
3795
|
+
setQuotes([]);
|
|
3796
|
+
setQuoteError(e instanceof Error ? e.message : "Failed to fetch quote");
|
|
3797
|
+
}
|
|
3798
|
+
} finally {
|
|
3799
|
+
if (!cancelled) setQuoteLoading(false);
|
|
3800
|
+
}
|
|
3801
|
+
}, QUOTE_DEBOUNCE_MS);
|
|
3802
|
+
return () => {
|
|
3803
|
+
cancelled = true;
|
|
3804
|
+
clearTimeout(t);
|
|
3805
|
+
};
|
|
3806
|
+
}, [step, selectedSell, selectedBuy, amount, provider, getSwapQuote]);
|
|
3807
|
+
const hash = transaction.step === "success" ? transaction.hash : null;
|
|
3808
|
+
const buildData = "buildData" in transaction ? transaction.buildData : null;
|
|
3809
|
+
const explorerNetwork = buildData?.summary.network?.toLowerCase().includes("testnet") ? "testnet" : buildData ? "public" : network === "testnet" ? "testnet" : "public";
|
|
3810
|
+
const explorerUrl = hash ? `https://stellar.expert/explorer/${explorerNetwork}/tx/${hash}` : null;
|
|
3811
|
+
const IN_FLIGHT_STEPS2 = [
|
|
3812
|
+
"building",
|
|
3813
|
+
"signing",
|
|
3814
|
+
"submitting",
|
|
3815
|
+
"submitted",
|
|
3816
|
+
"signing-submitting",
|
|
3817
|
+
"building-signing-submitting"
|
|
3818
|
+
];
|
|
3819
|
+
const isInProgress = IN_FLIGHT_STEPS2.includes(transaction.step);
|
|
3820
|
+
const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
|
|
3821
|
+
const txTitle = isInProgress ? "Swapping\u2026" : transaction.step === "success" ? "Swapped!" : transaction.step === "error" ? "Swap failed" : "Confirm Swap";
|
|
3822
|
+
async function handleSwap() {
|
|
3823
|
+
setFormError("");
|
|
3824
|
+
if (smartUnsupported) {
|
|
3825
|
+
setFormError("Swaps are not yet supported for smart (passkey) wallets");
|
|
3826
|
+
return;
|
|
3827
|
+
}
|
|
3828
|
+
if (!selectedSell || !selectedBuy) {
|
|
3829
|
+
setFormError("Select both assets");
|
|
3830
|
+
return;
|
|
3831
|
+
}
|
|
3832
|
+
const parsed = parseFloat(amount);
|
|
3833
|
+
if (!amount || isNaN(parsed) || parsed <= 0) {
|
|
3834
|
+
setFormError("Enter a valid amount");
|
|
3835
|
+
return;
|
|
3836
|
+
}
|
|
3837
|
+
if (selectedSell.available !== void 0 && parsed > parseFloat(selectedSell.available)) {
|
|
3838
|
+
setFormError("Insufficient balance");
|
|
3839
|
+
return;
|
|
3840
|
+
}
|
|
3841
|
+
if (!quote) {
|
|
3842
|
+
setFormError("No route available for this pair");
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3845
|
+
setStep("tx");
|
|
3846
|
+
await swap(quote);
|
|
3847
|
+
}
|
|
3848
|
+
async function handleRetry() {
|
|
3849
|
+
if (transaction.step === "error" && quote) await swap(quote);
|
|
3850
|
+
}
|
|
3851
|
+
function handleCopyHash() {
|
|
3852
|
+
if (!hash) return;
|
|
3853
|
+
navigator.clipboard.writeText(hash).then(() => {
|
|
3854
|
+
setCopied(true);
|
|
3855
|
+
if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
|
|
3856
|
+
copyTimerRef.current = setTimeout(() => {
|
|
3857
|
+
copyTimerRef.current = null;
|
|
3858
|
+
setCopied(false);
|
|
3859
|
+
}, 2e3);
|
|
3860
|
+
});
|
|
3861
|
+
}
|
|
3862
|
+
function handleBack() {
|
|
3863
|
+
setStep("form");
|
|
3864
|
+
setShowXdr(false);
|
|
3865
|
+
setCopied(false);
|
|
3866
|
+
}
|
|
3867
|
+
return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsx(
|
|
3868
|
+
SwapModalTemplate,
|
|
3869
|
+
{
|
|
3870
|
+
theme,
|
|
3871
|
+
accentColor,
|
|
3872
|
+
step,
|
|
3873
|
+
txTitle,
|
|
3874
|
+
sellOptions,
|
|
3875
|
+
buyOptions,
|
|
3876
|
+
selectedSell,
|
|
3877
|
+
selectedBuy,
|
|
3878
|
+
amount,
|
|
3879
|
+
provider,
|
|
3880
|
+
providers,
|
|
3881
|
+
quote,
|
|
3882
|
+
quoteLoading,
|
|
3883
|
+
quoteError,
|
|
3884
|
+
formError,
|
|
3885
|
+
isLoadingData,
|
|
3886
|
+
smartUnsupported,
|
|
3887
|
+
transaction,
|
|
3888
|
+
showXdr,
|
|
3889
|
+
copied,
|
|
3890
|
+
explorerUrl,
|
|
3891
|
+
walletType,
|
|
3892
|
+
showBack,
|
|
3893
|
+
isInProgress,
|
|
3894
|
+
onClose,
|
|
3895
|
+
onBack: handleBack,
|
|
3896
|
+
onSelectSell: setSelectedSell,
|
|
3897
|
+
onSelectBuy: setSelectedBuy,
|
|
3898
|
+
onAmountChange: setAmount,
|
|
3899
|
+
onProviderChange: setProvider,
|
|
3900
|
+
onSwap: () => void handleSwap(),
|
|
3901
|
+
onToggleXdr: () => setShowXdr((v) => !v),
|
|
3902
|
+
onCopyHash: handleCopyHash,
|
|
3903
|
+
onRetry: () => void handleRetry(),
|
|
3904
|
+
onDone: onClose
|
|
3905
|
+
}
|
|
3906
|
+
) });
|
|
3907
|
+
}
|
|
3307
3908
|
function describeDevice(s) {
|
|
3308
3909
|
if (s.deviceLabel) return s.deviceLabel;
|
|
3309
3910
|
if (!s.userAgent) return "Unknown device";
|
|
@@ -3998,7 +4599,6 @@ var PollarContext = createContext(null);
|
|
|
3998
4599
|
function PollarProvider({
|
|
3999
4600
|
client,
|
|
4000
4601
|
appConfig: appConfigProp,
|
|
4001
|
-
ui,
|
|
4002
4602
|
adapters,
|
|
4003
4603
|
onStorageDegrade,
|
|
4004
4604
|
children
|
|
@@ -4050,6 +4650,30 @@ function PollarProvider({
|
|
|
4050
4650
|
}
|
|
4051
4651
|
});
|
|
4052
4652
|
}, [pollarClient]);
|
|
4653
|
+
const sessionRef = useRef(sessionState);
|
|
4654
|
+
sessionRef.current = sessionState;
|
|
4655
|
+
useEffect(() => {
|
|
4656
|
+
const unsubscribes = [];
|
|
4657
|
+
for (const { id } of pollarClient.listWalletAdapters()) {
|
|
4658
|
+
const adapter = pollarClient.getWalletAdapter(id);
|
|
4659
|
+
if (!isInteractiveAuthAdapter(adapter) || !adapter.onProviderAuthChange) continue;
|
|
4660
|
+
let triggered = false;
|
|
4661
|
+
unsubscribes.push(
|
|
4662
|
+
adapter.onProviderAuthChange((state) => {
|
|
4663
|
+
if (!state.authenticated || !state.address) {
|
|
4664
|
+
triggered = false;
|
|
4665
|
+
return;
|
|
4666
|
+
}
|
|
4667
|
+
if (triggered || sessionRef.current?.wallet?.address) return;
|
|
4668
|
+
triggered = true;
|
|
4669
|
+
pollarClient.login({ provider: id });
|
|
4670
|
+
})
|
|
4671
|
+
);
|
|
4672
|
+
}
|
|
4673
|
+
return () => {
|
|
4674
|
+
for (const unsubscribe of unsubscribes) unsubscribe();
|
|
4675
|
+
};
|
|
4676
|
+
}, [pollarClient]);
|
|
4053
4677
|
useEffect(() => {
|
|
4054
4678
|
setModalErrorLogger(pollarClient.getLogger());
|
|
4055
4679
|
}, [pollarClient]);
|
|
@@ -4075,6 +4699,7 @@ function PollarProvider({
|
|
|
4075
4699
|
const [walletBalanceModalOpen, setWalletBalanceModalOpen] = useState(false);
|
|
4076
4700
|
const [enabledAssetsModalOpen, setEnabledAssetsModalOpen] = useState(false);
|
|
4077
4701
|
const [sendModalOpen, setSendModalOpen] = useState(false);
|
|
4702
|
+
const [swapModalOpen, setSwapModalOpen] = useState(false);
|
|
4078
4703
|
const [receiveModalOpen, setReceiveModalOpen] = useState(false);
|
|
4079
4704
|
const [sessionsModalOpen, setSessionsModalOpen] = useState(false);
|
|
4080
4705
|
const [distributionRulesModalOpen, setDistributionRulesModalOpen] = useState(false);
|
|
@@ -4082,8 +4707,6 @@ function PollarProvider({
|
|
|
4082
4707
|
const getClient = useCallback(() => pollarClient, [pollarClient]);
|
|
4083
4708
|
const refreshWalletBalance = useCallback(() => pollarClient.refreshBalance(), [pollarClient, walletAddress]);
|
|
4084
4709
|
const refreshAssets = useCallback(() => pollarClient.refreshAssets(), [pollarClient, walletAddress]);
|
|
4085
|
-
const renderWallets = ui?.renderWallets;
|
|
4086
|
-
const customProviders = ui?.customProviders;
|
|
4087
4710
|
const contextValue = useMemo(() => {
|
|
4088
4711
|
const styles = resolvedConfig.styles ?? {};
|
|
4089
4712
|
return {
|
|
@@ -4121,6 +4744,10 @@ function PollarProvider({
|
|
|
4121
4744
|
// send / receive
|
|
4122
4745
|
openSendModal: () => setSendModalOpen(true),
|
|
4123
4746
|
openReceiveModal: () => setReceiveModalOpen(true),
|
|
4747
|
+
// swap
|
|
4748
|
+
getSwapQuote: (params) => pollarClient.getSwapQuote(params),
|
|
4749
|
+
swap: (quote, opts) => pollarClient.swap(quote, opts),
|
|
4750
|
+
openSwapModal: () => setSwapModalOpen(true),
|
|
4124
4751
|
// sessions
|
|
4125
4752
|
sessions,
|
|
4126
4753
|
openSessionsModal: () => setSessionsModalOpen(true),
|
|
@@ -4139,8 +4766,6 @@ function PollarProvider({
|
|
|
4139
4766
|
// config
|
|
4140
4767
|
appConfig: resolvedConfig,
|
|
4141
4768
|
styles,
|
|
4142
|
-
renderWallets,
|
|
4143
|
-
customProviders,
|
|
4144
4769
|
adapters
|
|
4145
4770
|
};
|
|
4146
4771
|
}, [
|
|
@@ -4157,9 +4782,7 @@ function PollarProvider({
|
|
|
4157
4782
|
refreshAssets,
|
|
4158
4783
|
networkState,
|
|
4159
4784
|
resolvedConfig,
|
|
4160
|
-
adapters
|
|
4161
|
-
renderWallets,
|
|
4162
|
-
customProviders
|
|
4785
|
+
adapters
|
|
4163
4786
|
]);
|
|
4164
4787
|
return /* @__PURE__ */ jsxs(PollarContext.Provider, { value: contextValue, children: [
|
|
4165
4788
|
children,
|
|
@@ -4179,6 +4802,7 @@ function PollarProvider({
|
|
|
4179
4802
|
walletBalanceModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setWalletBalanceModalOpen(false), children: /* @__PURE__ */ jsx(WalletBalanceModal, { onClose: () => setWalletBalanceModalOpen(false) }) }),
|
|
4180
4803
|
enabledAssetsModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setEnabledAssetsModalOpen(false), children: /* @__PURE__ */ jsx(EnabledAssetsModal, { onClose: () => setEnabledAssetsModalOpen(false) }) }),
|
|
4181
4804
|
sendModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSendModalOpen(false), children: /* @__PURE__ */ jsx(SendModal, { onClose: () => setSendModalOpen(false) }) }),
|
|
4805
|
+
swapModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSwapModalOpen(false), children: /* @__PURE__ */ jsx(SwapModal, { onClose: () => setSwapModalOpen(false) }) }),
|
|
4182
4806
|
receiveModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setReceiveModalOpen(false), children: /* @__PURE__ */ jsx(ReceiveModal, { onClose: () => setReceiveModalOpen(false) }) }),
|
|
4183
4807
|
sessionsModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSessionsModalOpen(false), children: /* @__PURE__ */ jsx(SessionsModal, { onClose: () => setSessionsModalOpen(false) }) }),
|
|
4184
4808
|
distributionRulesModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setDistributionRulesModalOpen(false), children: /* @__PURE__ */ jsx(DistributionRulesModal, { onClose: () => setDistributionRulesModalOpen(false) }) })
|
|
@@ -4627,6 +5251,6 @@ function WalletButton() {
|
|
|
4627
5251
|
);
|
|
4628
5252
|
}
|
|
4629
5253
|
|
|
4630
|
-
export { DistributionRulesModal, DistributionRulesModalTemplate, EnabledAssetsModal, EnabledAssetsModalTemplate, KycModal, KycModalTemplate, KycStatus, LoginModalTemplate, PollarProvider, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, RouteDisplay, SendModal, SendModalTemplate, SessionsModal, SessionsModalTemplate, TransactionModalTemplate, TxHistoryModalTemplate, TxStatusView, WalletBalanceModal, WalletBalanceModalTemplate, WalletButton, WalletButtonTemplate, createPollarAdapterHook, usePollar };
|
|
5254
|
+
export { DistributionRulesModal, DistributionRulesModalTemplate, EnabledAssetsModal, EnabledAssetsModalTemplate, KycModal, KycModalTemplate, KycStatus, LoginModalTemplate, PollarProvider, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, RouteDisplay, SendModal, SendModalTemplate, SessionsModal, SessionsModalTemplate, SwapModal, SwapModalTemplate, TransactionModalTemplate, TxHistoryModalTemplate, TxStatusView, WalletBalanceModal, WalletBalanceModalTemplate, WalletButton, WalletButtonTemplate, createPollarAdapterHook, usePollar };
|
|
4631
5255
|
//# sourceMappingURL=index.mjs.map
|
|
4632
5256
|
//# sourceMappingURL=index.mjs.map
|