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