@pollar/react 0.12.0-rc.2 → 0.12.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 +13 -3
- package/dist/index.css +363 -172
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +201 -162
- package/dist/index.d.ts +201 -162
- package/dist/index.js +1460 -1548
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1461 -1549
- 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, describeRampAction,
|
|
2
|
+
import { AUTH_ERROR_CODES, rampLegTitle, rampRequirementCopy, rampTrustlineAsset, rampWalletStep, rampResolutionText, describeRampAction, rampLegStatus, rampNextApproval, rampOrderStopped, rampOrderReceive, rampRailLabel, rampNoRouteText, rampFieldError, rampFieldValid, rampLegNote, rampStepTitle, rampStepStatusText, rampLegTimeLeft, rampOrderResolutionText, rampCountries, rampQuoteFields, isPollarApiError, transactionErrorMessage, WalletType, isPollarClient, PollarClient, isInteractiveAuthAdapter, rampTrustlineErrorText, isPollarNetworkError, toBaseUnits, appUnavailableMessage, cosignRefusalMessage, fromBaseUnits, assertRampStellarSigner } from '@pollar/core';
|
|
3
3
|
import { forwardRef, createContext, useState, useCallback, useEffect, useMemo, useRef, useContext, Component } from 'react';
|
|
4
4
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { startAuthentication, startRegistration } from '@simplewebauthn/browser';
|
|
@@ -999,7 +999,6 @@ var require_QRCode = __commonJS({
|
|
|
999
999
|
});
|
|
1000
1000
|
|
|
1001
1001
|
// src/constants.ts
|
|
1002
|
-
var LOGO_POLLAR = "https://pollar.xyz/assets/logo_pollar.png";
|
|
1003
1002
|
var LOGO_POLLAR_WORDMARK_ON_LIGHT = "https://www.pollar.xyz/brandkit/pollar-logo-horizontal-on-light.png";
|
|
1004
1003
|
var LOGO_POLLAR_WORDMARK_ON_DARK = "https://www.pollar.xyz/brandkit/pollar-logo-horizontal-on-dark.png";
|
|
1005
1004
|
var LOGO_POLLAR_MARK_ON_LIGHT = "https://www.pollar.xyz/brandkit/pollar-mark-on-light.png";
|
|
@@ -1029,6 +1028,13 @@ var ModalErrorBoundary = class extends Component {
|
|
|
1029
1028
|
return this.props.children;
|
|
1030
1029
|
}
|
|
1031
1030
|
};
|
|
1031
|
+
function ModalLogo({ logoUrl }) {
|
|
1032
|
+
if (logoUrl) return /* @__PURE__ */ jsx("img", { src: logoUrl, alt: "Logo", className: "pollar-logo" });
|
|
1033
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1034
|
+
/* @__PURE__ */ jsx("img", { src: LOGO_POLLAR_MARK_ON_LIGHT, alt: "Pollar", className: "pollar-logo pollar-logo-on-light" }),
|
|
1035
|
+
/* @__PURE__ */ jsx("img", { src: LOGO_POLLAR_MARK_ON_DARK, alt: "Pollar", className: "pollar-logo pollar-logo-on-dark" })
|
|
1036
|
+
] });
|
|
1037
|
+
}
|
|
1032
1038
|
var PollarModalFooter = () => {
|
|
1033
1039
|
return /* @__PURE__ */ jsxs("div", { className: "pollar-footer", children: [
|
|
1034
1040
|
/* @__PURE__ */ jsx("span", { className: "pollar-footer-protected", children: "Protected by" }),
|
|
@@ -1036,7 +1042,7 @@ var PollarModalFooter = () => {
|
|
|
1036
1042
|
/* @__PURE__ */ jsx("img", { src: LOGO_POLLAR_WORDMARK_ON_DARK, alt: "Pollar", className: "pollar-footer-logo pollar-logo-on-dark" }),
|
|
1037
1043
|
/* @__PURE__ */ jsxs("span", { className: "pollar-footer-version", children: [
|
|
1038
1044
|
"v",
|
|
1039
|
-
"0.12.0
|
|
1045
|
+
"0.12.0"
|
|
1040
1046
|
] })
|
|
1041
1047
|
] });
|
|
1042
1048
|
};
|
|
@@ -1218,42 +1224,75 @@ function readableTextOn(background) {
|
|
|
1218
1224
|
const [r, g, b] = rgb;
|
|
1219
1225
|
return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 > 0.6 ? "#111827" : "#ffffff";
|
|
1220
1226
|
}
|
|
1227
|
+
var PALETTES = {
|
|
1228
|
+
light: {
|
|
1229
|
+
bg: "#ffffff",
|
|
1230
|
+
border: "#e5e7eb",
|
|
1231
|
+
text: "#111827",
|
|
1232
|
+
muted: "#6b7280",
|
|
1233
|
+
"input-bg": "#f9fafb",
|
|
1234
|
+
"error-bg": "#fef2f2",
|
|
1235
|
+
"error-border": "#fecaca",
|
|
1236
|
+
"error-text": "#dc2626",
|
|
1237
|
+
"success-text": "#16a34a"
|
|
1238
|
+
},
|
|
1239
|
+
dark: {
|
|
1240
|
+
bg: "#1a1a1a",
|
|
1241
|
+
border: "#374151",
|
|
1242
|
+
text: "#ffffff",
|
|
1243
|
+
muted: "#9ca3af",
|
|
1244
|
+
"input-bg": "#374151",
|
|
1245
|
+
"error-bg": "#2a1515",
|
|
1246
|
+
"error-border": "#7f1d1d",
|
|
1247
|
+
"error-text": "#f87171",
|
|
1248
|
+
"success-text": "#4ade80"
|
|
1249
|
+
}
|
|
1250
|
+
};
|
|
1251
|
+
function mix(fg, percent, bg) {
|
|
1252
|
+
return `color-mix(in srgb, ${fg} ${percent}%, ${bg})`;
|
|
1253
|
+
}
|
|
1221
1254
|
function buildModalCssVars(theme, accentColor, overrides = {}, variant = "compact") {
|
|
1222
1255
|
const isDark = theme === "dark";
|
|
1223
|
-
const
|
|
1256
|
+
const palette = isDark ? PALETTES.dark : PALETTES.light;
|
|
1257
|
+
const bg = color(overrides.backgroundColor, "");
|
|
1258
|
+
const text = color(overrides.textColor, "");
|
|
1259
|
+
const pinned = isDark || bg !== "" || text !== "";
|
|
1224
1260
|
const secondaryBg = color(overrides.buttonColor, "");
|
|
1225
|
-
|
|
1226
|
-
"--pollar-accent": accentColor,
|
|
1227
|
-
"--pollar-bg": color(overrides.backgroundColor, isDark ? "#1a1a1a" : "#ffffff"),
|
|
1228
|
-
"--pollar-border": isDark ? "#374151" : "#e5e7eb",
|
|
1229
|
-
"--pollar-text": textColor,
|
|
1230
|
-
"--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
|
|
1261
|
+
const vars = {
|
|
1262
|
+
"--pollar-brand-accent": accentColor,
|
|
1231
1263
|
// The primary button is the accent's, straight up; its label follows the
|
|
1232
1264
|
// accent's luminance so a pale accent doesn't render white-on-white.
|
|
1233
|
-
"--pollar-btn-primary-fg": readableTextOn(accentColor),
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
"--pollar-btn-secondary-fg": readableTextOn(secondaryBg)
|
|
1237
|
-
} : {},
|
|
1238
|
-
"--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
|
|
1239
|
-
"--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
|
|
1240
|
-
"--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
|
|
1241
|
-
"--pollar-error-text": isDark ? "#f87171" : "#dc2626",
|
|
1242
|
-
"--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
|
|
1243
|
-
"--pollar-logo-on-light-display": isDark ? "none" : "block",
|
|
1244
|
-
"--pollar-logo-on-dark-display": isDark ? "block" : "none",
|
|
1245
|
-
"--pollar-modal-border-radius": px(overrides.modalBorderRadius, DEFAULT_MODAL_BORDER_RADIUS),
|
|
1246
|
-
"--pollar-buttons-border-radius": px(overrides.buttonBorderRadius, DEFAULT_BUTTON_BORDER_RADIUS),
|
|
1247
|
-
"--pollar-buttons-height": "44px",
|
|
1248
|
-
"--pollar-input-height": "44px",
|
|
1249
|
-
"--pollar-input-border-radius": "0.5rem",
|
|
1250
|
-
"--pollar-card-border-radius": "10px",
|
|
1251
|
-
...variant === "hero" ? {
|
|
1252
|
-
"--pollar-modal-padding": "2rem",
|
|
1253
|
-
"--pollar-modal-heading-size": "1.375rem",
|
|
1254
|
-
"--pollar-modal-subtitle-size": "0.9rem"
|
|
1255
|
-
} : {}
|
|
1265
|
+
"--pollar-brand-btn-primary-fg": readableTextOn(accentColor),
|
|
1266
|
+
"--pollar-brand-modal-border-radius": px(overrides.modalBorderRadius, DEFAULT_MODAL_BORDER_RADIUS),
|
|
1267
|
+
"--pollar-brand-buttons-border-radius": px(overrides.buttonBorderRadius, DEFAULT_BUTTON_BORDER_RADIUS)
|
|
1256
1268
|
};
|
|
1269
|
+
if (secondaryBg) {
|
|
1270
|
+
vars["--pollar-brand-btn-secondary-bg"] = secondaryBg;
|
|
1271
|
+
vars["--pollar-brand-btn-secondary-fg"] = readableTextOn(secondaryBg);
|
|
1272
|
+
}
|
|
1273
|
+
if (pinned) {
|
|
1274
|
+
for (const [name, value] of Object.entries(palette)) vars[`--pollar-brand-${name}`] = value;
|
|
1275
|
+
vars["--pollar-brand-logo-on-light-display"] = isDark ? "none" : "block";
|
|
1276
|
+
vars["--pollar-brand-logo-on-dark-display"] = isDark ? "block" : "none";
|
|
1277
|
+
}
|
|
1278
|
+
if (bg || text) {
|
|
1279
|
+
const surface = bg || palette.bg;
|
|
1280
|
+
const ink = text || palette.text;
|
|
1281
|
+
vars["--pollar-brand-bg"] = surface;
|
|
1282
|
+
vars["--pollar-brand-text"] = ink;
|
|
1283
|
+
vars["--pollar-brand-border"] = mix(ink, 14, surface);
|
|
1284
|
+
vars["--pollar-brand-muted"] = mix(ink, 62, surface);
|
|
1285
|
+
vars["--pollar-brand-input-bg"] = mix(ink, 4, surface);
|
|
1286
|
+
const darkSurface = readableTextOn(surface) === "#ffffff";
|
|
1287
|
+
vars["--pollar-brand-logo-on-light-display"] = darkSurface ? "none" : "block";
|
|
1288
|
+
vars["--pollar-brand-logo-on-dark-display"] = darkSurface ? "block" : "none";
|
|
1289
|
+
}
|
|
1290
|
+
if (variant === "hero") {
|
|
1291
|
+
vars["--pollar-brand-modal-padding"] = "2rem";
|
|
1292
|
+
vars["--pollar-brand-modal-heading-size"] = "1.375rem";
|
|
1293
|
+
vars["--pollar-brand-modal-subtitle-size"] = "0.9rem";
|
|
1294
|
+
}
|
|
1295
|
+
return vars;
|
|
1257
1296
|
}
|
|
1258
1297
|
function modalChrome(styles) {
|
|
1259
1298
|
const zIndex = styles.modalZIndex;
|
|
@@ -1268,7 +1307,7 @@ function modalChrome(styles) {
|
|
|
1268
1307
|
buttonBorderRadius: styles.buttonBorderRadius
|
|
1269
1308
|
},
|
|
1270
1309
|
overlayStyle: {
|
|
1271
|
-
"--pollar-overlay-z-index": typeof zIndex === "number" && Number.isFinite(zIndex) ? zIndex : DEFAULT_OVERLAY_Z_INDEX
|
|
1310
|
+
"--pollar-brand-overlay-z-index": typeof zIndex === "number" && Number.isFinite(zIndex) ? zIndex : DEFAULT_OVERLAY_Z_INDEX
|
|
1272
1311
|
}
|
|
1273
1312
|
};
|
|
1274
1313
|
}
|
|
@@ -1953,6 +1992,8 @@ function KycModalTemplate({
|
|
|
1953
1992
|
reviewReason,
|
|
1954
1993
|
processing = false,
|
|
1955
1994
|
isLoading,
|
|
1995
|
+
startingProviderId = null,
|
|
1996
|
+
directOpen = false,
|
|
1956
1997
|
error,
|
|
1957
1998
|
onSelectProvider,
|
|
1958
1999
|
onDoneVerifying,
|
|
@@ -1961,6 +2002,7 @@ function KycModalTemplate({
|
|
|
1961
2002
|
onClose
|
|
1962
2003
|
}) {
|
|
1963
2004
|
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
|
|
2005
|
+
const busy = isLoading || startingProviderId !== null;
|
|
1964
2006
|
return /* @__PURE__ */ jsxs(
|
|
1965
2007
|
"div",
|
|
1966
2008
|
{
|
|
@@ -1988,7 +2030,7 @@ function KycModalTemplate({
|
|
|
1988
2030
|
type: "button",
|
|
1989
2031
|
className: "pollar-modal-close",
|
|
1990
2032
|
onClick: onRefresh,
|
|
1991
|
-
disabled:
|
|
2033
|
+
disabled: busy,
|
|
1992
2034
|
"aria-label": "Refresh",
|
|
1993
2035
|
title: "Refresh providers",
|
|
1994
2036
|
children: /* @__PURE__ */ jsx(
|
|
@@ -2018,7 +2060,14 @@ function KycModalTemplate({
|
|
|
2018
2060
|
] })
|
|
2019
2061
|
] }),
|
|
2020
2062
|
error && /* @__PURE__ */ jsx("p", { className: "pollar-kyc-error", role: "alert", children: error }),
|
|
2021
|
-
step === "select_provider" && (
|
|
2063
|
+
step === "select_provider" && (startingProviderId !== null && directOpen ? /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", "aria-live": "polite", children: [
|
|
2064
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
|
|
2065
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
2066
|
+
"Opening ",
|
|
2067
|
+
selectedProvider?.name ?? "verification",
|
|
2068
|
+
"\u2026"
|
|
2069
|
+
] })
|
|
2070
|
+
] }) : isLoading && providers.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "pollar-loading-block", children: [
|
|
2022
2071
|
/* @__PURE__ */ jsx("div", { className: "pollar-spinner" }),
|
|
2023
2072
|
/* @__PURE__ */ jsx("span", { children: "Loading providers\u2026" })
|
|
2024
2073
|
] }) : /* @__PURE__ */ jsxs("div", { className: "pollar-kyc-providers", children: [
|
|
@@ -2028,11 +2077,15 @@ function KycModalTemplate({
|
|
|
2028
2077
|
{
|
|
2029
2078
|
type: "button",
|
|
2030
2079
|
className: "pollar-kyc-provider-btn",
|
|
2031
|
-
disabled:
|
|
2080
|
+
disabled: busy,
|
|
2081
|
+
"aria-busy": startingProviderId === p.id,
|
|
2032
2082
|
onClick: () => onSelectProvider(p),
|
|
2033
2083
|
children: [
|
|
2034
2084
|
/* @__PURE__ */ jsx("span", { className: "pollar-kyc-provider-name", children: p.name }),
|
|
2035
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-kyc-provider-flow", children:
|
|
2085
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-kyc-provider-flow", children: startingProviderId === p.id ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2086
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
2087
|
+
"Opening\u2026"
|
|
2088
|
+
] }) : p.flow === "redirect" ? "Continue in a new tab" : "Continue here" })
|
|
2036
2089
|
]
|
|
2037
2090
|
},
|
|
2038
2091
|
p.id
|
|
@@ -2083,7 +2136,7 @@ function KycModalTemplate({
|
|
|
2083
2136
|
/* @__PURE__ */ jsx(KycStatus, { status: kycStatus, ...processing ? { label: "Approved" } : {} }),
|
|
2084
2137
|
/* @__PURE__ */ jsx("p", { className: "pollar-kyc-result-text", children: kycStatus === "approved" ? "Your identity has been verified successfully." : kycStatus === "rejected" ? "Your verification was not approved. Contact support for the next steps." : kycStatus === "expired" ? "Your verification expired. Start again to verify your identity." : processing ? kycProcessingMessage() : kycReviewMessage(reviewReason) }),
|
|
2085
2138
|
/* @__PURE__ */ jsxs("div", { className: "pollar-modal-actions", children: [
|
|
2086
|
-
kycStatus === "expired" && onStartAgain && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onStartAgain, disabled:
|
|
2139
|
+
kycStatus === "expired" && onStartAgain && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onStartAgain, disabled: busy, children: "Start again" }),
|
|
2087
2140
|
kycStatus !== "approved" && kycStatus !== "rejected" && kycStatus !== "expired" && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onDoneVerifying, children: "Check again" }),
|
|
2088
2141
|
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onClose, children: "Close" })
|
|
2089
2142
|
] })
|
|
@@ -2116,6 +2169,8 @@ function KycModal({
|
|
|
2116
2169
|
const [reviewReason, setReviewReason] = useState(null);
|
|
2117
2170
|
const [processing, setProcessing] = useState(false);
|
|
2118
2171
|
const [isLoading, setIsLoading] = useState(false);
|
|
2172
|
+
const [startingProviderId, setStartingProviderId] = useState(null);
|
|
2173
|
+
const [directOpen, setDirectOpen] = useState(false);
|
|
2119
2174
|
const [error, setError] = useState(null);
|
|
2120
2175
|
const idempotencyKeys = useRef({});
|
|
2121
2176
|
const autoOpened = useRef(false);
|
|
@@ -2143,7 +2198,7 @@ function KycModal({
|
|
|
2143
2198
|
starting.current = true;
|
|
2144
2199
|
setSelectedProvider(provider);
|
|
2145
2200
|
setError(null);
|
|
2146
|
-
|
|
2201
|
+
setStartingProviderId(provider.id);
|
|
2147
2202
|
const key = (_a = idempotencyKeys.current)[_b = provider.id] ?? (_a[_b] = newIdempotencyKey());
|
|
2148
2203
|
try {
|
|
2149
2204
|
const result = await client.resolveKyc(
|
|
@@ -2181,7 +2236,7 @@ function KycModal({
|
|
|
2181
2236
|
setStep("select_provider");
|
|
2182
2237
|
} finally {
|
|
2183
2238
|
starting.current = false;
|
|
2184
|
-
|
|
2239
|
+
setStartingProviderId(null);
|
|
2185
2240
|
}
|
|
2186
2241
|
}
|
|
2187
2242
|
const loadProviders = useCallback(() => {
|
|
@@ -2200,6 +2255,7 @@ function KycModal({
|
|
|
2200
2255
|
void loadProviders().then((list) => {
|
|
2201
2256
|
if (!providerId || autoOpened.current) return;
|
|
2202
2257
|
autoOpened.current = true;
|
|
2258
|
+
setDirectOpen(true);
|
|
2203
2259
|
const target = list.find((p) => p.id === providerId);
|
|
2204
2260
|
if (target) void handleSelectProvider(target);
|
|
2205
2261
|
else
|
|
@@ -2249,6 +2305,8 @@ function KycModal({
|
|
|
2249
2305
|
reviewReason,
|
|
2250
2306
|
processing,
|
|
2251
2307
|
isLoading,
|
|
2308
|
+
startingProviderId,
|
|
2309
|
+
directOpen,
|
|
2252
2310
|
error,
|
|
2253
2311
|
onSelectProvider: handleSelectProvider,
|
|
2254
2312
|
onDoneVerifying: handleDoneVerifying,
|
|
@@ -2938,7 +2996,7 @@ function LoginModalTemplate({
|
|
|
2938
2996
|
}
|
|
2939
2997
|
) }),
|
|
2940
2998
|
/* @__PURE__ */ jsxs("div", { className: "pollar-header", children: [
|
|
2941
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsx(
|
|
2999
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsx(ModalLogo, { logoUrl }) }),
|
|
2942
3000
|
/* @__PURE__ */ jsx("h2", { className: "pollar-title", children: appName }),
|
|
2943
3001
|
/* @__PURE__ */ jsx("p", { className: "pollar-subtitle", children: "Log in or sign up" })
|
|
2944
3002
|
] }),
|
|
@@ -3104,7 +3162,7 @@ function LoginModalStatus({
|
|
|
3104
3162
|
}
|
|
3105
3163
|
) }),
|
|
3106
3164
|
/* @__PURE__ */ jsxs("div", { className: "pollar-header", children: [
|
|
3107
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsx(
|
|
3165
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsx(ModalLogo, { logoUrl }) }),
|
|
3108
3166
|
/* @__PURE__ */ jsx("h2", { className: "pollar-title", children: appName }),
|
|
3109
3167
|
/* @__PURE__ */ jsx("p", { className: "pollar-subtitle", children: "Log in or sign up" })
|
|
3110
3168
|
] }),
|
|
@@ -3206,7 +3264,7 @@ function PrivyLoginSubmodal({
|
|
|
3206
3264
|
}
|
|
3207
3265
|
) }),
|
|
3208
3266
|
/* @__PURE__ */ jsxs("div", { className: "pollar-header", children: [
|
|
3209
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsx(
|
|
3267
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsx(ModalLogo, { logoUrl }) }),
|
|
3210
3268
|
/* @__PURE__ */ jsx("h2", { className: "pollar-title", children: appName }),
|
|
3211
3269
|
/* @__PURE__ */ jsx("p", { className: "pollar-subtitle", children: adapter.meta.label })
|
|
3212
3270
|
] }),
|
|
@@ -3407,256 +3465,45 @@ function LoginModal({ onClose }) {
|
|
|
3407
3465
|
}
|
|
3408
3466
|
) });
|
|
3409
3467
|
}
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
/* @__PURE__ */ jsx("path", { d: bgD, fill: bgColor }),
|
|
3418
|
-
/* @__PURE__ */ jsx("path", { d: fgD, fill: fgColor })
|
|
3419
|
-
] });
|
|
3420
|
-
});
|
|
3421
|
-
QRCodeSvg.displayName = "QRCodeSvg";
|
|
3422
|
-
function bytesToBinaryString(bytes) {
|
|
3423
|
-
return bytes.map((b) => String.fromCharCode(b & 255)).join("");
|
|
3424
|
-
}
|
|
3425
|
-
function encodeStringToUtf8Bytes(input) {
|
|
3426
|
-
return Array.from(new TextEncoder().encode(input));
|
|
3427
|
-
}
|
|
3428
|
-
var QRCode = forwardRef(function QRCode2({ bgColor = "#FFFFFF", fgColor = "#000000", level = "L", size = 256, value, ...props }, ref) {
|
|
3429
|
-
const qrcode = new import_QRCode.default(-1, import_ErrorCorrectLevel.default[level]);
|
|
3430
|
-
const utf8Bytes = encodeStringToUtf8Bytes(value);
|
|
3431
|
-
const binaryString = bytesToBinaryString(utf8Bytes);
|
|
3432
|
-
qrcode.addData(binaryString, "Byte");
|
|
3433
|
-
qrcode.make();
|
|
3434
|
-
const cells = qrcode.modules;
|
|
3435
|
-
return /* @__PURE__ */ jsx(
|
|
3436
|
-
QRCodeSvg,
|
|
3437
|
-
{
|
|
3438
|
-
...props,
|
|
3439
|
-
bgColor,
|
|
3440
|
-
bgD: cells.map(
|
|
3441
|
-
(row, rowIndex) => row.map((cell, cellIndex) => !cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")
|
|
3442
|
-
).join(" "),
|
|
3443
|
-
fgColor,
|
|
3444
|
-
fgD: cells.map(
|
|
3445
|
-
(row, rowIndex) => row.map((cell, cellIndex) => cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")
|
|
3446
|
-
).join(" "),
|
|
3447
|
-
ref,
|
|
3448
|
-
size,
|
|
3449
|
-
viewBoxSize: cells.length
|
|
3450
|
-
}
|
|
3451
|
-
);
|
|
3452
|
-
});
|
|
3453
|
-
function RampWorkflow({
|
|
3454
|
-
client,
|
|
3455
|
-
snapshot,
|
|
3456
|
-
onChange,
|
|
3457
|
-
onBusyChange
|
|
3458
|
-
}) {
|
|
3459
|
-
const model = describeRampAction(snapshot);
|
|
3460
|
-
const locked = useRef(false);
|
|
3461
|
-
useEffect(() => {
|
|
3462
|
-
setFields({});
|
|
3463
|
-
setError(null);
|
|
3464
|
-
}, [model.action?.actionId]);
|
|
3465
|
-
const [busy, setBusy] = useState(false);
|
|
3466
|
-
const [error, setError] = useState(null);
|
|
3467
|
-
const [fields, setFields] = useState({});
|
|
3468
|
-
const fieldsComplete = model.action?.kind !== "collect_information" || model.action.fields.every((field) => {
|
|
3469
|
-
const value = (fields[field.key] ?? "").trim();
|
|
3470
|
-
if (!value) return field.optional;
|
|
3471
|
-
if (field.type === "email") return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
3472
|
-
return field.type !== "select" || field.options?.some((option) => option.value === value);
|
|
3468
|
+
function findWalletBalance(balances, asset) {
|
|
3469
|
+
const { issuer } = asset;
|
|
3470
|
+
return balances.find((b) => {
|
|
3471
|
+
if (resolveChain(b.chain) !== asset.chain) return false;
|
|
3472
|
+
if (issuer === null) return b.type === "native" || !b.issuer && b.code === asset.code;
|
|
3473
|
+
if (b.code !== asset.code) return false;
|
|
3474
|
+
return issuer === void 0 || !b.issuer || b.issuer.toLowerCase() === issuer.toLowerCase();
|
|
3473
3475
|
});
|
|
3474
|
-
async function continueAction() {
|
|
3475
|
-
if (!model.action || locked.current || !fieldsComplete) return;
|
|
3476
|
-
locked.current = true;
|
|
3477
|
-
setBusy(true);
|
|
3478
|
-
onBusyChange?.(true);
|
|
3479
|
-
setError(null);
|
|
3480
|
-
try {
|
|
3481
|
-
onChange(
|
|
3482
|
-
model.canSign ? await client.signRampAction(snapshot.txId, snapshot) : await client.continueRamp(snapshot.txId, {
|
|
3483
|
-
actionId: model.action.actionId,
|
|
3484
|
-
transactionVersion: snapshot.transactionVersion,
|
|
3485
|
-
...model.action.kind === "collect_information" ? { fields } : {}
|
|
3486
|
-
})
|
|
3487
|
-
);
|
|
3488
|
-
} catch (e) {
|
|
3489
|
-
setError(e instanceof Error ? e.message : "Unable to continue.");
|
|
3490
|
-
} finally {
|
|
3491
|
-
locked.current = false;
|
|
3492
|
-
setBusy(false);
|
|
3493
|
-
onBusyChange?.(false);
|
|
3494
|
-
}
|
|
3495
|
-
}
|
|
3496
|
-
return /* @__PURE__ */ jsxs(
|
|
3497
|
-
"section",
|
|
3498
|
-
{
|
|
3499
|
-
className: "pollar-ramp-payment pollar-ramp-workflow",
|
|
3500
|
-
"aria-label": "Ramp progress",
|
|
3501
|
-
"aria-live": "polite",
|
|
3502
|
-
"aria-busy": busy,
|
|
3503
|
-
children: [
|
|
3504
|
-
/* @__PURE__ */ jsx("h3", { className: "pollar-ramp-payment-title", children: model.title }),
|
|
3505
|
-
snapshot.terms && /* @__PURE__ */ jsxs("p", { className: "pollar-ramp-terms", children: [
|
|
3506
|
-
snapshot.terms.fiatAmount,
|
|
3507
|
-
" ",
|
|
3508
|
-
snapshot.terms.fiatCurrency,
|
|
3509
|
-
" \xB7 ",
|
|
3510
|
-
snapshot.terms.cryptoAmount,
|
|
3511
|
-
" ",
|
|
3512
|
-
snapshot.terms.assetCode,
|
|
3513
|
-
/* @__PURE__ */ jsx("br", {}),
|
|
3514
|
-
"Includes ",
|
|
3515
|
-
snapshot.terms.feeAmount,
|
|
3516
|
-
" ",
|
|
3517
|
-
snapshot.terms.feeCurrency,
|
|
3518
|
-
" fee"
|
|
3519
|
-
] }),
|
|
3520
|
-
model.details.map((item, index) => /* @__PURE__ */ jsxs("p", { className: "pollar-ramp-workflow-detail", children: [
|
|
3521
|
-
/* @__PURE__ */ jsxs("strong", { children: [
|
|
3522
|
-
item.label,
|
|
3523
|
-
": "
|
|
3524
|
-
] }),
|
|
3525
|
-
item.value
|
|
3526
|
-
] }, index)),
|
|
3527
|
-
model.links.map((link, index) => /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("a", { className: "pollar-btn-primary pollar-ramp-hosted-link", href: link.url, target: "_blank", rel: "noopener noreferrer", children: link.label }) }, index)),
|
|
3528
|
-
model.qr && /* @__PURE__ */ jsx(QRCode, { value: model.qr, size: 180 }),
|
|
3529
|
-
model.qr && /* @__PURE__ */ jsx(
|
|
3530
|
-
"button",
|
|
3531
|
-
{
|
|
3532
|
-
className: "pollar-btn-secondary",
|
|
3533
|
-
type: "button",
|
|
3534
|
-
onClick: () => void navigator.clipboard.writeText(model.qr).catch(() => setError("Unable to copy. Select the payment code to copy it manually.")),
|
|
3535
|
-
children: "Copy payment code"
|
|
3536
|
-
}
|
|
3537
|
-
),
|
|
3538
|
-
model.action?.kind === "collect_information" && model.action.fields.map((field) => /* @__PURE__ */ jsxs("label", { className: "pollar-ramp-field", children: [
|
|
3539
|
-
/* @__PURE__ */ jsxs("span", { className: "pollar-ramp-label", children: [
|
|
3540
|
-
field.label,
|
|
3541
|
-
field.optional ? " (optional)" : ""
|
|
3542
|
-
] }),
|
|
3543
|
-
field.type === "select" ? /* @__PURE__ */ jsxs(
|
|
3544
|
-
"select",
|
|
3545
|
-
{
|
|
3546
|
-
className: "pollar-ramp-input",
|
|
3547
|
-
disabled: busy,
|
|
3548
|
-
value: fields[field.key] ?? "",
|
|
3549
|
-
onChange: (e) => setFields((previous) => ({ ...previous, [field.key]: e.target.value })),
|
|
3550
|
-
children: [
|
|
3551
|
-
/* @__PURE__ */ jsx("option", { value: "", children: "Choose" }),
|
|
3552
|
-
field.options?.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label }, option.value))
|
|
3553
|
-
]
|
|
3554
|
-
}
|
|
3555
|
-
) : /* @__PURE__ */ jsx(
|
|
3556
|
-
"input",
|
|
3557
|
-
{
|
|
3558
|
-
className: "pollar-ramp-input",
|
|
3559
|
-
disabled: busy,
|
|
3560
|
-
type: field.type,
|
|
3561
|
-
placeholder: field.placeholder,
|
|
3562
|
-
value: fields[field.key] ?? "",
|
|
3563
|
-
onChange: (e) => setFields((previous) => ({ ...previous, [field.key]: e.target.value }))
|
|
3564
|
-
}
|
|
3565
|
-
),
|
|
3566
|
-
field.hint && /* @__PURE__ */ jsx("small", { className: "pollar-ramp-field-hint", children: field.hint })
|
|
3567
|
-
] }, field.key)),
|
|
3568
|
-
(model.canContinue || model.canSign) && /* @__PURE__ */ jsx(
|
|
3569
|
-
"button",
|
|
3570
|
-
{
|
|
3571
|
-
className: "pollar-btn-primary",
|
|
3572
|
-
type: "button",
|
|
3573
|
-
disabled: busy || !fieldsComplete,
|
|
3574
|
-
onClick: () => void continueAction(),
|
|
3575
|
-
children: busy ? model.canSign ? "Waiting for your wallet\u2026" : "Continuing\u2026" : model.canSign ? "Authorize" : "Continue"
|
|
3576
|
-
}
|
|
3577
|
-
),
|
|
3578
|
-
snapshot.milestones?.map((milestone, index) => /* @__PURE__ */ jsxs("p", { children: [
|
|
3579
|
-
milestone.kind.replace(/_/g, " "),
|
|
3580
|
-
" \xB7 ",
|
|
3581
|
-
milestone.verifiedAt
|
|
3582
|
-
] }, index)),
|
|
3583
|
-
error && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-field-error", role: "alert", children: error }),
|
|
3584
|
-
/* @__PURE__ */ jsxs("small", { className: "pollar-ramp-reference", children: [
|
|
3585
|
-
"Reference: ",
|
|
3586
|
-
snapshot.txId
|
|
3587
|
-
] })
|
|
3588
|
-
]
|
|
3589
|
-
}
|
|
3590
|
-
);
|
|
3591
|
-
}
|
|
3592
|
-
|
|
3593
|
-
// src/components/ramp-widget/ramp-kyc.ts
|
|
3594
|
-
var nonEmpty = (value) => typeof value === "string" && !!value.trim();
|
|
3595
|
-
function requiredRampKyc(error) {
|
|
3596
|
-
if (!error || typeof error !== "object") return null;
|
|
3597
|
-
if (!("code" in error) || error.code !== "SDK_RAMPS_KYC_REQUIRED") return null;
|
|
3598
|
-
const body = "body" in error ? error.body : void 0;
|
|
3599
|
-
if (typeof body !== "object" || body === null) return null;
|
|
3600
|
-
const rampProviderId = "rampProviderId" in body ? body.rampProviderId : void 0;
|
|
3601
|
-
const corridorId = "corridorId" in body ? body.corridorId : void 0;
|
|
3602
|
-
const requirementType = "requirementType" in body ? body.requirementType : void 0;
|
|
3603
|
-
const optionId = "optionId" in body ? body.optionId : void 0;
|
|
3604
|
-
const kycProviderId = "kycProviderId" in body ? body.kycProviderId : void 0;
|
|
3605
|
-
if (!nonEmpty(rampProviderId) || !nonEmpty(corridorId)) return null;
|
|
3606
|
-
if ((requirementType === "FORM" || requirementType === "REGISTRY_CHECK" || requirementType === "PROVIDER_REGISTRATION") && nonEmpty(optionId)) {
|
|
3607
|
-
return { rampProviderId, corridorId, type: requirementType, optionId };
|
|
3608
|
-
}
|
|
3609
|
-
const kyc = nonEmpty(optionId) && requirementType === "KYC" ? optionId : kycProviderId;
|
|
3610
|
-
return nonEmpty(kyc) ? { rampProviderId, corridorId, type: "KYC", optionId: kyc } : null;
|
|
3611
|
-
}
|
|
3612
|
-
function pendingFromQuote(requirement) {
|
|
3613
|
-
return {
|
|
3614
|
-
rampProviderId: requirement.rampProviderId,
|
|
3615
|
-
corridorId: requirement.corridorId,
|
|
3616
|
-
type: requirement.type,
|
|
3617
|
-
optionId: requirement.optionId,
|
|
3618
|
-
progress: { position: requirement.completed + 1, total: requirement.total }
|
|
3619
|
-
};
|
|
3620
|
-
}
|
|
3621
|
-
function lockedRouteCopy(requirement) {
|
|
3622
|
-
if (requirement.type === "FORM") return { message: "Answer a few questions to see this route", action: "Continue" };
|
|
3623
|
-
if (requirement.type === "PROVIDER_REGISTRATION") {
|
|
3624
|
-
return { message: "Register with the provider to see this route", action: "Continue" };
|
|
3625
|
-
}
|
|
3626
|
-
if (requirement.type === "REGISTRY_CHECK") {
|
|
3627
|
-
return requirement.status === "pending" ? { message: "Your details are under review", action: null } : { message: "Confirm your details to see this route", action: "Confirm" };
|
|
3628
|
-
}
|
|
3629
|
-
switch (requirement.status) {
|
|
3630
|
-
case "expired":
|
|
3631
|
-
return { message: "Your verification expired", action: "Verify again" };
|
|
3632
|
-
case "pending":
|
|
3633
|
-
if (!requirement.reviewReason) return { message: "Verification in progress", action: "Continue" };
|
|
3634
|
-
return {
|
|
3635
|
-
message: requirement.reviewReason === "DUPLICATE_DOCUMENT" ? kycReviewMessage(requirement.reviewReason) : "Your verification is under review",
|
|
3636
|
-
action: null
|
|
3637
|
-
};
|
|
3638
|
-
case "rejected":
|
|
3639
|
-
return { message: "Verification was not approved", action: null };
|
|
3640
|
-
default:
|
|
3641
|
-
return { message: "Verify your identity to see this route", action: "Verify" };
|
|
3642
|
-
}
|
|
3643
3476
|
}
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
};
|
|
3650
|
-
|
|
3477
|
+
function useWalletAvailable(asset) {
|
|
3478
|
+
const { walletBalance, refreshWalletBalance } = usePollar();
|
|
3479
|
+
const wanted = !!asset;
|
|
3480
|
+
useEffect(() => {
|
|
3481
|
+
if (wanted && walletBalance.step === "idle") void refreshWalletBalance();
|
|
3482
|
+
}, [wanted, walletBalance.step, refreshWalletBalance]);
|
|
3483
|
+
if (!asset || walletBalance.step !== "loaded") return void 0;
|
|
3484
|
+
const record = findWalletBalance(walletBalance.data.balances, asset);
|
|
3485
|
+
return record ? record.available : "0";
|
|
3486
|
+
}
|
|
3487
|
+
var CUSTODY_LABEL = { COSIGNED: "co-signed", SELF_CUSTODY: "self-custody" };
|
|
3488
|
+
var assetOf = (node) => node.kind === "fiat" ? node.currency : node.code;
|
|
3489
|
+
function etaText(seconds) {
|
|
3490
|
+
if (seconds === null) return null;
|
|
3491
|
+
if (seconds < 90) return `~${Math.max(1, Math.round(seconds))} s`;
|
|
3492
|
+
if (seconds < 5400) return `~${Math.round(seconds / 60)} min`;
|
|
3493
|
+
return `~${Math.round(seconds / 3600)} h`;
|
|
3494
|
+
}
|
|
3495
|
+
function RouteDisplay({ quote, best = false, busy = false, disabled = false, onSelect }) {
|
|
3651
3496
|
const inert = busy || disabled;
|
|
3652
3497
|
const select = () => {
|
|
3653
3498
|
if (!inert) onSelect(quote);
|
|
3654
3499
|
};
|
|
3500
|
+
const first = quote.legs[0];
|
|
3501
|
+
const last = quote.legs[quote.legs.length - 1];
|
|
3655
3502
|
return /* @__PURE__ */ jsxs(
|
|
3656
3503
|
"div",
|
|
3657
3504
|
{
|
|
3658
3505
|
className: "pollar-ramp-route-card",
|
|
3659
|
-
"data-recommended":
|
|
3506
|
+
"data-recommended": best,
|
|
3660
3507
|
"data-busy": busy || void 0,
|
|
3661
3508
|
"data-disabled": disabled || void 0,
|
|
3662
3509
|
role: "button",
|
|
@@ -3667,55 +3514,152 @@ function RouteDisplay({ quote, busy = false, disabled = false, onSelect }) {
|
|
|
3667
3514
|
onKeyDown: (e) => e.key === "Enter" && select(),
|
|
3668
3515
|
children: [
|
|
3669
3516
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-route-left", children: [
|
|
3670
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-route-provider", children: quote.
|
|
3671
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-route-meta", children: busy ? "Starting\u2026" : [
|
|
3672
|
-
quote.route ? `${quote.route.asset.code} on ${quote.route.asset.chain}` : null,
|
|
3673
|
-
RAIL_LABELS[quote.rail] ?? quote.rail,
|
|
3674
|
-
quote.estimatedTime
|
|
3675
|
-
].filter(Boolean).join(" \xB7 ") })
|
|
3517
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-route-provider", children: first && last ? `${quote.amountIn} ${assetOf(first.from)} \u2192 ~${quote.amountOut} ${assetOf(last.to)}` : `~${quote.amountOut}` }),
|
|
3518
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-route-meta", children: busy ? "Starting\u2026" : [quote.legs.map((leg) => rampLegTitle(leg)).join(" \xB7 "), etaText(quote.etaSeconds)].filter(Boolean).join(" \xB7 ") })
|
|
3676
3519
|
] }),
|
|
3677
3520
|
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-route-right", children: busy ? /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3678
|
-
/* @__PURE__ */
|
|
3679
|
-
|
|
3521
|
+
/* @__PURE__ */ jsxs("span", { className: "pollar-ramp-route-fee", children: [
|
|
3522
|
+
quote.legs.length === 1 ? "1 step" : `${quote.legs.length} steps`,
|
|
3523
|
+
" \xB7 fees included"
|
|
3524
|
+
] }),
|
|
3525
|
+
best && /* @__PURE__ */ jsx("span", { className: "pollar-ramp-route-badge", children: "Best rate" })
|
|
3680
3526
|
] }) })
|
|
3681
3527
|
]
|
|
3682
3528
|
}
|
|
3683
3529
|
);
|
|
3684
3530
|
}
|
|
3685
|
-
function
|
|
3686
|
-
|
|
3531
|
+
function RejectedRouteDisplay({
|
|
3532
|
+
rejection,
|
|
3533
|
+
disabled = false,
|
|
3534
|
+
trusting = false,
|
|
3535
|
+
walletBusy = false,
|
|
3536
|
+
custodyChoice = false,
|
|
3537
|
+
onVerify,
|
|
3538
|
+
onTrust,
|
|
3539
|
+
onWalletStep
|
|
3540
|
+
}) {
|
|
3541
|
+
const requirement = rejection.requirement;
|
|
3542
|
+
const copy = requirement ? rampRequirementCopy(requirement) : null;
|
|
3543
|
+
const trustAsset = !requirement && onTrust ? rampTrustlineAsset(rejection) : null;
|
|
3544
|
+
const step = !requirement ? rampWalletStep(rejection) : null;
|
|
3545
|
+
const fromMenu = step?.action === "create_wallet" && custodyChoice;
|
|
3546
|
+
const walletStep = onWalletStep && !fromMenu ? step : null;
|
|
3547
|
+
const picks = custodyChoice && step?.action !== "set_up_recovery" ? ["COSIGNED", "SELF_CUSTODY"] : [void 0];
|
|
3548
|
+
const meta = copy ? copy.message : fromMenu ? "You need a wallet to receive this. Create it from the wallet menu, then find the route again." : rampResolutionText(rejection.failure);
|
|
3549
|
+
const busy = trusting || !!walletStep && walletBusy;
|
|
3687
3550
|
return /* @__PURE__ */ jsxs(
|
|
3688
3551
|
"div",
|
|
3689
3552
|
{
|
|
3690
3553
|
className: "pollar-ramp-route-card",
|
|
3691
3554
|
"data-locked": true,
|
|
3692
|
-
"data-kyc-status": requirement
|
|
3693
|
-
"data-disabled": disabled || void 0,
|
|
3555
|
+
"data-kyc-status": requirement?.status,
|
|
3556
|
+
"data-disabled": !(copy?.action && onVerify) && !trustAsset && !walletStep || disabled && !busy || void 0,
|
|
3694
3557
|
children: [
|
|
3695
3558
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-route-left", children: [
|
|
3696
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-route-provider", children:
|
|
3697
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-route-meta", children:
|
|
3559
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-route-provider", children: rejection.legs.map((leg) => rampLegTitle(leg)).join(" \xB7 ") }),
|
|
3560
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-route-meta", children: meta })
|
|
3698
3561
|
] }),
|
|
3699
|
-
|
|
3562
|
+
trustAsset && /* @__PURE__ */ jsx("div", { className: "pollar-ramp-route-right", children: /* @__PURE__ */ jsx(
|
|
3563
|
+
"button",
|
|
3564
|
+
{
|
|
3565
|
+
type: "button",
|
|
3566
|
+
className: "pollar-btn-secondary pollar-ramp-route-verify",
|
|
3567
|
+
disabled,
|
|
3568
|
+
"aria-busy": trusting,
|
|
3569
|
+
onClick: () => onTrust(trustAsset),
|
|
3570
|
+
children: trusting ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3571
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
3572
|
+
" Adding\u2026"
|
|
3573
|
+
] }) : `Add ${trustAsset.code} trustline`
|
|
3574
|
+
}
|
|
3575
|
+
) }),
|
|
3576
|
+
walletStep && /* @__PURE__ */ jsx("div", { className: "pollar-ramp-route-right", children: walletBusy ? /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-btn-secondary pollar-ramp-route-verify", disabled: true, "aria-busy": true, children: [
|
|
3577
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
3578
|
+
" ",
|
|
3579
|
+
walletStep.busyLabel
|
|
3580
|
+
] }) : picks.map((custody) => /* @__PURE__ */ jsx(
|
|
3581
|
+
"button",
|
|
3582
|
+
{
|
|
3583
|
+
type: "button",
|
|
3584
|
+
className: "pollar-btn-secondary pollar-ramp-route-verify",
|
|
3585
|
+
disabled,
|
|
3586
|
+
onClick: () => onWalletStep(walletStep, custody),
|
|
3587
|
+
children: custody ? `${walletStep.label} (${CUSTODY_LABEL[custody]})` : walletStep.label
|
|
3588
|
+
},
|
|
3589
|
+
custody ?? "app"
|
|
3590
|
+
)) }),
|
|
3591
|
+
requirement && copy?.action && onVerify && /* @__PURE__ */ jsx("div", { className: "pollar-ramp-route-right", children: /* @__PURE__ */ jsx(
|
|
3700
3592
|
"button",
|
|
3701
3593
|
{
|
|
3702
3594
|
type: "button",
|
|
3703
3595
|
className: "pollar-btn-secondary pollar-ramp-route-verify",
|
|
3704
3596
|
disabled,
|
|
3705
3597
|
onClick: () => onVerify(requirement),
|
|
3706
|
-
children: action
|
|
3598
|
+
children: copy.action
|
|
3707
3599
|
}
|
|
3708
3600
|
) })
|
|
3709
3601
|
]
|
|
3710
3602
|
}
|
|
3711
3603
|
);
|
|
3712
3604
|
}
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
const
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3605
|
+
function formatAvailable(available) {
|
|
3606
|
+
if (available === null) return "\u2014";
|
|
3607
|
+
const n = parseFloat(available);
|
|
3608
|
+
return isNaN(n) ? available : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
|
|
3609
|
+
}
|
|
3610
|
+
function AmountField({
|
|
3611
|
+
id,
|
|
3612
|
+
label,
|
|
3613
|
+
value,
|
|
3614
|
+
onChange,
|
|
3615
|
+
unit,
|
|
3616
|
+
available,
|
|
3617
|
+
onMax,
|
|
3618
|
+
placeholder = "0.00",
|
|
3619
|
+
disabled = false
|
|
3620
|
+
}) {
|
|
3621
|
+
const showBalance = available !== void 0;
|
|
3622
|
+
const canMax = showBalance && available !== null && parseFloat(available) > 0 && !disabled;
|
|
3623
|
+
return /* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
|
|
3624
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-label-row", children: [
|
|
3625
|
+
/* @__PURE__ */ jsx("label", { className: "pollar-send-label", htmlFor: id, children: label }),
|
|
3626
|
+
showBalance && /* @__PURE__ */ jsxs("span", { className: "pollar-send-hint", children: [
|
|
3627
|
+
"Available: ",
|
|
3628
|
+
formatAvailable(available),
|
|
3629
|
+
" ",
|
|
3630
|
+
unit ?? ""
|
|
3631
|
+
] })
|
|
3632
|
+
] }),
|
|
3633
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-input-shell", children: [
|
|
3634
|
+
/* @__PURE__ */ jsx(
|
|
3635
|
+
"input",
|
|
3636
|
+
{
|
|
3637
|
+
id,
|
|
3638
|
+
className: "pollar-input pollar-send-amount-input",
|
|
3639
|
+
type: "text",
|
|
3640
|
+
inputMode: "decimal",
|
|
3641
|
+
placeholder,
|
|
3642
|
+
value,
|
|
3643
|
+
disabled,
|
|
3644
|
+
onChange: (e) => onChange(e.target.value),
|
|
3645
|
+
"aria-label": id ? void 0 : label
|
|
3646
|
+
}
|
|
3647
|
+
),
|
|
3648
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-input-suffix", children: [
|
|
3649
|
+
showBalance && /* @__PURE__ */ jsx(
|
|
3650
|
+
"button",
|
|
3651
|
+
{
|
|
3652
|
+
type: "button",
|
|
3653
|
+
className: "pollar-send-inline-action",
|
|
3654
|
+
disabled: !canMax,
|
|
3655
|
+
onClick: () => onMax ? onMax() : available && onChange(available),
|
|
3656
|
+
children: "Max"
|
|
3657
|
+
}
|
|
3658
|
+
),
|
|
3659
|
+
unit && /* @__PURE__ */ jsx("span", { children: unit })
|
|
3660
|
+
] })
|
|
3661
|
+
] })
|
|
3662
|
+
] });
|
|
3719
3663
|
}
|
|
3720
3664
|
function scannableImageSrc(image) {
|
|
3721
3665
|
return image.encoding === "base64" ? `data:${image.mediaType};base64,${image.data}` : `data:${image.mediaType};charset=utf-8,${encodeURIComponent(image.data)}`;
|
|
@@ -3734,109 +3678,143 @@ function placeholderFor(field, fields, values) {
|
|
|
3734
3678
|
}
|
|
3735
3679
|
return field.placeholder;
|
|
3736
3680
|
}
|
|
3737
|
-
var CHAIN_NAME = { STELLAR: "Stellar", POLYGON: "Polygon", SOLANA: "Solana" };
|
|
3738
|
-
var EXPLORER_NAME = { STELLAR: "Stellar Expert", POLYGON: "Polygonscan", SOLANA: "Solana Explorer" };
|
|
3739
|
-
var LOADING_STEPS = ["Detecting your country\u2026", "Consulting providers\u2026", "Route found!"];
|
|
3740
3681
|
function flagEmoji(code) {
|
|
3741
3682
|
const cc = code.trim().toUpperCase();
|
|
3742
3683
|
if (!/^[A-Z]{2}$/.test(cc)) return "";
|
|
3743
3684
|
const base = 127462;
|
|
3744
3685
|
return String.fromCodePoint(base + (cc.charCodeAt(0) - 65), base + (cc.charCodeAt(1) - 65));
|
|
3745
3686
|
}
|
|
3746
|
-
var
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
}
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
return
|
|
3687
|
+
var CHAIN_NAME = { STELLAR: "Stellar", POLYGON: "Polygon", SOLANA: "Solana" };
|
|
3688
|
+
function explorerTxUrl2(chain, hash, network) {
|
|
3689
|
+
const testnet = network === "testnet";
|
|
3690
|
+
if (chain === "SOLANA") return `https://explorer.solana.com/tx/${hash}${testnet ? "?cluster=devnet" : ""}`;
|
|
3691
|
+
if (chain === "POLYGON") return `https://${testnet ? "amoy." : ""}polygonscan.com/tx/${hash}`;
|
|
3692
|
+
return `https://stellar.expert/explorer/${testnet ? "testnet" : "public"}/tx/${hash}`;
|
|
3693
|
+
}
|
|
3694
|
+
function legChain(leg) {
|
|
3695
|
+
if (leg.from.kind === "asset") return leg.from.chain;
|
|
3696
|
+
return leg.to.kind === "asset" ? leg.to.chain : "STELLAR";
|
|
3697
|
+
}
|
|
3698
|
+
function stepChain(kind, leg) {
|
|
3699
|
+
if (kind === "mint" && leg.to.kind === "asset") return leg.to.chain;
|
|
3700
|
+
return legChain(leg);
|
|
3701
|
+
}
|
|
3702
|
+
var timeLeftText = (seconds) => seconds <= 0 ? "Taking a little longer than usual" : seconds < 60 ? `About ${seconds}s left` : `About ${Math.ceil(seconds / 60)} min left`;
|
|
3703
|
+
function useNowEverySecond(running) {
|
|
3704
|
+
const [now, setNow] = useState(() => Date.now());
|
|
3705
|
+
useEffect(() => {
|
|
3706
|
+
if (!running) return;
|
|
3707
|
+
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
3708
|
+
return () => clearInterval(timer);
|
|
3709
|
+
}, [running]);
|
|
3710
|
+
return now;
|
|
3711
|
+
}
|
|
3712
|
+
var fiatKey = (fiat) => `${fiat.currency}:${fiat.rail}`;
|
|
3713
|
+
var assetKey3 = (asset) => `${asset.code}:${asset.chain}:${asset.identifier ?? ""}`;
|
|
3714
|
+
function trustKey(rejection) {
|
|
3715
|
+
const asset = rampTrustlineAsset(rejection);
|
|
3716
|
+
return asset ? `${asset.code}:${asset.issuer}` : null;
|
|
3717
|
+
}
|
|
3718
|
+
var LOADING_STEPS = ["Checking routes\u2026", "Quoting each step\u2026", "Route found!"];
|
|
3719
|
+
function useRenderAt(at) {
|
|
3720
|
+
const [, setTick] = useState(0);
|
|
3721
|
+
useEffect(() => {
|
|
3722
|
+
if (at === null) return;
|
|
3723
|
+
const timer = setTimeout(() => setTick((n) => n + 1), Math.max(0, at - Date.now()) + 50);
|
|
3724
|
+
return () => clearTimeout(timer);
|
|
3725
|
+
}, [at]);
|
|
3756
3726
|
}
|
|
3757
3727
|
function RampWidgetTemplate({
|
|
3758
|
-
workflowContent,
|
|
3759
|
-
routeSelector,
|
|
3760
3728
|
theme,
|
|
3761
3729
|
accentColor,
|
|
3762
3730
|
styleOverrides,
|
|
3731
|
+
network,
|
|
3763
3732
|
step,
|
|
3764
3733
|
flowSteps,
|
|
3765
3734
|
flowStepIndex,
|
|
3766
|
-
startingQuoteId,
|
|
3767
3735
|
direction,
|
|
3768
|
-
|
|
3769
|
-
currency,
|
|
3770
|
-
country,
|
|
3771
|
-
requiredFields,
|
|
3772
|
-
fieldValues,
|
|
3736
|
+
routesLoading,
|
|
3773
3737
|
countries,
|
|
3774
|
-
|
|
3775
|
-
|
|
3738
|
+
country,
|
|
3739
|
+
fiats,
|
|
3740
|
+
fiat,
|
|
3741
|
+
assets,
|
|
3742
|
+
asset,
|
|
3743
|
+
amount,
|
|
3744
|
+
sellAvailable,
|
|
3776
3745
|
quotes,
|
|
3777
|
-
|
|
3746
|
+
rejected,
|
|
3747
|
+
startingQuoteId,
|
|
3748
|
+
fields,
|
|
3749
|
+
fieldValues,
|
|
3750
|
+
order,
|
|
3751
|
+
pendingOrders,
|
|
3778
3752
|
isLoading,
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
kycUrl,
|
|
3782
|
-
tosUrl,
|
|
3783
|
-
kycBlocking,
|
|
3784
|
-
onboardingStatus,
|
|
3785
|
-
kycJustApproved,
|
|
3786
|
-
stellarTxHash,
|
|
3787
|
-
txHash,
|
|
3788
|
-
txChain,
|
|
3789
|
-
explorerUrl,
|
|
3790
|
-
fundsInTransit = false,
|
|
3791
|
-
retrying = false,
|
|
3792
|
-
onRetryTransit,
|
|
3793
|
-
depositInstructions,
|
|
3794
|
-
canComplete,
|
|
3795
|
-
completing,
|
|
3796
|
-
savedRamps = [],
|
|
3797
|
-
onResumeRamp,
|
|
3798
|
-
onDismissRamp,
|
|
3799
|
-
onDismissCurrentRamp,
|
|
3800
|
-
onExploreRoutes,
|
|
3753
|
+
refreshing,
|
|
3754
|
+
signing,
|
|
3801
3755
|
errorMsg,
|
|
3802
|
-
|
|
3756
|
+
notice = null,
|
|
3803
3757
|
onDirectionChange,
|
|
3804
|
-
onAmountChange,
|
|
3805
|
-
onFieldChange,
|
|
3806
3758
|
onCountryChange,
|
|
3759
|
+
onFiatChange,
|
|
3760
|
+
onAssetChange,
|
|
3761
|
+
onAmountChange,
|
|
3807
3762
|
onFindRoute,
|
|
3808
3763
|
onSelectQuote,
|
|
3809
3764
|
onVerifyRoute,
|
|
3765
|
+
trustingAsset = null,
|
|
3766
|
+
onTrustAsset,
|
|
3767
|
+
walletBusy = null,
|
|
3768
|
+
custodyChoice = false,
|
|
3769
|
+
onWalletStep,
|
|
3770
|
+
noChains = false,
|
|
3771
|
+
retrying = false,
|
|
3772
|
+
onRetryOrder,
|
|
3773
|
+
onSetUpRecovery,
|
|
3774
|
+
recoveryMissing = null,
|
|
3775
|
+
checkingPayment = false,
|
|
3776
|
+
onCheckPayment,
|
|
3777
|
+
pollTrouble = false,
|
|
3778
|
+
onFieldChange,
|
|
3810
3779
|
onContactContinue,
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3780
|
+
onSign,
|
|
3781
|
+
onApprove,
|
|
3782
|
+
onResumeOrder,
|
|
3783
|
+
onNewOrder,
|
|
3814
3784
|
onBack,
|
|
3785
|
+
onStepSelect,
|
|
3815
3786
|
onRetry,
|
|
3816
3787
|
onRefresh,
|
|
3817
3788
|
onClose
|
|
3818
3789
|
}) {
|
|
3819
|
-
const settledHash = txHash ?? stellarTxHash;
|
|
3820
|
-
const chainName = CHAIN_NAME[txChain ?? "STELLAR"];
|
|
3821
3790
|
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
|
|
3791
|
+
const onramp = direction === "ONRAMP";
|
|
3792
|
+
const sendUnit = onramp ? fiat?.currency : asset?.code;
|
|
3793
|
+
const view = order ? describeRampAction(order) : null;
|
|
3794
|
+
const settled = order ? ["completed", "failed", "refunded"].includes(order.state) : false;
|
|
3795
|
+
const running = order?.legs.find((leg) => rampLegStatus(leg) === "active" && order.pendingAction?.legIndex !== leg.index);
|
|
3796
|
+
const now = useNowEverySecond(step === "status" && !settled && !!running && running.etaSeconds !== null);
|
|
3797
|
+
const nextApproval = order && !settled ? rampNextApproval(order) : null;
|
|
3798
|
+
const stopped = order ? rampOrderStopped(order) : false;
|
|
3799
|
+
const receive = order ? rampOrderReceive(order) : null;
|
|
3800
|
+
const waitsOnRecovery = order?.failure?.resolutionAction === "set_up_recovery";
|
|
3801
|
+
const payBy = view?.action?.kind === "FIAT_PAYMENT" && view.expiresAt ? Date.parse(view.expiresAt) : null;
|
|
3802
|
+
useRenderAt(view?.canSign && view.expiresAt ? Date.parse(view.expiresAt) : null);
|
|
3803
|
+
const stepsOpen = !!onStepSelect && step !== "status" && !isLoading && startingQuoteId === null && trustingAsset === null && walletBusy === null;
|
|
3822
3804
|
const stepTitle = {
|
|
3823
|
-
input:
|
|
3824
|
-
loading_quote: "Finding best route",
|
|
3825
|
-
select_route: "
|
|
3805
|
+
input: onramp ? "Buy crypto" : "Sell crypto",
|
|
3806
|
+
loading_quote: "Finding the best route",
|
|
3807
|
+
select_route: "Choose a route",
|
|
3826
3808
|
contact: "Your details",
|
|
3827
|
-
status:
|
|
3809
|
+
status: order?.state === "completed" ? "Transfer completed" : onramp ? "Your purchase" : "Your sale",
|
|
3828
3810
|
error: "Something went wrong"
|
|
3829
3811
|
};
|
|
3830
3812
|
const stepSubtitle = {
|
|
3831
|
-
input:
|
|
3832
|
-
loading_quote: "Comparing
|
|
3833
|
-
select_route: "All
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
// money, not who you are. Say which, rather than asserting the Bridge case
|
|
3837
|
-
// over every provider.
|
|
3838
|
-
contact: `${provider || "This provider"} needs ${listOf(requiredFields.filter((f) => !f.optional).map((f) => f.label.toLowerCase()))} to continue`,
|
|
3839
|
-
status: workflowContent ? "Follow the next step below to continue" : `Finish the flow at ${provider || "the provider"} to continue`,
|
|
3813
|
+
input: onramp ? "Pick what you receive and how much you pay" : "Pick what you sell and how much",
|
|
3814
|
+
loading_quote: "Comparing routes in real time\u2026",
|
|
3815
|
+
select_route: "All amounts include fees",
|
|
3816
|
+
contact: `This route needs ${listOf(fields.filter((f) => !f.optional).map((f) => f.label.toLowerCase()))} to continue`,
|
|
3817
|
+
status: view?.title ?? "Processing",
|
|
3840
3818
|
error: "Please try again"
|
|
3841
3819
|
};
|
|
3842
3820
|
return /* @__PURE__ */ jsxs("div", { className: "pollar-modal-card pollar-ramp-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
|
|
@@ -3877,128 +3855,124 @@ function RampWidgetTemplate({
|
|
|
3877
3855
|
" of ",
|
|
3878
3856
|
flowSteps.length
|
|
3879
3857
|
] }),
|
|
3880
|
-
/* @__PURE__ */ jsx(
|
|
3881
|
-
"
|
|
3858
|
+
/* @__PURE__ */ jsx("ol", { className: "pollar-ramp-steps-track", children: flowSteps.map((label, i) => /* @__PURE__ */ jsx("li", { className: "pollar-ramp-steps-item", "aria-current": i === flowStepIndex ? "step" : void 0, children: /* @__PURE__ */ jsxs(
|
|
3859
|
+
"button",
|
|
3882
3860
|
{
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
"
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3861
|
+
type: "button",
|
|
3862
|
+
className: "pollar-ramp-steps-step",
|
|
3863
|
+
"data-done": i <= flowStepIndex || void 0,
|
|
3864
|
+
disabled: !stepsOpen || i >= flowStepIndex,
|
|
3865
|
+
onClick: () => onStepSelect?.(label),
|
|
3866
|
+
children: [
|
|
3867
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-steps-segment" }),
|
|
3868
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-steps-name", children: label })
|
|
3869
|
+
]
|
|
3890
3870
|
}
|
|
3891
|
-
)
|
|
3871
|
+
) }, label)) })
|
|
3892
3872
|
] }),
|
|
3893
|
-
step === "input" &&
|
|
3894
|
-
/* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: "
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
),
|
|
3911
|
-
onDismissRamp && /* @__PURE__ */ jsx(
|
|
3912
|
-
"button",
|
|
3913
|
-
{
|
|
3914
|
-
type: "button",
|
|
3915
|
-
className: "pollar-btn-secondary",
|
|
3916
|
-
disabled: isLoading,
|
|
3917
|
-
"aria-label": `Remove ${ramp.provider} ${ramp.txId.slice(-8)} from pending list`,
|
|
3918
|
-
onClick: () => onDismissRamp(ramp.txId),
|
|
3919
|
-
children: "Remove"
|
|
3920
|
-
}
|
|
3921
|
-
)
|
|
3922
|
-
] }, ramp.txId))
|
|
3873
|
+
step === "input" && pendingOrders.length > 0 && /* @__PURE__ */ jsxs("section", { className: "pollar-ramp-payment pollar-ramp-saved", "aria-label": "Pending operations", children: [
|
|
3874
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: "These operations are waiting for you. Starting another does not cancel them." }),
|
|
3875
|
+
pendingOrders.map((pending) => /* @__PURE__ */ jsx("div", { className: "pollar-ramp-saved-row", children: /* @__PURE__ */ jsxs(
|
|
3876
|
+
"button",
|
|
3877
|
+
{
|
|
3878
|
+
type: "button",
|
|
3879
|
+
className: "pollar-btn-secondary",
|
|
3880
|
+
disabled: isLoading,
|
|
3881
|
+
onClick: () => onResumeOrder(pending.id),
|
|
3882
|
+
children: [
|
|
3883
|
+
"Resume ",
|
|
3884
|
+
pending.direction === "ONRAMP" ? "purchase" : "sale",
|
|
3885
|
+
" \xB7 ",
|
|
3886
|
+
pending.id.slice(-8)
|
|
3887
|
+
]
|
|
3888
|
+
}
|
|
3889
|
+
) }, pending.id))
|
|
3923
3890
|
] }),
|
|
3924
3891
|
step === "input" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3925
|
-
noticeMsg && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", role: "status", children: noticeMsg }),
|
|
3926
3892
|
/* @__PURE__ */ jsxs("div", { className: "pollar-tabs", children: [
|
|
3927
|
-
/* @__PURE__ */ jsx(
|
|
3928
|
-
|
|
3929
|
-
{
|
|
3930
|
-
type: "button",
|
|
3931
|
-
className: "pollar-tab",
|
|
3932
|
-
"data-active": direction === "onramp",
|
|
3933
|
-
onClick: () => onDirectionChange("onramp"),
|
|
3934
|
-
children: "Buy"
|
|
3935
|
-
}
|
|
3936
|
-
),
|
|
3937
|
-
/* @__PURE__ */ jsx(
|
|
3938
|
-
"button",
|
|
3939
|
-
{
|
|
3940
|
-
type: "button",
|
|
3941
|
-
className: "pollar-tab",
|
|
3942
|
-
"data-active": direction === "offramp",
|
|
3943
|
-
onClick: () => onDirectionChange("offramp"),
|
|
3944
|
-
children: "Sell"
|
|
3945
|
-
}
|
|
3946
|
-
)
|
|
3893
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-tab", "data-active": onramp, onClick: () => onDirectionChange("ONRAMP"), children: "Buy" }),
|
|
3894
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-tab", "data-active": !onramp, onClick: () => onDirectionChange("OFFRAMP"), children: "Sell" })
|
|
3947
3895
|
] }),
|
|
3948
|
-
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-
|
|
3949
|
-
/* @__PURE__ */ jsx("
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
] }),
|
|
3969
|
-
routeSelector,
|
|
3970
|
-
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
|
|
3971
|
-
/* @__PURE__ */ jsxs("label", { className: "pollar-ramp-label", htmlFor: "pollar-ramp-amount", children: [
|
|
3972
|
-
"Amount",
|
|
3973
|
-
currency ? ` (${currency})` : ""
|
|
3896
|
+
routesLoading ? /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-input pollar-select-loading", children: [
|
|
3897
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
3898
|
+
/* @__PURE__ */ jsx("span", { children: "Loading routes\u2026" })
|
|
3899
|
+
] }) : countries.length === 0 ? /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: noChains ? "This app has no chains enabled, so there is nothing to buy or sell yet." : "No ramp routes are available for this app yet." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3900
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
|
|
3901
|
+
/* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", htmlFor: "pollar-ramp-country", children: "Country" }),
|
|
3902
|
+
/* @__PURE__ */ jsx(
|
|
3903
|
+
"select",
|
|
3904
|
+
{
|
|
3905
|
+
id: "pollar-ramp-country",
|
|
3906
|
+
className: "pollar-ramp-input",
|
|
3907
|
+
value: country,
|
|
3908
|
+
onChange: (e) => onCountryChange(e.target.value),
|
|
3909
|
+
children: countries.map((c) => /* @__PURE__ */ jsxs("option", { value: c.country, children: [
|
|
3910
|
+
flagEmoji(c.country),
|
|
3911
|
+
" ",
|
|
3912
|
+
c.country
|
|
3913
|
+
] }, c.country))
|
|
3914
|
+
}
|
|
3915
|
+
)
|
|
3974
3916
|
] }),
|
|
3975
|
-
/* @__PURE__ */
|
|
3976
|
-
"
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3917
|
+
fiats.length > 1 && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
|
|
3918
|
+
/* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", htmlFor: "pollar-ramp-fiat", children: onramp ? "Pay with" : "Receive in" }),
|
|
3919
|
+
/* @__PURE__ */ jsx(
|
|
3920
|
+
"select",
|
|
3921
|
+
{
|
|
3922
|
+
id: "pollar-ramp-fiat",
|
|
3923
|
+
className: "pollar-ramp-input",
|
|
3924
|
+
value: fiat ? fiatKey(fiat) : "",
|
|
3925
|
+
onChange: (e) => onFiatChange(e.target.value),
|
|
3926
|
+
children: fiats.map((f) => /* @__PURE__ */ jsxs("option", { value: fiatKey(f), children: [
|
|
3927
|
+
f.currency,
|
|
3928
|
+
" \xB7 ",
|
|
3929
|
+
rampRailLabel(f.rail, { language: formLanguage() })
|
|
3930
|
+
] }, fiatKey(f)))
|
|
3931
|
+
}
|
|
3932
|
+
)
|
|
3933
|
+
] }),
|
|
3934
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
|
|
3935
|
+
/* @__PURE__ */ jsx("label", { className: "pollar-ramp-label", htmlFor: "pollar-ramp-asset", children: onramp ? "Receive" : "Sell" }),
|
|
3936
|
+
/* @__PURE__ */ jsx(
|
|
3937
|
+
"select",
|
|
3938
|
+
{
|
|
3939
|
+
id: "pollar-ramp-asset",
|
|
3940
|
+
className: "pollar-ramp-input",
|
|
3941
|
+
value: asset ? assetKey3(asset) : "",
|
|
3942
|
+
onChange: (e) => onAssetChange(e.target.value),
|
|
3943
|
+
children: assets.map((a) => /* @__PURE__ */ jsxs("option", { value: assetKey3(a), children: [
|
|
3944
|
+
a.code,
|
|
3945
|
+
" on ",
|
|
3946
|
+
CHAIN_NAME[a.chain] ?? a.chain
|
|
3947
|
+
] }, assetKey3(a)))
|
|
3948
|
+
}
|
|
3949
|
+
)
|
|
3950
|
+
] }),
|
|
3951
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
|
|
3952
|
+
/* @__PURE__ */ jsx(
|
|
3953
|
+
AmountField,
|
|
3954
|
+
{
|
|
3955
|
+
id: "pollar-ramp-amount",
|
|
3956
|
+
label: onramp ? "You pay" : "You sell",
|
|
3957
|
+
value: amount,
|
|
3958
|
+
onChange: onAmountChange,
|
|
3959
|
+
unit: sendUnit,
|
|
3960
|
+
available: onramp ? void 0 : sellAvailable
|
|
3961
|
+
}
|
|
3962
|
+
),
|
|
3963
|
+
errorMsg && /* @__PURE__ */ jsx("span", { className: "pollar-ramp-field-error", children: errorMsg })
|
|
3964
|
+
] })
|
|
3988
3965
|
] }),
|
|
3989
|
-
/* @__PURE__ */
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
"button",
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
}
|
|
4000
|
-
)
|
|
4001
|
-
] })
|
|
3966
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsx(
|
|
3967
|
+
"button",
|
|
3968
|
+
{
|
|
3969
|
+
type: "button",
|
|
3970
|
+
className: "pollar-btn-primary",
|
|
3971
|
+
disabled: !amount || !fiat || !asset || isLoading || routesLoading,
|
|
3972
|
+
onClick: onFindRoute,
|
|
3973
|
+
children: "Find best route"
|
|
3974
|
+
}
|
|
3975
|
+
) })
|
|
4002
3976
|
] }),
|
|
4003
3977
|
step === "loading_quote" && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-loading", children: [
|
|
4004
3978
|
/* @__PURE__ */ jsx("div", { className: "pollar-spinner pollar-ramp-loading-spinner" }),
|
|
@@ -4008,33 +3982,44 @@ function RampWidgetTemplate({
|
|
|
4008
3982
|
] }, i))
|
|
4009
3983
|
] }),
|
|
4010
3984
|
step === "select_route" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4011
|
-
noticeMsg && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: noticeMsg }),
|
|
4012
3985
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-route-list", children: [
|
|
4013
3986
|
quotes.map((q, i) => /* @__PURE__ */ jsx(
|
|
4014
3987
|
RouteDisplay,
|
|
4015
3988
|
{
|
|
4016
3989
|
quote: q,
|
|
4017
|
-
|
|
3990
|
+
best: i === 0,
|
|
3991
|
+
busy: startingQuoteId === q.quoteId,
|
|
4018
3992
|
disabled: startingQuoteId != null && q.quoteId !== startingQuoteId,
|
|
4019
3993
|
onSelect: onSelectQuote
|
|
4020
3994
|
},
|
|
4021
|
-
|
|
3995
|
+
q.quoteId
|
|
4022
3996
|
)),
|
|
4023
|
-
|
|
4024
|
-
|
|
3997
|
+
rejected.map((r, i) => /* @__PURE__ */ jsx(
|
|
3998
|
+
RejectedRouteDisplay,
|
|
4025
3999
|
{
|
|
4026
|
-
|
|
4027
|
-
disabled: startingQuoteId != null,
|
|
4028
|
-
|
|
4000
|
+
rejection: r,
|
|
4001
|
+
disabled: startingQuoteId != null || trustingAsset !== null || walletBusy !== null,
|
|
4002
|
+
trusting: trustKey(r) === trustingAsset,
|
|
4003
|
+
walletBusy: walletBusy === i,
|
|
4004
|
+
custodyChoice,
|
|
4005
|
+
onVerify: onVerifyRoute,
|
|
4006
|
+
onTrust: onTrustAsset,
|
|
4007
|
+
onWalletStep: onWalletStep && ((step2, custody) => onWalletStep(step2, i, custody))
|
|
4029
4008
|
},
|
|
4030
|
-
|
|
4009
|
+
i
|
|
4031
4010
|
))
|
|
4032
4011
|
] }),
|
|
4012
|
+
quotes.length === 0 && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: rampNoRouteText(rejected) }),
|
|
4013
|
+
notice && /* @__PURE__ */ jsxs("p", { className: "pollar-ramp-payment-note", children: [
|
|
4014
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm", "aria-hidden": true }),
|
|
4015
|
+
" ",
|
|
4016
|
+
notice
|
|
4017
|
+
] }),
|
|
4033
4018
|
errorMsg && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", style: { color: "var(--pollar-error-text)" }, children: errorMsg }),
|
|
4034
|
-
/* @__PURE__ */ jsx("button", { type: "button", className:
|
|
4019
|
+
(errorMsg || !quotes.length) && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onBack, children: "Back" })
|
|
4035
4020
|
] }),
|
|
4036
4021
|
step === "contact" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4037
|
-
|
|
4022
|
+
fields.map((f) => /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-field", children: [
|
|
4038
4023
|
/* @__PURE__ */ jsxs("label", { className: "pollar-ramp-label", children: [
|
|
4039
4024
|
f.label,
|
|
4040
4025
|
f.optional && /* @__PURE__ */ jsx("span", { className: "pollar-ramp-field-optional", children: " (optional)" })
|
|
@@ -4056,184 +4041,178 @@ function RampWidgetTemplate({
|
|
|
4056
4041
|
type: f.type,
|
|
4057
4042
|
className: "pollar-ramp-input",
|
|
4058
4043
|
value: fieldValues[f.key] ?? "",
|
|
4059
|
-
placeholder: placeholderFor(f,
|
|
4044
|
+
placeholder: placeholderFor(f, fields, fieldValues),
|
|
4060
4045
|
autoComplete: f.type === "email" ? "email" : "off",
|
|
4061
4046
|
onChange: (e) => onFieldChange(f.key, e.target.value)
|
|
4062
4047
|
}
|
|
4063
4048
|
),
|
|
4064
4049
|
f.hint && /* @__PURE__ */ jsx("span", { className: "pollar-ramp-field-hint", children: f.hint }),
|
|
4065
|
-
|
|
4050
|
+
rampFieldError(f, fieldValues[f.key]) && /* @__PURE__ */ jsx("span", { className: "pollar-ramp-field-error", children: rampFieldError(f, fieldValues[f.key]) })
|
|
4066
4051
|
] }, f.key)),
|
|
4067
|
-
/* @__PURE__ */
|
|
4068
|
-
|
|
4069
|
-
|
|
4052
|
+
errorMsg && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-field-error", children: errorMsg }),
|
|
4053
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsx(
|
|
4054
|
+
"button",
|
|
4055
|
+
{
|
|
4056
|
+
type: "button",
|
|
4057
|
+
className: "pollar-btn-primary",
|
|
4058
|
+
disabled: fields.some((f) => !rampFieldValid(f, fieldValues[f.key])) || isLoading,
|
|
4059
|
+
onClick: onContactContinue,
|
|
4060
|
+
children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4061
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
4062
|
+
"Starting\u2026"
|
|
4063
|
+
] }) : "Continue"
|
|
4064
|
+
}
|
|
4065
|
+
) })
|
|
4066
|
+
] }),
|
|
4067
|
+
step === "status" && order && view && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment", children: [
|
|
4068
|
+
/* @__PURE__ */ jsx("ol", { className: "pollar-ramp-legs", "aria-label": "Progress", children: order.legs.map((leg) => {
|
|
4069
|
+
const status = rampLegStatus(leg);
|
|
4070
|
+
const hash = leg.onchainTxHash;
|
|
4071
|
+
const note = rampLegNote(leg);
|
|
4072
|
+
return /* @__PURE__ */ jsxs("li", { className: "pollar-ramp-leg", "data-status": status, children: [
|
|
4073
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-leg-dot", "aria-hidden": true }),
|
|
4074
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-leg-title", children: rampLegTitle(leg) }),
|
|
4075
|
+
status === "active" && !settled && /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm", "aria-label": "In progress" }),
|
|
4076
|
+
hash && /* @__PURE__ */ jsxs(
|
|
4077
|
+
"a",
|
|
4078
|
+
{
|
|
4079
|
+
className: "pollar-ramp-leg-link",
|
|
4080
|
+
href: explorerTxUrl2(legChain(leg), hash, network),
|
|
4081
|
+
target: "_blank",
|
|
4082
|
+
rel: "noopener noreferrer",
|
|
4083
|
+
children: [
|
|
4084
|
+
hash.slice(0, 6),
|
|
4085
|
+
"\u2026",
|
|
4086
|
+
hash.slice(-4)
|
|
4087
|
+
]
|
|
4088
|
+
}
|
|
4089
|
+
),
|
|
4090
|
+
note && /* @__PURE__ */ jsx("span", { className: "pollar-ramp-leg-note", children: note }),
|
|
4091
|
+
status === "active" && !settled && !!leg.steps?.length && /* @__PURE__ */ jsx("ol", { className: "pollar-ramp-steps", children: leg.steps.map((s) => /* @__PURE__ */ jsxs("li", { className: "pollar-ramp-step", "data-status": s.status, children: [
|
|
4092
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-step-title", children: rampStepTitle(s, leg) }),
|
|
4093
|
+
/* @__PURE__ */ jsxs("span", { className: "pollar-ramp-step-state", children: [
|
|
4094
|
+
s.status === "confirming" && /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm", "aria-hidden": true }),
|
|
4095
|
+
s.hash ? /* @__PURE__ */ jsx(
|
|
4096
|
+
"a",
|
|
4097
|
+
{
|
|
4098
|
+
className: "pollar-ramp-leg-link",
|
|
4099
|
+
href: explorerTxUrl2(stepChain(s.kind, leg), s.hash, network),
|
|
4100
|
+
target: "_blank",
|
|
4101
|
+
rel: "noopener noreferrer",
|
|
4102
|
+
children: rampStepStatusText(s)
|
|
4103
|
+
}
|
|
4104
|
+
) : rampStepStatusText(s)
|
|
4105
|
+
] })
|
|
4106
|
+
] }, s.kind)) }),
|
|
4107
|
+
running === leg && !settled && rampLegTimeLeft(leg, now) !== null && /* @__PURE__ */ jsx("span", { className: "pollar-ramp-leg-eta", children: timeLeftText(rampLegTimeLeft(leg, now)) })
|
|
4108
|
+
] }, leg.index);
|
|
4109
|
+
}) }),
|
|
4110
|
+
nextApproval && !order.pendingAction && /* @__PURE__ */ jsxs("p", { className: "pollar-ramp-next", children: [
|
|
4111
|
+
"Next: ",
|
|
4112
|
+
nextApproval,
|
|
4113
|
+
". You approve it on this device when it comes up."
|
|
4114
|
+
] }),
|
|
4115
|
+
receive && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
4116
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: order.state === "completed" ? "You received" : "You receive" }),
|
|
4117
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-value", children: [
|
|
4118
|
+
receive.estimated && "~",
|
|
4119
|
+
receive.amount,
|
|
4120
|
+
" ",
|
|
4121
|
+
receive.unit
|
|
4122
|
+
] })
|
|
4123
|
+
] }),
|
|
4124
|
+
order.failure && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
4125
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "What to do" }),
|
|
4126
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: rampOrderResolutionText(order) }),
|
|
4127
|
+
stopped && !settled && waitsOnRecovery && recoveryMissing !== false && onSetUpRecovery && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onSetUpRecovery, children: "Set up recovery" }),
|
|
4128
|
+
stopped && !settled && waitsOnRecovery && recoveryMissing === true && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: "Once it is set up, the order goes on by itself." }),
|
|
4129
|
+
stopped && !settled && order.failure.resolutionOwner === "END_USER" && onRetryOrder && /* @__PURE__ */ jsx(
|
|
4070
4130
|
"button",
|
|
4071
4131
|
{
|
|
4072
4132
|
type: "button",
|
|
4073
4133
|
className: "pollar-btn-primary",
|
|
4074
|
-
disabled:
|
|
4075
|
-
onClick:
|
|
4076
|
-
children:
|
|
4134
|
+
disabled: retrying || waitsOnRecovery && recoveryMissing === true,
|
|
4135
|
+
onClick: onRetryOrder,
|
|
4136
|
+
children: retrying ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4077
4137
|
/* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
4078
|
-
"
|
|
4079
|
-
] }) : "
|
|
4138
|
+
" Trying again\u2026"
|
|
4139
|
+
] }) : "Try again"
|
|
4080
4140
|
}
|
|
4081
|
-
)
|
|
4082
|
-
] })
|
|
4083
|
-
] }),
|
|
4084
|
-
step === "status" && workflowContent,
|
|
4085
|
-
step === "status" && onDismissCurrentRamp && txStatus !== "completed" && txStatus !== "failed" && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-explore", children: [
|
|
4086
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", disabled: completing, onClick: onDismissCurrentRamp, children: "Remove from pending list" }),
|
|
4087
|
-
/* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: "This only hides the operation in this tab. To request cancellation, open the provider link above when available or contact the provider\u2019s support. Payments and refunds must be confirmed by the provider." })
|
|
4088
|
-
] }),
|
|
4089
|
-
step === "status" && onExploreRoutes && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-explore", children: [
|
|
4090
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", disabled: completing, onClick: onExploreRoutes, children: txStatus === "completed" || txStatus === "failed" ? "Start another operation" : "Try another route" }),
|
|
4091
|
-
txStatus !== "completed" && txStatus !== "failed" && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: "Your current operation stays saved so you can resume it later." })
|
|
4092
|
-
] }),
|
|
4093
|
-
step === "status" && !workflowContent && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment", children: [
|
|
4094
|
-
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
4095
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Provider" }),
|
|
4096
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsx("code", { children: provider }) })
|
|
4097
|
-
] }),
|
|
4098
|
-
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
4099
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Status" }),
|
|
4100
|
-
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-value", children: [
|
|
4101
|
-
/* @__PURE__ */ jsx("code", { style: { color: txStatus === "completed" ? "var(--pollar-success-text)" : void 0 }, children: txStatus ? STATUS_LABEL[txStatus] : "Processing" }),
|
|
4102
|
-
txStatus !== "completed" && txStatus !== "failed" && /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm", "aria-label": "Checking status" })
|
|
4103
|
-
] })
|
|
4104
|
-
] }),
|
|
4105
|
-
fundsInTransit && txStatus !== "completed" && txStatus !== "failed" && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
4106
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Funds in transit" }),
|
|
4107
|
-
/* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: "Your money is safe in your own wallet, waiting for the next step of the transfer." }),
|
|
4108
|
-
onRetryTransit && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onRetryTransit, disabled: retrying, children: retrying ? "Retrying..." : "Retry now" })
|
|
4109
|
-
] }),
|
|
4110
|
-
settledHash && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
4111
|
-
/* @__PURE__ */ jsxs("span", { className: "pollar-ramp-payment-label", children: [
|
|
4112
|
-
chainName,
|
|
4113
|
-
" tx"
|
|
4114
|
-
] }),
|
|
4141
|
+
),
|
|
4115
4142
|
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-value", style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
4116
4143
|
/* @__PURE__ */ jsxs("code", { style: { flex: 1, wordBreak: "break-all" }, children: [
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
settledHash.slice(-8)
|
|
4144
|
+
"Order ",
|
|
4145
|
+
order.id
|
|
4120
4146
|
] }),
|
|
4121
|
-
/* @__PURE__ */ jsx(CopyButton, { value:
|
|
4122
|
-
explorerUrl && /* @__PURE__ */ jsx(
|
|
4123
|
-
"a",
|
|
4124
|
-
{
|
|
4125
|
-
href: explorerUrl,
|
|
4126
|
-
target: "_blank",
|
|
4127
|
-
rel: "noopener noreferrer",
|
|
4128
|
-
className: "pollar-copy-btn",
|
|
4129
|
-
"aria-label": `View on ${EXPLORER_NAME[txChain ?? "STELLAR"]}`,
|
|
4130
|
-
title: `View on ${EXPLORER_NAME[txChain ?? "STELLAR"]}`,
|
|
4131
|
-
children: /* @__PURE__ */ jsxs("svg", { width: "13", height: "13", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
|
|
4132
|
-
/* @__PURE__ */ jsx(
|
|
4133
|
-
"path",
|
|
4134
|
-
{
|
|
4135
|
-
d: "M6 3H3v8h8V8",
|
|
4136
|
-
stroke: "currentColor",
|
|
4137
|
-
strokeWidth: "1.5",
|
|
4138
|
-
strokeLinecap: "round",
|
|
4139
|
-
strokeLinejoin: "round"
|
|
4140
|
-
}
|
|
4141
|
-
),
|
|
4142
|
-
/* @__PURE__ */ jsx(
|
|
4143
|
-
"path",
|
|
4144
|
-
{
|
|
4145
|
-
d: "M8.5 2.5h3v3M11 3L6.5 7.5",
|
|
4146
|
-
stroke: "currentColor",
|
|
4147
|
-
strokeWidth: "1.5",
|
|
4148
|
-
strokeLinecap: "round",
|
|
4149
|
-
strokeLinejoin: "round"
|
|
4150
|
-
}
|
|
4151
|
-
)
|
|
4152
|
-
] })
|
|
4153
|
-
}
|
|
4154
|
-
)
|
|
4147
|
+
/* @__PURE__ */ jsx(CopyButton, { value: order.id, label: "Copy order id" })
|
|
4155
4148
|
] })
|
|
4156
4149
|
] }),
|
|
4157
|
-
|
|
4150
|
+
!settled && payBy !== null && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: payBy > Date.now() ? `Pay before ${new Date(payBy).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}.` : "This payment window has closed. If you have not paid, start a new operation." }),
|
|
4151
|
+
!settled && view.scannable && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
4158
4152
|
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: "Payment QR" }),
|
|
4159
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children:
|
|
4153
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: view.scannable.image.inlineSafe ? /* @__PURE__ */ jsx(
|
|
4160
4154
|
"div",
|
|
4161
4155
|
{
|
|
4162
4156
|
className: "pollar-ramp-qr",
|
|
4163
4157
|
"aria-label": "Payment QR",
|
|
4164
|
-
dangerouslySetInnerHTML: { __html:
|
|
4158
|
+
dangerouslySetInnerHTML: { __html: view.scannable.image.data }
|
|
4165
4159
|
}
|
|
4166
4160
|
) : /* @__PURE__ */ jsx(
|
|
4167
4161
|
"img",
|
|
4168
4162
|
{
|
|
4169
|
-
src: scannableImageSrc(
|
|
4163
|
+
src: scannableImageSrc(view.scannable.image),
|
|
4170
4164
|
alt: "Payment QR",
|
|
4171
4165
|
style: { width: "100%", maxWidth: 220, height: "auto", display: "block", margin: "0 auto" }
|
|
4172
4166
|
}
|
|
4173
4167
|
) })
|
|
4174
4168
|
] }),
|
|
4175
|
-
|
|
4176
|
-
|
|
4169
|
+
!settled && view.codeMissing && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", style: { color: "var(--pollar-error-text)" }, children: "The payment code could not be shown. Refresh; if it still does not appear, contact this app's support." }),
|
|
4170
|
+
!settled && view.scannable?.payload && view.scannable.payloadLabel && /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
4171
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: view.scannable.payloadLabel }),
|
|
4177
4172
|
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
4178
|
-
/* @__PURE__ */ jsx("code", { style: { flex: 1, wordBreak: "break-all" }, children:
|
|
4179
|
-
/* @__PURE__ */ jsx(
|
|
4180
|
-
CopyButton,
|
|
4181
|
-
{
|
|
4182
|
-
value: depositInstructions.scannable.payload,
|
|
4183
|
-
label: `Copy ${depositInstructions.scannable.payloadLabel}`
|
|
4184
|
-
}
|
|
4185
|
-
)
|
|
4173
|
+
/* @__PURE__ */ jsx("code", { style: { flex: 1, wordBreak: "break-all" }, children: view.scannable.payload }),
|
|
4174
|
+
/* @__PURE__ */ jsx(CopyButton, { value: view.scannable.payload, label: `Copy ${view.scannable.payloadLabel}` })
|
|
4186
4175
|
] }) })
|
|
4187
4176
|
] }),
|
|
4188
|
-
|
|
4189
|
-
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children:
|
|
4190
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children:
|
|
4191
|
-
/* @__PURE__ */ jsx("code", { style: { flex: 1, wordBreak: "break-all" }, children:
|
|
4192
|
-
/* @__PURE__ */ jsx(CopyButton, { value:
|
|
4193
|
-
] })
|
|
4194
|
-
] },
|
|
4195
|
-
|
|
4196
|
-
"Accept terms at ",
|
|
4197
|
-
provider
|
|
4198
|
-
] }),
|
|
4199
|
-
kycUrl && !depositInstructions && txStatus !== "completed" && /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenKyc, children: [
|
|
4200
|
-
"Continue at ",
|
|
4201
|
-
provider
|
|
4202
|
-
] }),
|
|
4203
|
-
kycBlocking && onboardingStatus === "awaiting_provider" && /* @__PURE__ */ jsxs("p", { className: "pollar-ramp-payment-note", children: [
|
|
4204
|
-
provider,
|
|
4205
|
-
" is still setting up your account for this payment method. Your verification is complete and there is nothing left for you to do \u2014 nothing has been sent, and this will update on its own once ",
|
|
4206
|
-
provider,
|
|
4207
|
-
" is ready."
|
|
4208
|
-
] }),
|
|
4209
|
-
kycBlocking && onboardingStatus !== "awaiting_provider" && /* @__PURE__ */ jsxs("p", { className: "pollar-ramp-payment-note", children: [
|
|
4210
|
-
provider,
|
|
4211
|
-
" needs to verify your identity before this payout. Nothing has been sent yet \u2014 complete verification with ",
|
|
4212
|
-
provider,
|
|
4213
|
-
", and this will update on its own."
|
|
4214
|
-
] }),
|
|
4215
|
-
kycJustApproved && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4216
|
-
/* @__PURE__ */ jsxs("p", { className: "pollar-ramp-payment-note", children: [
|
|
4217
|
-
provider,
|
|
4218
|
-
" approved your verification. Request a new quote to continue \u2014 the previous one was consumed."
|
|
4219
|
-
] }),
|
|
4220
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onRetry, children: "Request a new quote" })
|
|
4221
|
-
] }),
|
|
4222
|
-
canComplete && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", disabled: completing, onClick: onCompleteWithdraw, children: completing ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4177
|
+
!settled && view.details.map((d) => /* @__PURE__ */ jsxs("div", { className: "pollar-ramp-payment-field", children: [
|
|
4178
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-ramp-payment-label", children: d.label }),
|
|
4179
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
4180
|
+
/* @__PURE__ */ jsx("code", { style: { flex: 1, wordBreak: "break-all" }, children: d.value }),
|
|
4181
|
+
/* @__PURE__ */ jsx(CopyButton, { value: d.value, label: `Copy ${d.label}` })
|
|
4182
|
+
] }) })
|
|
4183
|
+
] }, d.label)),
|
|
4184
|
+
!settled && view.action?.kind === "FIAT_PAYMENT" && onCheckPayment && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", disabled: checkingPayment, onClick: onCheckPayment, children: checkingPayment ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4223
4185
|
/* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
|
|
4224
|
-
"
|
|
4225
|
-
] }) : "
|
|
4226
|
-
|
|
4227
|
-
/* @__PURE__ */ jsx("
|
|
4186
|
+
" Checking your payment..."
|
|
4187
|
+
] }) : "I've paid" }),
|
|
4188
|
+
!settled && view.canSign && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", disabled: signing, onClick: onSign, children: signing ? "Waiting for your wallet\u2026" : "Authorize" }),
|
|
4189
|
+
!settled && view.action?.kind === "SIGNATURE" && !view.canSign && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: "Preparing a new signature request\u2026" }),
|
|
4190
|
+
!settled && view.canApprove && /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onApprove, children: "Approve on this device" }),
|
|
4191
|
+
!settled && view.link && /* @__PURE__ */ jsx(
|
|
4192
|
+
"a",
|
|
4193
|
+
{
|
|
4194
|
+
className: "pollar-btn-primary pollar-ramp-hosted-link",
|
|
4195
|
+
href: view.link,
|
|
4196
|
+
target: "_blank",
|
|
4197
|
+
rel: "noopener noreferrer",
|
|
4198
|
+
children: view.linkLabel
|
|
4199
|
+
}
|
|
4200
|
+
),
|
|
4201
|
+
!settled && order.pendingAction?.kind === "KYC" && !view.link && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: view.note ?? "The provider is reviewing your details. This updates on its own." }),
|
|
4202
|
+
pollTrouble && !settled && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: "Having trouble reaching the server. Retrying\u2026" }),
|
|
4203
|
+
errorMsg && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-field-error", children: errorMsg }),
|
|
4204
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-ramp-explore", children: [
|
|
4205
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onNewOrder, children: "Start another operation" }),
|
|
4206
|
+
!stopped && /* @__PURE__ */ jsx("p", { className: "pollar-ramp-payment-note", children: "This one keeps going; you can resume it later." })
|
|
4207
|
+
] })
|
|
4228
4208
|
] }),
|
|
4229
|
-
step === "error" && /* @__PURE__ */ jsxs(
|
|
4230
|
-
/* @__PURE__ */ jsx("
|
|
4209
|
+
step === "error" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4210
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: errorMsg ?? "Something went wrong." }),
|
|
4231
4211
|
/* @__PURE__ */ jsxs("div", { className: "pollar-modal-actions", children: [
|
|
4232
4212
|
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Close" }),
|
|
4233
4213
|
/* @__PURE__ */ jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onRetry, children: "Try again" })
|
|
4234
4214
|
] })
|
|
4235
|
-
] })
|
|
4236
|
-
/* @__PURE__ */ jsx(PollarModalFooter, {})
|
|
4215
|
+
] })
|
|
4237
4216
|
] });
|
|
4238
4217
|
}
|
|
4239
4218
|
|
|
@@ -4727,776 +4706,590 @@ function ProviderRegistrationModal({
|
|
|
4727
4706
|
}
|
|
4728
4707
|
) });
|
|
4729
4708
|
}
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
function unavailableRampMessage(country, unavailable) {
|
|
4733
|
-
if (!unavailable.length) return `No ramp providers available for ${country} yet.`;
|
|
4734
|
-
return unavailable.map(
|
|
4735
|
-
({ provider, code }) => code === "SDK_RAMPS_PROVIDER_NOT_CONFIGURED" ? `${provider} is not configured correctly. Contact the app administrator to enable this provider.` : `${provider} is temporarily unavailable. Please try again later.`
|
|
4736
|
-
).join(" ");
|
|
4737
|
-
}
|
|
4738
|
-
async function quoteRampOptions(client, query, routes) {
|
|
4739
|
-
const matching = routes.filter(
|
|
4740
|
-
(route) => route.country === query.country && route.direction === query.direction && route.fiatCurrency === query.currency
|
|
4741
|
-
);
|
|
4742
|
-
const responses = await Promise.allSettled([
|
|
4743
|
-
client.getRampsQuote(query),
|
|
4744
|
-
...matching.map((route) => client.getRampsQuote({ ...query, routeId: route.routeId, chain: route.asset.chain }))
|
|
4745
|
-
]);
|
|
4746
|
-
const results = responses.flatMap((response) => response.status === "fulfilled" ? [response.value] : []);
|
|
4747
|
-
if (!results.length) throw responses[0].reason;
|
|
4748
|
-
const quotes = /* @__PURE__ */ new Map();
|
|
4749
|
-
const requirements = /* @__PURE__ */ new Map();
|
|
4750
|
-
const unavailable = /* @__PURE__ */ new Map();
|
|
4751
|
-
for (const result of results) {
|
|
4752
|
-
for (const quote of result.quotes) {
|
|
4753
|
-
const key = JSON.stringify([quote.provider, quote.route?.routeId, quote.route?.asset.chain, quote.rail, quote.protocol]);
|
|
4754
|
-
if (!quotes.has(key)) quotes.set(key, quote);
|
|
4755
|
-
}
|
|
4756
|
-
for (const requirement of result.requirementsRequired ?? [])
|
|
4757
|
-
requirements.set(`${requirement.rampProviderId}:${requirement.corridorId}`, requirement);
|
|
4758
|
-
for (const item of result.unavailable ?? []) unavailable.set(item.provider, item);
|
|
4759
|
-
}
|
|
4760
|
-
const failed = responses.find((response) => response.status === "rejected");
|
|
4761
|
-
if (!quotes.size && !requirements.size && failed?.status === "rejected") throw failed.reason;
|
|
4762
|
-
return {
|
|
4763
|
-
quotes: [...quotes.values()],
|
|
4764
|
-
requirementsRequired: [...requirements.values()],
|
|
4765
|
-
unavailable: [...unavailable.values()]
|
|
4766
|
-
};
|
|
4767
|
-
}
|
|
4768
|
-
var TERMINAL = ["completed", "failed"];
|
|
4769
|
-
var BANK_TYPES = ["CLABE", "PIX", "PSE", "ACH", "BREB"];
|
|
4770
|
-
function isBankType(value) {
|
|
4771
|
-
return BANK_TYPES.some((type) => type === value);
|
|
4772
|
-
}
|
|
4773
|
-
function requiredFieldsOf(quote) {
|
|
4774
|
-
return "requiredFields" in quote ? quote.requiredFields : [];
|
|
4775
|
-
}
|
|
4776
|
-
function flowStepsOf(quotes, selected) {
|
|
4777
|
-
const needsDetails = selected != null ? requiredFieldsOf(selected).length > 0 : quotes.some((q) => requiredFieldsOf(q).length > 0);
|
|
4778
|
-
return needsDetails ? ["Amount", "Provider", "Details", "Complete"] : ["Amount", "Provider", "Complete"];
|
|
4779
|
-
}
|
|
4780
|
-
var STEP_LABEL = {
|
|
4781
|
-
input: "Amount",
|
|
4782
|
-
loading_quote: "Amount",
|
|
4783
|
-
select_route: "Provider",
|
|
4784
|
-
contact: "Details",
|
|
4785
|
-
status: "Complete"
|
|
4786
|
-
};
|
|
4787
|
-
function brokenLimitOf(amount, quote) {
|
|
4788
|
-
const minAmount = "minAmount" in quote ? quote.minAmount : void 0;
|
|
4789
|
-
const maxAmount = "maxAmount" in quote ? quote.maxAmount : void 0;
|
|
4790
|
-
if (!Number.isFinite(amount)) return null;
|
|
4791
|
-
if (minAmount != null && amount < minAmount) return { limit: "min", value: minAmount };
|
|
4792
|
-
if (maxAmount != null && amount > maxAmount) return { limit: "max", value: maxAmount };
|
|
4793
|
-
return null;
|
|
4794
|
-
}
|
|
4795
|
-
function limitMessage(limit, value, currency) {
|
|
4796
|
-
return `The ${limit === "min" ? "minimum" : "maximum"} amount for this route is ${value} ${currency}.`;
|
|
4797
|
-
}
|
|
4709
|
+
var PAYMENT_CHECK_EVERY_MS = 1e4;
|
|
4710
|
+
var PAYMENT_CHECK_WINDOW_MS = 2 * 6e4;
|
|
4798
4711
|
var RAMP_ERROR_MESSAGES = {
|
|
4799
|
-
SDK_RAMPS_QUOTE_EXPIRED: "This quote expired.
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
SDK_RAMPS_ANCHOR_ERROR: "The provider rejected the request. Please try again in a moment.",
|
|
4805
|
-
SDK_RAMPS_BRIDGE_ERROR: "The provider rejected the request. Please try again in a moment.",
|
|
4806
|
-
SDK_RAMPS_ETHERFUSE_ERROR: "The provider rejected the request. Please try again in a moment.",
|
|
4807
|
-
SDK_RAMPS_INSUFFICIENT_BALANCE: "This wallet does not hold enough to cover that amount. Try a smaller one.",
|
|
4808
|
-
// Nothing moved on-chain, so the balance is untouched. Almost always no XLM
|
|
4809
|
-
// for the network fee on a wallet the app does not sponsor.
|
|
4810
|
-
SDK_RAMPS_ONCHAIN_SUBMIT_FAILED: "The network rejected the transaction, so nothing was sent. The wallet may need XLM for the fee."
|
|
4712
|
+
SDK_RAMPS_QUOTE_EXPIRED: "This quote expired. Find a route again.",
|
|
4713
|
+
SDK_RAMPS_QUOTE_NOT_FOUND: "This quote is no longer available. Find a route again.",
|
|
4714
|
+
SDK_RAMPS_ACTION_STALE: "This step changed. It was refreshed; try again.",
|
|
4715
|
+
SDK_RAMPS_TX_NOT_FOUND: "This operation was not found.",
|
|
4716
|
+
SDK_RAMPS_WALLET_NOT_READY: "Approve the new wallet account on your device, then try again."
|
|
4811
4717
|
};
|
|
4812
|
-
function rampErrorMessage(
|
|
4813
|
-
const
|
|
4814
|
-
if (
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
if ((limit === "min" || limit === "max") && typeof value === "number" && typeof currency === "string") {
|
|
4821
|
-
return limitMessage(limit, value, currency);
|
|
4822
|
-
}
|
|
4823
|
-
return RAMP_ERROR_MESSAGES[code] ?? (e instanceof Error ? e.message : fallback);
|
|
4824
|
-
}
|
|
4825
|
-
function readRampStorage(key) {
|
|
4826
|
-
try {
|
|
4827
|
-
return typeof window === "undefined" ? null : window.sessionStorage.getItem(key);
|
|
4828
|
-
} catch {
|
|
4829
|
-
return null;
|
|
4830
|
-
}
|
|
4831
|
-
}
|
|
4832
|
-
function writeRampStorage(key, value) {
|
|
4833
|
-
try {
|
|
4834
|
-
if (typeof window === "undefined") return;
|
|
4835
|
-
if (value === null) window.sessionStorage.removeItem(key);
|
|
4836
|
-
else window.sessionStorage.setItem(key, value);
|
|
4837
|
-
} catch {
|
|
4718
|
+
function rampErrorMessage(error, fallback) {
|
|
4719
|
+
const unavailable = appUnavailableMessage(error);
|
|
4720
|
+
if (unavailable) return unavailable;
|
|
4721
|
+
if (isPollarApiError(error)) {
|
|
4722
|
+
const known = RAMP_ERROR_MESSAGES[error.code];
|
|
4723
|
+
if (known) return known;
|
|
4724
|
+
const message = error.body.message;
|
|
4725
|
+
if (typeof message === "string" && message && !/^[A-Z0-9_]+$/.test(message)) return message;
|
|
4838
4726
|
}
|
|
4727
|
+
return fallback;
|
|
4839
4728
|
}
|
|
4840
|
-
function
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
return Array.isArray(value) ? value.filter((item) => typeof item?.txId === "string" && typeof item?.provider === "string") : [];
|
|
4844
|
-
} catch {
|
|
4845
|
-
return [];
|
|
4846
|
-
}
|
|
4729
|
+
function routeKey(quote) {
|
|
4730
|
+
const node = (n) => n.kind === "asset" ? `${n.code}:${n.chain}` : `${n.currency}:${n.rail}`;
|
|
4731
|
+
return quote.legs.map((leg) => `${leg.kind}:${node(leg.from)}>${node(leg.to)}`).join("|");
|
|
4847
4732
|
}
|
|
4848
|
-
|
|
4733
|
+
var DECIMAL = /^\d+(\.\d+)?$/;
|
|
4734
|
+
async function signLegWithWallet(client, orderId, actionId) {
|
|
4735
|
+
const lent = [];
|
|
4736
|
+
const lend = (chain, encoding, handler) => {
|
|
4737
|
+
try {
|
|
4738
|
+
lent.push(client.registerRampSigningHandler(chain, encoding, handler));
|
|
4739
|
+
} catch {
|
|
4740
|
+
}
|
|
4741
|
+
};
|
|
4742
|
+
lend("STELLAR", "xdr", async (action) => {
|
|
4743
|
+
const wallet = client.getWallet();
|
|
4744
|
+
if (!wallet) throw new Error("Connect the Stellar wallet this step was built for.");
|
|
4745
|
+
assertRampStellarSigner(action, wallet.address);
|
|
4746
|
+
const outcome = await client.signTx(action.payload.value);
|
|
4747
|
+
if (client.getWallet()?.address !== wallet.address)
|
|
4748
|
+
throw new Error("The connected wallet changed. Refresh before signing.");
|
|
4749
|
+
if (outcome.status === "signed") return outcome.signedXdr;
|
|
4750
|
+
throw new Error(
|
|
4751
|
+
outcome.status === "error" ? outcome.message ?? outcome.details ?? "Signing was cancelled." : "Signing was cancelled."
|
|
4752
|
+
);
|
|
4753
|
+
});
|
|
4754
|
+
lend("SOLANA", "solana-v0-json", async (action) => {
|
|
4755
|
+
const payload = JSON.parse(action.payload.value);
|
|
4756
|
+
const solanaWallet = () => client.getWallets().find((w) => w.chain === "SOLANA" && w.custody === "external");
|
|
4757
|
+
const wallet = solanaWallet();
|
|
4758
|
+
if (!wallet || payload.from !== wallet.address || !payload.unsignedTransaction)
|
|
4759
|
+
throw new Error("This step must be signed by the Solana wallet it was built for. Reconnect that wallet.");
|
|
4760
|
+
const signed = await client.signSolanaTransaction(payload.unsignedTransaction);
|
|
4761
|
+
if (solanaWallet()?.address !== wallet.address) throw new Error("The connected wallet changed. Refresh before signing.");
|
|
4762
|
+
return signed;
|
|
4763
|
+
});
|
|
4849
4764
|
try {
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
return [];
|
|
4765
|
+
return await client.signRampLeg(orderId, actionId);
|
|
4766
|
+
} finally {
|
|
4767
|
+
for (const release of lent) release();
|
|
4854
4768
|
}
|
|
4855
4769
|
}
|
|
4856
|
-
function explorerTxUrl2(chain, hash, network) {
|
|
4857
|
-
if (!hash) return null;
|
|
4858
|
-
const testnet = network === "testnet";
|
|
4859
|
-
if (chain === "SOLANA") return `https://explorer.solana.com/tx/${hash}${testnet ? "?cluster=devnet" : ""}`;
|
|
4860
|
-
if (chain === "POLYGON") return `https://${testnet ? "amoy." : ""}polygonscan.com/tx/${hash}`;
|
|
4861
|
-
return `https://stellar.expert/explorer/${testnet ? "testnet" : "public"}/tx/${hash}`;
|
|
4862
|
-
}
|
|
4863
4770
|
function RampWidget({ onClose }) {
|
|
4864
|
-
const {
|
|
4865
|
-
|
|
4771
|
+
const {
|
|
4772
|
+
getClient,
|
|
4773
|
+
styles,
|
|
4774
|
+
network,
|
|
4775
|
+
openCosignModal,
|
|
4776
|
+
setCosignNextStep,
|
|
4777
|
+
openRecoveryModal,
|
|
4778
|
+
recovery,
|
|
4779
|
+
recoveryLocked,
|
|
4780
|
+
appConfig,
|
|
4781
|
+
cosign,
|
|
4782
|
+
refreshWalletBalance
|
|
4783
|
+
} = usePollar();
|
|
4866
4784
|
const client = getClient();
|
|
4867
4785
|
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
4868
4786
|
const [step, setStep] = useState("input");
|
|
4869
|
-
const [direction, setDirection] = useState("
|
|
4870
|
-
const [
|
|
4871
|
-
const [
|
|
4787
|
+
const [direction, setDirection] = useState("ONRAMP");
|
|
4788
|
+
const [routes, setRoutes] = useState([]);
|
|
4789
|
+
const [routesLoading, setRoutesLoading] = useState(true);
|
|
4872
4790
|
const [country, setCountry] = useState("");
|
|
4873
|
-
const [
|
|
4874
|
-
const
|
|
4875
|
-
const [
|
|
4876
|
-
const [countriesLoading, setCountriesLoading] = useState(true);
|
|
4877
|
-
const [refreshing, setRefreshing] = useState(false);
|
|
4791
|
+
const [fiatChoice, setFiatChoice] = useState("");
|
|
4792
|
+
const [assetChoice, setAssetChoice] = useState("");
|
|
4793
|
+
const [amount, setAmount] = useState("");
|
|
4878
4794
|
const [quotes, setQuotes] = useState([]);
|
|
4879
|
-
const [
|
|
4880
|
-
const [
|
|
4795
|
+
const [rejected, setRejected] = useState([]);
|
|
4796
|
+
const [selected, setSelected] = useState(null);
|
|
4797
|
+
const [startingQuoteId, setStartingQuoteId] = useState(null);
|
|
4798
|
+
const [fieldValues, setFieldValues] = useState({});
|
|
4799
|
+
const [order, setOrder] = useState(null);
|
|
4800
|
+
const [pendingOrders, setPendingOrders] = useState([]);
|
|
4881
4801
|
const [isLoading, setIsLoading] = useState(false);
|
|
4882
|
-
const [
|
|
4883
|
-
const [
|
|
4884
|
-
const kycAttempt = useRef(null);
|
|
4885
|
-
useEffect(
|
|
4886
|
-
() => () => {
|
|
4887
|
-
kycAttempt.current = null;
|
|
4888
|
-
},
|
|
4889
|
-
[]
|
|
4890
|
-
);
|
|
4891
|
-
const [txId, setTxId] = useState(null);
|
|
4892
|
-
const [provider, setProvider] = useState("");
|
|
4893
|
-
const [kycUrl, setKycUrl] = useState(null);
|
|
4894
|
-
const [tosUrl, setTosUrl] = useState(null);
|
|
4895
|
-
const [kycPending, setKycPending] = useState(false);
|
|
4896
|
-
const [kycApproved, setKycApproved] = useState(false);
|
|
4897
|
-
const [onboardingStatus, setOnboardingStatus] = useState(void 0);
|
|
4898
|
-
const [txStatus, setTxStatus] = useState(null);
|
|
4899
|
-
const [stellarTxHash, setStellarTxHash] = useState(null);
|
|
4900
|
-
const [txHash, setTxHash] = useState(null);
|
|
4901
|
-
const [txChain, setTxChain] = useState(null);
|
|
4902
|
-
const [fundsInTransit, setFundsInTransit] = useState(false);
|
|
4903
|
-
const [retrying, setRetrying] = useState(false);
|
|
4904
|
-
const [depositInstructions, setDepositInstructions] = useState(null);
|
|
4905
|
-
const [workflow, setWorkflow] = useState(null);
|
|
4906
|
-
const workflowRef = useRef(null);
|
|
4907
|
-
const storageKey = `pollar:ramp:${client.apiKey}:${walletAddress}`;
|
|
4908
|
-
const [savedRamps, setSavedRamps] = useState([]);
|
|
4909
|
-
const [legacySignature, setLegacySignature] = useState(void 0);
|
|
4910
|
-
function acceptWorkflow(incoming) {
|
|
4911
|
-
if (hiddenRampsOf(storageKey).includes(incoming.txId)) return false;
|
|
4912
|
-
const next = mergeRampSnapshot(workflowRef.current, incoming);
|
|
4913
|
-
workflowRef.current = next;
|
|
4914
|
-
setWorkflow(next);
|
|
4915
|
-
if (next === incoming) {
|
|
4916
|
-
const pending = savedRampsOf(storageKey).filter((item) => item.txId !== incoming.txId);
|
|
4917
|
-
if (!["completed", "failed", "refunded"].includes(incoming.lifecycleState ?? incoming.status))
|
|
4918
|
-
pending.push({
|
|
4919
|
-
txId: incoming.txId,
|
|
4920
|
-
provider: "provider" in incoming && typeof incoming.provider === "string" ? incoming.provider : provider || "Ramp"
|
|
4921
|
-
});
|
|
4922
|
-
writeRampStorage(`${storageKey}:saved`, JSON.stringify(pending));
|
|
4923
|
-
writeRampStorage(storageKey, incoming.txId);
|
|
4924
|
-
writeRampStorage(`${storageKey}:selection`, null);
|
|
4925
|
-
setSavedRamps(pending);
|
|
4926
|
-
}
|
|
4927
|
-
return next === incoming;
|
|
4928
|
-
}
|
|
4929
|
-
const [routes, setRoutes] = useState([]);
|
|
4930
|
-
const countries = mergeRampCountries(legacyCountries, routes);
|
|
4931
|
-
useEffect(() => {
|
|
4932
|
-
if (!country && countries[0]) {
|
|
4933
|
-
setCountry(countries[0].code);
|
|
4934
|
-
setCurrency(countries[0].currency ?? "");
|
|
4935
|
-
}
|
|
4936
|
-
}, [countries, country]);
|
|
4937
|
-
useEffect(() => {
|
|
4938
|
-
let active = true;
|
|
4939
|
-
void client.getRampRoutes().then((result) => {
|
|
4940
|
-
if (active) setRoutes(result.routes);
|
|
4941
|
-
}).catch(() => {
|
|
4942
|
-
});
|
|
4943
|
-
return () => {
|
|
4944
|
-
active = false;
|
|
4945
|
-
};
|
|
4946
|
-
}, [client]);
|
|
4947
|
-
const [completing, setCompleting] = useState(false);
|
|
4948
|
-
const completionLocked = useRef(false);
|
|
4802
|
+
const [refreshing, setRefreshing] = useState(false);
|
|
4803
|
+
const [signing, setSigning] = useState(false);
|
|
4949
4804
|
const [errorMsg, setErrorMsg] = useState(null);
|
|
4805
|
+
const [verifying, setVerifying] = useState(null);
|
|
4806
|
+
const [trustingAsset, setTrustingAsset] = useState(null);
|
|
4807
|
+
const [walletBusy, setWalletBusy] = useState(null);
|
|
4808
|
+
const [retrying, setRetrying] = useState(false);
|
|
4809
|
+
const [awaitingAccount, setAwaitingAccount] = useState(null);
|
|
4810
|
+
const [pollTrouble, setPollTrouble] = useState(false);
|
|
4811
|
+
const [pollKey, setPollKey] = useState(0);
|
|
4812
|
+
const [paymentCheckUntil, setPaymentCheckUntil] = useState(null);
|
|
4813
|
+
const checkErrorRef = useRef(null);
|
|
4814
|
+
const promptedApproval = useRef(null);
|
|
4815
|
+
const custodyChoice = appConfig.application?.walletCustodyMode === "USER_CHOICE";
|
|
4816
|
+
const appChains = appConfig.application?.chains;
|
|
4817
|
+
const verifyAttempt = useRef(null);
|
|
4818
|
+
const countries = useMemo(() => rampCountries(routes), [routes]);
|
|
4819
|
+
const fiats = countries.find((c) => c.country === country)?.fiats ?? [];
|
|
4820
|
+
const fiat = fiats.find((f) => fiatKey(f) === fiatChoice) ?? fiats[0] ?? null;
|
|
4821
|
+
const assets = useMemo(() => {
|
|
4822
|
+
const seen = /* @__PURE__ */ new Map();
|
|
4823
|
+
for (const route of routes)
|
|
4824
|
+
if (fiat && route.fiat.country === country && fiatKey(route.fiat) === fiatKey(fiat))
|
|
4825
|
+
seen.set(assetKey3(route.asset), route.asset);
|
|
4826
|
+
return [...seen.values()];
|
|
4827
|
+
}, [routes, country, fiat]);
|
|
4828
|
+
const asset = assets.find((a) => assetKey3(a) === assetChoice) ?? assets[0] ?? null;
|
|
4829
|
+
const fields = selected ? rampQuoteFields(selected) : [];
|
|
4830
|
+
const sellAvailable = useWalletAvailable(
|
|
4831
|
+
direction === "OFFRAMP" && asset ? { chain: asset.chain, code: asset.code, issuer: asset.identifier } : null
|
|
4832
|
+
);
|
|
4950
4833
|
useEffect(() => {
|
|
4951
|
-
if (
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
const savedId = [new URLSearchParams(window.location.search).get("rampTxId"), readRampStorage(storageKey)].find(
|
|
4956
|
-
(id) => id && !hidden.includes(id)
|
|
4957
|
-
);
|
|
4958
|
-
if (!savedId) return;
|
|
4959
|
-
let active = true;
|
|
4960
|
-
void client.getRampTransaction(savedId).then(async (result) => {
|
|
4961
|
-
if (!active || result.transactionVersion === void 0) return;
|
|
4962
|
-
setDirection(result.direction);
|
|
4963
|
-
await applyResult(result);
|
|
4964
|
-
}).catch(() => {
|
|
4965
|
-
if (active)
|
|
4966
|
-
setErrorMsg("Could not restore the saved ramp. Retry opening the modal; do not create a replacement order.");
|
|
4967
|
-
});
|
|
4968
|
-
return () => {
|
|
4969
|
-
active = false;
|
|
4970
|
-
};
|
|
4971
|
-
}, [client, storageKey, walletAddress]);
|
|
4972
|
-
async function resumeSavedRamp(id) {
|
|
4973
|
-
if (completionLocked.current) return;
|
|
4974
|
-
setIsLoading(true);
|
|
4975
|
-
setErrorMsg(null);
|
|
4834
|
+
if (direction === "OFFRAMP") void refreshWalletBalance();
|
|
4835
|
+
}, [direction, refreshWalletBalance]);
|
|
4836
|
+
async function loadRoutes(next) {
|
|
4837
|
+
setRoutesLoading(true);
|
|
4976
4838
|
try {
|
|
4977
|
-
const
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4839
|
+
const { routes: found } = await client.getRampRoutes(next);
|
|
4840
|
+
setRoutes(found);
|
|
4841
|
+
const first = rampCountries(found)[0]?.country ?? "";
|
|
4842
|
+
setCountry((current) => found.some((r) => r.fiat.country === current) ? current : first);
|
|
4981
4843
|
} catch (error) {
|
|
4982
|
-
|
|
4844
|
+
setRoutes([]);
|
|
4845
|
+
setErrorMsg(rampErrorMessage(error, "Could not load the ramp routes."));
|
|
4983
4846
|
} finally {
|
|
4984
|
-
|
|
4847
|
+
setRoutesLoading(false);
|
|
4985
4848
|
}
|
|
4986
4849
|
}
|
|
4987
|
-
|
|
4988
|
-
directionRef.current = direction;
|
|
4989
|
-
function applySettlement(tx) {
|
|
4990
|
-
if (tx.stellarTxHash) setStellarTxHash(tx.stellarTxHash);
|
|
4991
|
-
if (tx.txHash) setTxHash(tx.txHash);
|
|
4992
|
-
if (tx.chain) setTxChain(tx.chain);
|
|
4993
|
-
setFundsInTransit(tx.fundsInTransit === true);
|
|
4994
|
-
}
|
|
4995
|
-
async function handleRetryTransit() {
|
|
4996
|
-
if (!txId || retrying) return;
|
|
4997
|
-
setRetrying(true);
|
|
4998
|
-
setErrorMsg(null);
|
|
4850
|
+
async function loadPendingOrders() {
|
|
4999
4851
|
try {
|
|
5000
|
-
const
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
setErrorMsg(e instanceof Error && e.message ? e.message : "Could not retry the transfer. Try again in a moment.");
|
|
5005
|
-
} finally {
|
|
5006
|
-
setRetrying(false);
|
|
4852
|
+
const page = await client.listRampOrders({ open: "true", limit: 5 });
|
|
4853
|
+
setPendingOrders(page.orders);
|
|
4854
|
+
} catch {
|
|
4855
|
+
setPendingOrders([]);
|
|
5007
4856
|
}
|
|
5008
4857
|
}
|
|
5009
|
-
const workflowTerminal = !!workflow && ["completed", "failed", "refunded"].includes(workflow.lifecycleState ?? workflow.status);
|
|
5010
4858
|
useEffect(() => {
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
let active = true;
|
|
5014
|
-
const id = setInterval(async () => {
|
|
5015
|
-
try {
|
|
5016
|
-
const tx = await client.getRampTransaction(txId);
|
|
5017
|
-
if (!active) return;
|
|
5018
|
-
if (tx.transactionVersion !== void 0 && !acceptWorkflow(tx)) return;
|
|
5019
|
-
setTxStatus(tx.status);
|
|
5020
|
-
applySettlement(tx);
|
|
5021
|
-
const pending = "pendingSignature" in tx ? tx.pendingSignature : void 0;
|
|
5022
|
-
if (pending) setLegacySignature(pending);
|
|
5023
|
-
if (tx.kycUrl) setKycUrl(tx.kycUrl);
|
|
5024
|
-
if (tx.depositInstructions) setDepositInstructions(tx.depositInstructions);
|
|
5025
|
-
if (TERMINAL.includes(tx.status)) clearInterval(id);
|
|
5026
|
-
} catch {
|
|
5027
|
-
}
|
|
5028
|
-
}, 5e3);
|
|
5029
|
-
return () => {
|
|
5030
|
-
active = false;
|
|
5031
|
-
clearInterval(id);
|
|
5032
|
-
};
|
|
5033
|
-
}, [step, txId, txStatus, workflowTerminal, client]);
|
|
4859
|
+
void loadRoutes(direction);
|
|
4860
|
+
}, [client, direction]);
|
|
5034
4861
|
useEffect(() => {
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
const check = async () => {
|
|
5039
|
-
try {
|
|
5040
|
-
const { hasApproved } = await client.getRampKycStatus();
|
|
5041
|
-
if (active && hasApproved) setKycApproved(true);
|
|
5042
|
-
} catch {
|
|
5043
|
-
}
|
|
5044
|
-
};
|
|
5045
|
-
void check();
|
|
5046
|
-
const id = setInterval(check, 1e4);
|
|
5047
|
-
return () => {
|
|
5048
|
-
active = false;
|
|
5049
|
-
clearInterval(id);
|
|
5050
|
-
};
|
|
5051
|
-
}, [step, kycPending, kycApproved, onboardingStatus, workflow, client, provider]);
|
|
5052
|
-
async function loadCountries(resetSelection) {
|
|
5053
|
-
setCountriesLoading(true);
|
|
5054
|
-
try {
|
|
5055
|
-
const { countries: list } = await client.getRampCountries();
|
|
5056
|
-
setCountries(list);
|
|
5057
|
-
const available = mergeRampCountries(list, routes);
|
|
5058
|
-
const first = available[0];
|
|
5059
|
-
const stillValid = available.some((c) => c.code === country);
|
|
5060
|
-
if (first && (resetSelection || !stillValid)) {
|
|
5061
|
-
setCountry(first.code);
|
|
5062
|
-
if (first.currency) setCurrency(first.currency);
|
|
5063
|
-
}
|
|
5064
|
-
} catch {
|
|
5065
|
-
setCountries([]);
|
|
5066
|
-
} finally {
|
|
5067
|
-
setCountriesLoading(false);
|
|
5068
|
-
}
|
|
5069
|
-
}
|
|
4862
|
+
void loadPendingOrders();
|
|
4863
|
+
}, [client]);
|
|
4864
|
+
const orderId = order?.id ?? null;
|
|
5070
4865
|
useEffect(() => {
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
direction
|
|
5092
|
-
},
|
|
5093
|
-
routes
|
|
5094
|
-
);
|
|
5095
|
-
setQuotes(result.quotes ?? []);
|
|
5096
|
-
setRequirementsRequired(result.requirementsRequired ?? []);
|
|
5097
|
-
} else if (step === "status" && txId) {
|
|
5098
|
-
const tx = await client.getRampTransaction(txId);
|
|
5099
|
-
if (tx.transactionVersion !== void 0 && !acceptWorkflow(tx)) return;
|
|
5100
|
-
setTxStatus(tx.status);
|
|
5101
|
-
applySettlement(tx);
|
|
5102
|
-
if (tx.kycUrl) setKycUrl(tx.kycUrl);
|
|
5103
|
-
if (tx.depositInstructions) setDepositInstructions(tx.depositInstructions);
|
|
5104
|
-
}
|
|
5105
|
-
} catch {
|
|
5106
|
-
} finally {
|
|
5107
|
-
setRefreshing(false);
|
|
5108
|
-
}
|
|
5109
|
-
}
|
|
5110
|
-
function resetToInput({ keepMessage = false } = {}) {
|
|
5111
|
-
writeRampStorage(storageKey, null);
|
|
5112
|
-
writeRampStorage(`${storageKey}:selection`, "1");
|
|
5113
|
-
setStep("input");
|
|
5114
|
-
setQuotes([]);
|
|
5115
|
-
setRequirementsRequired([]);
|
|
5116
|
-
setSelectedQuote(null);
|
|
5117
|
-
setFieldValues({});
|
|
5118
|
-
setWorkflow(null);
|
|
5119
|
-
workflowRef.current = null;
|
|
5120
|
-
setLegacySignature(void 0);
|
|
5121
|
-
setTxId(null);
|
|
5122
|
-
setProvider("");
|
|
5123
|
-
setKycUrl(null);
|
|
5124
|
-
setTosUrl(null);
|
|
5125
|
-
setTxStatus(null);
|
|
5126
|
-
setStellarTxHash(null);
|
|
5127
|
-
setTxHash(null);
|
|
5128
|
-
setTxChain(null);
|
|
5129
|
-
setFundsInTransit(false);
|
|
5130
|
-
setDepositInstructions(null);
|
|
5131
|
-
setKycPending(false);
|
|
5132
|
-
setKycApproved(false);
|
|
5133
|
-
setNoticeMsg(null);
|
|
5134
|
-
if (!keepMessage) setErrorMsg(null);
|
|
5135
|
-
}
|
|
5136
|
-
function dismissSavedRamp(id) {
|
|
5137
|
-
if (completionLocked.current) return;
|
|
5138
|
-
const pending = savedRampsOf(storageKey).filter((ramp) => ramp.txId !== id);
|
|
5139
|
-
writeRampStorage(`${storageKey}:saved`, JSON.stringify(pending));
|
|
5140
|
-
writeRampStorage(`${storageKey}:hidden`, JSON.stringify([.../* @__PURE__ */ new Set([...hiddenRampsOf(storageKey), id])]));
|
|
5141
|
-
if (readRampStorage(storageKey) === id) writeRampStorage(storageKey, null);
|
|
5142
|
-
setSavedRamps(pending);
|
|
5143
|
-
if (txId === id) resetToInput();
|
|
5144
|
-
setNoticeMsg(
|
|
5145
|
-
"Removed from this tab\u2019s pending list. The operation may still be active at the provider; no payment was cancelled or refunded."
|
|
5146
|
-
);
|
|
5147
|
-
}
|
|
5148
|
-
async function resumeWithSignature(id, ps) {
|
|
5149
|
-
const outcome = await client.signTx(ps.unsignedXdr, { skipSponsorship: ps.action === "sep10" });
|
|
5150
|
-
if (outcome.status === "cosign_pending") {
|
|
5151
|
-
setErrorMsg("Approve the signature on your device, then resume.");
|
|
5152
|
-
setStep("error");
|
|
4866
|
+
if (step !== "status" || !orderId) return;
|
|
4867
|
+
const controller = new AbortController();
|
|
4868
|
+
client.pollRampOrder(orderId, {
|
|
4869
|
+
signal: controller.signal,
|
|
4870
|
+
onUpdate: (next) => {
|
|
4871
|
+
setOrder(next);
|
|
4872
|
+
setPollTrouble(false);
|
|
4873
|
+
},
|
|
4874
|
+
onError: () => setPollTrouble(true)
|
|
4875
|
+
}).catch((error) => {
|
|
4876
|
+
if (!controller.signal.aborted) setErrorMsg(rampErrorMessage(error, "This operation could not be read."));
|
|
4877
|
+
});
|
|
4878
|
+
return () => controller.abort();
|
|
4879
|
+
}, [client, step, orderId, pollKey]);
|
|
4880
|
+
const awaitingPayment = step === "status" && order?.pendingAction?.kind === "FIAT_PAYMENT";
|
|
4881
|
+
useEffect(() => {
|
|
4882
|
+
if (paymentCheckUntil === null || !orderId) return;
|
|
4883
|
+
if (!awaitingPayment) {
|
|
4884
|
+
setPaymentCheckUntil(null);
|
|
4885
|
+
setPollKey((key) => key + 1);
|
|
5153
4886
|
return;
|
|
5154
4887
|
}
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
4888
|
+
const timer = setInterval(() => {
|
|
4889
|
+
if (Date.now() >= paymentCheckUntil) {
|
|
4890
|
+
setPaymentCheckUntil(null);
|
|
4891
|
+
return;
|
|
4892
|
+
}
|
|
4893
|
+
client.checkRampOrder(orderId).then(setOrder).catch(() => void 0);
|
|
4894
|
+
}, PAYMENT_CHECK_EVERY_MS);
|
|
4895
|
+
return () => clearInterval(timer);
|
|
4896
|
+
}, [client, orderId, awaitingPayment, paymentCheckUntil]);
|
|
4897
|
+
useEffect(() => {
|
|
4898
|
+
if (awaitingPayment || checkErrorRef.current === null) return;
|
|
4899
|
+
const shown = checkErrorRef.current;
|
|
4900
|
+
checkErrorRef.current = null;
|
|
4901
|
+
setErrorMsg((current) => current === shown ? null : current);
|
|
4902
|
+
}, [awaitingPayment]);
|
|
4903
|
+
const approval = order?.pendingAction?.kind === "COSIGN_APPROVAL" ? order.pendingAction.actionId : null;
|
|
4904
|
+
useEffect(() => {
|
|
4905
|
+
if (!approval || promptedApproval.current === approval) return;
|
|
4906
|
+
promptedApproval.current = approval;
|
|
4907
|
+
void client.cosign.pending().catch(() => void 0).then(() => openCosignModal());
|
|
4908
|
+
}, [approval, client, openCosignModal]);
|
|
4909
|
+
const nextApproval = step === "status" && order ? rampNextApproval(order) : null;
|
|
4910
|
+
useEffect(() => {
|
|
4911
|
+
setCosignNextStep(nextApproval);
|
|
4912
|
+
}, [nextApproval, setCosignNextStep]);
|
|
4913
|
+
useEffect(() => () => setCosignNextStep(null), [setCosignNextStep]);
|
|
4914
|
+
const resolvedRequest = cosign.lastResolved;
|
|
4915
|
+
useEffect(() => {
|
|
4916
|
+
if (!awaitingAccount || resolvedRequest?.id !== awaitingAccount.requestId) return;
|
|
4917
|
+
setAwaitingAccount(null);
|
|
4918
|
+
if (resolvedRequest.status !== "APPROVED") {
|
|
4919
|
+
setErrorMsg("The new account was not approved, so this route cannot start.");
|
|
5158
4920
|
return;
|
|
5159
4921
|
}
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
async function applyResult(result) {
|
|
5167
|
-
if ("transactionVersion" in result && result.transactionVersion !== void 0 && !acceptWorkflow(result)) return;
|
|
5168
|
-
setTxId(result.txId);
|
|
5169
|
-
setProvider(result.provider);
|
|
5170
|
-
setLegacySignature(result.pendingSignature);
|
|
5171
|
-
setKycUrl(result.kycUrl ?? null);
|
|
5172
|
-
setTosUrl(result.tosUrl ?? null);
|
|
5173
|
-
setOnboardingStatus(result.onboardingStatus);
|
|
5174
|
-
setKycPending(result.kycRequired === true);
|
|
5175
|
-
if (result.kycRequired) setKycApproved(false);
|
|
5176
|
-
setTxStatus(result.status);
|
|
5177
|
-
setStellarTxHash(result.stellarTxHash ?? null);
|
|
5178
|
-
setDepositInstructions(result.depositInstructions ?? null);
|
|
5179
|
-
setStep("status");
|
|
5180
|
-
}
|
|
5181
|
-
async function loadQuotes() {
|
|
5182
|
-
const result = await quoteRampOptions(
|
|
5183
|
-
client,
|
|
5184
|
-
{
|
|
5185
|
-
country,
|
|
5186
|
-
amount: Number(amount),
|
|
5187
|
-
amountExact: amount,
|
|
5188
|
-
currency,
|
|
5189
|
-
direction
|
|
5190
|
-
},
|
|
5191
|
-
routes
|
|
5192
|
-
);
|
|
5193
|
-
const list = result.quotes ?? [];
|
|
5194
|
-
const locked = result.requirementsRequired ?? [];
|
|
5195
|
-
if (list.length === 0 && locked.length === 0) {
|
|
5196
|
-
setErrorMsg(unavailableRampMessage(country, result.unavailable ?? []));
|
|
5197
|
-
setStep("error");
|
|
5198
|
-
return false;
|
|
5199
|
-
}
|
|
5200
|
-
setQuotes(list);
|
|
5201
|
-
setRequirementsRequired(locked);
|
|
5202
|
-
return true;
|
|
4922
|
+
void resumeRoute(awaitingAccount.routeKey);
|
|
4923
|
+
}, [awaitingAccount, resolvedRequest]);
|
|
4924
|
+
function handleDirectionChange(next) {
|
|
4925
|
+
setDirection(next);
|
|
4926
|
+
setErrorMsg(null);
|
|
4927
|
+
setAwaitingAccount(null);
|
|
5203
4928
|
}
|
|
5204
4929
|
async function handleFindRoute() {
|
|
4930
|
+
if (!fiat || !asset) return [];
|
|
4931
|
+
if (!DECIMAL.test(amount.trim()) || Number(amount) <= 0) {
|
|
4932
|
+
setErrorMsg("Enter an amount greater than zero.");
|
|
4933
|
+
return [];
|
|
4934
|
+
}
|
|
5205
4935
|
setStep("loading_quote");
|
|
5206
|
-
setIsLoading(true);
|
|
5207
4936
|
setErrorMsg(null);
|
|
4937
|
+
setSelected(null);
|
|
5208
4938
|
try {
|
|
5209
|
-
|
|
4939
|
+
const result = await client.quoteRamp({
|
|
4940
|
+
direction,
|
|
4941
|
+
fiat: { currency: fiat.currency, rail: fiat.rail, country: fiat.country },
|
|
4942
|
+
asset: { code: asset.code, identifier: asset.identifier, chain: asset.chain },
|
|
4943
|
+
amount: { value: amount.trim(), denomination: "in" }
|
|
4944
|
+
});
|
|
4945
|
+
setQuotes(result.quotes);
|
|
4946
|
+
setRejected(result.rejected);
|
|
5210
4947
|
setStep("select_route");
|
|
5211
|
-
|
|
5212
|
-
|
|
4948
|
+
return result.quotes;
|
|
4949
|
+
} catch (error) {
|
|
4950
|
+
if (isPollarApiError(error) && error.code === "SDK_RAMPS_NO_ROUTE") {
|
|
4951
|
+
setQuotes([]);
|
|
4952
|
+
setRejected(Array.isArray(error.body.rejected) ? error.body.rejected : []);
|
|
4953
|
+
setStep("select_route");
|
|
4954
|
+
return [];
|
|
4955
|
+
}
|
|
4956
|
+
setErrorMsg(rampErrorMessage(error, "Could not find a route. Please try again."));
|
|
5213
4957
|
setStep("error");
|
|
4958
|
+
return [];
|
|
4959
|
+
}
|
|
4960
|
+
}
|
|
4961
|
+
function handleVerifyRoute(requirement) {
|
|
4962
|
+
setErrorMsg(null);
|
|
4963
|
+
verifyAttempt.current = requirement;
|
|
4964
|
+
setVerifying(requirement);
|
|
4965
|
+
}
|
|
4966
|
+
function closeVerification() {
|
|
4967
|
+
verifyAttempt.current = null;
|
|
4968
|
+
setVerifying(null);
|
|
4969
|
+
}
|
|
4970
|
+
function verificationDone(requirement) {
|
|
4971
|
+
if (verifyAttempt.current !== requirement) return;
|
|
4972
|
+
closeVerification();
|
|
4973
|
+
void handleFindRoute();
|
|
4974
|
+
}
|
|
4975
|
+
async function handleTrustAsset(asset2) {
|
|
4976
|
+
if (trustingAsset) return;
|
|
4977
|
+
setTrustingAsset(`${asset2.code}:${asset2.issuer}`);
|
|
4978
|
+
setErrorMsg(null);
|
|
4979
|
+
try {
|
|
4980
|
+
const outcome = await client.setTrustline(asset2);
|
|
4981
|
+
if (outcome.status === "error") {
|
|
4982
|
+
setErrorMsg(rampTrustlineErrorText(outcome, asset2.code));
|
|
4983
|
+
return;
|
|
4984
|
+
}
|
|
4985
|
+
if (outcome.status === "cosign_pending") {
|
|
4986
|
+
setErrorMsg(`Approve the ${asset2.code} trustline, then refresh the routes.`);
|
|
4987
|
+
openCosignModal();
|
|
4988
|
+
return;
|
|
4989
|
+
}
|
|
4990
|
+
await client.refreshAssets().catch(() => {
|
|
4991
|
+
});
|
|
4992
|
+
await handleFindRoute();
|
|
4993
|
+
} catch (error) {
|
|
4994
|
+
setErrorMsg(rampErrorMessage(error, `Could not add the ${asset2.code} trustline. Please try again.`));
|
|
5214
4995
|
} finally {
|
|
5215
|
-
|
|
4996
|
+
setTrustingAsset(null);
|
|
5216
4997
|
}
|
|
5217
4998
|
}
|
|
5218
|
-
function
|
|
5219
|
-
|
|
4999
|
+
async function handleWalletStep(walletStep, index, custody) {
|
|
5000
|
+
if (walletBusy !== null) return;
|
|
5001
|
+
setWalletBusy(index);
|
|
5220
5002
|
setErrorMsg(null);
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5003
|
+
try {
|
|
5004
|
+
const { recoveryRequired } = await client.runRampWalletStep(walletStep, custody);
|
|
5005
|
+
if (recoveryRequired) {
|
|
5006
|
+
setErrorMsg("Add a way to recover your wallet, then find the route again.");
|
|
5007
|
+
openRecoveryModal();
|
|
5008
|
+
return;
|
|
5009
|
+
}
|
|
5010
|
+
await handleFindRoute();
|
|
5011
|
+
} catch (error) {
|
|
5012
|
+
const code = isPollarApiError(error) ? error.code : null;
|
|
5013
|
+
if (code === "SDK_RAMPS_WALLET_NOT_READY") {
|
|
5014
|
+
setErrorMsg("Approve the new account, then find the route again.");
|
|
5015
|
+
openCosignModal();
|
|
5016
|
+
return;
|
|
5017
|
+
}
|
|
5018
|
+
setErrorMsg(
|
|
5019
|
+
code === "SDK_WALLET_PROVISIONING_DISABLED" ? "This app does not create wallets." : rampErrorMessage(error, "Could not prepare the wallet. Please try again.")
|
|
5020
|
+
);
|
|
5021
|
+
} finally {
|
|
5022
|
+
setWalletBusy(null);
|
|
5226
5023
|
}
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5024
|
+
}
|
|
5025
|
+
async function resumeRoute(key) {
|
|
5026
|
+
const same = (await handleFindRoute()).find((q) => routeKey(q) === key);
|
|
5027
|
+
if (same) handleSelectQuote(same, true);
|
|
5028
|
+
else setErrorMsg("That route is no longer available. Pick another one.");
|
|
5029
|
+
}
|
|
5030
|
+
function handleSelectQuote(quote, fresh = false) {
|
|
5031
|
+
if (!fresh && Date.parse(quote.expiresAt) <= Date.now()) {
|
|
5032
|
+
void resumeRoute(routeKey(quote));
|
|
5231
5033
|
return;
|
|
5232
5034
|
}
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
if (
|
|
5035
|
+
setSelected(quote);
|
|
5036
|
+
setErrorMsg(null);
|
|
5037
|
+
const missing = rampQuoteFields(quote).some((f) => !f.optional && !(fieldValues[f.key] ?? "").trim());
|
|
5038
|
+
if (missing) setStep("contact");
|
|
5039
|
+
else void startOrder(quote, fresh);
|
|
5237
5040
|
}
|
|
5238
|
-
async function
|
|
5041
|
+
async function startOrder(quote, fresh = false) {
|
|
5239
5042
|
setIsLoading(true);
|
|
5043
|
+
setStartingQuoteId(quote.quoteId);
|
|
5240
5044
|
setErrorMsg(null);
|
|
5045
|
+
setAwaitingAccount(null);
|
|
5241
5046
|
try {
|
|
5242
|
-
const
|
|
5047
|
+
const payee = Object.fromEntries(
|
|
5048
|
+
rampQuoteFields(quote).map((f) => [f.key, (fieldValues[f.key] ?? "").trim()]).filter(([, value]) => value)
|
|
5049
|
+
);
|
|
5050
|
+
const created = await client.createRampOrder({
|
|
5243
5051
|
quoteId: quote.quoteId,
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
else extraFields[f.key] = val;
|
|
5052
|
+
...Object.keys(payee).length ? { payee } : {}
|
|
5053
|
+
});
|
|
5054
|
+
setOrder(created);
|
|
5055
|
+
setStep("status");
|
|
5056
|
+
} catch (error) {
|
|
5057
|
+
if (isPollarApiError(error) && error.code === "SDK_RAMPS_WALLET_NOT_READY") {
|
|
5058
|
+
const pending = await client.cosign.pending().catch(() => []);
|
|
5059
|
+
const request = pending.find((r) => r.intent === "add_accounts");
|
|
5060
|
+
if (request) setAwaitingAccount({ routeKey: routeKey(quote), requestId: request.id });
|
|
5061
|
+
else setErrorMsg(rampErrorMessage(error, "Could not start the operation. Please try again."));
|
|
5062
|
+
openCosignModal();
|
|
5063
|
+
setStep("select_route");
|
|
5064
|
+
return;
|
|
5258
5065
|
}
|
|
5259
|
-
if (
|
|
5260
|
-
|
|
5261
|
-
requiredFieldsOf(quote).map((field) => [field.key, (fieldValues[field.key] ?? "").trim()]).filter(([, value]) => value)
|
|
5262
|
-
);
|
|
5263
|
-
else if (Object.keys(extraFields).length > 0) body.fields = extraFields;
|
|
5264
|
-
const onrampBody = {
|
|
5265
|
-
quoteId: body.quoteId,
|
|
5266
|
-
amount: body.amount,
|
|
5267
|
-
currency: body.currency,
|
|
5268
|
-
country: body.country,
|
|
5269
|
-
...body.amountExact !== void 0 ? { amountExact: body.amountExact } : {},
|
|
5270
|
-
...body.walletAddress !== void 0 ? { walletAddress: body.walletAddress } : {},
|
|
5271
|
-
...body.email !== void 0 ? { email: body.email } : {},
|
|
5272
|
-
...body.fullName !== void 0 ? { fullName: body.fullName } : {},
|
|
5273
|
-
...body.fields !== void 0 ? { fields: body.fields } : {}
|
|
5274
|
-
};
|
|
5275
|
-
const result = direction === "onramp" ? await client.createOnRamp(onrampBody) : await client.createOffRamp(body);
|
|
5276
|
-
await applyResult(result);
|
|
5277
|
-
} catch (e) {
|
|
5278
|
-
const requirement = requiredRampKyc(e);
|
|
5279
|
-
if (requirement) {
|
|
5280
|
-
setStep(requiredFieldsOf(quote).length ? "contact" : "select_route");
|
|
5281
|
-
setErrorMsg(
|
|
5282
|
-
requirement.type === "KYC" ? "Identity verification is required before continuing." : "A few more details are required before continuing."
|
|
5283
|
-
);
|
|
5284
|
-
kycAttempt.current = requirement;
|
|
5285
|
-
setPendingKyc(requirement);
|
|
5066
|
+
if (isPollarApiError(error) && error.code === "SDK_RAMPS_QUOTE_EXPIRED" && !fresh) {
|
|
5067
|
+
void resumeRoute(routeKey(quote));
|
|
5286
5068
|
return;
|
|
5287
5069
|
}
|
|
5288
|
-
setErrorMsg(rampErrorMessage(
|
|
5289
|
-
setStep("
|
|
5070
|
+
setErrorMsg(rampErrorMessage(error, "Could not start the operation. Please try again."));
|
|
5071
|
+
if (isPollarApiError(error) && error.code === "VALIDATION_ERROR" && rampQuoteFields(quote).length) setStep("contact");
|
|
5072
|
+
else setStep("select_route");
|
|
5290
5073
|
} finally {
|
|
5291
5074
|
setIsLoading(false);
|
|
5075
|
+
setStartingQuoteId(null);
|
|
5292
5076
|
}
|
|
5293
5077
|
}
|
|
5294
|
-
async function
|
|
5295
|
-
|
|
5078
|
+
async function handleSign() {
|
|
5079
|
+
const action = order?.pendingAction;
|
|
5080
|
+
if (!order || action?.kind !== "SIGNATURE" || signing) return;
|
|
5081
|
+
setSigning(true);
|
|
5082
|
+
setErrorMsg(null);
|
|
5083
|
+
try {
|
|
5084
|
+
setOrder(await signLegWithWallet(client, order.id, action.actionId));
|
|
5085
|
+
} catch (error) {
|
|
5086
|
+
setErrorMsg(rampErrorMessage(error, error instanceof Error && error.message ? error.message : "Signing was cancelled."));
|
|
5087
|
+
setOrder(await client.getRampOrder(order.id).catch(() => order));
|
|
5088
|
+
} finally {
|
|
5089
|
+
setSigning(false);
|
|
5090
|
+
}
|
|
5091
|
+
}
|
|
5092
|
+
async function handleResumeOrder(id) {
|
|
5296
5093
|
setIsLoading(true);
|
|
5297
5094
|
setErrorMsg(null);
|
|
5298
|
-
setSelectedQuote(null);
|
|
5299
5095
|
try {
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
);
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
setErrorMsg(rampErrorMessage(e, "Failed to fetch quotes."));
|
|
5307
|
-
setStep("error");
|
|
5096
|
+
const found = await client.getRampOrder(id);
|
|
5097
|
+
setDirection(found.direction);
|
|
5098
|
+
setOrder(found);
|
|
5099
|
+
setStep("status");
|
|
5100
|
+
} catch (error) {
|
|
5101
|
+
setErrorMsg(rampErrorMessage(error, "Could not resume the operation."));
|
|
5308
5102
|
} finally {
|
|
5309
5103
|
setIsLoading(false);
|
|
5310
5104
|
}
|
|
5311
5105
|
}
|
|
5312
|
-
function
|
|
5313
|
-
|
|
5106
|
+
function handleNewOrder() {
|
|
5107
|
+
setAwaitingAccount(null);
|
|
5108
|
+
setOrder(null);
|
|
5109
|
+
setSelected(null);
|
|
5110
|
+
setQuotes([]);
|
|
5111
|
+
setRejected([]);
|
|
5314
5112
|
setErrorMsg(null);
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
setPendingKyc(attempt);
|
|
5113
|
+
setStep("input");
|
|
5114
|
+
void loadPendingOrders();
|
|
5318
5115
|
}
|
|
5319
|
-
function
|
|
5320
|
-
|
|
5116
|
+
function handleBack() {
|
|
5117
|
+
setErrorMsg(null);
|
|
5118
|
+
setAwaitingAccount(null);
|
|
5119
|
+
setStep(step === "contact" ? "select_route" : "input");
|
|
5321
5120
|
}
|
|
5322
|
-
function
|
|
5323
|
-
|
|
5121
|
+
function handleStepSelect(target) {
|
|
5122
|
+
setErrorMsg(null);
|
|
5123
|
+
setAwaitingAccount(null);
|
|
5124
|
+
setStep(target === "Route" ? "select_route" : "input");
|
|
5324
5125
|
}
|
|
5325
|
-
async function
|
|
5326
|
-
if (!
|
|
5327
|
-
completionLocked.current = true;
|
|
5328
|
-
setCompleting(true);
|
|
5126
|
+
async function handleCheckPayment() {
|
|
5127
|
+
if (!order || paymentCheckUntil !== null) return;
|
|
5329
5128
|
setErrorMsg(null);
|
|
5129
|
+
setPaymentCheckUntil(Date.now() + PAYMENT_CHECK_WINDOW_MS);
|
|
5330
5130
|
try {
|
|
5331
|
-
await
|
|
5332
|
-
} catch (
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5131
|
+
setOrder(await client.checkRampOrder(order.id));
|
|
5132
|
+
} catch (error) {
|
|
5133
|
+
if (isPollarNetworkError(error)) return;
|
|
5134
|
+
setPaymentCheckUntil(null);
|
|
5135
|
+
const message = rampErrorMessage(error, "Could not check the payment. Please try again.");
|
|
5136
|
+
checkErrorRef.current = message;
|
|
5137
|
+
setErrorMsg(message);
|
|
5338
5138
|
}
|
|
5339
5139
|
}
|
|
5340
|
-
async function
|
|
5341
|
-
if (!
|
|
5342
|
-
|
|
5343
|
-
setCompleting(true);
|
|
5140
|
+
async function handleRetryOrder() {
|
|
5141
|
+
if (!order || retrying) return;
|
|
5142
|
+
setRetrying(true);
|
|
5344
5143
|
setErrorMsg(null);
|
|
5345
5144
|
try {
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
}
|
|
5351
|
-
setTxStatus(result.status);
|
|
5352
|
-
setStellarTxHash(result.stellarTxHash ?? null);
|
|
5353
|
-
} catch (e) {
|
|
5354
|
-
const msg = e instanceof Error ? e.message : "";
|
|
5355
|
-
setErrorMsg(
|
|
5356
|
-
msg.includes("KYC") ? "Finish KYC at the provider first, then try again." : msg || "Failed to complete the withdrawal."
|
|
5357
|
-
);
|
|
5145
|
+
setOrder(await client.retryRampOrder(order.id));
|
|
5146
|
+
setPollKey((key) => key + 1);
|
|
5147
|
+
} catch (error) {
|
|
5148
|
+
setErrorMsg(rampErrorMessage(error, "Could not try again. Please try again."));
|
|
5358
5149
|
} finally {
|
|
5359
|
-
|
|
5360
|
-
setCompleting(false);
|
|
5150
|
+
setRetrying(false);
|
|
5361
5151
|
}
|
|
5362
5152
|
}
|
|
5363
|
-
const
|
|
5364
|
-
const
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
void requoteAfterKyc("FORM");
|
|
5382
|
-
}
|
|
5153
|
+
const heldForRecovery = step === "status" && order?.failure?.resolutionAction === "set_up_recovery";
|
|
5154
|
+
const wasRecoveryLocked = useRef(recoveryLocked);
|
|
5155
|
+
useEffect(() => {
|
|
5156
|
+
if (heldForRecovery && wasRecoveryLocked.current && !recoveryLocked && recovery) void handleRetryOrder();
|
|
5157
|
+
wasRecoveryLocked.current = recoveryLocked;
|
|
5158
|
+
}, [heldForRecovery, recoveryLocked, recovery]);
|
|
5159
|
+
async function handleRefresh() {
|
|
5160
|
+
if (refreshing) return;
|
|
5161
|
+
setRefreshing(true);
|
|
5162
|
+
try {
|
|
5163
|
+
if (step === "status" && order) {
|
|
5164
|
+
setOrder(await client.getRampOrder(order.id));
|
|
5165
|
+
setPollKey((key) => key + 1);
|
|
5166
|
+
} else if (step === "select_route") await handleFindRoute();
|
|
5167
|
+
else {
|
|
5168
|
+
await loadRoutes(direction);
|
|
5169
|
+
await loadPendingOrders();
|
|
5170
|
+
if (direction === "OFFRAMP") await refreshWalletBalance();
|
|
5383
5171
|
}
|
|
5384
|
-
)
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
setPendingKyc(null);
|
|
5390
|
-
};
|
|
5391
|
-
const done = () => {
|
|
5392
|
-
if (kycAttempt.current !== pendingKyc) return;
|
|
5393
|
-
close();
|
|
5394
|
-
void requoteAfterKyc(pendingKyc.type);
|
|
5395
|
-
};
|
|
5396
|
-
const progress = pendingKyc.progress ? { progress: pendingKyc.progress } : {};
|
|
5397
|
-
return pendingKyc.type === "REGISTRY_CHECK" ? /* @__PURE__ */ jsx(RegistryCheckModal, { optionId: pendingKyc.optionId, ...progress, onClose: close, onApproved: done }) : /* @__PURE__ */ jsx(ProviderRegistrationModal, { corridorId: pendingKyc.corridorId, ...progress, onClose: close, onRegistered: done });
|
|
5172
|
+
} catch (error) {
|
|
5173
|
+
setErrorMsg(rampErrorMessage(error, "Could not refresh."));
|
|
5174
|
+
} finally {
|
|
5175
|
+
setRefreshing(false);
|
|
5176
|
+
}
|
|
5398
5177
|
}
|
|
5399
|
-
|
|
5178
|
+
const flowSteps = fields.length || quotes.some((q) => rampQuoteFields(q).length) ? ["Amount", "Route", "Details", "Complete"] : ["Amount", "Route", "Complete"];
|
|
5179
|
+
const stepLabel = {
|
|
5180
|
+
input: "Amount",
|
|
5181
|
+
loading_quote: "Amount",
|
|
5182
|
+
select_route: "Route",
|
|
5183
|
+
contact: "Details",
|
|
5184
|
+
status: "Complete"
|
|
5185
|
+
};
|
|
5186
|
+
const label = stepLabel[step];
|
|
5187
|
+
if (verifying) {
|
|
5188
|
+
const progress = { progress: { position: verifying.completed + 1, total: verifying.total } };
|
|
5189
|
+
const done = () => verificationDone(verifying);
|
|
5190
|
+
if (verifying.type === "FORM")
|
|
5191
|
+
return /* @__PURE__ */ jsx(RequirementFormModal, { formId: verifying.optionId, ...progress, onClose: closeVerification, onSubmitted: done });
|
|
5192
|
+
if (verifying.type === "REGISTRY_CHECK")
|
|
5193
|
+
return /* @__PURE__ */ jsx(RegistryCheckModal, { optionId: verifying.optionId, ...progress, onClose: closeVerification, onApproved: done });
|
|
5194
|
+
if (verifying.type === "PROVIDER_REGISTRATION")
|
|
5195
|
+
return /* @__PURE__ */ jsx(
|
|
5196
|
+
ProviderRegistrationModal,
|
|
5197
|
+
{
|
|
5198
|
+
corridorId: verifying.corridorId,
|
|
5199
|
+
...progress,
|
|
5200
|
+
onClose: closeVerification,
|
|
5201
|
+
onRegistered: done
|
|
5202
|
+
}
|
|
5203
|
+
);
|
|
5400
5204
|
return /* @__PURE__ */ jsx(
|
|
5401
5205
|
KycModal,
|
|
5402
5206
|
{
|
|
5403
5207
|
country,
|
|
5404
|
-
corridorId:
|
|
5405
|
-
providerId:
|
|
5406
|
-
onClose:
|
|
5407
|
-
|
|
5408
|
-
setPendingKyc(null);
|
|
5409
|
-
},
|
|
5410
|
-
onApproved: () => {
|
|
5411
|
-
if (kycAttempt.current !== pendingKyc) return;
|
|
5412
|
-
kycAttempt.current = null;
|
|
5413
|
-
setPendingKyc(null);
|
|
5414
|
-
void requoteAfterKyc();
|
|
5415
|
-
}
|
|
5208
|
+
corridorId: verifying.corridorId,
|
|
5209
|
+
providerId: verifying.optionId,
|
|
5210
|
+
onClose: closeVerification,
|
|
5211
|
+
onApproved: done
|
|
5416
5212
|
}
|
|
5417
5213
|
);
|
|
5418
5214
|
}
|
|
5419
5215
|
return /* @__PURE__ */ jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsx(
|
|
5420
5216
|
RampWidgetTemplate,
|
|
5421
5217
|
{
|
|
5422
|
-
workflowContent: workflow ? /* @__PURE__ */ jsx(
|
|
5423
|
-
RampWorkflow,
|
|
5424
|
-
{
|
|
5425
|
-
client,
|
|
5426
|
-
snapshot: workflow,
|
|
5427
|
-
onBusyChange: (busy) => {
|
|
5428
|
-
completionLocked.current = busy;
|
|
5429
|
-
setCompleting(busy);
|
|
5430
|
-
},
|
|
5431
|
-
onChange: (next) => {
|
|
5432
|
-
if (acceptWorkflow(next)) setTxStatus(next.status);
|
|
5433
|
-
}
|
|
5434
|
-
}
|
|
5435
|
-
) : legacySignature && step === "status" && txStatus !== "completed" && txStatus !== "failed" ? /* @__PURE__ */ jsx("button", { type: "button", disabled: completing, onClick: () => void handleLegacySignature(), children: "Authorize wallet request" }) : void 0,
|
|
5436
5218
|
theme,
|
|
5437
5219
|
accentColor,
|
|
5438
|
-
styleOverrides,
|
|
5220
|
+
...styleOverrides ? { styleOverrides } : {},
|
|
5221
|
+
network,
|
|
5439
5222
|
step,
|
|
5440
5223
|
flowSteps,
|
|
5441
|
-
flowStepIndex,
|
|
5442
|
-
startingQuoteId: isLoading && selectedQuote ? selectedQuote.quoteId : null,
|
|
5224
|
+
flowStepIndex: label ? flowSteps.indexOf(label) : -1,
|
|
5443
5225
|
direction,
|
|
5444
|
-
|
|
5445
|
-
currency,
|
|
5446
|
-
country,
|
|
5447
|
-
requiredFields: selectedQuote ? requiredFieldsOf(selectedQuote) : [],
|
|
5448
|
-
fieldValues,
|
|
5226
|
+
routesLoading,
|
|
5449
5227
|
countries,
|
|
5450
|
-
|
|
5451
|
-
|
|
5228
|
+
country,
|
|
5229
|
+
fiats,
|
|
5230
|
+
fiat,
|
|
5231
|
+
assets,
|
|
5232
|
+
asset,
|
|
5233
|
+
amount,
|
|
5234
|
+
sellAvailable,
|
|
5452
5235
|
quotes,
|
|
5453
|
-
|
|
5236
|
+
rejected,
|
|
5237
|
+
startingQuoteId,
|
|
5238
|
+
fields,
|
|
5239
|
+
fieldValues,
|
|
5240
|
+
order,
|
|
5241
|
+
pendingOrders,
|
|
5454
5242
|
isLoading,
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
kycUrl,
|
|
5458
|
-
tosUrl,
|
|
5459
|
-
kycBlocking,
|
|
5460
|
-
onboardingStatus: onboardingStatus ?? null,
|
|
5461
|
-
kycJustApproved: kycPending && kycApproved,
|
|
5462
|
-
stellarTxHash,
|
|
5463
|
-
txHash,
|
|
5464
|
-
txChain,
|
|
5465
|
-
explorerUrl: explorerTxUrl2(txChain ?? "STELLAR", txHash ?? stellarTxHash, network),
|
|
5466
|
-
fundsInTransit,
|
|
5467
|
-
retrying,
|
|
5468
|
-
onRetryTransit: handleRetryTransit,
|
|
5469
|
-
depositInstructions,
|
|
5470
|
-
canComplete,
|
|
5471
|
-
completing,
|
|
5472
|
-
savedRamps,
|
|
5473
|
-
onResumeRamp: resumeSavedRamp,
|
|
5474
|
-
onDismissRamp: dismissSavedRamp,
|
|
5475
|
-
onDismissCurrentRamp: workflow ? () => dismissSavedRamp(workflow.txId) : void 0,
|
|
5476
|
-
onExploreRoutes: workflow ? () => {
|
|
5477
|
-
if (!completionLocked.current) resetToInput();
|
|
5478
|
-
} : void 0,
|
|
5243
|
+
refreshing,
|
|
5244
|
+
signing,
|
|
5479
5245
|
errorMsg,
|
|
5480
|
-
|
|
5481
|
-
onDirectionChange:
|
|
5482
|
-
|
|
5246
|
+
notice: awaitingAccount ? "Approve the new account on your device. The order starts once it is approved." : null,
|
|
5247
|
+
onDirectionChange: handleDirectionChange,
|
|
5248
|
+
onCountryChange: (next) => {
|
|
5249
|
+
setCountry(next);
|
|
5250
|
+
setFiatChoice("");
|
|
5251
|
+
setAssetChoice("");
|
|
5252
|
+
},
|
|
5253
|
+
onFiatChange: (key) => {
|
|
5254
|
+
setFiatChoice(key);
|
|
5255
|
+
setAssetChoice("");
|
|
5483
5256
|
},
|
|
5484
|
-
|
|
5485
|
-
|
|
5257
|
+
onAssetChange: setAssetChoice,
|
|
5258
|
+
onAmountChange: (value) => {
|
|
5259
|
+
setAmount(value);
|
|
5486
5260
|
setErrorMsg(null);
|
|
5487
5261
|
},
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
onFindRoute: handleFindRoute,
|
|
5491
|
-
onSelectQuote: handleSelectQuote,
|
|
5262
|
+
onFindRoute: () => void handleFindRoute(),
|
|
5263
|
+
onSelectQuote: (quote) => handleSelectQuote(quote),
|
|
5492
5264
|
onVerifyRoute: handleVerifyRoute,
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5265
|
+
trustingAsset,
|
|
5266
|
+
onTrustAsset: (asset2) => void handleTrustAsset(asset2),
|
|
5267
|
+
walletBusy,
|
|
5268
|
+
custodyChoice,
|
|
5269
|
+
onWalletStep: (walletStep, index, custody) => void handleWalletStep(walletStep, index, custody),
|
|
5270
|
+
noChains: Array.isArray(appChains) && appChains.length === 0,
|
|
5271
|
+
onFieldChange: (key, value) => setFieldValues((current) => ({ ...current, [key]: value })),
|
|
5272
|
+
onContactContinue: () => {
|
|
5273
|
+
if (selected) void startOrder(selected);
|
|
5274
|
+
},
|
|
5275
|
+
onSign: () => void handleSign(),
|
|
5276
|
+
onApprove: openCosignModal,
|
|
5277
|
+
retrying,
|
|
5278
|
+
onRetryOrder: () => void handleRetryOrder(),
|
|
5279
|
+
onSetUpRecovery: openRecoveryModal,
|
|
5280
|
+
recoveryMissing: recovery === null ? null : recoveryLocked,
|
|
5281
|
+
pollTrouble,
|
|
5282
|
+
checkingPayment: paymentCheckUntil !== null,
|
|
5283
|
+
onCheckPayment: () => void handleCheckPayment(),
|
|
5284
|
+
onResumeOrder: (id) => void handleResumeOrder(id),
|
|
5285
|
+
onNewOrder: handleNewOrder,
|
|
5286
|
+
onBack: handleBack,
|
|
5287
|
+
onStepSelect: handleStepSelect,
|
|
5288
|
+
onRetry: () => {
|
|
5289
|
+
setErrorMsg(null);
|
|
5290
|
+
setStep("input");
|
|
5291
|
+
},
|
|
5292
|
+
onRefresh: () => void handleRefresh(),
|
|
5500
5293
|
onClose
|
|
5501
5294
|
}
|
|
5502
5295
|
) });
|
|
@@ -5513,6 +5306,49 @@ function walletNotReadyReason(wallet, chain) {
|
|
|
5513
5306
|
}
|
|
5514
5307
|
return null;
|
|
5515
5308
|
}
|
|
5309
|
+
|
|
5310
|
+
// src/lib/qr-code/index.tsx
|
|
5311
|
+
var import_ErrorCorrectLevel = __toESM(require_ErrorCorrectLevel());
|
|
5312
|
+
var import_QRCode = __toESM(require_QRCode());
|
|
5313
|
+
var QRCodeSvg = forwardRef(function QRCodeSvg2({ bgColor, bgD, fgD, fgColor, size, title, viewBoxSize, xmlns = "http://www.w3.org/2000/svg", ...props }, ref) {
|
|
5314
|
+
return /* @__PURE__ */ jsxs("svg", { ...props, height: size, ref, viewBox: `0 0 ${viewBoxSize} ${viewBoxSize}`, width: size, xmlns, children: [
|
|
5315
|
+
title ? /* @__PURE__ */ jsx("title", { children: title }) : null,
|
|
5316
|
+
/* @__PURE__ */ jsx("path", { d: bgD, fill: bgColor }),
|
|
5317
|
+
/* @__PURE__ */ jsx("path", { d: fgD, fill: fgColor })
|
|
5318
|
+
] });
|
|
5319
|
+
});
|
|
5320
|
+
QRCodeSvg.displayName = "QRCodeSvg";
|
|
5321
|
+
function bytesToBinaryString(bytes) {
|
|
5322
|
+
return bytes.map((b) => String.fromCharCode(b & 255)).join("");
|
|
5323
|
+
}
|
|
5324
|
+
function encodeStringToUtf8Bytes(input) {
|
|
5325
|
+
return Array.from(new TextEncoder().encode(input));
|
|
5326
|
+
}
|
|
5327
|
+
var QRCode = forwardRef(function QRCode2({ bgColor = "#FFFFFF", fgColor = "#000000", level = "L", size = 256, value, ...props }, ref) {
|
|
5328
|
+
const qrcode = new import_QRCode.default(-1, import_ErrorCorrectLevel.default[level]);
|
|
5329
|
+
const utf8Bytes = encodeStringToUtf8Bytes(value);
|
|
5330
|
+
const binaryString = bytesToBinaryString(utf8Bytes);
|
|
5331
|
+
qrcode.addData(binaryString, "Byte");
|
|
5332
|
+
qrcode.make();
|
|
5333
|
+
const cells = qrcode.modules;
|
|
5334
|
+
return /* @__PURE__ */ jsx(
|
|
5335
|
+
QRCodeSvg,
|
|
5336
|
+
{
|
|
5337
|
+
...props,
|
|
5338
|
+
bgColor,
|
|
5339
|
+
bgD: cells.map(
|
|
5340
|
+
(row, rowIndex) => row.map((cell, cellIndex) => !cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")
|
|
5341
|
+
).join(" "),
|
|
5342
|
+
fgColor,
|
|
5343
|
+
fgD: cells.map(
|
|
5344
|
+
(row, rowIndex) => row.map((cell, cellIndex) => cell ? `M ${cellIndex} ${rowIndex} l 1 0 0 1 -1 0 Z` : "").join(" ")
|
|
5345
|
+
).join(" "),
|
|
5346
|
+
ref,
|
|
5347
|
+
size,
|
|
5348
|
+
viewBoxSize: cells.length
|
|
5349
|
+
}
|
|
5350
|
+
);
|
|
5351
|
+
});
|
|
5516
5352
|
function PollarLogo(props) {
|
|
5517
5353
|
return /* @__PURE__ */ jsxs("svg", { width: "45", height: "48", viewBox: "0 0 45 48", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: [
|
|
5518
5354
|
/* @__PURE__ */ jsx(
|
|
@@ -5912,7 +5748,7 @@ function formatBalance(balance) {
|
|
|
5912
5748
|
const n = parseFloat(balance);
|
|
5913
5749
|
return isNaN(n) ? balance : n.toLocaleString(void 0, { maximumFractionDigits: 7 });
|
|
5914
5750
|
}
|
|
5915
|
-
function
|
|
5751
|
+
function assetKey4(record) {
|
|
5916
5752
|
return `${record.code}:${record.issuer ?? "native"}`;
|
|
5917
5753
|
}
|
|
5918
5754
|
function chainLabel(chain) {
|
|
@@ -5983,8 +5819,8 @@ function SendAssetSelector({ assets, selectedAsset, loading, onSelectAsset }) {
|
|
|
5983
5819
|
}
|
|
5984
5820
|
),
|
|
5985
5821
|
open && assets.length > 0 && /* @__PURE__ */ jsx("div", { className: "pollar-send-asset-menu", role: "listbox", "aria-label": "Assets", children: assets.map((asset) => {
|
|
5986
|
-
const key =
|
|
5987
|
-
const selected = selectedAsset ? key ===
|
|
5822
|
+
const key = assetKey4(asset);
|
|
5823
|
+
const selected = selectedAsset ? key === assetKey4(selectedAsset) : false;
|
|
5988
5824
|
return /* @__PURE__ */ jsxs(
|
|
5989
5825
|
"button",
|
|
5990
5826
|
{
|
|
@@ -6028,6 +5864,9 @@ function SendModalTemplate({
|
|
|
6028
5864
|
destination,
|
|
6029
5865
|
formError,
|
|
6030
5866
|
isLoadingBalance,
|
|
5867
|
+
isCheckingDestination = false,
|
|
5868
|
+
minStartingBalance = 1,
|
|
5869
|
+
onCreateAccount,
|
|
6031
5870
|
transaction,
|
|
6032
5871
|
showXdr,
|
|
6033
5872
|
copied,
|
|
@@ -6057,8 +5896,10 @@ function SendModalTemplate({
|
|
|
6057
5896
|
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
|
|
6058
5897
|
const parsedAmount = amount ? Number(amount) : 0;
|
|
6059
5898
|
const availableAmount = selectedAsset?.available === null || selectedAsset?.available === void 0 ? 0 : Number(selectedAsset.available);
|
|
6060
|
-
const canSubmit = canSendOnChain && !notReadyReason && !!selectedAsset && Number.isFinite(parsedAmount) && parsedAmount > 0 && parsedAmount <= availableAmount && !!destination.trim() && !isLoadingBalance;
|
|
6061
|
-
const title = step === "form" ? "Send" : txTitle;
|
|
5899
|
+
const canSubmit = canSendOnChain && !notReadyReason && !!selectedAsset && Number.isFinite(parsedAmount) && parsedAmount > 0 && parsedAmount <= availableAmount && !!destination.trim() && !isLoadingBalance && !isCheckingDestination;
|
|
5900
|
+
const title = step === "form" ? "Send" : step === "create-account" ? "Create account?" : txTitle;
|
|
5901
|
+
const createsWithNative = selectedAsset?.type === "native";
|
|
5902
|
+
const meetsMinimum = Number.isFinite(parsedAmount) && parsedAmount >= minStartingBalance;
|
|
6062
5903
|
return /* @__PURE__ */ jsxs(
|
|
6063
5904
|
"div",
|
|
6064
5905
|
{
|
|
@@ -6108,44 +5949,18 @@ function SendModalTemplate({
|
|
|
6108
5949
|
onSelectAsset
|
|
6109
5950
|
}
|
|
6110
5951
|
),
|
|
6111
|
-
/* @__PURE__ */
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
"input",
|
|
6124
|
-
{
|
|
6125
|
-
className: "pollar-input pollar-send-amount-input",
|
|
6126
|
-
type: "text",
|
|
6127
|
-
inputMode: "decimal",
|
|
6128
|
-
placeholder: "0.00",
|
|
6129
|
-
value: amount,
|
|
6130
|
-
onChange: (e) => onAmountChange(e.target.value),
|
|
6131
|
-
"aria-label": "Amount"
|
|
6132
|
-
}
|
|
6133
|
-
),
|
|
6134
|
-
/* @__PURE__ */ jsxs("div", { className: "pollar-send-input-suffix", children: [
|
|
6135
|
-
/* @__PURE__ */ jsx(
|
|
6136
|
-
"button",
|
|
6137
|
-
{
|
|
6138
|
-
type: "button",
|
|
6139
|
-
className: "pollar-send-inline-action",
|
|
6140
|
-
onClick: onMax,
|
|
6141
|
-
disabled: !selectedAsset?.available,
|
|
6142
|
-
children: "Max"
|
|
6143
|
-
}
|
|
6144
|
-
),
|
|
6145
|
-
/* @__PURE__ */ jsx("span", { children: selectedAsset?.code ?? "" })
|
|
6146
|
-
] })
|
|
6147
|
-
] })
|
|
6148
|
-
] }),
|
|
5952
|
+
/* @__PURE__ */ jsx(
|
|
5953
|
+
AmountField,
|
|
5954
|
+
{
|
|
5955
|
+
id: "pollar-send-amount",
|
|
5956
|
+
label: "Amount",
|
|
5957
|
+
value: amount,
|
|
5958
|
+
onChange: onAmountChange,
|
|
5959
|
+
unit: selectedAsset?.code,
|
|
5960
|
+
available: selectedAsset ? selectedAsset.available : void 0,
|
|
5961
|
+
onMax
|
|
5962
|
+
}
|
|
5963
|
+
),
|
|
6149
5964
|
/* @__PURE__ */ jsxs("div", { className: "pollar-send-field", children: [
|
|
6150
5965
|
/* @__PURE__ */ jsx("label", { className: "pollar-send-label", children: "Destination wallet" }),
|
|
6151
5966
|
/* @__PURE__ */ jsxs("div", { className: "pollar-send-input-shell", children: [
|
|
@@ -6197,7 +6012,41 @@ function SendModalTemplate({
|
|
|
6197
6012
|
] })
|
|
6198
6013
|
] }),
|
|
6199
6014
|
formError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: formError }),
|
|
6200
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsx("button", { className: "pollar-btn-primary", onClick: onSubmit, disabled: !canSubmit, children: "Continue" }) })
|
|
6015
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsx("button", { className: "pollar-btn-primary", onClick: onSubmit, disabled: !canSubmit, children: isCheckingDestination ? "Checking destination\u2026" : "Continue" }) })
|
|
6016
|
+
] }),
|
|
6017
|
+
step === "create-account" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6018
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-notice", children: [
|
|
6019
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-send-notice-title", children: "This account doesn't exist yet" }),
|
|
6020
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-send-notice-address", children: destination.trim() }),
|
|
6021
|
+
createsWithNative ? /* @__PURE__ */ jsxs("p", { children: [
|
|
6022
|
+
"A Stellar account has to be created and funded before it can receive payments. Instead of a payment, this will",
|
|
6023
|
+
" ",
|
|
6024
|
+
/* @__PURE__ */ jsx("strong", { children: "create the account" }),
|
|
6025
|
+
" with ",
|
|
6026
|
+
amount,
|
|
6027
|
+
" XLM as its starting balance."
|
|
6028
|
+
] }) : /* @__PURE__ */ jsxs("p", { children: [
|
|
6029
|
+
"It can't receive ",
|
|
6030
|
+
selectedAsset?.code ?? "this asset",
|
|
6031
|
+
" yet: it has to be created and funded with XLM first, and then add a trustline for ",
|
|
6032
|
+
selectedAsset?.code ?? "the asset",
|
|
6033
|
+
"."
|
|
6034
|
+
] }),
|
|
6035
|
+
createsWithNative && !meetsMinimum && /* @__PURE__ */ jsxs("p", { className: "pollar-send-notice-warning", children: [
|
|
6036
|
+
"A new account needs a starting balance of at least ",
|
|
6037
|
+
minStartingBalance,
|
|
6038
|
+
" XLM. Go back and raise the amount to create it."
|
|
6039
|
+
] }),
|
|
6040
|
+
/* @__PURE__ */ jsx("p", { children: "Or wait until another wallet funds it, and send afterwards." })
|
|
6041
|
+
] }),
|
|
6042
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-send-account-actions", children: [
|
|
6043
|
+
createsWithNative && onCreateAccount && /* @__PURE__ */ jsxs("button", { className: "pollar-btn-primary", onClick: onCreateAccount, disabled: !meetsMinimum, children: [
|
|
6044
|
+
"Create account with ",
|
|
6045
|
+
amount,
|
|
6046
|
+
" XLM"
|
|
6047
|
+
] }),
|
|
6048
|
+
/* @__PURE__ */ jsx("button", { className: "pollar-btn-secondary", onClick: onBack, children: "I'll wait until it's funded" })
|
|
6049
|
+
] })
|
|
6201
6050
|
] }),
|
|
6202
6051
|
step === "tx" && /* @__PURE__ */ jsx(
|
|
6203
6052
|
TxStatusView,
|
|
@@ -6234,6 +6083,7 @@ function parseMemo(type, raw) {
|
|
|
6234
6083
|
if (!/^\d+$/.test(value) || BigInt(value) > MAX_MEMO_ID) return "The memo ID must be a whole number up to 2^64 - 1.";
|
|
6235
6084
|
return { type, value };
|
|
6236
6085
|
}
|
|
6086
|
+
var MIN_STARTING_BALANCE_XLM = 1;
|
|
6237
6087
|
function assetParam(record) {
|
|
6238
6088
|
if (record.type === "native") return { type: "native" };
|
|
6239
6089
|
if (record.type === "credit_alphanum4") {
|
|
@@ -6251,11 +6101,14 @@ function SendModal({ onClose }) {
|
|
|
6251
6101
|
tx: transaction,
|
|
6252
6102
|
wallet,
|
|
6253
6103
|
network,
|
|
6254
|
-
styles
|
|
6104
|
+
styles,
|
|
6105
|
+
getClient
|
|
6255
6106
|
} = usePollar();
|
|
6256
6107
|
const walletType = wallet?.custody === "external" ? wallet.provider : null;
|
|
6257
6108
|
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
6258
6109
|
const [step, setStep] = useState("form");
|
|
6110
|
+
const [createsAccount, setCreatesAccount] = useState(false);
|
|
6111
|
+
const [checkingDestination, setCheckingDestination] = useState(false);
|
|
6259
6112
|
const [amount, setAmount] = useState("");
|
|
6260
6113
|
const [destination, setDestination] = useState("");
|
|
6261
6114
|
const [memo, setMemo] = useState("");
|
|
@@ -6311,8 +6164,15 @@ function SendModal({ onClose }) {
|
|
|
6311
6164
|
"building-signing-submitting"
|
|
6312
6165
|
];
|
|
6313
6166
|
const isInProgress = IN_FLIGHT_STEPS3.includes(transaction.step);
|
|
6314
|
-
const showBack = step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
|
|
6315
|
-
const txTitle = isInProgress ? "Sending\u2026" : transaction.step === "success" ? "Sent!" : transaction.step === "error" ? "Send failed" : "Confirm Send";
|
|
6167
|
+
const showBack = step === "create-account" || step === "tx" && (transaction.step === "error" || transaction.step === "success") && !isInProgress;
|
|
6168
|
+
const txTitle = createsAccount ? isInProgress ? "Creating account\u2026" : transaction.step === "success" ? "Account created!" : transaction.step === "error" ? "Create account failed" : "Confirm Create Account" : isInProgress ? "Sending\u2026" : transaction.step === "success" ? "Sent!" : transaction.step === "error" ? "Send failed" : "Confirm Send";
|
|
6169
|
+
async function stellarAccountExists(address) {
|
|
6170
|
+
try {
|
|
6171
|
+
return (await getClient().getWalletBalance(address)).exists;
|
|
6172
|
+
} catch {
|
|
6173
|
+
return null;
|
|
6174
|
+
}
|
|
6175
|
+
}
|
|
6316
6176
|
async function handleSubmit() {
|
|
6317
6177
|
setFormError("");
|
|
6318
6178
|
if (!canSendOnChain) {
|
|
@@ -6359,6 +6219,16 @@ function SendModal({ onClose }) {
|
|
|
6359
6219
|
return;
|
|
6360
6220
|
}
|
|
6361
6221
|
}
|
|
6222
|
+
if (selectedChain === "STELLAR") {
|
|
6223
|
+
setCheckingDestination(true);
|
|
6224
|
+
const exists = await stellarAccountExists(destination.trim());
|
|
6225
|
+
setCheckingDestination(false);
|
|
6226
|
+
if (exists === false) {
|
|
6227
|
+
setStep("create-account");
|
|
6228
|
+
return;
|
|
6229
|
+
}
|
|
6230
|
+
}
|
|
6231
|
+
setCreatesAccount(false);
|
|
6362
6232
|
setStep("tx");
|
|
6363
6233
|
if (selectedChain === "SOLANA" || selectedChain === "POLYGON") {
|
|
6364
6234
|
await sendPayment({
|
|
@@ -6377,6 +6247,17 @@ function SendModal({ onClose }) {
|
|
|
6377
6247
|
parsedMemo ? { memo: parsedMemo } : void 0
|
|
6378
6248
|
);
|
|
6379
6249
|
}
|
|
6250
|
+
async function handleCreateAccount() {
|
|
6251
|
+
const parsedMemo = parseMemo(memoType, memo);
|
|
6252
|
+
if (typeof parsedMemo === "string" || parseFloat(amount) < MIN_STARTING_BALANCE_XLM) return;
|
|
6253
|
+
setCreatesAccount(true);
|
|
6254
|
+
setStep("tx");
|
|
6255
|
+
await buildTx(
|
|
6256
|
+
"create_account",
|
|
6257
|
+
{ destination: destination.trim(), startingBalance: amount },
|
|
6258
|
+
parsedMemo ? { memo: parsedMemo } : void 0
|
|
6259
|
+
);
|
|
6260
|
+
}
|
|
6380
6261
|
function handleSignAndSend() {
|
|
6381
6262
|
if (transaction.step === "built") {
|
|
6382
6263
|
void signAndSubmitTx(transaction.buildData.unsignedXdr);
|
|
@@ -6431,6 +6312,7 @@ function SendModal({ onClose }) {
|
|
|
6431
6312
|
}
|
|
6432
6313
|
function handleBack() {
|
|
6433
6314
|
setStep("form");
|
|
6315
|
+
setCreatesAccount(false);
|
|
6434
6316
|
setShowXdr(false);
|
|
6435
6317
|
setCopied(false);
|
|
6436
6318
|
}
|
|
@@ -6453,6 +6335,9 @@ function SendModal({ onClose }) {
|
|
|
6453
6335
|
destination,
|
|
6454
6336
|
formError,
|
|
6455
6337
|
isLoadingBalance: walletBalance.step === "loading",
|
|
6338
|
+
isCheckingDestination: checkingDestination,
|
|
6339
|
+
minStartingBalance: MIN_STARTING_BALANCE_XLM,
|
|
6340
|
+
onCreateAccount: () => void handleCreateAccount(),
|
|
6456
6341
|
transaction,
|
|
6457
6342
|
showXdr,
|
|
6458
6343
|
copied,
|
|
@@ -6740,7 +6625,7 @@ function SwapModalTemplate({
|
|
|
6740
6625
|
] })
|
|
6741
6626
|
] }),
|
|
6742
6627
|
/* @__PURE__ */ jsxs("div", { className: "pollar-swap-panel-main", children: [
|
|
6743
|
-
/* @__PURE__ */ jsx("div", { className: `pollar-swap-output${quoteLoading ? " is-loading" : ""}`, "aria-live": "polite", children: quoteLoading ? /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }) : formatAmount2(quote
|
|
6628
|
+
/* @__PURE__ */ jsx("div", { className: `pollar-swap-output${quoteLoading ? " is-loading" : ""}`, "aria-live": "polite", children: quoteLoading ? /* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm" }) : quote ? `~${formatAmount2(quote.amountOut)}` : "\u2014" }),
|
|
6744
6629
|
/* @__PURE__ */ jsxs("div", { className: "pollar-swap-panel-selector", children: [
|
|
6745
6630
|
/* @__PURE__ */ jsx(
|
|
6746
6631
|
AssetPill,
|
|
@@ -7204,7 +7089,6 @@ function EarnModal({ onClose }) {
|
|
|
7204
7089
|
earnWithdraw,
|
|
7205
7090
|
tx: transaction,
|
|
7206
7091
|
wallet,
|
|
7207
|
-
walletBalance,
|
|
7208
7092
|
refreshWalletBalance,
|
|
7209
7093
|
enabledAssets,
|
|
7210
7094
|
refreshAssets,
|
|
@@ -7286,13 +7170,9 @@ function EarnModal({ onClose }) {
|
|
|
7286
7170
|
const withdrawUnit = position?.withdrawUnit ?? "asset";
|
|
7287
7171
|
const assetCode = selectedOpportunity?.asset.code ?? "";
|
|
7288
7172
|
const amountUnitLabel = tab === "deposit" ? assetCode : withdrawUnit === "shares" ? "shares" : assetCode;
|
|
7289
|
-
const walletAvailable = (
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
const issuer = selectedOpportunity.asset.issuer;
|
|
7293
|
-
const rec = balances.find((b) => issuer === null ? b.type === "native" : b.code === assetCode && b.issuer === issuer);
|
|
7294
|
-
return rec ? rec.available : null;
|
|
7295
|
-
})();
|
|
7173
|
+
const walletAvailable = useWalletAvailable(
|
|
7174
|
+
selectedOpportunity ? { chain: "STELLAR", code: assetCode, issuer: selectedOpportunity.asset.issuer } : null
|
|
7175
|
+
);
|
|
7296
7176
|
const depositAssetRecord = (() => {
|
|
7297
7177
|
if (!selectedOpportunity?.asset.issuer || enabledAssets.step !== "loaded") return void 0;
|
|
7298
7178
|
return enabledAssets.data.assets.find(
|
|
@@ -7526,37 +7406,17 @@ function EarnModal({ onClose }) {
|
|
|
7526
7406
|
] })
|
|
7527
7407
|
] })
|
|
7528
7408
|
] }),
|
|
7529
|
-
/* @__PURE__ */
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
formatAmount3(position.withdrawable),
|
|
7541
|
-
" ",
|
|
7542
|
-
amountUnitLabel
|
|
7543
|
-
] })
|
|
7544
|
-
] }),
|
|
7545
|
-
/* @__PURE__ */ jsxs("div", { className: "pollar-earn-amount", children: [
|
|
7546
|
-
/* @__PURE__ */ jsx(
|
|
7547
|
-
"input",
|
|
7548
|
-
{
|
|
7549
|
-
className: "pollar-input",
|
|
7550
|
-
type: "text",
|
|
7551
|
-
inputMode: "decimal",
|
|
7552
|
-
placeholder: "0.00",
|
|
7553
|
-
value: amount,
|
|
7554
|
-
onChange: (e) => setAmount(e.target.value)
|
|
7555
|
-
}
|
|
7556
|
-
),
|
|
7557
|
-
amountUnitLabel && /* @__PURE__ */ jsx("span", { className: "pollar-earn-amount-unit", children: amountUnitLabel })
|
|
7558
|
-
] })
|
|
7559
|
-
] }),
|
|
7409
|
+
/* @__PURE__ */ jsx(
|
|
7410
|
+
AmountField,
|
|
7411
|
+
{
|
|
7412
|
+
id: "pollar-earn-amount",
|
|
7413
|
+
label: tab === "deposit" ? "Amount" : "Withdraw amount",
|
|
7414
|
+
value: amount,
|
|
7415
|
+
onChange: setAmount,
|
|
7416
|
+
unit: amountUnitLabel,
|
|
7417
|
+
available: tab === "deposit" ? walletAvailable : position ? position.withdrawable : void 0
|
|
7418
|
+
}
|
|
7419
|
+
),
|
|
7560
7420
|
formError && /* @__PURE__ */ jsx("div", { className: "pollar-modal-error", children: formError }),
|
|
7561
7421
|
depositNeedsTrustline && selectedOpportunity && /* @__PURE__ */ jsxs("div", { className: "pollar-swap-trustline-notice", children: [
|
|
7562
7422
|
"To deposit ",
|
|
@@ -7588,7 +7448,7 @@ function EarnModal({ onClose }) {
|
|
|
7588
7448
|
}
|
|
7589
7449
|
|
|
7590
7450
|
// src/components/card-modal/card-kyc.ts
|
|
7591
|
-
var
|
|
7451
|
+
var nonEmpty = (value) => typeof value === "string" && !!value.trim();
|
|
7592
7452
|
function requiredCardStep(error) {
|
|
7593
7453
|
if (!error || typeof error !== "object") return null;
|
|
7594
7454
|
if (!("code" in error) || error.code !== "SDK_CARDS_REQUIREMENT_REQUIRED") return null;
|
|
@@ -7597,7 +7457,7 @@ function requiredCardStep(error) {
|
|
|
7597
7457
|
const cardProviderId = "cardProviderId" in body ? body.cardProviderId : void 0;
|
|
7598
7458
|
const requirementType = "requirementType" in body ? body.requirementType : void 0;
|
|
7599
7459
|
const optionId = "optionId" in body ? body.optionId : void 0;
|
|
7600
|
-
if (!
|
|
7460
|
+
if (!nonEmpty(cardProviderId) || !nonEmpty(optionId)) return null;
|
|
7601
7461
|
if (requirementType === "KYC" || requirementType === "FORM" || requirementType === "REGISTRY_CHECK" || requirementType === "PROVIDER_REGISTRATION") {
|
|
7602
7462
|
return { cardProviderId, type: requirementType, optionId };
|
|
7603
7463
|
}
|
|
@@ -7752,6 +7612,8 @@ function CardModal({ onClose }) {
|
|
|
7752
7612
|
const [error, setError] = useState("");
|
|
7753
7613
|
const revealTimer = useRef(null);
|
|
7754
7614
|
const provider = providers?.[0] ?? null;
|
|
7615
|
+
const fundingAsset = provider?.fundingAssets[0] ?? "USDC";
|
|
7616
|
+
const fundAvailable = useWalletAvailable(panel === "fund" ? { chain: "STELLAR", code: fundingAsset } : null);
|
|
7755
7617
|
const card = cards?.[0] ?? null;
|
|
7756
7618
|
const loadHolder = useCallback(async () => {
|
|
7757
7619
|
const h = await getClient().getCardHolder();
|
|
@@ -8277,19 +8139,18 @@ function CardModal({ onClose }) {
|
|
|
8277
8139
|
provider.fundingAssets.join(" or ") || "USDC",
|
|
8278
8140
|
" from your wallet to your card. It takes a few minutes to cross to the card network."
|
|
8279
8141
|
] }),
|
|
8280
|
-
/* @__PURE__ */
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
"
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
] }),
|
|
8142
|
+
/* @__PURE__ */ jsx(
|
|
8143
|
+
AmountField,
|
|
8144
|
+
{
|
|
8145
|
+
id: "pollar-card-fund-amount",
|
|
8146
|
+
label: "Amount",
|
|
8147
|
+
value: fundAmount,
|
|
8148
|
+
onChange: (value) => setFundAmount(value.replace(/[^0-9.]/g, "")),
|
|
8149
|
+
unit: fundingAsset,
|
|
8150
|
+
available: fundAvailable,
|
|
8151
|
+
placeholder: "10"
|
|
8152
|
+
}
|
|
8153
|
+
),
|
|
8293
8154
|
/* @__PURE__ */ jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsx(
|
|
8294
8155
|
"button",
|
|
8295
8156
|
{
|
|
@@ -8711,6 +8572,12 @@ function detailRows(request) {
|
|
|
8711
8572
|
function CloseIcon2() {
|
|
8712
8573
|
return /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "m3 3 8 8M11 3l-8 8", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round" }) });
|
|
8713
8574
|
}
|
|
8575
|
+
function VerifiedIcon() {
|
|
8576
|
+
return /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
|
|
8577
|
+
/* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
|
|
8578
|
+
/* @__PURE__ */ jsx("path", { d: "M3.5 7l2.5 2.5 4.5-5", stroke: "white", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
8579
|
+
] });
|
|
8580
|
+
}
|
|
8714
8581
|
function CosignModalTemplate({
|
|
8715
8582
|
theme,
|
|
8716
8583
|
accentColor,
|
|
@@ -8723,6 +8590,8 @@ function CosignModalTemplate({
|
|
|
8723
8590
|
approveBlocked = false,
|
|
8724
8591
|
lastResolved,
|
|
8725
8592
|
explorerUrl,
|
|
8593
|
+
closesIn = null,
|
|
8594
|
+
nextStep = null,
|
|
8726
8595
|
onSelect,
|
|
8727
8596
|
onApprove,
|
|
8728
8597
|
onReject,
|
|
@@ -8731,6 +8600,8 @@ function CosignModalTemplate({
|
|
|
8731
8600
|
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
|
|
8732
8601
|
const verified = verification?.ok === true;
|
|
8733
8602
|
const canVote = !!current && verified && !busy && !approveBlocked;
|
|
8603
|
+
const [verifiedOpenFor, setVerifiedOpenFor] = useState(null);
|
|
8604
|
+
const verifiedOpen = !!current && verifiedOpenFor === current.id;
|
|
8734
8605
|
return /* @__PURE__ */ jsxs(
|
|
8735
8606
|
"div",
|
|
8736
8607
|
{
|
|
@@ -8743,27 +8614,48 @@ function CosignModalTemplate({
|
|
|
8743
8614
|
/* @__PURE__ */ jsx("h2", { className: "pollar-modal-title", children: "Confirm with your device" }),
|
|
8744
8615
|
/* @__PURE__ */ jsx("div", { className: "pollar-modal-header-actions", children: /* @__PURE__ */ jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", title: "Close", children: /* @__PURE__ */ jsx(CloseIcon2, {}) }) })
|
|
8745
8616
|
] }),
|
|
8746
|
-
pending.length === 0 && /* @__PURE__ */
|
|
8747
|
-
lastResolved
|
|
8748
|
-
/* @__PURE__ */
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
|
|
8617
|
+
pending.length === 0 && /* @__PURE__ */ jsxs("div", { className: "pollar-cosign-empty", children: [
|
|
8618
|
+
lastResolved ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8619
|
+
lastResolved.status === "APPROVED" && /* @__PURE__ */ jsxs("svg", { className: "pollar-cosign-approved-icon", width: "44", height: "44", viewBox: "0 0 14 14", fill: "none", "aria-hidden": true, children: [
|
|
8620
|
+
/* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "7", fill: "currentColor" }),
|
|
8621
|
+
/* @__PURE__ */ jsx(
|
|
8622
|
+
"path",
|
|
8623
|
+
{
|
|
8624
|
+
d: "M3.5 7l2.5 2.5 4.5-5",
|
|
8625
|
+
stroke: "white",
|
|
8626
|
+
strokeWidth: "1.2",
|
|
8627
|
+
strokeLinecap: "round",
|
|
8628
|
+
strokeLinejoin: "round"
|
|
8629
|
+
}
|
|
8630
|
+
)
|
|
8631
|
+
] }),
|
|
8632
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-cosign-empty-title", children: lastResolved.status === "APPROVED" ? "Approved" : lastResolved.status === "REJECTED" ? "Rejected" : lastResolved.status.toLowerCase() }),
|
|
8633
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-cosign-muted", children: lastResolved.submit?.hash ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8634
|
+
"Sent. Transaction",
|
|
8635
|
+
" ",
|
|
8636
|
+
explorerUrl ? /* @__PURE__ */ jsx("a", { className: "pollar-cosign-tx-link", href: explorerUrl, target: "_blank", rel: "noopener noreferrer", children: cropAddress(lastResolved.submit.hash) }) : cropAddress(lastResolved.submit.hash),
|
|
8637
|
+
/* @__PURE__ */ jsx(
|
|
8638
|
+
CopyButton,
|
|
8639
|
+
{
|
|
8640
|
+
value: lastResolved.submit.hash,
|
|
8641
|
+
label: "Copy transaction hash",
|
|
8642
|
+
className: "pollar-copy-btn-sm pollar-cosign-copy"
|
|
8643
|
+
}
|
|
8644
|
+
)
|
|
8645
|
+
] }) : lastResolved.signedXdr ? "Signed. The app will send it." : "Nothing was signed." })
|
|
8646
|
+
] }) : /* @__PURE__ */ jsx("p", { className: "pollar-cosign-muted", children: "Nothing waits for your approval." }),
|
|
8647
|
+
nextStep && /* @__PURE__ */ jsxs("p", { className: "pollar-cosign-next", children: [
|
|
8648
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm", "aria-hidden": true }),
|
|
8649
|
+
" Next: ",
|
|
8650
|
+
nextStep,
|
|
8651
|
+
". It appears here in a few seconds."
|
|
8759
8652
|
] }),
|
|
8760
|
-
/* @__PURE__ */
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
"
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
] }) : /* @__PURE__ */ jsx("p", { className: "pollar-cosign-muted", children: "Nothing waits for your approval." }) }),
|
|
8653
|
+
closesIn !== null && /* @__PURE__ */ jsxs("p", { className: "pollar-cosign-muted pollar-cosign-closing", children: [
|
|
8654
|
+
"Closing in ",
|
|
8655
|
+
closesIn,
|
|
8656
|
+
"s"
|
|
8657
|
+
] })
|
|
8658
|
+
] }),
|
|
8767
8659
|
pending.length > 1 && /* @__PURE__ */ jsx("ul", { className: "pollar-cosign-list", children: pending.map((r) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
8768
8660
|
"button",
|
|
8769
8661
|
{
|
|
@@ -8777,7 +8669,26 @@ function CosignModalTemplate({
|
|
|
8777
8669
|
}
|
|
8778
8670
|
) }, r.id)) }),
|
|
8779
8671
|
current && /* @__PURE__ */ jsxs("div", { className: "pollar-cosign-detail", children: [
|
|
8780
|
-
/* @__PURE__ */
|
|
8672
|
+
/* @__PURE__ */ jsxs("div", { className: "pollar-cosign-detail-head", children: [
|
|
8673
|
+
/* @__PURE__ */ jsx("p", { className: "pollar-cosign-detail-title", children: labelOf(current) }),
|
|
8674
|
+
!verification && /* @__PURE__ */ jsxs("span", { className: "pollar-cosign-chip", children: [
|
|
8675
|
+
/* @__PURE__ */ jsx("span", { className: "pollar-spinner pollar-spinner-sm", "aria-hidden": true }),
|
|
8676
|
+
"Checking..."
|
|
8677
|
+
] }),
|
|
8678
|
+
verification?.ok && /* @__PURE__ */ jsxs(
|
|
8679
|
+
"button",
|
|
8680
|
+
{
|
|
8681
|
+
type: "button",
|
|
8682
|
+
className: "pollar-cosign-chip pollar-cosign-chip-ok",
|
|
8683
|
+
"aria-expanded": verifiedOpen,
|
|
8684
|
+
onClick: () => setVerifiedOpenFor(verifiedOpen ? null : current.id),
|
|
8685
|
+
children: [
|
|
8686
|
+
/* @__PURE__ */ jsx(VerifiedIcon, {}),
|
|
8687
|
+
"Verified"
|
|
8688
|
+
]
|
|
8689
|
+
}
|
|
8690
|
+
)
|
|
8691
|
+
] }),
|
|
8781
8692
|
current.summary && /* @__PURE__ */ jsx("p", { className: "pollar-cosign-muted", children: current.summary }),
|
|
8782
8693
|
/* @__PURE__ */ jsxs("dl", { className: "pollar-cosign-rows", children: [
|
|
8783
8694
|
detailRows(current).map(([k, v]) => /* @__PURE__ */ jsxs("div", { className: "pollar-cosign-row", children: [
|
|
@@ -8789,17 +8700,11 @@ function CosignModalTemplate({
|
|
|
8789
8700
|
/* @__PURE__ */ jsx("dd", { children: expiresIn(current) })
|
|
8790
8701
|
] })
|
|
8791
8702
|
] }),
|
|
8792
|
-
/* @__PURE__ */
|
|
8793
|
-
|
|
8794
|
-
|
|
8795
|
-
|
|
8796
|
-
|
|
8797
|
-
!verification && "Checking the transaction against Turnkey...",
|
|
8798
|
-
verification?.ok && "Verified: this is exactly what will be signed.",
|
|
8799
|
-
verification && !verification.ok && `Not verified: ${verification.reason}`
|
|
8800
|
-
]
|
|
8801
|
-
}
|
|
8802
|
-
),
|
|
8703
|
+
verification?.ok && verifiedOpen && /* @__PURE__ */ jsx("div", { className: "pollar-cosign-verify pollar-cosign-verify-ok", children: "Checked against Turnkey: this is exactly what will be signed." }),
|
|
8704
|
+
verification && !verification.ok && /* @__PURE__ */ jsxs("div", { className: "pollar-cosign-verify pollar-cosign-verify-bad", children: [
|
|
8705
|
+
"Not verified: ",
|
|
8706
|
+
verification.reason
|
|
8707
|
+
] }),
|
|
8803
8708
|
error && /* @__PURE__ */ jsx("div", { className: "pollar-cosign-error", children: error }),
|
|
8804
8709
|
/* @__PURE__ */ jsxs("div", { className: "pollar-cosign-actions", children: [
|
|
8805
8710
|
/* @__PURE__ */ jsx(
|
|
@@ -8829,10 +8734,13 @@ function CosignModalTemplate({
|
|
|
8829
8734
|
}
|
|
8830
8735
|
);
|
|
8831
8736
|
}
|
|
8832
|
-
|
|
8737
|
+
var CLOSE_AFTER_SECONDS = 3;
|
|
8738
|
+
var CLOSE_AFTER_SENT_SECONDS = 5;
|
|
8739
|
+
var NEXT_REQUEST_EVERY_MS = 2e3;
|
|
8740
|
+
function CosignModal({ nextStep = null, onClose }) {
|
|
8833
8741
|
const { getClient, styles, network } = usePollar();
|
|
8834
8742
|
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
8835
|
-
const { pending, lastResolved, approve, reject, verify, inspectQuorum } = useCosign();
|
|
8743
|
+
const { pending, lastResolved, loaded, refresh, approve, reject, verify, inspectQuorum } = useCosign();
|
|
8836
8744
|
const [selectedId, setSelectedId] = useState(null);
|
|
8837
8745
|
const [verification, setVerification] = useState(null);
|
|
8838
8746
|
const [busy, setBusy] = useState(null);
|
|
@@ -8875,6 +8783,33 @@ function CosignModal({ onClose }) {
|
|
|
8875
8783
|
if (authState.step === "idle") onCloseRef.current();
|
|
8876
8784
|
});
|
|
8877
8785
|
}, [getClient]);
|
|
8786
|
+
const silent = pending.length === 0 && (lastResolved ? lastResolved.status === "APPROVED" && !lastResolved.submit?.hash && !lastResolved.signedXdr : loaded);
|
|
8787
|
+
const sent = pending.length === 0 && lastResolved?.status === "APPROVED" && !!lastResolved.submit?.hash;
|
|
8788
|
+
const awaitingNext = sent && !!nextStep;
|
|
8789
|
+
const closeAfter = awaitingNext ? null : sent ? CLOSE_AFTER_SENT_SECONDS : silent ? CLOSE_AFTER_SECONDS : null;
|
|
8790
|
+
useEffect(() => {
|
|
8791
|
+
if (!awaitingNext) return;
|
|
8792
|
+
const timer = setInterval(() => void refresh().catch(() => void 0), NEXT_REQUEST_EVERY_MS);
|
|
8793
|
+
return () => clearInterval(timer);
|
|
8794
|
+
}, [awaitingNext, refresh]);
|
|
8795
|
+
const [closesIn, setClosesIn] = useState(null);
|
|
8796
|
+
useEffect(() => {
|
|
8797
|
+
if (closeAfter === null) {
|
|
8798
|
+
setClosesIn(null);
|
|
8799
|
+
return;
|
|
8800
|
+
}
|
|
8801
|
+
let left = closeAfter;
|
|
8802
|
+
setClosesIn(left);
|
|
8803
|
+
const timer = setInterval(() => {
|
|
8804
|
+
left -= 1;
|
|
8805
|
+
if (left > 0) setClosesIn(left);
|
|
8806
|
+
else {
|
|
8807
|
+
clearInterval(timer);
|
|
8808
|
+
onCloseRef.current();
|
|
8809
|
+
}
|
|
8810
|
+
}, 1e3);
|
|
8811
|
+
return () => clearInterval(timer);
|
|
8812
|
+
}, [closeAfter, lastResolved?.id]);
|
|
8878
8813
|
const run = useCallback(
|
|
8879
8814
|
async (kind, request, action) => {
|
|
8880
8815
|
setBusy(kind);
|
|
@@ -8903,6 +8838,8 @@ function CosignModal({ onClose }) {
|
|
|
8903
8838
|
error,
|
|
8904
8839
|
approveBlocked: !!current && approveFailedFor === current.id,
|
|
8905
8840
|
...lastResolved ? { lastResolved } : {},
|
|
8841
|
+
closesIn,
|
|
8842
|
+
nextStep: awaitingNext ? nextStep : null,
|
|
8906
8843
|
explorerUrl: lastResolved?.submit?.hash ? explorerTxUrl(lastResolved.network, lastResolved.submit.hash, network) : null,
|
|
8907
8844
|
onSelect: (r) => setSelectedId(r.id),
|
|
8908
8845
|
onApprove: (r) => void run("approving", r, approve),
|
|
@@ -9282,7 +9219,7 @@ function RecoveryModalTemplate(p) {
|
|
|
9282
9219
|
);
|
|
9283
9220
|
}
|
|
9284
9221
|
function errorText2(err) {
|
|
9285
|
-
return transactionErrorMessage(isPollarApiError(err) ? err.code : null, err instanceof Error ? err.message : null);
|
|
9222
|
+
return cosignRefusalMessage(err) ?? transactionErrorMessage(isPollarApiError(err) ? err.code : null, err instanceof Error ? err.message : null);
|
|
9286
9223
|
}
|
|
9287
9224
|
function RecoveryModal({ onClose }) {
|
|
9288
9225
|
const { getClient, styles, refreshRecovery, appConfig } = usePollar();
|
|
@@ -10296,6 +10233,7 @@ function PollarProvider({
|
|
|
10296
10233
|
const [receiveModalOpen, setReceiveModalOpen] = useState(false);
|
|
10297
10234
|
const [sessionsModalOpen, setSessionsModalOpen] = useState(false);
|
|
10298
10235
|
const [cosignModalOpen, setCosignModalOpen] = useState(false);
|
|
10236
|
+
const [cosignNextStep, setCosignNextStep] = useState(null);
|
|
10299
10237
|
const [recoveryModalOpen, setRecoveryModalOpen] = useState(false);
|
|
10300
10238
|
const cosignPendingCount = useRef(0);
|
|
10301
10239
|
useEffect(() => {
|
|
@@ -10446,6 +10384,7 @@ function PollarProvider({
|
|
|
10446
10384
|
// cosign
|
|
10447
10385
|
cosign,
|
|
10448
10386
|
openCosignModal: () => setCosignModalOpen(true),
|
|
10387
|
+
setCosignNextStep,
|
|
10449
10388
|
recovery,
|
|
10450
10389
|
recoveryLocked,
|
|
10451
10390
|
refreshRecovery,
|
|
@@ -10536,7 +10475,7 @@ function PollarProvider({
|
|
|
10536
10475
|
/* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setCardModalOpen(false), children: /* @__PURE__ */ jsx(CardModal, { onClose: () => setCardModalOpen(false) }) }, `${cardModalKey}:${walletAddress}`),
|
|
10537
10476
|
receiveModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setReceiveModalOpen(false), children: /* @__PURE__ */ jsx(ReceiveModal, { onClose: () => setReceiveModalOpen(false) }) }),
|
|
10538
10477
|
sessionsModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setSessionsModalOpen(false), children: /* @__PURE__ */ jsx(SessionsModal, { onClose: () => setSessionsModalOpen(false) }) }),
|
|
10539
|
-
cosignModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setCosignModalOpen(false), children: /* @__PURE__ */ jsx(CosignModal, { onClose: () => setCosignModalOpen(false) }) }),
|
|
10478
|
+
cosignModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setCosignModalOpen(false), children: /* @__PURE__ */ jsx(CosignModal, { nextStep: cosignNextStep, onClose: () => setCosignModalOpen(false) }) }),
|
|
10540
10479
|
custodyMigration?.required && !custodyMigrationLater && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: refreshCustodyMigration, children: /* @__PURE__ */ jsx(
|
|
10541
10480
|
CustodyMigrationModal,
|
|
10542
10481
|
{
|
|
@@ -10553,7 +10492,15 @@ function PollarProvider({
|
|
|
10553
10492
|
}
|
|
10554
10493
|
}
|
|
10555
10494
|
) }),
|
|
10556
|
-
recoveryModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setRecoveryModalOpen(false), children: /* @__PURE__ */ jsx(
|
|
10495
|
+
recoveryModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setRecoveryModalOpen(false), children: /* @__PURE__ */ jsx(
|
|
10496
|
+
RecoveryModal,
|
|
10497
|
+
{
|
|
10498
|
+
onClose: () => {
|
|
10499
|
+
setRecoveryModalOpen(false);
|
|
10500
|
+
refreshRecovery();
|
|
10501
|
+
}
|
|
10502
|
+
}
|
|
10503
|
+
) }),
|
|
10557
10504
|
firstConfirmation && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: firstConfirmation.reject, children: /* @__PURE__ */ jsx(ConfirmModal, { confirmation: firstConfirmation }, firstConfirmation.id) }),
|
|
10558
10505
|
distributionRulesModalOpen && /* @__PURE__ */ jsx(ModalErrorBoundary, { onClose: () => setDistributionRulesModalOpen(false), children: /* @__PURE__ */ jsx(DistributionRulesModal, { onClose: () => setDistributionRulesModalOpen(false) }) })
|
|
10559
10506
|
] });
|
|
@@ -10585,8 +10532,9 @@ function createPollarAdapterHook(key) {
|
|
|
10585
10532
|
);
|
|
10586
10533
|
};
|
|
10587
10534
|
}
|
|
10588
|
-
function ButtonLogo() {
|
|
10589
|
-
|
|
10535
|
+
function ButtonLogo({ accentColor }) {
|
|
10536
|
+
const src = readableTextOn(accentColor) === "#ffffff" ? LOGO_POLLAR_MARK_ON_DARK : LOGO_POLLAR_MARK_ON_LIGHT;
|
|
10537
|
+
return /* @__PURE__ */ jsx("img", { src, alt: "Pollar", width: 22, height: 22, className: "pollar-wallet-btn-logo" });
|
|
10590
10538
|
}
|
|
10591
10539
|
function cropWallet(address) {
|
|
10592
10540
|
if (address.length <= 12) return address;
|
|
@@ -10594,12 +10542,11 @@ function cropWallet(address) {
|
|
|
10594
10542
|
}
|
|
10595
10543
|
function WalletButtonTemplate({
|
|
10596
10544
|
walletAddress,
|
|
10545
|
+
theme,
|
|
10597
10546
|
accentColor,
|
|
10547
|
+
styleOverrides,
|
|
10598
10548
|
open,
|
|
10599
10549
|
copied,
|
|
10600
|
-
dropdownBg,
|
|
10601
|
-
dropdownBorder,
|
|
10602
|
-
itemColor,
|
|
10603
10550
|
wrapperRef,
|
|
10604
10551
|
isInProgress,
|
|
10605
10552
|
showCreateAccount,
|
|
@@ -10628,9 +10575,10 @@ function WalletButtonTemplate({
|
|
|
10628
10575
|
}) {
|
|
10629
10576
|
const [selfCustodyNotice, setSelfCustodyNotice] = useState(false);
|
|
10630
10577
|
const [risksAccepted, setRisksAccepted] = useState(false);
|
|
10578
|
+
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
|
|
10631
10579
|
if (!walletAddress && signedIn) {
|
|
10632
|
-
return /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-wrapper", ref: wrapperRef, children: [
|
|
10633
|
-
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-btn",
|
|
10580
|
+
return /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-wrapper", ref: wrapperRef, style: cssVars, children: [
|
|
10581
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-btn", onClick: onToggleOpen, children: [
|
|
10634
10582
|
/* @__PURE__ */ jsx("span", { className: "pollar-wallet-btn-label", children: onCreateWallet ? "No wallet" : "Signed in" }),
|
|
10635
10583
|
/* @__PURE__ */ jsx(
|
|
10636
10584
|
"svg",
|
|
@@ -10646,22 +10594,13 @@ function WalletButtonTemplate({
|
|
|
10646
10594
|
}
|
|
10647
10595
|
)
|
|
10648
10596
|
] }),
|
|
10649
|
-
open && /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-dropdown",
|
|
10597
|
+
open && /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-dropdown", children: [
|
|
10650
10598
|
createWalletError && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10651
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice",
|
|
10599
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice", role: "status", children: createWalletError }),
|
|
10652
10600
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" })
|
|
10653
10601
|
] }),
|
|
10654
10602
|
onCreateWallet && !custodyChoice && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10655
|
-
/* @__PURE__ */ jsx(
|
|
10656
|
-
"button",
|
|
10657
|
-
{
|
|
10658
|
-
className: "pollar-wallet-dropdown-item",
|
|
10659
|
-
style: { color: itemColor },
|
|
10660
|
-
onClick: () => onCreateWallet(),
|
|
10661
|
-
disabled: creatingWallet,
|
|
10662
|
-
children: creatingWallet ? "Creating wallet\u2026" : "Create wallet"
|
|
10663
|
-
}
|
|
10664
|
-
),
|
|
10603
|
+
/* @__PURE__ */ jsx("button", { className: "pollar-wallet-dropdown-item", onClick: () => onCreateWallet(), disabled: creatingWallet, children: creatingWallet ? "Creating wallet\u2026" : "Create wallet" }),
|
|
10665
10604
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" })
|
|
10666
10605
|
] }),
|
|
10667
10606
|
onCreateWallet && custodyChoice && !selfCustodyNotice && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -10669,29 +10608,27 @@ function WalletButtonTemplate({
|
|
|
10669
10608
|
"button",
|
|
10670
10609
|
{
|
|
10671
10610
|
className: "pollar-wallet-dropdown-item",
|
|
10672
|
-
style: { color: itemColor },
|
|
10673
10611
|
onClick: () => onCreateWallet("COSIGNED"),
|
|
10674
10612
|
disabled: creatingWallet,
|
|
10675
10613
|
children: creatingWallet ? "Creating wallet\u2026" : "Create co-signed wallet"
|
|
10676
10614
|
}
|
|
10677
10615
|
),
|
|
10678
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice",
|
|
10616
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice", children: "You and the app approve every signature together. Your wallet can be recovered with help." }),
|
|
10679
10617
|
/* @__PURE__ */ jsx(
|
|
10680
10618
|
"button",
|
|
10681
10619
|
{
|
|
10682
10620
|
className: "pollar-wallet-dropdown-item",
|
|
10683
|
-
style: { color: itemColor },
|
|
10684
10621
|
onClick: () => setSelfCustodyNotice(true),
|
|
10685
10622
|
disabled: creatingWallet,
|
|
10686
10623
|
children: "Create self-custody wallet"
|
|
10687
10624
|
}
|
|
10688
10625
|
),
|
|
10689
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice",
|
|
10626
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice", children: "Only your device signs. Nobody else can move or recover your funds." }),
|
|
10690
10627
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" })
|
|
10691
10628
|
] }),
|
|
10692
10629
|
onCreateWallet && custodyChoice && selfCustodyNotice && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10693
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice",
|
|
10694
|
-
/* @__PURE__ */ jsxs("label", { className: "pollar-wallet-dropdown-notice",
|
|
10630
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice", role: "alert", children: "In a self-custody wallet only your device can sign. If you lose this device and every recovery method, nobody can recover the wallet or its funds, not the app and not Pollar. Nobody can undo or freeze a transaction you sign." }),
|
|
10631
|
+
/* @__PURE__ */ jsxs("label", { className: "pollar-wallet-dropdown-notice", children: [
|
|
10695
10632
|
/* @__PURE__ */ jsx(
|
|
10696
10633
|
"input",
|
|
10697
10634
|
{
|
|
@@ -10708,7 +10645,6 @@ function WalletButtonTemplate({
|
|
|
10708
10645
|
"button",
|
|
10709
10646
|
{
|
|
10710
10647
|
className: "pollar-wallet-dropdown-item",
|
|
10711
|
-
style: { color: itemColor },
|
|
10712
10648
|
onClick: () => onCreateWallet("SELF_CUSTODY"),
|
|
10713
10649
|
disabled: creatingWallet || !risksAccepted,
|
|
10714
10650
|
children: creatingWallet ? "Creating wallet\u2026" : "Create self-custody wallet"
|
|
@@ -10718,7 +10654,6 @@ function WalletButtonTemplate({
|
|
|
10718
10654
|
"button",
|
|
10719
10655
|
{
|
|
10720
10656
|
className: "pollar-wallet-dropdown-item",
|
|
10721
|
-
style: { color: itemColor },
|
|
10722
10657
|
onClick: () => {
|
|
10723
10658
|
setSelfCustodyNotice(false);
|
|
10724
10659
|
setRisksAccepted(false);
|
|
@@ -10729,24 +10664,23 @@ function WalletButtonTemplate({
|
|
|
10729
10664
|
),
|
|
10730
10665
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" })
|
|
10731
10666
|
] }),
|
|
10732
|
-
/* @__PURE__ */ jsx("button", { className: "pollar-wallet-dropdown-item",
|
|
10667
|
+
/* @__PURE__ */ jsx("button", { className: "pollar-wallet-dropdown-item", onClick: onSessions, children: "Active sessions" }),
|
|
10733
10668
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" }),
|
|
10734
10669
|
/* @__PURE__ */ jsx("button", { className: "pollar-wallet-dropdown-item pollar-danger", onClick: onLogout, children: "Log out" })
|
|
10735
10670
|
] })
|
|
10736
10671
|
] });
|
|
10737
10672
|
}
|
|
10738
10673
|
if (!walletAddress) {
|
|
10739
|
-
return /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-wallet-login-btn", style:
|
|
10740
|
-
/* @__PURE__ */ jsx(ButtonLogo, {}),
|
|
10674
|
+
return /* @__PURE__ */ jsxs("button", { type: "button", className: "pollar-wallet-login-btn", style: cssVars, onClick: onLogin, children: [
|
|
10675
|
+
/* @__PURE__ */ jsx(ButtonLogo, { accentColor }),
|
|
10741
10676
|
"Login with Pollar"
|
|
10742
10677
|
] });
|
|
10743
10678
|
}
|
|
10744
|
-
return /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-wrapper", ref: wrapperRef, children: [
|
|
10679
|
+
return /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-wrapper", ref: wrapperRef, style: cssVars, children: [
|
|
10745
10680
|
/* @__PURE__ */ jsxs(
|
|
10746
10681
|
"button",
|
|
10747
10682
|
{
|
|
10748
10683
|
className: "pollar-wallet-btn",
|
|
10749
|
-
style: { backgroundColor: accentColor },
|
|
10750
10684
|
onClick: isInProgress ? void 0 : onToggleOpen,
|
|
10751
10685
|
disabled: isInProgress,
|
|
10752
10686
|
"aria-busy": isInProgress,
|
|
@@ -10783,50 +10717,41 @@ function WalletButtonTemplate({
|
|
|
10783
10717
|
]
|
|
10784
10718
|
}
|
|
10785
10719
|
),
|
|
10786
|
-
open && /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-dropdown",
|
|
10720
|
+
open && /* @__PURE__ */ jsxs("div", { className: "pollar-wallet-dropdown", children: [
|
|
10787
10721
|
recoveryLocked && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10788
10722
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice pollar-danger", role: "alert", children: "Locked: add a way to recover this wallet before sending or receiving. If you lose this device without one, the funds are lost." }),
|
|
10789
10723
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" })
|
|
10790
10724
|
] }),
|
|
10791
10725
|
notReadyReason && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10792
|
-
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice",
|
|
10726
|
+
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-notice", role: "status", children: notReadyReason }),
|
|
10793
10727
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" })
|
|
10794
10728
|
] }),
|
|
10795
10729
|
showCreateAccount && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10796
|
-
/* @__PURE__ */ jsxs(
|
|
10797
|
-
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
|
|
10805
|
-
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
|
|
10810
|
-
|
|
10811
|
-
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
10818
|
-
/* @__PURE__ */ jsx("line", { x1: "19", y1: "8", x2: "19", y2: "14" }),
|
|
10819
|
-
/* @__PURE__ */ jsx("line", { x1: "22", y1: "11", x2: "16", y2: "11" })
|
|
10820
|
-
]
|
|
10821
|
-
}
|
|
10822
|
-
),
|
|
10823
|
-
creatingAccount ? "Creating account\u2026" : "Create account"
|
|
10824
|
-
]
|
|
10825
|
-
}
|
|
10826
|
-
),
|
|
10730
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", onClick: onCreateAccount, disabled: creatingAccount, children: [
|
|
10731
|
+
/* @__PURE__ */ jsxs(
|
|
10732
|
+
"svg",
|
|
10733
|
+
{
|
|
10734
|
+
width: "14",
|
|
10735
|
+
height: "14",
|
|
10736
|
+
viewBox: "0 0 24 24",
|
|
10737
|
+
fill: "none",
|
|
10738
|
+
stroke: "currentColor",
|
|
10739
|
+
strokeWidth: "2",
|
|
10740
|
+
strokeLinecap: "round",
|
|
10741
|
+
strokeLinejoin: "round",
|
|
10742
|
+
children: [
|
|
10743
|
+
/* @__PURE__ */ jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
|
|
10744
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "7", r: "4" }),
|
|
10745
|
+
/* @__PURE__ */ jsx("line", { x1: "19", y1: "8", x2: "19", y2: "14" }),
|
|
10746
|
+
/* @__PURE__ */ jsx("line", { x1: "22", y1: "11", x2: "16", y2: "11" })
|
|
10747
|
+
]
|
|
10748
|
+
}
|
|
10749
|
+
),
|
|
10750
|
+
creatingAccount ? "Creating account\u2026" : "Create account"
|
|
10751
|
+
] }),
|
|
10827
10752
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" })
|
|
10828
10753
|
] }),
|
|
10829
|
-
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item",
|
|
10754
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", onClick: onSend, children: [
|
|
10830
10755
|
/* @__PURE__ */ jsxs(
|
|
10831
10756
|
"svg",
|
|
10832
10757
|
{
|
|
@@ -10846,7 +10771,7 @@ function WalletButtonTemplate({
|
|
|
10846
10771
|
),
|
|
10847
10772
|
"Send"
|
|
10848
10773
|
] }),
|
|
10849
|
-
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item",
|
|
10774
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", onClick: onReceive, children: [
|
|
10850
10775
|
/* @__PURE__ */ jsxs(
|
|
10851
10776
|
"svg",
|
|
10852
10777
|
{
|
|
@@ -10868,7 +10793,7 @@ function WalletButtonTemplate({
|
|
|
10868
10793
|
"Receive"
|
|
10869
10794
|
] }),
|
|
10870
10795
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" }),
|
|
10871
|
-
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item",
|
|
10796
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", onClick: onCopy, children: [
|
|
10872
10797
|
/* @__PURE__ */ jsxs(
|
|
10873
10798
|
"svg",
|
|
10874
10799
|
{
|
|
@@ -10888,7 +10813,7 @@ function WalletButtonTemplate({
|
|
|
10888
10813
|
),
|
|
10889
10814
|
copied ? "Copied!" : "Copy address"
|
|
10890
10815
|
] }),
|
|
10891
|
-
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item",
|
|
10816
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", onClick: onWalletBalance, children: [
|
|
10892
10817
|
/* @__PURE__ */ jsxs(
|
|
10893
10818
|
"svg",
|
|
10894
10819
|
{
|
|
@@ -10909,7 +10834,7 @@ function WalletButtonTemplate({
|
|
|
10909
10834
|
),
|
|
10910
10835
|
"Wallet balance"
|
|
10911
10836
|
] }),
|
|
10912
|
-
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item",
|
|
10837
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", onClick: onTxHistory, children: [
|
|
10913
10838
|
/* @__PURE__ */ jsxs(
|
|
10914
10839
|
"svg",
|
|
10915
10840
|
{
|
|
@@ -10933,7 +10858,7 @@ function WalletButtonTemplate({
|
|
|
10933
10858
|
"Transaction history"
|
|
10934
10859
|
] }),
|
|
10935
10860
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" }),
|
|
10936
|
-
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item",
|
|
10861
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", onClick: onRamp, children: [
|
|
10937
10862
|
/* @__PURE__ */ jsxs(
|
|
10938
10863
|
"svg",
|
|
10939
10864
|
{
|
|
@@ -10955,7 +10880,7 @@ function WalletButtonTemplate({
|
|
|
10955
10880
|
),
|
|
10956
10881
|
"Buy / Sell"
|
|
10957
10882
|
] }),
|
|
10958
|
-
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item",
|
|
10883
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", onClick: onKyc, children: [
|
|
10959
10884
|
/* @__PURE__ */ jsxs(
|
|
10960
10885
|
"svg",
|
|
10961
10886
|
{
|
|
@@ -10976,7 +10901,7 @@ function WalletButtonTemplate({
|
|
|
10976
10901
|
),
|
|
10977
10902
|
"Identity verification"
|
|
10978
10903
|
] }),
|
|
10979
|
-
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item",
|
|
10904
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", onClick: onDistributionRules, children: [
|
|
10980
10905
|
/* @__PURE__ */ jsxs(
|
|
10981
10906
|
"svg",
|
|
10982
10907
|
{
|
|
@@ -10999,7 +10924,7 @@ function WalletButtonTemplate({
|
|
|
10999
10924
|
),
|
|
11000
10925
|
"Distribution rules"
|
|
11001
10926
|
] }),
|
|
11002
|
-
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item",
|
|
10927
|
+
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item", onClick: onSessions, children: [
|
|
11003
10928
|
/* @__PURE__ */ jsxs(
|
|
11004
10929
|
"svg",
|
|
11005
10930
|
{
|
|
@@ -11020,31 +10945,23 @@ function WalletButtonTemplate({
|
|
|
11020
10945
|
),
|
|
11021
10946
|
"Active sessions"
|
|
11022
10947
|
] }),
|
|
11023
|
-
onRecovery && /* @__PURE__ */ jsxs(
|
|
11024
|
-
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11036
|
-
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
strokeLinejoin: "round",
|
|
11041
|
-
children: /* @__PURE__ */ jsx("path", { d: "M12 2 4 5v6c0 5 3.4 9.3 8 11 4.6-1.7 8-6 8-11V5l-8-3z" })
|
|
11042
|
-
}
|
|
11043
|
-
),
|
|
11044
|
-
recoveryLocked ? "Set up wallet recovery" : "Wallet recovery"
|
|
11045
|
-
]
|
|
11046
|
-
}
|
|
11047
|
-
),
|
|
10948
|
+
onRecovery && /* @__PURE__ */ jsxs("button", { className: `pollar-wallet-dropdown-item${recoveryLocked ? " pollar-danger" : ""}`, onClick: onRecovery, children: [
|
|
10949
|
+
/* @__PURE__ */ jsx(
|
|
10950
|
+
"svg",
|
|
10951
|
+
{
|
|
10952
|
+
width: "14",
|
|
10953
|
+
height: "14",
|
|
10954
|
+
viewBox: "0 0 24 24",
|
|
10955
|
+
fill: "none",
|
|
10956
|
+
stroke: "currentColor",
|
|
10957
|
+
strokeWidth: "2",
|
|
10958
|
+
strokeLinecap: "round",
|
|
10959
|
+
strokeLinejoin: "round",
|
|
10960
|
+
children: /* @__PURE__ */ jsx("path", { d: "M12 2 4 5v6c0 5 3.4 9.3 8 11 4.6-1.7 8-6 8-11V5l-8-3z" })
|
|
10961
|
+
}
|
|
10962
|
+
),
|
|
10963
|
+
recoveryLocked ? "Set up wallet recovery" : "Wallet recovery"
|
|
10964
|
+
] }),
|
|
11048
10965
|
/* @__PURE__ */ jsx("div", { className: "pollar-wallet-dropdown-divider" }),
|
|
11049
10966
|
/* @__PURE__ */ jsxs("button", { className: "pollar-wallet-dropdown-item pollar-danger", onClick: onLogout, children: [
|
|
11050
10967
|
/* @__PURE__ */ jsxs(
|
|
@@ -11105,11 +11022,7 @@ function WalletButton() {
|
|
|
11105
11022
|
const isInProgress = transaction.step === "building" || transaction.step === "signing";
|
|
11106
11023
|
const canCreateAccount = !created && wallet?.custody === "external" && wallet.existsOnStellar === false && wallet.fundingMode === "IMMEDIATE";
|
|
11107
11024
|
const notReadyReason = walletNotReadyReason(wallet, primaryChain);
|
|
11108
|
-
const { theme
|
|
11109
|
-
const isDark = theme === "dark";
|
|
11110
|
-
const dropdownBg = isDark ? "#18181b" : "#fff";
|
|
11111
|
-
const dropdownBorder = isDark ? "#3f3f46" : "#e4e4e7";
|
|
11112
|
-
const itemColor = isDark ? "#fafafa" : "#18181b";
|
|
11025
|
+
const { theme, accentColor, styleOverrides } = modalChrome(styles);
|
|
11113
11026
|
useEffect(() => {
|
|
11114
11027
|
function handleClickOutside(e) {
|
|
11115
11028
|
if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
|
|
@@ -11208,12 +11121,11 @@ function WalletButton() {
|
|
|
11208
11121
|
WalletButtonTemplate,
|
|
11209
11122
|
{
|
|
11210
11123
|
walletAddress: walletAddress ?? null,
|
|
11124
|
+
theme,
|
|
11211
11125
|
accentColor,
|
|
11126
|
+
styleOverrides,
|
|
11212
11127
|
open,
|
|
11213
11128
|
copied,
|
|
11214
|
-
dropdownBg,
|
|
11215
|
-
dropdownBorder,
|
|
11216
|
-
itemColor,
|
|
11217
11129
|
wrapperRef,
|
|
11218
11130
|
isInProgress,
|
|
11219
11131
|
showCreateAccount: canCreateAccount,
|
|
@@ -11243,6 +11155,6 @@ function WalletButton() {
|
|
|
11243
11155
|
);
|
|
11244
11156
|
}
|
|
11245
11157
|
|
|
11246
|
-
export { CardModal, ChainSelect, CosignModal, CosignModalTemplate, CustodyMigrationModal, CustodyMigrationModalTemplate, DistributionRulesModal, DistributionRulesModalTemplate, EarnModal, EnabledAssetsModal, EnabledAssetsModalTemplate, KycModal, KycModalTemplate, KycStatus, LoginModalTemplate, PollarProvider, ProviderRegistrationModal, RampWidget, RampWidgetTemplate,
|
|
11158
|
+
export { CardModal, ChainSelect, CosignModal, CosignModalTemplate, CustodyMigrationModal, CustodyMigrationModalTemplate, DistributionRulesModal, DistributionRulesModalTemplate, EarnModal, EnabledAssetsModal, EnabledAssetsModalTemplate, KycModal, KycModalTemplate, KycStatus, LoginModalTemplate, PollarProvider, ProviderRegistrationModal, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, RecoveryModal, RecoveryModalTemplate, RegistryCheckModal, RejectedRouteDisplay, RequirementFormModal, RouteDisplay, SendModal, SendModalTemplate, SessionsModal, SessionsModalTemplate, SwapModal, SwapModalTemplate, TransactionModalTemplate, TxHistoryModalTemplate, TxStatusView, WalletBalanceModal, WalletBalanceModalTemplate, WalletButton, WalletButtonTemplate, addressForChain, browserPasskeyCeremony, browserPasskeySigner, browserRecoveryPasskey, buildModalCssVars, chainsOf, createPollarAdapterHook, modalChrome, readableTextOn, resolveChain, useChains, useCosign, usePollar, walletNotReadyReason };
|
|
11247
11159
|
//# sourceMappingURL=index.mjs.map
|
|
11248
11160
|
//# sourceMappingURL=index.mjs.map
|