@swype-org/react-sdk 0.1.28 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +382 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -68
- package/dist/index.d.ts +85 -68
- package/dist/index.js +384 -76
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -28,9 +28,9 @@ var darkTheme = {
|
|
|
28
28
|
textMuted: "#7fa4b0",
|
|
29
29
|
textInverse: "#052027",
|
|
30
30
|
border: "#2b4551",
|
|
31
|
-
borderFocus: "#
|
|
32
|
-
accent: "#
|
|
33
|
-
accentHover: "#
|
|
31
|
+
borderFocus: "#28b67a",
|
|
32
|
+
accent: "#28b67a",
|
|
33
|
+
accentHover: "#219866",
|
|
34
34
|
accentText: "#ffffff",
|
|
35
35
|
success: "#0f9d73",
|
|
36
36
|
successBg: "#0f2f2a",
|
|
@@ -52,9 +52,9 @@ var lightTheme = {
|
|
|
52
52
|
textMuted: "#7d97a1",
|
|
53
53
|
textInverse: "#ffffff",
|
|
54
54
|
border: "#d2e4ea",
|
|
55
|
-
borderFocus: "#
|
|
56
|
-
accent: "#
|
|
57
|
-
accentHover: "#
|
|
55
|
+
borderFocus: "#28b67a",
|
|
56
|
+
accent: "#28b67a",
|
|
57
|
+
accentHover: "#219866",
|
|
58
58
|
accentText: "#ffffff",
|
|
59
59
|
success: "#0f9d73",
|
|
60
60
|
successBg: "#e6f7f1",
|
|
@@ -77,26 +77,6 @@ var wagmiConfig = wagmi.createConfig({
|
|
|
77
77
|
[chains.base.id]: wagmi.http()
|
|
78
78
|
}
|
|
79
79
|
});
|
|
80
|
-
var PRIVY_MODAL_CENTER_CSS = `
|
|
81
|
-
@media (max-width: 440px) {
|
|
82
|
-
#privy-dialog [data-headlessui-state] {
|
|
83
|
-
position: static !important;
|
|
84
|
-
bottom: auto !important;
|
|
85
|
-
margin: auto !important;
|
|
86
|
-
width: 360px !important;
|
|
87
|
-
max-width: calc(100vw - 32px) !important;
|
|
88
|
-
box-shadow: 0px 8px 36px rgba(55, 65, 81, 0.15) !important;
|
|
89
|
-
border-radius: var(--privy-border-radius-lg) !important;
|
|
90
|
-
transform: none !important;
|
|
91
|
-
transition: opacity 100ms ease-in !important;
|
|
92
|
-
}
|
|
93
|
-
#privy-dialog [data-headlessui-state].entering,
|
|
94
|
-
#privy-dialog [data-headlessui-state].leaving {
|
|
95
|
-
opacity: 0 !important;
|
|
96
|
-
transform: none !important;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
`;
|
|
100
80
|
var SwypeContext = react.createContext(null);
|
|
101
81
|
function SwypeProvider({
|
|
102
82
|
apiBaseUrl,
|
|
@@ -107,15 +87,6 @@ function SwypeProvider({
|
|
|
107
87
|
if (!queryClientRef.current) {
|
|
108
88
|
queryClientRef.current = new reactQuery.QueryClient();
|
|
109
89
|
}
|
|
110
|
-
react.useEffect(() => {
|
|
111
|
-
const style = document.createElement("style");
|
|
112
|
-
style.setAttribute("data-swype", "privy-modal-center");
|
|
113
|
-
style.textContent = PRIVY_MODAL_CENTER_CSS;
|
|
114
|
-
document.head.appendChild(style);
|
|
115
|
-
return () => {
|
|
116
|
-
style.remove();
|
|
117
|
-
};
|
|
118
|
-
}, []);
|
|
119
90
|
const [depositAmount, setDepositAmountRaw] = react.useState(null);
|
|
120
91
|
const setDepositAmount = react.useCallback((amount) => {
|
|
121
92
|
setDepositAmountRaw(amount);
|
|
@@ -138,6 +109,12 @@ function SwypeProvider({
|
|
|
138
109
|
appearance: {
|
|
139
110
|
theme,
|
|
140
111
|
accentColor: getTheme(theme).accent
|
|
112
|
+
},
|
|
113
|
+
intl: {
|
|
114
|
+
defaultCountry: "US"
|
|
115
|
+
},
|
|
116
|
+
embeddedWallets: {
|
|
117
|
+
showWalletUIs: false
|
|
141
118
|
}
|
|
142
119
|
},
|
|
143
120
|
children: /* @__PURE__ */ jsxRuntime.jsx(SwypeContext.Provider, { value, children })
|
|
@@ -176,6 +153,7 @@ __export(api_exports, {
|
|
|
176
153
|
fetchAccounts: () => fetchAccounts,
|
|
177
154
|
fetchAuthorizationSession: () => fetchAuthorizationSession,
|
|
178
155
|
fetchChains: () => fetchChains,
|
|
156
|
+
fetchMerchantPublicKey: () => fetchMerchantPublicKey,
|
|
179
157
|
fetchProviders: () => fetchProviders,
|
|
180
158
|
fetchTransfer: () => fetchTransfer,
|
|
181
159
|
fetchUserConfig: () => fetchUserConfig,
|
|
@@ -218,9 +196,13 @@ async function fetchAccounts(apiBaseUrl, token, credentialId) {
|
|
|
218
196
|
return data.items;
|
|
219
197
|
}
|
|
220
198
|
async function createTransfer(apiBaseUrl, token, params) {
|
|
199
|
+
if (!params.merchantAuthorization) {
|
|
200
|
+
throw new Error("merchantAuthorization is required for transfer creation.");
|
|
201
|
+
}
|
|
221
202
|
const body = {
|
|
222
203
|
id: params.id ?? crypto.randomUUID(),
|
|
223
204
|
credentialId: params.credentialId,
|
|
205
|
+
merchantAuthorization: params.merchantAuthorization,
|
|
224
206
|
sources: [{ [params.sourceType]: params.sourceId }],
|
|
225
207
|
destinations: [
|
|
226
208
|
{
|
|
@@ -245,6 +227,13 @@ async function createTransfer(apiBaseUrl, token, params) {
|
|
|
245
227
|
if (!res.ok) await throwApiError(res);
|
|
246
228
|
return await res.json();
|
|
247
229
|
}
|
|
230
|
+
async function fetchMerchantPublicKey(apiBaseUrl, merchantId) {
|
|
231
|
+
const res = await fetch(
|
|
232
|
+
`${apiBaseUrl}/v1/merchants/${encodeURIComponent(merchantId)}/public-key`
|
|
233
|
+
);
|
|
234
|
+
if (!res.ok) await throwApiError(res);
|
|
235
|
+
return await res.json();
|
|
236
|
+
}
|
|
248
237
|
async function fetchTransfer(apiBaseUrl, token, transferId, authorizationSessionToken) {
|
|
249
238
|
if (!token && !authorizationSessionToken) {
|
|
250
239
|
throw new Error("Missing auth credentials for transfer fetch.");
|
|
@@ -2100,6 +2089,46 @@ function AdvancedSettings({
|
|
|
2100
2089
|
] });
|
|
2101
2090
|
}
|
|
2102
2091
|
|
|
2092
|
+
// src/auth.ts
|
|
2093
|
+
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2094
|
+
var PHONE_DIGIT_PATTERN = /^\d{7,15}$/;
|
|
2095
|
+
function normalizePhoneNumber(rawValue) {
|
|
2096
|
+
const trimmed = rawValue.trim();
|
|
2097
|
+
if (!trimmed) return null;
|
|
2098
|
+
const hasExplicitCountryCode = trimmed.startsWith("+");
|
|
2099
|
+
const digits = trimmed.replace(/\D/g, "");
|
|
2100
|
+
if (!PHONE_DIGIT_PATTERN.test(digits)) return null;
|
|
2101
|
+
return hasExplicitCountryCode ? `+${digits}` : digits;
|
|
2102
|
+
}
|
|
2103
|
+
function normalizeAuthIdentifier(rawValue) {
|
|
2104
|
+
const trimmed = rawValue.trim();
|
|
2105
|
+
if (!trimmed) return null;
|
|
2106
|
+
if (EMAIL_PATTERN.test(trimmed)) {
|
|
2107
|
+
return {
|
|
2108
|
+
kind: "email",
|
|
2109
|
+
value: trimmed.toLowerCase()
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
const normalizedPhoneNumber = normalizePhoneNumber(trimmed);
|
|
2113
|
+
if (normalizedPhoneNumber) {
|
|
2114
|
+
return {
|
|
2115
|
+
kind: "phone",
|
|
2116
|
+
value: normalizedPhoneNumber
|
|
2117
|
+
};
|
|
2118
|
+
}
|
|
2119
|
+
return null;
|
|
2120
|
+
}
|
|
2121
|
+
function maskAuthIdentifier(identifier) {
|
|
2122
|
+
if (identifier.kind === "email") {
|
|
2123
|
+
const [localPart, domain = ""] = identifier.value.split("@");
|
|
2124
|
+
const localPrefix = localPart.slice(0, 2);
|
|
2125
|
+
return `${localPrefix}${"*".repeat(Math.max(localPart.length - 2, 0))}@${domain}`;
|
|
2126
|
+
}
|
|
2127
|
+
const digits = identifier.value.replace(/\D/g, "");
|
|
2128
|
+
const visibleSuffix = digits.slice(-4);
|
|
2129
|
+
return `***-***-${visibleSuffix}`;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2103
2132
|
// src/processingStatus.ts
|
|
2104
2133
|
var PROCESSING_TIMEOUT_MS = 18e4;
|
|
2105
2134
|
function resolvePreferredTransfer(polledTransfer, localTransfer) {
|
|
@@ -2124,14 +2153,20 @@ function hasProcessingTimedOut(processingStartedAtMs, nowMs) {
|
|
|
2124
2153
|
function buildProcessingTimeoutMessage(status) {
|
|
2125
2154
|
return `Payment is taking longer than expected (status: ${status}). Please try again.`;
|
|
2126
2155
|
}
|
|
2156
|
+
|
|
2157
|
+
// src/walletFlow.ts
|
|
2158
|
+
var MOBILE_USER_AGENT_PATTERN = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
|
|
2159
|
+
function isMobileUserAgent(userAgent) {
|
|
2160
|
+
if (!userAgent) {
|
|
2161
|
+
return false;
|
|
2162
|
+
}
|
|
2163
|
+
return MOBILE_USER_AGENT_PATTERN.test(userAgent);
|
|
2164
|
+
}
|
|
2165
|
+
function shouldUseWalletConnector(options) {
|
|
2166
|
+
return options.useWalletConnector ?? !isMobileUserAgent(options.userAgent);
|
|
2167
|
+
}
|
|
2127
2168
|
var ACTIVE_CREDENTIAL_STORAGE_KEY = "swype_active_credential_id";
|
|
2128
2169
|
var MIN_SEND_AMOUNT_USD = 0.25;
|
|
2129
|
-
function isMobile() {
|
|
2130
|
-
if (typeof navigator === "undefined") return false;
|
|
2131
|
-
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
2132
|
-
navigator.userAgent
|
|
2133
|
-
);
|
|
2134
|
-
}
|
|
2135
2170
|
function computeSmartDefaults(accts, transferAmount) {
|
|
2136
2171
|
if (accts.length === 0) return null;
|
|
2137
2172
|
for (const acct of accts) {
|
|
@@ -2206,10 +2241,21 @@ function SwypePayment({
|
|
|
2206
2241
|
onComplete,
|
|
2207
2242
|
onError,
|
|
2208
2243
|
useWalletConnector,
|
|
2209
|
-
idempotencyKey
|
|
2244
|
+
idempotencyKey,
|
|
2245
|
+
merchantAuthorization
|
|
2210
2246
|
}) {
|
|
2211
2247
|
const { apiBaseUrl, tokens, depositAmount } = useSwypeConfig();
|
|
2212
|
-
const { ready, authenticated, user,
|
|
2248
|
+
const { ready, authenticated, user, logout, getAccessToken } = reactAuth.usePrivy();
|
|
2249
|
+
const {
|
|
2250
|
+
sendCode: sendEmailCode,
|
|
2251
|
+
loginWithCode: loginWithEmailCode,
|
|
2252
|
+
state: emailLoginState
|
|
2253
|
+
} = reactAuth.useLoginWithEmail();
|
|
2254
|
+
const {
|
|
2255
|
+
sendCode: sendSmsCode,
|
|
2256
|
+
loginWithCode: loginWithSmsCode,
|
|
2257
|
+
state: smsLoginState
|
|
2258
|
+
} = reactAuth.useLoginWithSms();
|
|
2213
2259
|
const [step, setStep] = react.useState("login");
|
|
2214
2260
|
const [error, setError] = react.useState(null);
|
|
2215
2261
|
const [providers, setProviders] = react.useState([]);
|
|
@@ -2234,6 +2280,11 @@ function SwypePayment({
|
|
|
2234
2280
|
if (typeof window === "undefined") return null;
|
|
2235
2281
|
return window.localStorage.getItem(ACTIVE_CREDENTIAL_STORAGE_KEY);
|
|
2236
2282
|
});
|
|
2283
|
+
const [authInput, setAuthInput] = react.useState("");
|
|
2284
|
+
const [verificationTarget, setVerificationTarget] = react.useState(
|
|
2285
|
+
null
|
|
2286
|
+
);
|
|
2287
|
+
const [otpCode, setOtpCode] = react.useState("");
|
|
2237
2288
|
const [mobileFlow, setMobileFlow] = react.useState(false);
|
|
2238
2289
|
const pollingTransferIdRef = react.useRef(null);
|
|
2239
2290
|
const mobileSigningTransferIdRef = react.useRef(null);
|
|
@@ -2251,9 +2302,81 @@ function SwypePayment({
|
|
|
2251
2302
|
setAmount(depositAmount.toString());
|
|
2252
2303
|
}
|
|
2253
2304
|
}, [depositAmount]);
|
|
2305
|
+
const resetHeadlessLogin = react.useCallback(() => {
|
|
2306
|
+
setAuthInput("");
|
|
2307
|
+
setVerificationTarget(null);
|
|
2308
|
+
setOtpCode("");
|
|
2309
|
+
}, []);
|
|
2310
|
+
const activeOtpStatus = verificationTarget?.kind === "email" ? emailLoginState.status : verificationTarget?.kind === "phone" ? smsLoginState.status : "initial";
|
|
2311
|
+
const activeOtpErrorMessage = verificationTarget?.kind === "email" && emailLoginState.status === "error" ? emailLoginState.error?.message ?? "Failed to continue with email." : verificationTarget?.kind === "phone" && smsLoginState.status === "error" ? smsLoginState.error?.message ?? "Failed to continue with phone number." : null;
|
|
2312
|
+
react.useEffect(() => {
|
|
2313
|
+
if (activeOtpErrorMessage) {
|
|
2314
|
+
setError(activeOtpErrorMessage);
|
|
2315
|
+
}
|
|
2316
|
+
}, [activeOtpErrorMessage]);
|
|
2317
|
+
const handleSendLoginCode = react.useCallback(async () => {
|
|
2318
|
+
const normalizedIdentifier = normalizeAuthIdentifier(authInput);
|
|
2319
|
+
if (!normalizedIdentifier) {
|
|
2320
|
+
setError("Enter a valid email address or phone number.");
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
setError(null);
|
|
2324
|
+
setOtpCode("");
|
|
2325
|
+
try {
|
|
2326
|
+
if (normalizedIdentifier.kind === "email") {
|
|
2327
|
+
await sendEmailCode({ email: normalizedIdentifier.value });
|
|
2328
|
+
} else {
|
|
2329
|
+
await sendSmsCode({ phoneNumber: normalizedIdentifier.value });
|
|
2330
|
+
}
|
|
2331
|
+
setVerificationTarget(normalizedIdentifier);
|
|
2332
|
+
} catch (err) {
|
|
2333
|
+
const msg = err instanceof Error ? err.message : "Failed to send verification code";
|
|
2334
|
+
setError(msg);
|
|
2335
|
+
}
|
|
2336
|
+
}, [authInput, sendEmailCode, sendSmsCode]);
|
|
2337
|
+
const handleVerifyLoginCode = react.useCallback(async () => {
|
|
2338
|
+
if (!verificationTarget) return;
|
|
2339
|
+
const trimmedCode = otpCode.trim();
|
|
2340
|
+
if (!/^\d{6}$/.test(trimmedCode)) {
|
|
2341
|
+
setError("Enter the 6-digit verification code.");
|
|
2342
|
+
return;
|
|
2343
|
+
}
|
|
2344
|
+
setError(null);
|
|
2345
|
+
try {
|
|
2346
|
+
if (verificationTarget.kind === "email") {
|
|
2347
|
+
await loginWithEmailCode({ code: trimmedCode });
|
|
2348
|
+
} else {
|
|
2349
|
+
await loginWithSmsCode({ code: trimmedCode });
|
|
2350
|
+
}
|
|
2351
|
+
} catch (err) {
|
|
2352
|
+
const msg = err instanceof Error ? err.message : "Failed to verify code";
|
|
2353
|
+
setError(msg);
|
|
2354
|
+
}
|
|
2355
|
+
}, [verificationTarget, otpCode, loginWithEmailCode, loginWithSmsCode]);
|
|
2356
|
+
const handleResendLoginCode = react.useCallback(async () => {
|
|
2357
|
+
if (!verificationTarget) return;
|
|
2358
|
+
setError(null);
|
|
2359
|
+
try {
|
|
2360
|
+
if (verificationTarget.kind === "email") {
|
|
2361
|
+
await sendEmailCode({ email: verificationTarget.value });
|
|
2362
|
+
} else {
|
|
2363
|
+
await sendSmsCode({ phoneNumber: verificationTarget.value });
|
|
2364
|
+
}
|
|
2365
|
+
} catch (err) {
|
|
2366
|
+
const msg = err instanceof Error ? err.message : "Failed to resend code";
|
|
2367
|
+
setError(msg);
|
|
2368
|
+
}
|
|
2369
|
+
}, [verificationTarget, sendEmailCode, sendSmsCode]);
|
|
2370
|
+
const handleEditIdentifier = react.useCallback(() => {
|
|
2371
|
+
setError(null);
|
|
2372
|
+
setVerificationTarget(null);
|
|
2373
|
+
setOtpCode("");
|
|
2374
|
+
}, []);
|
|
2254
2375
|
react.useEffect(() => {
|
|
2255
2376
|
if (!ready || !authenticated || step !== "login") return;
|
|
2256
2377
|
let cancelled = false;
|
|
2378
|
+
setError(null);
|
|
2379
|
+
resetHeadlessLogin();
|
|
2257
2380
|
const checkPasskey = async () => {
|
|
2258
2381
|
try {
|
|
2259
2382
|
const token = await getAccessToken();
|
|
@@ -2302,7 +2425,16 @@ function SwypePayment({
|
|
|
2302
2425
|
return () => {
|
|
2303
2426
|
cancelled = true;
|
|
2304
2427
|
};
|
|
2305
|
-
}, [
|
|
2428
|
+
}, [
|
|
2429
|
+
ready,
|
|
2430
|
+
authenticated,
|
|
2431
|
+
step,
|
|
2432
|
+
depositAmount,
|
|
2433
|
+
apiBaseUrl,
|
|
2434
|
+
getAccessToken,
|
|
2435
|
+
activeCredentialId,
|
|
2436
|
+
resetHeadlessLogin
|
|
2437
|
+
]);
|
|
2306
2438
|
const loadingDataRef = react.useRef(false);
|
|
2307
2439
|
react.useEffect(() => {
|
|
2308
2440
|
if (!authenticated) return;
|
|
@@ -2522,6 +2654,7 @@ function SwypePayment({
|
|
|
2522
2654
|
const t = await createTransfer(apiBaseUrl, token, {
|
|
2523
2655
|
id: idempotencyKey,
|
|
2524
2656
|
credentialId: activeCredentialId,
|
|
2657
|
+
merchantAuthorization,
|
|
2525
2658
|
sourceType: effectiveSourceType,
|
|
2526
2659
|
sourceId: effectiveSourceId,
|
|
2527
2660
|
destination,
|
|
@@ -2529,8 +2662,11 @@ function SwypePayment({
|
|
|
2529
2662
|
});
|
|
2530
2663
|
setTransfer(t);
|
|
2531
2664
|
if (t.authorizationSessions && t.authorizationSessions.length > 0) {
|
|
2532
|
-
const
|
|
2533
|
-
|
|
2665
|
+
const shouldUseConnector = shouldUseWalletConnector({
|
|
2666
|
+
useWalletConnector,
|
|
2667
|
+
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
2668
|
+
});
|
|
2669
|
+
if (!shouldUseConnector) {
|
|
2534
2670
|
setMobileFlow(true);
|
|
2535
2671
|
pollingTransferIdRef.current = t.id;
|
|
2536
2672
|
polling.startPolling(t.id);
|
|
@@ -2611,7 +2747,8 @@ function SwypePayment({
|
|
|
2611
2747
|
processingStartedAtRef.current = null;
|
|
2612
2748
|
pollingTransferIdRef.current = null;
|
|
2613
2749
|
mobileSigningTransferIdRef.current = null;
|
|
2614
|
-
|
|
2750
|
+
resetHeadlessLogin();
|
|
2751
|
+
}, [logout, polling, depositAmount, resetHeadlessLogin]);
|
|
2615
2752
|
const handleConnectNewAccount = (providerId) => {
|
|
2616
2753
|
setSelectedProviderId(providerId);
|
|
2617
2754
|
setSelectedAccountId(null);
|
|
@@ -2648,7 +2785,7 @@ function SwypePayment({
|
|
|
2648
2785
|
cursor: "pointer",
|
|
2649
2786
|
transition: "filter 0.15s ease, transform 0.15s ease",
|
|
2650
2787
|
fontFamily: "inherit",
|
|
2651
|
-
boxShadow: "0 8px 18px rgba(
|
|
2788
|
+
boxShadow: "0 8px 18px rgba(40, 182, 122, 0.28)"
|
|
2652
2789
|
};
|
|
2653
2790
|
const btnDisabled = {
|
|
2654
2791
|
...btnPrimary,
|
|
@@ -2660,6 +2797,33 @@ function SwypePayment({
|
|
|
2660
2797
|
background: tokens.bgCard,
|
|
2661
2798
|
color: tokens.textSecondary,
|
|
2662
2799
|
border: `1px solid ${tokens.border}`});
|
|
2800
|
+
const textFieldStyle = {
|
|
2801
|
+
width: "100%",
|
|
2802
|
+
padding: "15px 16px",
|
|
2803
|
+
borderRadius: "16px",
|
|
2804
|
+
border: `1px solid ${tokens.border}`,
|
|
2805
|
+
background: tokens.bgInput,
|
|
2806
|
+
color: tokens.text,
|
|
2807
|
+
fontSize: "0.98rem",
|
|
2808
|
+
fontFamily: "inherit",
|
|
2809
|
+
outline: "none",
|
|
2810
|
+
boxSizing: "border-box"
|
|
2811
|
+
};
|
|
2812
|
+
const authCaptionStyle = {
|
|
2813
|
+
fontSize: "0.84rem",
|
|
2814
|
+
color: tokens.textSecondary,
|
|
2815
|
+
margin: 0,
|
|
2816
|
+
lineHeight: 1.5
|
|
2817
|
+
};
|
|
2818
|
+
const authTertiaryButtonStyle = {
|
|
2819
|
+
background: "transparent",
|
|
2820
|
+
border: "none",
|
|
2821
|
+
color: tokens.textMuted,
|
|
2822
|
+
cursor: "pointer",
|
|
2823
|
+
fontFamily: "inherit",
|
|
2824
|
+
fontSize: "0.84rem",
|
|
2825
|
+
padding: 0
|
|
2826
|
+
};
|
|
2663
2827
|
const errorStyle = {
|
|
2664
2828
|
background: tokens.errorBg,
|
|
2665
2829
|
border: `1px solid ${tokens.error}66`,
|
|
@@ -2720,6 +2884,7 @@ function SwypePayment({
|
|
|
2720
2884
|
]
|
|
2721
2885
|
}
|
|
2722
2886
|
);
|
|
2887
|
+
const placeholderProviders = ["A", "B", "C", "D", "E"];
|
|
2723
2888
|
const displayedSelectSourceChoices = selectSourceChoices.length > 0 ? selectSourceChoices : [
|
|
2724
2889
|
{
|
|
2725
2890
|
chainName: "Base",
|
|
@@ -2755,43 +2920,186 @@ function SwypePayment({
|
|
|
2755
2920
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "center", padding: "24px 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { label: "Initializing..." }) }) });
|
|
2756
2921
|
}
|
|
2757
2922
|
if (step === "login" && !authenticated) {
|
|
2923
|
+
const isAwaitingOtp = verificationTarget !== null;
|
|
2924
|
+
const isSendingCode = activeOtpStatus === "sending-code";
|
|
2925
|
+
const isSubmittingCode = activeOtpStatus === "submitting-code";
|
|
2926
|
+
const continueDisabled = authInput.trim().length === 0 || isSendingCode || isSubmittingCode;
|
|
2927
|
+
const verifyDisabled = otpCode.trim().length !== 6 || isSubmittingCode;
|
|
2758
2928
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center" }, children: [
|
|
2759
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2760
|
-
"
|
|
2929
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2930
|
+
"div",
|
|
2761
2931
|
{
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2932
|
+
style: {
|
|
2933
|
+
width: 56,
|
|
2934
|
+
height: 56,
|
|
2935
|
+
borderRadius: 14,
|
|
2936
|
+
background: tokens.accent,
|
|
2937
|
+
color: tokens.accentText,
|
|
2938
|
+
display: "flex",
|
|
2939
|
+
alignItems: "center",
|
|
2940
|
+
justifyContent: "center",
|
|
2941
|
+
fontWeight: 700,
|
|
2942
|
+
fontSize: "1.35rem",
|
|
2943
|
+
margin: "0 auto 24px",
|
|
2944
|
+
boxShadow: "0 10px 20px rgba(40, 182, 122, 0.22)"
|
|
2945
|
+
},
|
|
2946
|
+
children: "S"
|
|
2947
|
+
}
|
|
2948
|
+
),
|
|
2949
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2950
|
+
"h2",
|
|
2951
|
+
{
|
|
2952
|
+
style: {
|
|
2953
|
+
...headingStyle,
|
|
2954
|
+
fontSize: "2.05rem",
|
|
2955
|
+
lineHeight: 1.15,
|
|
2956
|
+
marginBottom: "10px",
|
|
2957
|
+
whiteSpace: "pre-line"
|
|
2958
|
+
},
|
|
2959
|
+
children: isAwaitingOtp ? "Enter your code." : "One-time setup.\nOne-tap deposits after."
|
|
2779
2960
|
}
|
|
2780
2961
|
),
|
|
2781
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: { ...headingStyle, marginBottom: "8px" }, children: "Pay with Swype" }),
|
|
2782
2962
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2783
2963
|
"p",
|
|
2784
2964
|
{
|
|
2785
2965
|
style: {
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
lineHeight: 1.5
|
|
2966
|
+
...authCaptionStyle,
|
|
2967
|
+
margin: "0 0 26px 0",
|
|
2968
|
+
whiteSpace: "pre-line"
|
|
2790
2969
|
},
|
|
2791
|
-
children:
|
|
2970
|
+
children: isAwaitingOtp ? `We sent a 6-digit code to ${maskAuthIdentifier(verificationTarget)}.` : "Protected by Face ID."
|
|
2792
2971
|
}
|
|
2793
2972
|
),
|
|
2794
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
2973
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorStyle, children: error }),
|
|
2974
|
+
isAwaitingOtp ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2975
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2976
|
+
"input",
|
|
2977
|
+
{
|
|
2978
|
+
id: "swype-login-code",
|
|
2979
|
+
type: "text",
|
|
2980
|
+
inputMode: "numeric",
|
|
2981
|
+
autoComplete: "one-time-code",
|
|
2982
|
+
placeholder: "Verification code",
|
|
2983
|
+
value: otpCode,
|
|
2984
|
+
onChange: (event) => {
|
|
2985
|
+
setOtpCode(event.target.value.replace(/\D/g, "").slice(0, 6));
|
|
2986
|
+
},
|
|
2987
|
+
style: {
|
|
2988
|
+
...textFieldStyle,
|
|
2989
|
+
textAlign: "center",
|
|
2990
|
+
letterSpacing: "0.24em",
|
|
2991
|
+
marginBottom: "14px"
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
),
|
|
2995
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2996
|
+
"button",
|
|
2997
|
+
{
|
|
2998
|
+
style: verifyDisabled ? btnDisabled : btnPrimary,
|
|
2999
|
+
disabled: verifyDisabled,
|
|
3000
|
+
onClick: handleVerifyLoginCode,
|
|
3001
|
+
children: isSubmittingCode ? "Verifying..." : "Continue"
|
|
3002
|
+
}
|
|
3003
|
+
),
|
|
3004
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3005
|
+
"div",
|
|
3006
|
+
{
|
|
3007
|
+
style: {
|
|
3008
|
+
display: "flex",
|
|
3009
|
+
justifyContent: "space-between",
|
|
3010
|
+
gap: "12px",
|
|
3011
|
+
marginTop: "14px"
|
|
3012
|
+
},
|
|
3013
|
+
children: [
|
|
3014
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: authTertiaryButtonStyle, onClick: handleEditIdentifier, children: "Use a different email or phone" }),
|
|
3015
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3016
|
+
"button",
|
|
3017
|
+
{
|
|
3018
|
+
type: "button",
|
|
3019
|
+
style: authTertiaryButtonStyle,
|
|
3020
|
+
onClick: handleResendLoginCode,
|
|
3021
|
+
disabled: isSendingCode || isSubmittingCode,
|
|
3022
|
+
children: isSendingCode ? "Sending..." : "Resend code"
|
|
3023
|
+
}
|
|
3024
|
+
)
|
|
3025
|
+
]
|
|
3026
|
+
}
|
|
3027
|
+
)
|
|
3028
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3029
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3030
|
+
"input",
|
|
3031
|
+
{
|
|
3032
|
+
id: "swype-login-identifier",
|
|
3033
|
+
type: "text",
|
|
3034
|
+
inputMode: "text",
|
|
3035
|
+
autoComplete: "username",
|
|
3036
|
+
placeholder: "Email or phone number",
|
|
3037
|
+
value: authInput,
|
|
3038
|
+
onChange: (event) => setAuthInput(event.target.value),
|
|
3039
|
+
style: { ...textFieldStyle, marginBottom: "14px" }
|
|
3040
|
+
}
|
|
3041
|
+
),
|
|
3042
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3043
|
+
"button",
|
|
3044
|
+
{
|
|
3045
|
+
style: continueDisabled ? btnDisabled : btnPrimary,
|
|
3046
|
+
disabled: continueDisabled,
|
|
3047
|
+
onClick: handleSendLoginCode,
|
|
3048
|
+
children: isSendingCode ? "Sending code..." : "Continue"
|
|
3049
|
+
}
|
|
3050
|
+
),
|
|
3051
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3052
|
+
"div",
|
|
3053
|
+
{
|
|
3054
|
+
style: {
|
|
3055
|
+
display: "flex",
|
|
3056
|
+
alignItems: "center",
|
|
3057
|
+
gap: "10px",
|
|
3058
|
+
margin: "22px 0 14px",
|
|
3059
|
+
color: tokens.textMuted,
|
|
3060
|
+
fontSize: "0.82rem"
|
|
3061
|
+
},
|
|
3062
|
+
children: [
|
|
3063
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, height: 1, background: tokens.border } }),
|
|
3064
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "works with" }),
|
|
3065
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, height: 1, background: tokens.border } })
|
|
3066
|
+
]
|
|
3067
|
+
}
|
|
3068
|
+
),
|
|
3069
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3070
|
+
"div",
|
|
3071
|
+
{
|
|
3072
|
+
"aria-label": "Works with placeholder providers",
|
|
3073
|
+
style: {
|
|
3074
|
+
display: "flex",
|
|
3075
|
+
justifyContent: "center",
|
|
3076
|
+
gap: "12px",
|
|
3077
|
+
marginBottom: "18px"
|
|
3078
|
+
},
|
|
3079
|
+
children: placeholderProviders.map((providerLabel) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3080
|
+
"div",
|
|
3081
|
+
{
|
|
3082
|
+
style: {
|
|
3083
|
+
width: 34,
|
|
3084
|
+
height: 34,
|
|
3085
|
+
borderRadius: 999,
|
|
3086
|
+
border: `1px solid ${tokens.border}`,
|
|
3087
|
+
background: tokens.bgInput,
|
|
3088
|
+
color: tokens.textMuted,
|
|
3089
|
+
display: "flex",
|
|
3090
|
+
alignItems: "center",
|
|
3091
|
+
justifyContent: "center",
|
|
3092
|
+
fontSize: "0.78rem",
|
|
3093
|
+
fontWeight: 600
|
|
3094
|
+
},
|
|
3095
|
+
children: providerLabel
|
|
3096
|
+
},
|
|
3097
|
+
providerLabel
|
|
3098
|
+
))
|
|
3099
|
+
}
|
|
3100
|
+
),
|
|
3101
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...authCaptionStyle, color: tokens.textMuted }, children: "Powered by Swype. Non-custodial." })
|
|
3102
|
+
] })
|
|
2795
3103
|
] }) });
|
|
2796
3104
|
}
|
|
2797
3105
|
if (step === "register-passkey") {
|