@pollar/react 0.10.0-rc.8 → 0.10.0
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 +109 -103
- package/dist/index.css +40 -11
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +83 -34
- package/dist/index.d.ts +83 -34
- package/dist/index.js +866 -199
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +866 -201
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
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
|
|
1036
|
+
"0.10.0"
|
|
1037
1037
|
] })
|
|
1038
1038
|
] })
|
|
1039
1039
|
] });
|
|
@@ -1853,12 +1853,39 @@ var GoogleButton = ({ disabled, onClick }) => {
|
|
|
1853
1853
|
function WalletAdapterButtons({
|
|
1854
1854
|
walletAdapters,
|
|
1855
1855
|
onConnect,
|
|
1856
|
-
isLoading
|
|
1856
|
+
isLoading,
|
|
1857
|
+
variant = "list"
|
|
1857
1858
|
}) {
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1859
|
+
if (variant === "entry") {
|
|
1860
|
+
return /* @__PURE__ */ jsx(Fragment, { children: walletAdapters.map((a) => /* @__PURE__ */ jsxs(
|
|
1861
|
+
"button",
|
|
1862
|
+
{
|
|
1863
|
+
type: "button",
|
|
1864
|
+
disabled: isLoading,
|
|
1865
|
+
className: "pollar-wallet-entry-btn",
|
|
1866
|
+
onClick: () => onConnect(a.id),
|
|
1867
|
+
children: [
|
|
1868
|
+
a.meta.iconUrl && /* @__PURE__ */ jsx("img", { src: a.meta.iconUrl, alt: a.meta.label, className: "pollar-wallet-icon" }),
|
|
1869
|
+
a.meta.label
|
|
1870
|
+
]
|
|
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
|
+
)) });
|
|
1862
1889
|
}
|
|
1863
1890
|
var AUTH_STATE_MESSAGES = {
|
|
1864
1891
|
idle: "",
|
|
@@ -1915,7 +1942,6 @@ function LoginModalTemplate({
|
|
|
1915
1942
|
onWalletConnect,
|
|
1916
1943
|
onLoginSmartWallet,
|
|
1917
1944
|
onCreateSmartWallet,
|
|
1918
|
-
renderWallets,
|
|
1919
1945
|
authState,
|
|
1920
1946
|
codeInputKey,
|
|
1921
1947
|
onCodeSubmit,
|
|
@@ -1923,10 +1949,19 @@ function LoginModalTemplate({
|
|
|
1923
1949
|
onCancel,
|
|
1924
1950
|
onRetry
|
|
1925
1951
|
}) {
|
|
1926
|
-
const [showWalletPicker, setShowWalletPicker] = useState(false);
|
|
1927
1952
|
const [showPasskeyChooser, setShowPasskeyChooser] = useState(false);
|
|
1953
|
+
const [activeGroup, setActiveGroup] = useState(null);
|
|
1928
1954
|
const isDark = theme === "dark";
|
|
1929
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 ?? [];
|
|
1930
1965
|
const cssVars = {
|
|
1931
1966
|
"--pollar-accent": accentColor,
|
|
1932
1967
|
"--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
|
|
@@ -1990,11 +2025,17 @@ function LoginModalTemplate({
|
|
|
1990
2025
|
/* @__PURE__ */ jsx(BackButton, { onClick: onBack }),
|
|
1991
2026
|
/* @__PURE__ */ jsx(EmailCodeInput, { email, onSubmit: onCodeSubmit ?? (() => {
|
|
1992
2027
|
}) }, codeInputKey)
|
|
1993
|
-
] }) :
|
|
1994
|
-
/* @__PURE__ */ jsx(BackButton, { onClick: () =>
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
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
|
+
)
|
|
1998
2039
|
] }) : showPasskeyChooser ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1999
2040
|
/* @__PURE__ */ jsx(BackButton, { onClick: () => setShowPasskeyChooser(false) }),
|
|
2000
2041
|
/* @__PURE__ */ jsxs("div", { className: "pollar-wallet-section", children: [
|
|
@@ -2036,32 +2077,45 @@ function LoginModalTemplate({
|
|
|
2036
2077
|
enabledSocial.some(([key]) => key === "github") && /* @__PURE__ */ jsx(GithubButton, { disabled: isLoading, onClick: () => onSocialLogin?.("github") })
|
|
2037
2078
|
] }),
|
|
2038
2079
|
(embeddedWallets || smartWallet) && /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-section", children: [
|
|
2039
|
-
embeddedWallets && /* @__PURE__ */ jsxs(
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
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
|
+
] }),
|
|
2065
2119
|
smartWallet && /* @__PURE__ */ jsxs(
|
|
2066
2120
|
"button",
|
|
2067
2121
|
{
|
|
@@ -2102,13 +2156,142 @@ function LoginModalTemplate({
|
|
|
2102
2156
|
/* @__PURE__ */ jsx(PollarModalFooter, {})
|
|
2103
2157
|
] });
|
|
2104
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
|
+
}
|
|
2105
2287
|
function LoginModal({ onClose }) {
|
|
2106
2288
|
const [email, setEmail] = useState("");
|
|
2107
|
-
const { getClient, styles, appConfig: config
|
|
2289
|
+
const { getClient, styles, appConfig: config } = usePollar();
|
|
2108
2290
|
const [authState, setAuthState] = useState(() => getClient().getAuthState());
|
|
2109
2291
|
const walletAdapters = useMemo(() => getClient().listWalletAdapters(), [getClient]);
|
|
2110
2292
|
const [codeInputKey, setCodeInputKey] = useState(0);
|
|
2111
2293
|
const pendingEmail = useRef(null);
|
|
2294
|
+
const [interactiveAdapter, setInteractiveAdapter] = useState(null);
|
|
2112
2295
|
const onCloseRef = useRef(onClose);
|
|
2113
2296
|
onCloseRef.current = onClose;
|
|
2114
2297
|
const autoCloseTimer = useRef(null);
|
|
@@ -2156,6 +2339,11 @@ function LoginModal({ onClose }) {
|
|
|
2156
2339
|
getClient().login({ provider });
|
|
2157
2340
|
}
|
|
2158
2341
|
function handleWalletConnect(type) {
|
|
2342
|
+
const adapter = getClient().getWalletAdapter(type);
|
|
2343
|
+
if (isInteractiveAuthAdapter(adapter)) {
|
|
2344
|
+
setInteractiveAdapter(adapter);
|
|
2345
|
+
return;
|
|
2346
|
+
}
|
|
2159
2347
|
getClient().login({ provider: type });
|
|
2160
2348
|
}
|
|
2161
2349
|
function handleLoginSmartWallet() {
|
|
@@ -2177,7 +2365,26 @@ function LoginModal({ onClose }) {
|
|
|
2177
2365
|
getClient().beginEmailLogin();
|
|
2178
2366
|
}
|
|
2179
2367
|
}
|
|
2180
|
-
|
|
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(
|
|
2181
2388
|
LoginModalTemplate,
|
|
2182
2389
|
{
|
|
2183
2390
|
theme,
|
|
@@ -2202,7 +2409,6 @@ function LoginModal({ onClose }) {
|
|
|
2202
2409
|
onWalletConnect: handleWalletConnect,
|
|
2203
2410
|
onLoginSmartWallet: handleLoginSmartWallet,
|
|
2204
2411
|
onCreateSmartWallet: handleCreateSmartWallet,
|
|
2205
|
-
...renderWallets !== void 0 && { renderWallets },
|
|
2206
2412
|
authState,
|
|
2207
2413
|
codeInputKey,
|
|
2208
2414
|
onCodeSubmit: handleVerifyCode,
|
|
@@ -2259,6 +2465,12 @@ var COUNTRY_CURRENCIES = {
|
|
|
2259
2465
|
PE: "PEN",
|
|
2260
2466
|
AR: "ARS"
|
|
2261
2467
|
};
|
|
2468
|
+
var STATUS_LABEL = {
|
|
2469
|
+
pending: "Pending",
|
|
2470
|
+
processing: "Processing",
|
|
2471
|
+
completed: "Completed",
|
|
2472
|
+
failed: "Failed"
|
|
2473
|
+
};
|
|
2262
2474
|
function RampWidgetTemplate({
|
|
2263
2475
|
theme,
|
|
2264
2476
|
accentColor,
|
|
@@ -2268,15 +2480,23 @@ function RampWidgetTemplate({
|
|
|
2268
2480
|
currency,
|
|
2269
2481
|
country,
|
|
2270
2482
|
quotes,
|
|
2271
|
-
paymentInstructions,
|
|
2272
2483
|
isLoading,
|
|
2484
|
+
provider,
|
|
2485
|
+
txStatus,
|
|
2486
|
+
kycUrl,
|
|
2487
|
+
stellarTxHash,
|
|
2488
|
+
canComplete,
|
|
2489
|
+
completing,
|
|
2490
|
+
errorMsg,
|
|
2273
2491
|
onDirectionChange,
|
|
2274
2492
|
onAmountChange,
|
|
2275
2493
|
onCurrencyChange,
|
|
2276
2494
|
onCountryChange,
|
|
2277
2495
|
onFindRoute,
|
|
2278
2496
|
onSelectQuote,
|
|
2279
|
-
|
|
2497
|
+
onOpenKyc,
|
|
2498
|
+
onCompleteWithdraw,
|
|
2499
|
+
onRetry,
|
|
2280
2500
|
onClose
|
|
2281
2501
|
}) {
|
|
2282
2502
|
const isDark = theme === "dark";
|
|
@@ -2304,13 +2524,15 @@ function RampWidgetTemplate({
|
|
|
2304
2524
|
input: direction === "onramp" ? "Buy crypto" : "Sell crypto",
|
|
2305
2525
|
loading_quote: "Finding best route",
|
|
2306
2526
|
select_route: "Select provider",
|
|
2307
|
-
|
|
2527
|
+
status: direction === "onramp" ? "Complete your deposit" : "Complete your withdrawal",
|
|
2528
|
+
error: "Something went wrong"
|
|
2308
2529
|
};
|
|
2309
2530
|
const stepSubtitle = {
|
|
2310
2531
|
input: direction === "onramp" ? "Enter the amount you want to deposit" : "Enter the amount you want to withdraw",
|
|
2311
2532
|
loading_quote: "Comparing providers in real time\u2026",
|
|
2312
2533
|
select_route: "All prices include fees",
|
|
2313
|
-
|
|
2534
|
+
status: `Finish the flow at ${provider || "the provider"} to continue`,
|
|
2535
|
+
error: "Please try again"
|
|
2314
2536
|
};
|
|
2315
2537
|
return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-ramp-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
|
|
2316
2538
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-header", children: [
|
|
@@ -2406,183 +2628,183 @@ function RampWidgetTemplate({
|
|
|
2406
2628
|
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-route-list", children: quotes.map((q, i) => /* @__PURE__ */ jsx(RouteDisplay, { quote: q, onSelect: onSelectQuote }, i)) }),
|
|
2407
2629
|
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" })
|
|
2408
2630
|
] }),
|
|
2409
|
-
step === "
|
|
2410
|
-
/* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-title", children: paymentInstructions.type }),
|
|
2631
|
+
step === "status" && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment", children: [
|
|
2411
2632
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2412
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children:
|
|
2413
|
-
/* @__PURE__ */
|
|
2414
|
-
/* @__PURE__ */ jsx("code", { children: paymentInstructions.value }),
|
|
2415
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-ramp-copy-btn", onClick: () => onCopy(paymentInstructions.value), children: "Copy" })
|
|
2416
|
-
] })
|
|
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 }) })
|
|
2417
2635
|
] }),
|
|
2418
2636
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
2419
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "
|
|
2420
|
-
/* @__PURE__ */
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
" ",
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
"button",
|
|
2428
|
-
{
|
|
2429
|
-
type: "button",
|
|
2430
|
-
className: "pollar-ramp-copy-btn",
|
|
2431
|
-
onClick: () => onCopy(`${paymentInstructions.amount} ${paymentInstructions.currency}`),
|
|
2432
|
-
children: "Copy"
|
|
2433
|
-
}
|
|
2434
|
-
)
|
|
2435
|
-
] })
|
|
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
|
+
) })
|
|
2436
2645
|
] }),
|
|
2437
|
-
|
|
2438
|
-
"
|
|
2439
|
-
|
|
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
|
+
] }) })
|
|
2440
2653
|
] }),
|
|
2441
|
-
/* @__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
|
+
] })
|
|
2442
2668
|
] })
|
|
2443
2669
|
] });
|
|
2444
2670
|
}
|
|
2445
|
-
var
|
|
2446
|
-
{
|
|
2447
|
-
quoteId: "meld-default",
|
|
2448
|
-
provider: "Meld",
|
|
2449
|
-
fee: 1.2,
|
|
2450
|
-
feeCurrency: "USD",
|
|
2451
|
-
rate: 1,
|
|
2452
|
-
rail: "ACH",
|
|
2453
|
-
protocol: "REST",
|
|
2454
|
-
estimatedTime: "~20 min",
|
|
2455
|
-
recommended: true
|
|
2456
|
-
}
|
|
2457
|
-
];
|
|
2458
|
-
var MOCK_QUOTES = {
|
|
2459
|
-
MX: [
|
|
2460
|
-
{
|
|
2461
|
-
quoteId: "etherfuse-mx",
|
|
2462
|
-
provider: "Etherfuse",
|
|
2463
|
-
fee: 0.5,
|
|
2464
|
-
feeCurrency: "MXN",
|
|
2465
|
-
rate: 17.2,
|
|
2466
|
-
rail: "SPEI",
|
|
2467
|
-
protocol: "SEP-24",
|
|
2468
|
-
estimatedTime: "~10 min",
|
|
2469
|
-
recommended: true
|
|
2470
|
-
},
|
|
2471
|
-
{
|
|
2472
|
-
quoteId: "alfredpay-mx",
|
|
2473
|
-
provider: "AlfredPay",
|
|
2474
|
-
fee: 0.8,
|
|
2475
|
-
feeCurrency: "MXN",
|
|
2476
|
-
rate: 17.1,
|
|
2477
|
-
rail: "SPEI",
|
|
2478
|
-
protocol: "REST",
|
|
2479
|
-
estimatedTime: "~15 min",
|
|
2480
|
-
recommended: false
|
|
2481
|
-
}
|
|
2482
|
-
],
|
|
2483
|
-
BR: [
|
|
2484
|
-
{
|
|
2485
|
-
quoteId: "abroad-br",
|
|
2486
|
-
provider: "Abroad",
|
|
2487
|
-
fee: 0.6,
|
|
2488
|
-
feeCurrency: "BRL",
|
|
2489
|
-
rate: 5.1,
|
|
2490
|
-
rail: "PIX",
|
|
2491
|
-
protocol: "REST",
|
|
2492
|
-
estimatedTime: "~5 min",
|
|
2493
|
-
recommended: true
|
|
2494
|
-
}
|
|
2495
|
-
],
|
|
2496
|
-
CO: [
|
|
2497
|
-
{
|
|
2498
|
-
quoteId: "abroad-co",
|
|
2499
|
-
provider: "Abroad",
|
|
2500
|
-
fee: 0.7,
|
|
2501
|
-
feeCurrency: "COP",
|
|
2502
|
-
rate: 4100,
|
|
2503
|
-
rail: "PSE",
|
|
2504
|
-
protocol: "REST",
|
|
2505
|
-
estimatedTime: "~10 min",
|
|
2506
|
-
recommended: true
|
|
2507
|
-
},
|
|
2508
|
-
{
|
|
2509
|
-
quoteId: "koywe-co",
|
|
2510
|
-
provider: "Koywe",
|
|
2511
|
-
fee: 0.9,
|
|
2512
|
-
feeCurrency: "COP",
|
|
2513
|
-
rate: 4095,
|
|
2514
|
-
rail: "PSE",
|
|
2515
|
-
protocol: "REST",
|
|
2516
|
-
estimatedTime: "~15 min",
|
|
2517
|
-
recommended: false
|
|
2518
|
-
}
|
|
2519
|
-
],
|
|
2520
|
-
DEFAULT: MOCK_DEFAULT_QUOTES
|
|
2521
|
-
};
|
|
2522
|
-
var MOCK_PAYMENT = {
|
|
2523
|
-
type: "CLABE",
|
|
2524
|
-
value: "646180157088723456",
|
|
2525
|
-
amount: 1e3,
|
|
2526
|
-
currency: "MXN",
|
|
2527
|
-
expiresAt: new Date(Date.now() + 30 * 60 * 1e3).toISOString()
|
|
2528
|
-
};
|
|
2671
|
+
var TERMINAL = ["completed", "failed"];
|
|
2529
2672
|
function RampWidget({ onClose }) {
|
|
2530
|
-
const { getClient, wallet, styles } = usePollar();
|
|
2673
|
+
const { getClient, signTx, wallet, styles } = usePollar();
|
|
2531
2674
|
const walletAddress = wallet?.address ?? "";
|
|
2675
|
+
const client = getClient();
|
|
2676
|
+
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
2532
2677
|
const [step, setStep] = useState("input");
|
|
2533
2678
|
const [direction, setDirection] = useState("onramp");
|
|
2534
2679
|
const [amount, setAmount] = useState("");
|
|
2535
|
-
const [currency, setCurrency] = useState("
|
|
2536
|
-
const [country, setCountry] = useState("
|
|
2680
|
+
const [currency, setCurrency] = useState("ARS");
|
|
2681
|
+
const [country, setCountry] = useState("AR");
|
|
2537
2682
|
const [quotes, setQuotes] = useState([]);
|
|
2538
|
-
const [paymentInstructions, setPaymentInstructions] = useState(null);
|
|
2539
2683
|
const [isLoading, setIsLoading] = useState(false);
|
|
2540
|
-
const
|
|
2541
|
-
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
|
+
}
|
|
2542
2748
|
async function handleFindRoute() {
|
|
2543
2749
|
setStep("loading_quote");
|
|
2544
2750
|
setIsLoading(true);
|
|
2751
|
+
setErrorMsg(null);
|
|
2545
2752
|
try {
|
|
2546
|
-
const result = await client.getRampsQuote({
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
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");
|
|
2556
2765
|
} finally {
|
|
2557
2766
|
setIsLoading(false);
|
|
2558
|
-
setStep("select_route");
|
|
2559
2767
|
}
|
|
2560
2768
|
}
|
|
2561
2769
|
async function handleSelectQuote(quote) {
|
|
2562
|
-
if (!walletAddress) return;
|
|
2563
2770
|
setIsLoading(true);
|
|
2564
|
-
|
|
2565
|
-
quoteId: `${quote.provider}-${Date.now()}`,
|
|
2566
|
-
amount: Number(amount),
|
|
2567
|
-
currency,
|
|
2568
|
-
country,
|
|
2569
|
-
walletAddress
|
|
2570
|
-
};
|
|
2771
|
+
setErrorMsg(null);
|
|
2571
2772
|
try {
|
|
2572
|
-
const
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
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");
|
|
2577
2779
|
} finally {
|
|
2578
2780
|
setIsLoading(false);
|
|
2579
|
-
setStep("payment_instructions");
|
|
2580
2781
|
}
|
|
2581
2782
|
}
|
|
2582
|
-
function
|
|
2583
|
-
|
|
2584
|
-
});
|
|
2783
|
+
function handleOpenKyc() {
|
|
2784
|
+
if (kycUrl) window.open(kycUrl, "_blank", "noopener,noreferrer");
|
|
2585
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
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
const canComplete = direction === "offramp" && step === "status" && txStatus !== "completed" && !stellarTxHash;
|
|
2586
2808
|
return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsx(
|
|
2587
2809
|
RampWidgetTemplate,
|
|
2588
2810
|
{
|
|
@@ -2594,15 +2816,23 @@ function RampWidget({ onClose }) {
|
|
|
2594
2816
|
currency,
|
|
2595
2817
|
country,
|
|
2596
2818
|
quotes,
|
|
2597
|
-
paymentInstructions,
|
|
2598
2819
|
isLoading,
|
|
2820
|
+
provider,
|
|
2821
|
+
txStatus,
|
|
2822
|
+
kycUrl,
|
|
2823
|
+
stellarTxHash,
|
|
2824
|
+
canComplete,
|
|
2825
|
+
completing,
|
|
2826
|
+
errorMsg,
|
|
2599
2827
|
onDirectionChange: setDirection,
|
|
2600
2828
|
onAmountChange: setAmount,
|
|
2601
2829
|
onCurrencyChange: setCurrency,
|
|
2602
2830
|
onCountryChange: setCountry,
|
|
2603
2831
|
onFindRoute: handleFindRoute,
|
|
2604
2832
|
onSelectQuote: handleSelectQuote,
|
|
2605
|
-
|
|
2833
|
+
onOpenKyc: handleOpenKyc,
|
|
2834
|
+
onCompleteWithdraw: handleCompleteWithdraw,
|
|
2835
|
+
onRetry: resetToInput,
|
|
2606
2836
|
onClose
|
|
2607
2837
|
}
|
|
2608
2838
|
) });
|
|
@@ -3266,6 +3496,415 @@ function SendModal({ onClose }) {
|
|
|
3266
3496
|
}
|
|
3267
3497
|
) });
|
|
3268
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
|
+
}
|
|
3269
3908
|
function describeDevice(s) {
|
|
3270
3909
|
if (s.deviceLabel) return s.deviceLabel;
|
|
3271
3910
|
if (!s.userAgent) return "Unknown device";
|
|
@@ -3960,7 +4599,6 @@ var PollarContext = createContext(null);
|
|
|
3960
4599
|
function PollarProvider({
|
|
3961
4600
|
client,
|
|
3962
4601
|
appConfig: appConfigProp,
|
|
3963
|
-
ui,
|
|
3964
4602
|
adapters,
|
|
3965
4603
|
onStorageDegrade,
|
|
3966
4604
|
children
|
|
@@ -4012,6 +4650,30 @@ function PollarProvider({
|
|
|
4012
4650
|
}
|
|
4013
4651
|
});
|
|
4014
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]);
|
|
4015
4677
|
useEffect(() => {
|
|
4016
4678
|
setModalErrorLogger(pollarClient.getLogger());
|
|
4017
4679
|
}, [pollarClient]);
|
|
@@ -4037,6 +4699,7 @@ function PollarProvider({
|
|
|
4037
4699
|
const [walletBalanceModalOpen, setWalletBalanceModalOpen] = useState(false);
|
|
4038
4700
|
const [enabledAssetsModalOpen, setEnabledAssetsModalOpen] = useState(false);
|
|
4039
4701
|
const [sendModalOpen, setSendModalOpen] = useState(false);
|
|
4702
|
+
const [swapModalOpen, setSwapModalOpen] = useState(false);
|
|
4040
4703
|
const [receiveModalOpen, setReceiveModalOpen] = useState(false);
|
|
4041
4704
|
const [sessionsModalOpen, setSessionsModalOpen] = useState(false);
|
|
4042
4705
|
const [distributionRulesModalOpen, setDistributionRulesModalOpen] = useState(false);
|
|
@@ -4044,7 +4707,6 @@ function PollarProvider({
|
|
|
4044
4707
|
const getClient = useCallback(() => pollarClient, [pollarClient]);
|
|
4045
4708
|
const refreshWalletBalance = useCallback(() => pollarClient.refreshBalance(), [pollarClient, walletAddress]);
|
|
4046
4709
|
const refreshAssets = useCallback(() => pollarClient.refreshAssets(), [pollarClient, walletAddress]);
|
|
4047
|
-
const renderWallets = ui?.renderWallets;
|
|
4048
4710
|
const contextValue = useMemo(() => {
|
|
4049
4711
|
const styles = resolvedConfig.styles ?? {};
|
|
4050
4712
|
return {
|
|
@@ -4082,6 +4744,10 @@ function PollarProvider({
|
|
|
4082
4744
|
// send / receive
|
|
4083
4745
|
openSendModal: () => setSendModalOpen(true),
|
|
4084
4746
|
openReceiveModal: () => setReceiveModalOpen(true),
|
|
4747
|
+
// swap
|
|
4748
|
+
getSwapQuote: (params) => pollarClient.getSwapQuote(params),
|
|
4749
|
+
swap: (quote, opts) => pollarClient.swap(quote, opts),
|
|
4750
|
+
openSwapModal: () => setSwapModalOpen(true),
|
|
4085
4751
|
// sessions
|
|
4086
4752
|
sessions,
|
|
4087
4753
|
openSessionsModal: () => setSessionsModalOpen(true),
|
|
@@ -4100,7 +4766,6 @@ function PollarProvider({
|
|
|
4100
4766
|
// config
|
|
4101
4767
|
appConfig: resolvedConfig,
|
|
4102
4768
|
styles,
|
|
4103
|
-
renderWallets,
|
|
4104
4769
|
adapters
|
|
4105
4770
|
};
|
|
4106
4771
|
}, [
|
|
@@ -4117,8 +4782,7 @@ function PollarProvider({
|
|
|
4117
4782
|
refreshAssets,
|
|
4118
4783
|
networkState,
|
|
4119
4784
|
resolvedConfig,
|
|
4120
|
-
adapters
|
|
4121
|
-
renderWallets
|
|
4785
|
+
adapters
|
|
4122
4786
|
]);
|
|
4123
4787
|
return /* @__PURE__ */ jsxs(PollarContext.Provider, { value: contextValue, children: [
|
|
4124
4788
|
children,
|
|
@@ -4138,6 +4802,7 @@ function PollarProvider({
|
|
|
4138
4802
|
walletBalanceModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setWalletBalanceModalOpen(false), children: /* @__PURE__ */ jsx(WalletBalanceModal, { onClose: () => setWalletBalanceModalOpen(false) }) }),
|
|
4139
4803
|
enabledAssetsModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setEnabledAssetsModalOpen(false), children: /* @__PURE__ */ jsx(EnabledAssetsModal, { onClose: () => setEnabledAssetsModalOpen(false) }) }),
|
|
4140
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) }) }),
|
|
4141
4806
|
receiveModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setReceiveModalOpen(false), children: /* @__PURE__ */ jsx(ReceiveModal, { onClose: () => setReceiveModalOpen(false) }) }),
|
|
4142
4807
|
sessionsModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSessionsModalOpen(false), children: /* @__PURE__ */ jsx(SessionsModal, { onClose: () => setSessionsModalOpen(false) }) }),
|
|
4143
4808
|
distributionRulesModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setDistributionRulesModalOpen(false), children: /* @__PURE__ */ jsx(DistributionRulesModal, { onClose: () => setDistributionRulesModalOpen(false) }) })
|
|
@@ -4586,6 +5251,6 @@ function WalletButton() {
|
|
|
4586
5251
|
);
|
|
4587
5252
|
}
|
|
4588
5253
|
|
|
4589
|
-
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 };
|
|
4590
5255
|
//# sourceMappingURL=index.mjs.map
|
|
4591
5256
|
//# sourceMappingURL=index.mjs.map
|