@swype-org/react-sdk 0.1.33 → 0.1.35

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.d.cts CHANGED
@@ -50,6 +50,8 @@ interface Account {
50
50
  id: string;
51
51
  name: string;
52
52
  wallets: Wallet[];
53
+ /** Remaining One-Tap allowance in USD, or null when not configured. */
54
+ remainingAllowance?: number | null;
53
55
  createDate: string;
54
56
  updateDate: string;
55
57
  authorizationSessions?: AuthorizationSession[];
@@ -195,7 +197,7 @@ interface UserConfig {
195
197
  /** Theme mode */
196
198
  type ThemeMode = 'light' | 'dark';
197
199
  /** Steps in the payment flow */
198
- type PaymentStep = 'login' | 'otp-verify' | 'create-passkey' | 'wallet-picker' | 'setup' | 'setup-status' | 'deposit' | 'low-balance' | 'processing' | 'success';
200
+ type PaymentStep = 'login' | 'otp-verify' | 'create-passkey' | 'wallet-picker' | 'setup' | 'setup-status' | 'deposit' | 'low-balance' | 'processing' | 'select-source' | 'success';
199
201
  /** User-selected advanced settings for chain/asset override */
200
202
  interface AdvancedSettings {
201
203
  /** Override asset (e.g. 'USDC', 'USDT'). Null = let backend decide. */
@@ -369,8 +371,12 @@ interface SwypePaymentProps {
369
371
  merchantName?: string;
370
372
  /** Called when the user taps the back button */
371
373
  onBack?: () => void;
374
+ /** Called when the user dismisses the success screen (tap Done or countdown expires). When set, overrides the default "start new payment" behavior. */
375
+ onDismiss?: () => void;
376
+ /** Seconds to count down on the success screen before auto-dismissing. */
377
+ autoCloseSeconds?: number;
372
378
  }
373
- declare function SwypePayment({ destination, onComplete, onError, useWalletConnector, idempotencyKey, merchantAuthorization, merchantName, onBack, }: SwypePaymentProps): react_jsx_runtime.JSX.Element | null;
379
+ declare function SwypePayment({ destination, onComplete, onError, useWalletConnector, idempotencyKey, merchantAuthorization, merchantName, onBack, onDismiss, autoCloseSeconds, }: SwypePaymentProps): react_jsx_runtime.JSX.Element | null;
374
380
 
375
381
  type AccessTokenGetter = () => Promise<string | null | undefined>;
376
382
  /**
package/dist/index.d.ts CHANGED
@@ -50,6 +50,8 @@ interface Account {
50
50
  id: string;
51
51
  name: string;
52
52
  wallets: Wallet[];
53
+ /** Remaining One-Tap allowance in USD, or null when not configured. */
54
+ remainingAllowance?: number | null;
53
55
  createDate: string;
54
56
  updateDate: string;
55
57
  authorizationSessions?: AuthorizationSession[];
@@ -195,7 +197,7 @@ interface UserConfig {
195
197
  /** Theme mode */
196
198
  type ThemeMode = 'light' | 'dark';
197
199
  /** Steps in the payment flow */
198
- type PaymentStep = 'login' | 'otp-verify' | 'create-passkey' | 'wallet-picker' | 'setup' | 'setup-status' | 'deposit' | 'low-balance' | 'processing' | 'success';
200
+ type PaymentStep = 'login' | 'otp-verify' | 'create-passkey' | 'wallet-picker' | 'setup' | 'setup-status' | 'deposit' | 'low-balance' | 'processing' | 'select-source' | 'success';
199
201
  /** User-selected advanced settings for chain/asset override */
200
202
  interface AdvancedSettings {
201
203
  /** Override asset (e.g. 'USDC', 'USDT'). Null = let backend decide. */
@@ -369,8 +371,12 @@ interface SwypePaymentProps {
369
371
  merchantName?: string;
370
372
  /** Called when the user taps the back button */
371
373
  onBack?: () => void;
374
+ /** Called when the user dismisses the success screen (tap Done or countdown expires). When set, overrides the default "start new payment" behavior. */
375
+ onDismiss?: () => void;
376
+ /** Seconds to count down on the success screen before auto-dismissing. */
377
+ autoCloseSeconds?: number;
372
378
  }
373
- declare function SwypePayment({ destination, onComplete, onError, useWalletConnector, idempotencyKey, merchantAuthorization, merchantName, onBack, }: SwypePaymentProps): react_jsx_runtime.JSX.Element | null;
379
+ declare function SwypePayment({ destination, onComplete, onError, useWalletConnector, idempotencyKey, merchantAuthorization, merchantName, onBack, onDismiss, autoCloseSeconds, }: SwypePaymentProps): react_jsx_runtime.JSX.Element | null;
374
380
 
375
381
  type AccessTokenGetter = () => Promise<string | null | undefined>;
376
382
  /**
package/dist/index.js CHANGED
@@ -1724,7 +1724,7 @@ var circleStyle = (bg, size) => ({
1724
1724
  function OtpInput({ value, onChange, length = 6, disabled }) {
1725
1725
  const { tokens } = useSwypeConfig();
1726
1726
  const inputsRef = useRef([]);
1727
- const digits = value.padEnd(length, "").split("").slice(0, length);
1727
+ const digits = value.padEnd(length).split("").slice(0, length);
1728
1728
  const focusInput = useCallback((index) => {
1729
1729
  const clamped = Math.max(0, Math.min(index, length - 1));
1730
1730
  inputsRef.current[clamped]?.focus();
@@ -3008,8 +3008,7 @@ function DepositScreen({
3008
3008
  onLogout
3009
3009
  }) {
3010
3010
  const { tokens } = useSwypeConfig();
3011
- const [amount, setAmount] = useState(initialAmount);
3012
- const sliderMax = Math.min(remainingLimit, availableBalance, 500);
3011
+ const amount = initialAmount;
3013
3012
  const isLowBalance = availableBalance < MIN_DEPOSIT;
3014
3013
  const canDeposit = amount >= MIN_DEPOSIT && amount <= remainingLimit && !isLowBalance && !processing;
3015
3014
  const headerTitle = merchantName ? `Deposit to ${merchantName}` : "Deposit";
@@ -3121,17 +3120,6 @@ function DepositScreen({
3121
3120
  /* @__PURE__ */ jsx("span", { style: chevronStyle2, children: ">" })
3122
3121
  ] })
3123
3122
  ] }),
