@swype-org/react-sdk 0.1.32 → 0.1.34
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 +473 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +474 -76
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createContext, useRef, useState, useCallback, useMemo, useContext, useEffect } from 'react';
|
|
2
|
-
import { PrivyProvider, usePrivy, useLoginWithEmail, useLoginWithSms } from '@privy-io/react-auth';
|
|
2
|
+
import { PrivyProvider, usePrivy, useLoginWithEmail, useLoginWithSms, useLoginWithOAuth } 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';
|
|
@@ -1448,8 +1448,20 @@ function hasProcessingTimedOut(processingStartedAtMs, nowMs) {
|
|
|
1448
1448
|
if (!processingStartedAtMs) return false;
|
|
1449
1449
|
return nowMs - processingStartedAtMs >= PROCESSING_TIMEOUT_MS;
|
|
1450
1450
|
}
|
|
1451
|
+
var STATUS_DISPLAY_LABELS = {
|
|
1452
|
+
CREATED: "created",
|
|
1453
|
+
AUTHORIZED: "authorized",
|
|
1454
|
+
SENDING: "sending",
|
|
1455
|
+
SENT: "confirming delivery",
|
|
1456
|
+
COMPLETED: "completed",
|
|
1457
|
+
FAILED: "failed"
|
|
1458
|
+
};
|
|
1459
|
+
function getStatusDisplayLabel(status) {
|
|
1460
|
+
return STATUS_DISPLAY_LABELS[status] ?? status;
|
|
1461
|
+
}
|
|
1451
1462
|
function buildProcessingTimeoutMessage(status) {
|
|
1452
|
-
|
|
1463
|
+
const label = getStatusDisplayLabel(status);
|
|
1464
|
+
return `Payment is taking longer than expected (status: ${label}). Please try again.`;
|
|
1453
1465
|
}
|
|
1454
1466
|
|
|
1455
1467
|
// src/walletFlow.ts
|
|
@@ -1712,7 +1724,7 @@ var circleStyle = (bg, size) => ({
|
|
|
1712
1724
|
function OtpInput({ value, onChange, length = 6, disabled }) {
|
|
1713
1725
|
const { tokens } = useSwypeConfig();
|
|
1714
1726
|
const inputsRef = useRef([]);
|
|
1715
|
-
const digits = value.padEnd(length
|
|
1727
|
+
const digits = value.padEnd(length).split("").slice(0, length);
|
|
1716
1728
|
const focusInput = useCallback((index) => {
|
|
1717
1729
|
const clamped = Math.max(0, Math.min(index, length - 1));
|
|
1718
1730
|
inputsRef.current[clamped]?.focus();
|
|
@@ -2115,34 +2127,50 @@ function LoginScreen({
|
|
|
2115
2127
|
onSubmit,
|
|
2116
2128
|
sending,
|
|
2117
2129
|
error,
|
|
2118
|
-
onBack
|
|
2130
|
+
onBack,
|
|
2131
|
+
merchantInitials,
|
|
2132
|
+
onSocialLogin
|
|
2119
2133
|
}) {
|
|
2120
2134
|
const { tokens } = useSwypeConfig();
|
|
2121
2135
|
const disabled = authInput.trim().length === 0 || sending;
|
|
2122
|
-
const walletLogos = ["MM", "R", "O", "P", "+"];
|
|
2123
2136
|
return /* @__PURE__ */ jsxs(
|
|
2124
2137
|
ScreenLayout,
|
|
2125
2138
|
{
|
|
2126
2139
|
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2127
2140
|
/* @__PURE__ */ jsx(PrimaryButton, { onClick: onSubmit, disabled, loading: sending, children: "Continue" }),
|
|
2128
|
-
/* @__PURE__ */ jsxs(
|
|
2129
|
-
/* @__PURE__ */
|
|
2130
|
-
|
|
2131
|
-
|
|
2141
|
+
onSocialLogin && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2142
|
+
/* @__PURE__ */ jsxs("div", { style: dividerStyle(tokens), children: [
|
|
2143
|
+
/* @__PURE__ */ jsx("div", { style: dividerLineStyle(tokens.border) }),
|
|
2144
|
+
/* @__PURE__ */ jsx("span", { children: "or continue with" }),
|
|
2145
|
+
/* @__PURE__ */ jsx("div", { style: dividerLineStyle(tokens.border) })
|
|
2146
|
+
] }),
|
|
2147
|
+
/* @__PURE__ */ jsx("div", { style: socialRowStyle, children: ["google", "apple", "twitter"].map((provider) => /* @__PURE__ */ jsx(
|
|
2148
|
+
"button",
|
|
2149
|
+
{
|
|
2150
|
+
type: "button",
|
|
2151
|
+
onClick: () => onSocialLogin(provider),
|
|
2152
|
+
style: socialButtonStyle(tokens),
|
|
2153
|
+
children: socialLabel(provider)
|
|
2154
|
+
},
|
|
2155
|
+
provider
|
|
2156
|
+
)) })
|
|
2157
|
+
] }),
|
|
2158
|
+
/* @__PURE__ */ jsxs("div", { style: walletSectionStyle, children: [
|
|
2159
|
+
/* @__PURE__ */ jsx("span", { style: walletLabelStyle(tokens.textMuted), children: "Works with" }),
|
|
2160
|
+
/* @__PURE__ */ jsx("div", { style: walletLogosStyle, children: walletIcons.map(({ key, emoji }) => /* @__PURE__ */ jsx("span", { style: walletEmojiStyle, children: emoji }, key)) })
|
|
2132
2161
|
] }),
|
|
2133
|
-
/* @__PURE__ */ jsx("div", { style: logosRowStyle, children: walletLogos.map((label) => /* @__PURE__ */ jsx("div", { style: logoCircleStyle(tokens), children: label }, label)) }),
|
|
2134
2162
|
/* @__PURE__ */ jsx(PoweredByFooter, {})
|
|
2135
2163
|
] }),
|
|
2136
2164
|
children: [
|
|
2137
|
-
/* @__PURE__ */ jsx(
|
|
2165
|
+
/* @__PURE__ */ jsx(
|
|
2166
|
+
ScreenHeader,
|
|
2167
|
+
{
|
|
2168
|
+
onBack,
|
|
2169
|
+
right: merchantInitials ? /* @__PURE__ */ jsx("div", { style: avatarStyle(tokens), children: merchantInitials }) : void 0
|
|
2170
|
+
}
|
|
2171
|
+
),
|
|
2138
2172
|
/* @__PURE__ */ jsxs("div", { style: contentStyle, children: [
|
|
2139
|
-
/* @__PURE__ */ jsx(
|
|
2140
|
-
"path",
|
|
2141
|
-
{
|
|
2142
|
-
d: "M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4z",
|
|
2143
|
-
fill: tokens.accent
|
|
2144
|
-
}
|
|
2145
|
-
) }) }),
|
|
2173
|
+
/* @__PURE__ */ jsx("div", { style: iconBoxStyle(tokens.accent), children: /* @__PURE__ */ jsx("span", { style: iconLetterStyle, children: "S" }) }),
|
|
2146
2174
|
/* @__PURE__ */ jsx("h2", { style: headingStyle(tokens.text), children: "One-time setup.\nOne-tap deposits after." }),
|
|
2147
2175
|
/* @__PURE__ */ jsx("p", { style: subtitleStyle(tokens.textSecondary), children: "Protected by Face ID." }),
|
|
2148
2176
|
error && /* @__PURE__ */ jsx("div", { style: errorStyle(tokens), children: error }),
|
|
@@ -2167,6 +2195,23 @@ function LoginScreen({
|
|
|
2167
2195
|
}
|
|
2168
2196
|
);
|
|
2169
2197
|
}
|
|
2198
|
+
var walletIcons = [
|
|
2199
|
+
{ key: "metamask", emoji: "\u{1F98A}" },
|
|
2200
|
+
{ key: "rabby", emoji: "\u{1F430}" },
|
|
2201
|
+
{ key: "phantom", emoji: "\u25C6" },
|
|
2202
|
+
{ key: "rainbow", emoji: "\u{1F439}" },
|
|
2203
|
+
{ key: "coinbase", emoji: "\u{1F535}" }
|
|
2204
|
+
];
|
|
2205
|
+
function socialLabel(provider) {
|
|
2206
|
+
switch (provider) {
|
|
2207
|
+
case "google":
|
|
2208
|
+
return "Google";
|
|
2209
|
+
case "apple":
|
|
2210
|
+
return "Apple";
|
|
2211
|
+
case "twitter":
|
|
2212
|
+
return "X";
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2170
2215
|
var contentStyle = {
|
|
2171
2216
|
textAlign: "center",
|
|
2172
2217
|
flex: 1,
|
|
@@ -2175,10 +2220,25 @@ var contentStyle = {
|
|
|
2175
2220
|
alignItems: "center",
|
|
2176
2221
|
paddingTop: 24
|
|
2177
2222
|
};
|
|
2223
|
+
var iconBoxStyle = (accent) => ({
|
|
2224
|
+
width: 56,
|
|
2225
|
+
height: 56,
|
|
2226
|
+
borderRadius: 16,
|
|
2227
|
+
background: accent,
|
|
2228
|
+
display: "flex",
|
|
2229
|
+
alignItems: "center",
|
|
2230
|
+
justifyContent: "center"
|
|
2231
|
+
});
|
|
2232
|
+
var iconLetterStyle = {
|
|
2233
|
+
color: "#fff",
|
|
2234
|
+
fontSize: "1.5rem",
|
|
2235
|
+
fontWeight: 700,
|
|
2236
|
+
lineHeight: 1
|
|
2237
|
+
};
|
|
2178
2238
|
var headingStyle = (color) => ({
|
|
2179
|
-
fontSize: "1.
|
|
2239
|
+
fontSize: "1.45rem",
|
|
2180
2240
|
fontWeight: 700,
|
|
2181
|
-
lineHeight: 1.
|
|
2241
|
+
lineHeight: 1.25,
|
|
2182
2242
|
letterSpacing: "-0.02em",
|
|
2183
2243
|
color,
|
|
2184
2244
|
margin: "20px 0 8px",
|
|
@@ -2227,24 +2287,55 @@ var dividerLineStyle = (color) => ({
|
|
|
2227
2287
|
height: 1,
|
|
2228
2288
|
background: color
|
|
2229
2289
|
});
|
|
2230
|
-
var
|
|
2290
|
+
var socialRowStyle = {
|
|
2291
|
+
display: "flex",
|
|
2292
|
+
gap: 10,
|
|
2293
|
+
marginBottom: 20
|
|
2294
|
+
};
|
|
2295
|
+
var socialButtonStyle = (tokens) => ({
|
|
2296
|
+
flex: 1,
|
|
2297
|
+
padding: "12px 0",
|
|
2298
|
+
borderRadius: 12,
|
|
2299
|
+
border: `1px solid ${tokens.border}`,
|
|
2300
|
+
background: "transparent",
|
|
2301
|
+
color: tokens.text,
|
|
2302
|
+
fontSize: "0.88rem",
|
|
2303
|
+
fontWeight: 600,
|
|
2304
|
+
fontFamily: "inherit",
|
|
2305
|
+
cursor: "pointer"
|
|
2306
|
+
});
|
|
2307
|
+
var walletSectionStyle = {
|
|
2308
|
+
textAlign: "center",
|
|
2309
|
+
marginBottom: 8,
|
|
2310
|
+
marginTop: 4
|
|
2311
|
+
};
|
|
2312
|
+
var walletLabelStyle = (color) => ({
|
|
2313
|
+
fontSize: "0.78rem",
|
|
2314
|
+
color,
|
|
2315
|
+
display: "block",
|
|
2316
|
+
marginBottom: 10
|
|
2317
|
+
});
|
|
2318
|
+
var walletLogosStyle = {
|
|
2231
2319
|
display: "flex",
|
|
2232
2320
|
justifyContent: "center",
|
|
2233
|
-
gap:
|
|
2234
|
-
marginBottom: 8
|
|
2321
|
+
gap: 16
|
|
2235
2322
|
};
|
|
2236
|
-
var
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2323
|
+
var walletEmojiStyle = {
|
|
2324
|
+
fontSize: "1.4rem",
|
|
2325
|
+
lineHeight: 1
|
|
2326
|
+
};
|
|
2327
|
+
var avatarStyle = (tokens) => ({
|
|
2328
|
+
width: 28,
|
|
2329
|
+
height: 28,
|
|
2330
|
+
borderRadius: "50%",
|
|
2240
2331
|
border: `1px solid ${tokens.border}`,
|
|
2241
|
-
background: tokens.bgInput,
|
|
2242
|
-
color: tokens.textMuted,
|
|
2243
2332
|
display: "flex",
|
|
2244
2333
|
alignItems: "center",
|
|
2245
2334
|
justifyContent: "center",
|
|
2246
|
-
fontSize: "0.
|
|
2247
|
-
fontWeight:
|
|
2335
|
+
fontSize: "0.6rem",
|
|
2336
|
+
fontWeight: 700,
|
|
2337
|
+
color: tokens.textMuted,
|
|
2338
|
+
background: "transparent"
|
|
2248
2339
|
});
|
|
2249
2340
|
var RESEND_COOLDOWN_SECONDS = 30;
|
|
2250
2341
|
function OtpVerifyScreen({
|
|
@@ -2896,7 +2987,7 @@ var swipeHintStyle = (color) => ({
|
|
|
2896
2987
|
color,
|
|
2897
2988
|
margin: "12px 0 0"
|
|
2898
2989
|
});
|
|
2899
|
-
var MIN_DEPOSIT =
|
|
2990
|
+
var MIN_DEPOSIT = 0.25;
|
|
2900
2991
|
function DepositScreen({
|
|
2901
2992
|
merchantName,
|
|
2902
2993
|
sourceName,
|
|
@@ -2917,8 +3008,7 @@ function DepositScreen({
|
|
|
2917
3008
|
onLogout
|
|
2918
3009
|
}) {
|
|
2919
3010
|
const { tokens } = useSwypeConfig();
|
|
2920
|
-
const
|
|
2921
|
-
const sliderMax = Math.min(remainingLimit, availableBalance, 500);
|
|
3011
|
+
const amount = initialAmount;
|
|
2922
3012
|
const isLowBalance = availableBalance < MIN_DEPOSIT;
|
|
2923
3013
|
const canDeposit = amount >= MIN_DEPOSIT && amount <= remainingLimit && !isLowBalance && !processing;
|
|
2924
3014
|
const headerTitle = merchantName ? `Deposit to ${merchantName}` : "Deposit";
|
|
@@ -3030,17 +3120,6 @@ function DepositScreen({
|
|
|
3030
3120
|
/* @__PURE__ */ jsx("span", { style: chevronStyle2, children: ">" })
|
|
3031
3121
|
] })
|
|
3032
3122
|
] }),
|
|
3033
|
-
/* @__PURE__ */ jsx(
|
|
3034
|
-
LimitSlider,
|
|
3035
|
-
{
|
|
3036
|
-
value: amount,
|
|
3037
|
-
min: MIN_DEPOSIT,
|
|
3038
|
-
max: sliderMax > MIN_DEPOSIT ? sliderMax : 20,
|
|
3039
|
-
step: 0.5,
|
|
3040
|
-
ticks: [MIN_DEPOSIT, 5, 10, 20].filter((t) => t <= sliderMax || t <= 20),
|
|
3041
|
-
onChange: setAmount
|
|
3042
|
-
}
|
|
3043
|
-
),
|
|
3044
3123
|
/* @__PURE__ */ jsxs("div", { style: detailsStyle, children: [
|
|
3045
3124
|
/* @__PURE__ */ jsxs("div", { style: detailRowStyle(tokens.textMuted), children: [
|
|
3046
3125
|
"Remaining limit: ",
|
|
@@ -3049,13 +3128,13 @@ function DepositScreen({
|
|
|
3049
3128
|
remainingLimit.toFixed(2)
|
|
3050
3129
|
] })
|
|
3051
3130
|
] }),
|
|
3052
|
-
estimatedFeeUsd != null && estimatedFeePct != null
|
|
3131
|
+
estimatedFeeUsd != null && estimatedFeePct != null ? /* @__PURE__ */ jsxs("div", { style: detailRowStyle(tokens.textMuted), children: [
|
|
3053
3132
|
"Fee: ~$",
|
|
3054
3133
|
estimatedFeeUsd.toFixed(2),
|
|
3055
3134
|
" (",
|
|
3056
3135
|
estimatedFeePct.toFixed(1),
|
|
3057
3136
|
"%)"
|
|
3058
|
-
] })
|
|
3137
|
+
] }) : /* @__PURE__ */ jsx("div", { style: detailRowStyle(tokens.textMuted), children: "Fees calculated at time of transfer" })
|
|
3059
3138
|
] }),
|
|
3060
3139
|
error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle5(tokens), children: error })
|
|
3061
3140
|
]
|
|
@@ -3165,14 +3244,45 @@ function SuccessScreen({
|
|
|
3165
3244
|
onDone,
|
|
3166
3245
|
onLogout,
|
|
3167
3246
|
onIncreaseLimits,
|
|
3168
|
-
onManageAccount
|
|
3247
|
+
onManageAccount,
|
|
3248
|
+
autoCloseSeconds
|
|
3169
3249
|
}) {
|
|
3170
3250
|
const { tokens } = useSwypeConfig();
|
|
3251
|
+
const [countdown, setCountdown] = useState(autoCloseSeconds ?? 0);
|
|
3252
|
+
const doneCalledRef = useRef(false);
|
|
3253
|
+
const handleDone = useCallback(() => {
|
|
3254
|
+
if (doneCalledRef.current) return;
|
|
3255
|
+
doneCalledRef.current = true;
|
|
3256
|
+
onDone();
|
|
3257
|
+
}, [onDone]);
|
|
3258
|
+
useEffect(() => {
|
|
3259
|
+
if (!autoCloseSeconds || autoCloseSeconds <= 0) return;
|
|
3260
|
+
const intervalId = window.setInterval(() => {
|
|
3261
|
+
setCountdown((prev) => {
|
|
3262
|
+
if (prev <= 1) {
|
|
3263
|
+
window.clearInterval(intervalId);
|
|
3264
|
+
return 0;
|
|
3265
|
+
}
|
|
3266
|
+
return prev - 1;
|
|
3267
|
+
});
|
|
3268
|
+
}, 1e3);
|
|
3269
|
+
return () => window.clearInterval(intervalId);
|
|
3270
|
+
}, [autoCloseSeconds]);
|
|
3271
|
+
useEffect(() => {
|
|
3272
|
+
if (autoCloseSeconds && countdown === 0) {
|
|
3273
|
+
handleDone();
|
|
3274
|
+
}
|
|
3275
|
+
}, [autoCloseSeconds, countdown, handleDone]);
|
|
3171
3276
|
return /* @__PURE__ */ jsxs(
|
|
3172
3277
|
ScreenLayout,
|
|
3173
3278
|
{
|
|
3174
3279
|
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3175
|
-
/* @__PURE__ */ jsx(PrimaryButton, { onClick:
|
|
3280
|
+
/* @__PURE__ */ jsx(PrimaryButton, { onClick: handleDone, children: "Done" }),
|
|
3281
|
+
autoCloseSeconds != null && autoCloseSeconds > 0 && /* @__PURE__ */ jsxs("p", { style: countdownStyle(tokens.textMuted), children: [
|
|
3282
|
+
"Returning to app in ",
|
|
3283
|
+
countdown,
|
|
3284
|
+
"s\u2026"
|
|
3285
|
+
] }),
|
|
3176
3286
|
onManageAccount && /* @__PURE__ */ jsx("button", { type: "button", onClick: onManageAccount, style: manageStyle(tokens.textMuted), children: "Manage Swype account \u2192" }),
|
|
3177
3287
|
/* @__PURE__ */ jsx(PoweredByFooter, {})
|
|
3178
3288
|
] }),
|
|
@@ -3296,6 +3406,12 @@ var upsellLinkStyle = (color) => ({
|
|
|
3296
3406
|
fontFamily: "inherit",
|
|
3297
3407
|
padding: 0
|
|
3298
3408
|
});
|
|
3409
|
+
var countdownStyle = (color) => ({
|
|
3410
|
+
fontSize: "0.82rem",
|
|
3411
|
+
color,
|
|
3412
|
+
margin: "10px 0 0",
|
|
3413
|
+
textAlign: "center"
|
|
3414
|
+
});
|
|
3299
3415
|
var manageStyle = (color) => ({
|
|
3300
3416
|
background: "transparent",
|
|
3301
3417
|
border: "none",
|
|
@@ -3309,6 +3425,233 @@ var manageStyle = (color) => ({
|
|
|
3309
3425
|
textAlign: "center",
|
|
3310
3426
|
padding: "12px 0 0"
|
|
3311
3427
|
});
|
|
3428
|
+
function SelectSourceScreen({
|
|
3429
|
+
choices,
|
|
3430
|
+
selectedChainName,
|
|
3431
|
+
selectedTokenSymbol,
|
|
3432
|
+
recommended,
|
|
3433
|
+
onChainChange,
|
|
3434
|
+
onTokenChange,
|
|
3435
|
+
onConfirm,
|
|
3436
|
+
onLogout
|
|
3437
|
+
}) {
|
|
3438
|
+
const { tokens } = useSwypeConfig();
|
|
3439
|
+
const selectedChain = choices.find((c) => c.chainName === selectedChainName) ?? choices[0];
|
|
3440
|
+
const tokenChoices = selectedChain?.tokens ?? [];
|
|
3441
|
+
const canConfirm = !!selectedChainName && !!selectedTokenSymbol;
|
|
3442
|
+
return /* @__PURE__ */ jsxs(
|
|
3443
|
+
ScreenLayout,
|
|
3444
|
+
{
|
|
3445
|
+
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3446
|
+
/* @__PURE__ */ jsx(PrimaryButton, { onClick: onConfirm, disabled: !canConfirm, children: "Confirm source" }),
|
|
3447
|
+
/* @__PURE__ */ jsx(PoweredByFooter, {})
|
|
3448
|
+
] }),
|
|
3449
|
+
children: [
|
|
3450
|
+
/* @__PURE__ */ jsx(
|
|
3451
|
+
ScreenHeader,
|
|
3452
|
+
{
|
|
3453
|
+
title: "Select Source",
|
|
3454
|
+
right: /* @__PURE__ */ jsx(SettingsMenu, { onLogout })
|
|
3455
|
+
}
|
|
3456
|
+
),
|
|
3457
|
+
/* @__PURE__ */ jsx("p", { style: subtitleStyle7(tokens.textMuted), children: "Choose which chain and token to pay from." }),
|
|
3458
|
+
/* @__PURE__ */ jsx("label", { style: labelStyle2(tokens.textSecondary), children: "Chain" }),
|
|
3459
|
+
/* @__PURE__ */ jsx("div", { style: optionListStyle, children: choices.map((chain) => {
|
|
3460
|
+
const isSelected = chain.chainName === selectedChainName;
|
|
3461
|
+
const isRecommended = chain.chainName === recommended?.chainName;
|
|
3462
|
+
return /* @__PURE__ */ jsxs(
|
|
3463
|
+
"button",
|
|
3464
|
+
{
|
|
3465
|
+
type: "button",
|
|
3466
|
+
onClick: () => onChainChange(chain.chainName),
|
|
3467
|
+
style: optionButtonStyle(tokens, isSelected),
|
|
3468
|
+
children: [
|
|
3469
|
+
/* @__PURE__ */ jsxs("div", { style: optionContentStyle, children: [
|
|
3470
|
+
/* @__PURE__ */ jsxs("span", { style: optionNameStyle(tokens.text), children: [
|
|
3471
|
+
chain.chainName,
|
|
3472
|
+
isRecommended && /* @__PURE__ */ jsx("span", { style: recommendedBadgeStyle(tokens.accent), children: " recommended" })
|
|
3473
|
+
] }),
|
|
3474
|
+
/* @__PURE__ */ jsxs("span", { style: optionBalanceStyle(tokens.textMuted), children: [
|
|
3475
|
+
"$",
|
|
3476
|
+
chain.balance.toFixed(2)
|
|
3477
|
+
] })
|
|
3478
|
+
] }),
|
|
3479
|
+
/* @__PURE__ */ jsx("div", { style: radioStyle(tokens, isSelected), children: isSelected && /* @__PURE__ */ jsx("div", { style: radioDotStyle(tokens.accent) }) })
|
|
3480
|
+
]
|
|
3481
|
+
},
|
|
3482
|
+
chain.chainName
|
|
3483
|
+
);
|
|
3484
|
+
}) }),
|
|
3485
|
+
tokenChoices.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3486
|
+
/* @__PURE__ */ jsx("label", { style: labelStyle2(tokens.textSecondary), children: "Token" }),
|
|
3487
|
+
/* @__PURE__ */ jsx("div", { style: optionListStyle, children: tokenChoices.map((token) => {
|
|
3488
|
+
const isSelected = token.tokenSymbol === selectedTokenSymbol;
|
|
3489
|
+
return /* @__PURE__ */ jsxs(
|
|
3490
|
+
"button",
|
|
3491
|
+
{
|
|
3492
|
+
type: "button",
|
|
3493
|
+
onClick: () => onTokenChange(token.tokenSymbol),
|
|
3494
|
+
style: optionButtonStyle(tokens, isSelected),
|
|
3495
|
+
children: [
|
|
3496
|
+
/* @__PURE__ */ jsxs("div", { style: optionContentStyle, children: [
|
|
3497
|
+
/* @__PURE__ */ jsx("span", { style: optionNameStyle(tokens.text), children: token.tokenSymbol }),
|
|
3498
|
+
/* @__PURE__ */ jsxs("span", { style: optionBalanceStyle(tokens.textMuted), children: [
|
|
3499
|
+
"$",
|
|
3500
|
+
token.balance.toFixed(2)
|
|
3501
|
+
] })
|
|
3502
|
+
] }),
|
|
3503
|
+
/* @__PURE__ */ jsx("div", { style: radioStyle(tokens, isSelected), children: isSelected && /* @__PURE__ */ jsx("div", { style: radioDotStyle(tokens.accent) }) })
|
|
3504
|
+
]
|
|
3505
|
+
},
|
|
3506
|
+
token.tokenSymbol
|
|
3507
|
+
);
|
|
3508
|
+
}) })
|
|
3509
|
+
] })
|
|
3510
|
+
]
|
|
3511
|
+
}
|
|
3512
|
+
);
|
|
3513
|
+
}
|
|
3514
|
+
var subtitleStyle7 = (color) => ({
|
|
3515
|
+
fontSize: "0.85rem",
|
|
3516
|
+
color,
|
|
3517
|
+
margin: "0 0 20px",
|
|
3518
|
+
lineHeight: 1.5
|
|
3519
|
+
});
|
|
3520
|
+
var labelStyle2 = (color) => ({
|
|
3521
|
+
display: "block",
|
|
3522
|
+
fontSize: "0.75rem",
|
|
3523
|
+
fontWeight: 600,
|
|
3524
|
+
color,
|
|
3525
|
+
textTransform: "uppercase",
|
|
3526
|
+
letterSpacing: "0.05em",
|
|
3527
|
+
marginBottom: 8
|
|
3528
|
+
});
|
|
3529
|
+
var optionListStyle = {
|
|
3530
|
+
display: "flex",
|
|
3531
|
+
flexDirection: "column",
|
|
3532
|
+
gap: 8,
|
|
3533
|
+
marginBottom: 20
|
|
3534
|
+
};
|
|
3535
|
+
var optionButtonStyle = (tokens, selected) => ({
|
|
3536
|
+
display: "flex",
|
|
3537
|
+
alignItems: "center",
|
|
3538
|
+
justifyContent: "space-between",
|
|
3539
|
+
padding: "14px 16px",
|
|
3540
|
+
background: tokens.bgInput,
|
|
3541
|
+
border: `1.5px solid ${selected ? tokens.accent : tokens.border}`,
|
|
3542
|
+
borderRadius: 14,
|
|
3543
|
+
cursor: "pointer",
|
|
3544
|
+
fontFamily: "inherit",
|
|
3545
|
+
textAlign: "left",
|
|
3546
|
+
transition: "border-color 0.15s ease"
|
|
3547
|
+
});
|
|
3548
|
+
var optionContentStyle = {
|
|
3549
|
+
display: "flex",
|
|
3550
|
+
flexDirection: "column",
|
|
3551
|
+
gap: 2
|
|
3552
|
+
};
|
|
3553
|
+
var optionNameStyle = (color) => ({
|
|
3554
|
+
fontSize: "0.9rem",
|
|
3555
|
+
fontWeight: 600,
|
|
3556
|
+
color
|
|
3557
|
+
});
|
|
3558
|
+
var recommendedBadgeStyle = (color) => ({
|
|
3559
|
+
fontSize: "0.7rem",
|
|
3560
|
+
fontWeight: 500,
|
|
3561
|
+
color,
|
|
3562
|
+
marginLeft: 6
|
|
3563
|
+
});
|
|
3564
|
+
var optionBalanceStyle = (color) => ({
|
|
3565
|
+
fontSize: "0.78rem",
|
|
3566
|
+
color
|
|
3567
|
+
});
|
|
3568
|
+
var radioStyle = (tokens, selected) => ({
|
|
3569
|
+
width: 20,
|
|
3570
|
+
height: 20,
|
|
3571
|
+
borderRadius: "50%",
|
|
3572
|
+
border: `2px solid ${selected ? tokens.accent : tokens.border}`,
|
|
3573
|
+
display: "flex",
|
|
3574
|
+
alignItems: "center",
|
|
3575
|
+
justifyContent: "center",
|
|
3576
|
+
flexShrink: 0
|
|
3577
|
+
});
|
|
3578
|
+
var radioDotStyle = (color) => ({
|
|
3579
|
+
width: 10,
|
|
3580
|
+
height: 10,
|
|
3581
|
+
borderRadius: "50%",
|
|
3582
|
+
background: color
|
|
3583
|
+
});
|
|
3584
|
+
var STEP_LABELS = ["Creating transfer", "Verifying", "Sent", "Done"];
|
|
3585
|
+
var PHASE_ACTIVE_INDEX = {
|
|
3586
|
+
creating: 0,
|
|
3587
|
+
verifying: 1,
|
|
3588
|
+
sent: 2,
|
|
3589
|
+
done: 4
|
|
3590
|
+
};
|
|
3591
|
+
function buildSteps(phase) {
|
|
3592
|
+
const activeIdx = PHASE_ACTIVE_INDEX[phase];
|
|
3593
|
+
return STEP_LABELS.map((label, i) => ({
|
|
3594
|
+
label,
|
|
3595
|
+
status: i < activeIdx ? "complete" : i === activeIdx ? "active" : "pending"
|
|
3596
|
+
}));
|
|
3597
|
+
}
|
|
3598
|
+
function TransferStatusScreen({
|
|
3599
|
+
phase,
|
|
3600
|
+
error,
|
|
3601
|
+
onLogout
|
|
3602
|
+
}) {
|
|
3603
|
+
const { tokens } = useSwypeConfig();
|
|
3604
|
+
const steps = buildSteps(phase);
|
|
3605
|
+
return /* @__PURE__ */ jsxs(ScreenLayout, { children: [
|
|
3606
|
+
/* @__PURE__ */ jsx(ScreenHeader, { right: /* @__PURE__ */ jsx(SettingsMenu, { onLogout }) }),
|
|
3607
|
+
/* @__PURE__ */ jsxs("div", { style: contentStyle6, children: [
|
|
3608
|
+
/* @__PURE__ */ jsx(Spinner, { size: 48 }),
|
|
3609
|
+
/* @__PURE__ */ jsx("h2", { style: headingStyle8(tokens.text), children: "Processing Transfer..." }),
|
|
3610
|
+
error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle6(tokens), children: error }),
|
|
3611
|
+
/* @__PURE__ */ jsx("div", { style: stepsWrapStyle2, children: /* @__PURE__ */ jsx(StepList, { steps }) }),
|
|
3612
|
+
/* @__PURE__ */ jsx("p", { style: waitHintStyle2(tokens.textMuted), children: "Usually takes a few seconds" })
|
|
3613
|
+
] })
|
|
3614
|
+
] });
|
|
3615
|
+
}
|
|
3616
|
+
var contentStyle6 = {
|
|
3617
|
+
flex: 1,
|
|
3618
|
+
display: "flex",
|
|
3619
|
+
flexDirection: "column",
|
|
3620
|
+
alignItems: "center",
|
|
3621
|
+
justifyContent: "center",
|
|
3622
|
+
textAlign: "center",
|
|
3623
|
+
padding: "0 24px"
|
|
3624
|
+
};
|
|
3625
|
+
var headingStyle8 = (color) => ({
|
|
3626
|
+
fontSize: "1.45rem",
|
|
3627
|
+
fontWeight: 700,
|
|
3628
|
+
letterSpacing: "-0.02em",
|
|
3629
|
+
color,
|
|
3630
|
+
margin: "20px 0 16px"
|
|
3631
|
+
});
|
|
3632
|
+
var errorBannerStyle6 = (tokens) => ({
|
|
3633
|
+
background: tokens.errorBg,
|
|
3634
|
+
border: `1px solid ${tokens.error}66`,
|
|
3635
|
+
borderRadius: 16,
|
|
3636
|
+
padding: "11px 14px",
|
|
3637
|
+
color: tokens.error,
|
|
3638
|
+
fontSize: "0.84rem",
|
|
3639
|
+
marginBottom: 14,
|
|
3640
|
+
lineHeight: 1.5,
|
|
3641
|
+
width: "100%",
|
|
3642
|
+
textAlign: "left"
|
|
3643
|
+
});
|
|
3644
|
+
var stepsWrapStyle2 = {
|
|
3645
|
+
width: "100%",
|
|
3646
|
+
maxWidth: 280,
|
|
3647
|
+
textAlign: "left",
|
|
3648
|
+
marginBottom: 16
|
|
3649
|
+
};
|
|
3650
|
+
var waitHintStyle2 = (color) => ({
|
|
3651
|
+
fontSize: "0.82rem",
|
|
3652
|
+
color,
|
|
3653
|
+
margin: 0
|
|
3654
|
+
});
|
|
3312
3655
|
var ACTIVE_CREDENTIAL_STORAGE_KEY = "swype_active_credential_id";
|
|
3313
3656
|
var MIN_SEND_AMOUNT_USD = 0.25;
|
|
3314
3657
|
function computeSmartDefaults(accts, transferAmount) {
|
|
@@ -3387,7 +3730,9 @@ function SwypePayment({
|
|
|
3387
3730
|
idempotencyKey,
|
|
3388
3731
|
merchantAuthorization,
|
|
3389
3732
|
merchantName,
|
|
3390
|
-
onBack
|
|
3733
|
+
onBack,
|
|
3734
|
+
onDismiss,
|
|
3735
|
+
autoCloseSeconds
|
|
3391
3736
|
}) {
|
|
3392
3737
|
const { apiBaseUrl, tokens, depositAmount } = useSwypeConfig();
|
|
3393
3738
|
const { ready, authenticated, user, logout, getAccessToken } = usePrivy();
|
|
@@ -3401,6 +3746,7 @@ function SwypePayment({
|
|
|
3401
3746
|
loginWithCode: loginWithSmsCode,
|
|
3402
3747
|
state: smsLoginState
|
|
3403
3748
|
} = useLoginWithSms();
|
|
3749
|
+
const { initOAuth } = useLoginWithOAuth();
|
|
3404
3750
|
const [step, setStep] = useState("login");
|
|
3405
3751
|
const [error, setError] = useState(null);
|
|
3406
3752
|
const [providers, setProviders] = useState([]);
|
|
@@ -3449,6 +3795,14 @@ function SwypePayment({
|
|
|
3449
3795
|
setVerificationTarget(null);
|
|
3450
3796
|
setOtpCode("");
|
|
3451
3797
|
}, []);
|
|
3798
|
+
const handleSocialLogin = useCallback(async (provider) => {
|
|
3799
|
+
setError(null);
|
|
3800
|
+
try {
|
|
3801
|
+
await initOAuth({ provider });
|
|
3802
|
+
} catch (err) {
|
|
3803
|
+
setError(err instanceof Error ? err.message : "Social login failed");
|
|
3804
|
+
}
|
|
3805
|
+
}, [initOAuth]);
|
|
3452
3806
|
const activeOtpStatus = verificationTarget?.kind === "email" ? emailLoginState.status : verificationTarget?.kind === "phone" ? smsLoginState.status : "initial";
|
|
3453
3807
|
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;
|
|
3454
3808
|
useEffect(() => {
|
|
@@ -3517,6 +3871,9 @@ function SwypePayment({
|
|
|
3517
3871
|
if (!token || cancelled) return;
|
|
3518
3872
|
const { config } = await fetchUserConfig(apiBaseUrl, token);
|
|
3519
3873
|
if (cancelled) return;
|
|
3874
|
+
if (config.defaultAllowance != null) {
|
|
3875
|
+
setOneTapLimit(config.defaultAllowance);
|
|
3876
|
+
}
|
|
3520
3877
|
const allPasskeys = config.passkeys ?? (config.passkey ? [config.passkey] : []);
|
|
3521
3878
|
if (allPasskeys.length === 0) {
|
|
3522
3879
|
setStep("create-passkey");
|
|
@@ -3701,6 +4058,26 @@ function SwypePayment({
|
|
|
3701
4058
|
}
|
|
3702
4059
|
initializedSelectSourceActionRef.current = pendingSelectSourceAction.id;
|
|
3703
4060
|
}, [pendingSelectSourceAction, selectSourceChoices, selectSourceRecommended]);
|
|
4061
|
+
useEffect(() => {
|
|
4062
|
+
if (pendingSelectSourceAction && step === "processing") {
|
|
4063
|
+
setStep("select-source");
|
|
4064
|
+
} else if (!pendingSelectSourceAction && step === "select-source") {
|
|
4065
|
+
setStep("processing");
|
|
4066
|
+
}
|
|
4067
|
+
}, [pendingSelectSourceAction, step]);
|
|
4068
|
+
const handleSelectSourceChainChange = useCallback(
|
|
4069
|
+
(chainName) => {
|
|
4070
|
+
setSelectSourceChainName(chainName);
|
|
4071
|
+
const chain = selectSourceChoices.find((c) => c.chainName === chainName);
|
|
4072
|
+
if (!chain || chain.tokens.length === 0) return;
|
|
4073
|
+
const recommendedToken = selectSourceRecommended?.chainName === chainName ? selectSourceRecommended.tokenSymbol : null;
|
|
4074
|
+
const hasRecommended = !!recommendedToken && chain.tokens.some((t) => t.tokenSymbol === recommendedToken);
|
|
4075
|
+
setSelectSourceTokenSymbol(
|
|
4076
|
+
hasRecommended ? recommendedToken : chain.tokens[0].tokenSymbol
|
|
4077
|
+
);
|
|
4078
|
+
},
|
|
4079
|
+
[selectSourceChoices, selectSourceRecommended]
|
|
4080
|
+
);
|
|
3704
4081
|
const selectedAccount = accounts.find((a) => a.id === selectedAccountId);
|
|
3705
4082
|
const selectedWallet = selectedAccount?.wallets.find((w) => w.id === selectedWalletId);
|
|
3706
4083
|
const sourceName = selectedAccount?.name ?? selectedWallet?.chain.name ?? "Wallet";
|
|
@@ -3876,6 +4253,7 @@ function SwypePayment({
|
|
|
3876
4253
|
}
|
|
3877
4254
|
const setupAmount = depositAmount ?? MIN_SEND_AMOUNT_USD;
|
|
3878
4255
|
const t = await createTransfer(apiBaseUrl, token, {
|
|
4256
|
+
id: idempotencyKey,
|
|
3879
4257
|
credentialId: activeCredentialId ?? "",
|
|
3880
4258
|
merchantAuthorization,
|
|
3881
4259
|
sourceType,
|
|
@@ -3904,6 +4282,7 @@ function SwypePayment({
|
|
|
3904
4282
|
}
|
|
3905
4283
|
}, [
|
|
3906
4284
|
getAccessToken,
|
|
4285
|
+
idempotencyKey,
|
|
3907
4286
|
sourceId,
|
|
3908
4287
|
sourceType,
|
|
3909
4288
|
activeCredentialId,
|
|
@@ -3974,7 +4353,9 @@ function SwypePayment({
|
|
|
3974
4353
|
onSubmit: handleSendLoginCode,
|
|
3975
4354
|
sending: activeOtpStatus === "sending-code",
|
|
3976
4355
|
error,
|
|
3977
|
-
onBack
|
|
4356
|
+
onBack,
|
|
4357
|
+
merchantInitials: merchantName ? merchantName.slice(0, 2).toUpperCase() : void 0,
|
|
4358
|
+
onSocialLogin: handleSocialLogin
|
|
3978
4359
|
}
|
|
3979
4360
|
);
|
|
3980
4361
|
}
|
|
@@ -4001,6 +4382,9 @@ function SwypePayment({
|
|
|
4001
4382
|
}
|
|
4002
4383
|
);
|
|
4003
4384
|
}
|
|
4385
|
+
if ((step === "login" || step === "otp-verify") && authenticated) {
|
|
4386
|
+
return /* @__PURE__ */ jsx(ScreenLayout, { children: /* @__PURE__ */ jsx("div", { style: { textAlign: "center", padding: "48px 0", flex: 1, display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx(Spinner, { label: "Verifying your passkey..." }) }) });
|
|
4387
|
+
}
|
|
4004
4388
|
if (step === "create-passkey") {
|
|
4005
4389
|
return /* @__PURE__ */ jsx(
|
|
4006
4390
|
CreatePasskeyScreen,
|
|
@@ -4066,11 +4450,9 @@ function SwypePayment({
|
|
|
4066
4450
|
sourceAddress,
|
|
4067
4451
|
sourceVerified,
|
|
4068
4452
|
availableBalance: maxSourceBalance,
|
|
4069
|
-
remainingLimit: oneTapLimit,
|
|
4453
|
+
remainingLimit: selectedAccount?.remainingAllowance ?? oneTapLimit,
|
|
4070
4454
|
tokenCount,
|
|
4071
4455
|
initialAmount: parsedAmt,
|
|
4072
|
-
estimatedFeePct: 0.6,
|
|
4073
|
-
estimatedFeeUsd: parsedAmt * 6e-3,
|
|
4074
4456
|
processing: creatingTransfer,
|
|
4075
4457
|
error,
|
|
4076
4458
|
onDeposit: handlePay,
|
|
@@ -4082,24 +4464,36 @@ function SwypePayment({
|
|
|
4082
4464
|
);
|
|
4083
4465
|
}
|
|
4084
4466
|
if (step === "processing") {
|
|
4085
|
-
const
|
|
4086
|
-
const
|
|
4087
|
-
return /* @__PURE__ */ jsx(
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4467
|
+
const polledStatus = polling.transfer?.status;
|
|
4468
|
+
const transferPhase = creatingTransfer ? "creating" : mobileFlow || authExecutor.executing || transferSigning.signing ? "verifying" : polledStatus === "SENDING" || polledStatus === "SENT" || polling.isPolling ? "sent" : "creating";
|
|
4469
|
+
return /* @__PURE__ */ jsx(
|
|
4470
|
+
TransferStatusScreen,
|
|
4471
|
+
{
|
|
4472
|
+
phase: transferPhase,
|
|
4473
|
+
error: error || authExecutor.error || transferSigning.error || polling.error,
|
|
4474
|
+
onLogout: handleLogout
|
|
4475
|
+
}
|
|
4476
|
+
);
|
|
4477
|
+
}
|
|
4478
|
+
if (step === "select-source") {
|
|
4479
|
+
return /* @__PURE__ */ jsx(
|
|
4480
|
+
SelectSourceScreen,
|
|
4481
|
+
{
|
|
4482
|
+
choices: selectSourceChoices,
|
|
4483
|
+
selectedChainName: selectSourceChainName,
|
|
4484
|
+
selectedTokenSymbol: selectSourceTokenSymbol,
|
|
4485
|
+
recommended: selectSourceRecommended,
|
|
4486
|
+
onChainChange: handleSelectSourceChainChange,
|
|
4487
|
+
onTokenChange: setSelectSourceTokenSymbol,
|
|
4488
|
+
onConfirm: () => {
|
|
4489
|
+
authExecutor.resolveSelectSource({
|
|
4490
|
+
chainName: selectSourceChainName,
|
|
4491
|
+
tokenSymbol: selectSourceTokenSymbol
|
|
4492
|
+
});
|
|
4493
|
+
},
|
|
4494
|
+
onLogout: handleLogout
|
|
4495
|
+
}
|
|
4496
|
+
);
|
|
4103
4497
|
}
|
|
4104
4498
|
if (step === "success") {
|
|
4105
4499
|
transfer?.status === "COMPLETED";
|
|
@@ -4112,9 +4506,13 @@ function SwypePayment({
|
|
|
4112
4506
|
currency: displayCurrency,
|
|
4113
4507
|
merchantName,
|
|
4114
4508
|
sourceName,
|
|
4115
|
-
remainingLimit:
|
|
4116
|
-
|
|
4117
|
-
|
|
4509
|
+
remainingLimit: (() => {
|
|
4510
|
+
const limit = selectedAccount?.remainingAllowance ?? oneTapLimit;
|
|
4511
|
+
return limit > displayAmount ? limit - displayAmount : 0;
|
|
4512
|
+
})(),
|
|
4513
|
+
onDone: onDismiss ?? handleNewPayment,
|
|
4514
|
+
onLogout: handleLogout,
|
|
4515
|
+
autoCloseSeconds
|
|
4118
4516
|
}
|
|
4119
4517
|
);
|
|
4120
4518
|
}
|
|
@@ -4127,7 +4525,7 @@ function SwypePayment({
|
|
|
4127
4525
|
sourceAddress,
|
|
4128
4526
|
sourceVerified,
|
|
4129
4527
|
availableBalance: 0,
|
|
4130
|
-
remainingLimit: oneTapLimit,
|
|
4528
|
+
remainingLimit: selectedAccount?.remainingAllowance ?? oneTapLimit,
|
|
4131
4529
|
tokenCount,
|
|
4132
4530
|
initialAmount: depositAmount ?? 5,
|
|
4133
4531
|
processing: false,
|