@swype-org/react-sdk 0.1.33 → 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.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();
@@ -3804,6 +4058,26 @@ function SwypePayment({
3804
4058
  }
3805
4059
  initializedSelectSourceActionRef.current = pendingSelectSourceAction.id;
3806
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
+ );
3807
4081
  const selectedAccount = accounts.find((a) => a.id === selectedAccountId);
3808
4082
  const selectedWallet = selectedAccount?.wallets.find((w) => w.id === selectedWalletId);
3809
4083
  const sourceName = selectedAccount?.name ?? selectedWallet?.chain.name ?? "Wallet";
@@ -4108,6 +4382,9 @@ function SwypePayment({
4108
4382
  }
4109
4383
  );
4110
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
+ }
4111
4388
  if (step === "create-passkey") {
4112
4389
  return /* @__PURE__ */ jsx(
4113
4390
  CreatePasskeyScreen,
@@ -4173,7 +4450,7 @@ function SwypePayment({
4173
4450
  sourceAddress,
4174
4451
  sourceVerified,
4175
4452
  availableBalance: maxSourceBalance,
4176
- remainingLimit: oneTapLimit,
4453
+ remainingLimit: selectedAccount?.remainingAllowance ?? oneTapLimit,
4177
4454
  tokenCount,
4178
4455
  initialAmount: parsedAmt,
4179
4456
  processing: creatingTransfer,
@@ -4187,25 +4464,36 @@ function SwypePayment({
4187
4464
  );
4188
4465
  }
4189
4466
  if (step === "processing") {
4190
- const currentActionType = authExecutor.currentAction?.type;
4191
4467
  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
- ] }) });
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
+ );
4209
4497
  }
4210
4498
  if (step === "success") {
4211
4499
  transfer?.status === "COMPLETED";
@@ -4218,9 +4506,13 @@ function SwypePayment({
4218
4506
  currency: displayCurrency,
4219
4507
  merchantName,
4220
4508
  sourceName,
4221
- remainingLimit: oneTapLimit > displayAmount ? oneTapLimit - displayAmount : 0,
4222
- onDone: handleNewPayment,
4223
- onLogout: handleLogout
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
4224
4516
  }
4225
4517
  );
4226
4518
  }
@@ -4233,7 +4525,7 @@ function SwypePayment({
4233
4525
  sourceAddress,
4234
4526
  sourceVerified,
4235
4527
  availableBalance: 0,
4236
- remainingLimit: oneTapLimit,
4528
+ remainingLimit: selectedAccount?.remainingAllowance ?? oneTapLimit,
4237
4529
  tokenCount,
4238
4530
  initialAmount: depositAmount ?? 5,
4239
4531
  processing: false,