3124
- /* @__PURE__ */ jsx(
3125
- LimitSlider,
3126
- {
3127
- value: amount,
3128
- min: MIN_DEPOSIT,
3129
- max: sliderMax > MIN_DEPOSIT ? sliderMax : 20,
3130
- step: 0.5,
3131
- ticks: [MIN_DEPOSIT, 1, 5, 10, 20].filter((t) => t <= sliderMax || t <= 20),
3132
- onChange: setAmount
3133
- }
3134
- ),
3135
3123
  /* @__PURE__ */ jsxs("div", { style: detailsStyle, children: [
3136
3124
  /* @__PURE__ */ jsxs("div", { style: detailRowStyle(tokens.textMuted), children: [
3137
3125
  "Remaining limit: ",
@@ -3256,14 +3244,45 @@ function SuccessScreen({
3256
3244
  onDone,
3257
3245
  onLogout,
3258
3246
  onIncreaseLimits,
3259
- onManageAccount
3247
+ onManageAccount,
3248
+ autoCloseSeconds
3260
3249
  }) {
3261
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]);
3262
3276
  return /* @__PURE__ */ jsxs(
3263
3277
  ScreenLayout,
3264
3278
  {
3265
3279
  footer: /* @__PURE__ */ jsxs(Fragment, { children: [
3266
- /* @__PURE__ */ jsx(PrimaryButton, { onClick: onDone, children: "Done" }),
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
+ ] }),
3267
3286
  onManageAccount && /* @__PURE__ */ jsx("button", { type: "button", onClick: onManageAccount, style: manageStyle(tokens.textMuted), children: "Manage Swype account \u2192" }),
3268
3287
  /* @__PURE__ */ jsx(PoweredByFooter, {})
3269
3288
  ] }),
@@ -3387,6 +3406,12 @@ var upsellLinkStyle = (color) => ({
3387
3406
  fontFamily: "inherit",
3388
3407
  padding: 0
3389
3408
  });
3409
+ var countdownStyle = (color) => ({
3410
+ fontSize: "0.82rem",
3411
+ color,
3412
+ margin: "10px 0 0",
3413
+ textAlign: "center"
3414
+ });
3390
3415
  var manageStyle = (color) => ({
3391
3416
  background: "transparent",
3392
3417
  border: "none",
@@ -3400,6 +3425,233 @@ var manageStyle = (color) => ({
3400
3425
  textAlign: "center",
3401
3426
  padding: "12px 0 0"
3402
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
+ });
3403
3655
  var ACTIVE_CREDENTIAL_STORAGE_KEY = "swype_active_credential_id";
3404
3656
  var MIN_SEND_AMOUNT_USD = 0.25;
3405
3657
  function computeSmartDefaults(accts, transferAmount) {
@@ -3478,7 +3730,9 @@ function SwypePayment({
3478
3730
  idempotencyKey,
3479
3731
  merchantAuthorization,
3480
3732
  merchantName,
3481
- onBack
3733
+ onBack,
3734
+ onDismiss,
3735
+ autoCloseSeconds
3482
3736
  }) {
3483
3737
  const { apiBaseUrl, tokens, depositAmount } = useSwypeConfig();
3484
3738
  const { ready, authenticated, user, logout, getAccessToken } = usePrivy();
@@ -3526,6 +3780,7 @@ function SwypePayment({
3526
3780
  const [selectSourceChainName, setSelectSourceChainName] = useState("");
3527
3781
  const [selectSourceTokenSymbol, setSelectSourceTokenSymbol] = useState("");
3528
3782
  const initializedSelectSourceActionRef = useRef(null);
3783
+ const preSelectSourceStepRef = useRef(null);
3529
3784
  const authExecutor = useAuthorizationExecutor();
3530
3785
  const polling = useTransferPolling();
3531
3786
  const transferSigning = useTransferSigning();
@@ -3541,7 +3796,7 @@ function SwypePayment({
3541
3796
  setVerificationTarget(null);
3542
3797
  setOtpCode("");
3543
3798
  }, []);
3544
- const handleSocialLogin = useCallback(async (provider) => {
3799
+ useCallback(async (provider) => {
3545
3800
  setError(null);
3546
3801
  try {
3547
3802
  await initOAuth({ provider });
@@ -3804,6 +4059,44 @@ function SwypePayment({
3804
4059
  }
3805
4060
  initializedSelectSourceActionRef.current = pendingSelectSourceAction.id;
3806
4061
  }, [pendingSelectSourceAction, selectSourceChoices, selectSourceRecommended]);
4062
+ useEffect(() => {
4063
+ if (pendingSelectSourceAction && (step === "processing" || step === "setup-status")) {
4064
+ preSelectSourceStepRef.current = step;
4065
+ setStep("select-source");
4066
+ } else if (!pendingSelectSourceAction && step === "select-source") {
4067
+ setStep(preSelectSourceStepRef.current ?? "processing");
4068
+ preSelectSourceStepRef.current = null;
4069
+ }
4070
+ }, [pendingSelectSourceAction, step]);
4071
+ const SETUP_ACTION_LABELS = useMemo(() => ({
4072
+ OPEN_PROVIDER: "Connecting wallet",
4073
+ SELECT_SOURCE: "Selecting source",
4074
+ SWITCH_CHAIN: "Switching network",
4075
+ APPROVE_PERMIT2: "Approving tokens",
4076
+ SIGN_PERMIT2: "Signing permit",
4077
+ DEPLOY_SMART_ACCOUNT: "Setting up account",
4078
+ CREATE_SMART_ACCOUNT: "Creating account"
4079
+ }), []);
4080
+ useEffect(() => {
4081
+ if (step !== "setup-status") return;
4082
+ const actionType = authExecutor.currentAction?.type;
4083
+ if (!actionType) return;
4084
+ const label = SETUP_ACTION_LABELS[actionType];
4085
+ if (label) setSetupStepLabel(label);
4086
+ }, [step, authExecutor.currentAction, SETUP_ACTION_LABELS]);
4087
+ const handleSelectSourceChainChange = useCallback(
4088
+ (chainName) => {
4089
+ setSelectSourceChainName(chainName);
4090
+ const chain = selectSourceChoices.find((c) => c.chainName === chainName);
4091
+ if (!chain || chain.tokens.length === 0) return;
4092
+ const recommendedToken = selectSourceRecommended?.chainName === chainName ? selectSourceRecommended.tokenSymbol : null;
4093
+ const hasRecommended = !!recommendedToken && chain.tokens.some((t) => t.tokenSymbol === recommendedToken);
4094
+ setSelectSourceTokenSymbol(
4095
+ hasRecommended ? recommendedToken : chain.tokens[0].tokenSymbol
4096
+ );
4097
+ },
4098
+ [selectSourceChoices, selectSourceRecommended]
4099
+ );
3807
4100
  const selectedAccount = accounts.find((a) => a.id === selectedAccountId);
3808
4101
  const selectedWallet = selectedAccount?.wallets.find((w) => w.id === selectedWalletId);
3809
4102
  const sourceName = selectedAccount?.name ?? selectedWallet?.chain.name ?? "Wallet";
@@ -3969,7 +4262,7 @@ function SwypePayment({
3969
4262
  setOneTapLimit(limit);
3970
4263
  setStep("setup-status");
3971
4264
  setSetupComplete(false);
3972
- setSetupStepLabel("Approving tokens");
4265
+ setSetupStepLabel("Preparing");
3973
4266
  setError(null);
3974
4267
  try {
3975
4268
  const token = await getAccessToken();
@@ -4080,8 +4373,7 @@ function SwypePayment({
4080
4373
  sending: activeOtpStatus === "sending-code",
4081
4374
  error,
4082
4375
  onBack,
4083
- merchantInitials: merchantName ? merchantName.slice(0, 2).toUpperCase() : void 0,
4084
- onSocialLogin: handleSocialLogin
4376
+ merchantInitials: merchantName ? merchantName.slice(0, 2).toUpperCase() : void 0
4085
4377
  }
4086
4378
  );
4087
4379
  }
@@ -4108,6 +4400,9 @@ function SwypePayment({
4108
4400
  }
4109
4401
  );
4110
4402
  }
4403
+ if ((step === "login" || step === "otp-verify") && authenticated) {
4404
+ 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..." }) }) });
4405
+ }
4111
4406
  if (step === "create-passkey") {
4112
4407
  return /* @__PURE__ */ jsx(
4113
4408
  CreatePasskeyScreen,
@@ -4173,7 +4468,7 @@ function SwypePayment({
4173
4468
  sourceAddress,
4174
4469
  sourceVerified,
4175
4470
  availableBalance: maxSourceBalance,
4176
- remainingLimit: oneTapLimit,
4471
+ remainingLimit: selectedAccount?.remainingAllowance ?? oneTapLimit,
4177
4472
  tokenCount,
4178
4473
  initialAmount: parsedAmt,
4179
4474
  processing: creatingTransfer,
@@ -4187,25 +4482,36 @@ function SwypePayment({
4187
4482
  );
4188
4483
  }
4189
4484
  if (step === "processing") {
4190
- const currentActionType = authExecutor.currentAction?.type;
4191
4485
  const polledStatus = polling.transfer?.status;
4192
- const statusLabel = creatingTransfer ? "Creating Transfer" : mobileFlow ? "Waiting for Authorization" : authExecutor.executing ? currentActionType?.replace(/_/g, " ") ?? "Authorizing" : transferSigning.signing ? "Sending transfer" : polledStatus === "SENDING" ? "Sending transfer..." : polledStatus === "SENT" ? "Confirming delivery..." : polling.isPolling ? "Transfer Sent" : "Please wait...";
4193
- return /* @__PURE__ */ jsx(ScreenLayout, { children: /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "48px 0", flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }, children: [
4194
- /* @__PURE__ */ jsx(Spinner, { size: 48 }),
4195
- /* @__PURE__ */ jsx("h2", { style: { fontSize: "1.4rem", fontWeight: 700, color: tokens.text, marginTop: 20, marginBottom: 8 }, children: statusLabel }),
4196
- (error || authExecutor.error || transferSigning.error || polling.error) && /* @__PURE__ */ jsx("div", { style: {
4197
- background: tokens.errorBg,
4198
- border: `1px solid ${tokens.error}66`,
4199
- borderRadius: 16,
4200
- padding: "11px 14px",
4201
- color: tokens.error,
4202
- fontSize: "0.84rem",
4203
- marginTop: 16,
4204
- lineHeight: 1.5,
4205
- textAlign: "left",
4206
- maxWidth: 340
4207
- }, children: error || authExecutor.error || transferSigning.error || polling.error })
4208
- ] }) });
4486
+ const transferPhase = creatingTransfer ? "creating" : mobileFlow || authExecutor.executing || transferSigning.signing ? "verifying" : polledStatus === "SENDING" || polledStatus === "SENT" || polling.isPolling ? "sent" : "creating";
4487
+ return /* @__PURE__ */ jsx(
4488
+ TransferStatusScreen,
4489
+ {
4490
+ phase: transferPhase,
4491
+ error: error || authExecutor.error || transferSigning.error || polling.error,
4492
+ onLogout: handleLogout
4493
+ }
4494
+ );
4495
+ }
4496
+ if (step === "select-source") {
4497
+ return /* @__PURE__ */ jsx(
4498
+ SelectSourceScreen,
4499
+ {
4500
+ choices: selectSourceChoices,
4501
+ selectedChainName: selectSourceChainName,
4502
+ selectedTokenSymbol: selectSourceTokenSymbol,
4503
+ recommended: selectSourceRecommended,
4504
+ onChainChange: handleSelectSourceChainChange,
4505
+ onTokenChange: setSelectSourceTokenSymbol,
4506
+ onConfirm: () => {
4507
+ authExecutor.resolveSelectSource({
4508
+ chainName: selectSourceChainName,
4509
+ tokenSymbol: selectSourceTokenSymbol
4510
+ });
4511
+ },
4512
+ onLogout: handleLogout
4513
+ }
4514
+ );
4209
4515
  }
4210
4516
  if (step === "success") {
4211
4517
  transfer?.status === "COMPLETED";
@@ -4218,9 +4524,13 @@ function SwypePayment({
4218
4524
  currency: displayCurrency,
4219
4525
  merchantName,
4220
4526
  sourceName,
4221
- remainingLimit: oneTapLimit > displayAmount ? oneTapLimit - displayAmount : 0,
4222
- onDone: handleNewPayment,
4223
- onLogout: handleLogout
4527
+ remainingLimit: (() => {
4528
+ const limit = selectedAccount?.remainingAllowance ?? oneTapLimit;
4529
+ return limit > displayAmount ? limit - displayAmount : 0;
4530
+ })(),
4531
+ onDone: onDismiss ?? handleNewPayment,
4532
+ onLogout: handleLogout,
4533
+ autoCloseSeconds
4224
4534
  }
4225
4535
  );
4226
4536
  }
@@ -4233,7 +4543,7 @@ function SwypePayment({
4233
4543
  sourceAddress,
4234
4544
  sourceVerified,
4235
4545
  availableBalance: 0,
4236
- remainingLimit: oneTapLimit,
4546
+ remainingLimit: selectedAccount?.remainingAllowance ?? oneTapLimit,
4237
4547
  tokenCount,
4238
4548
  initialAmount: depositAmount ?? 5,
4239
4549
  processing: false,