@swype-org/react-sdk 0.2.215 → 0.2.221

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.js CHANGED
@@ -962,7 +962,8 @@ function sanitizeAdvertisedWallets(value) {
962
962
  }
963
963
  var STATIC_BRIDGE_DEDUPE_RDNS = /* @__PURE__ */ new Set([
964
964
  "com.coinbase.wallet",
965
- "io.metamask"
965
+ "io.metamask",
966
+ "app.phantom"
966
967
  ]);
967
968
  function buildBridgedConnector(wallet) {
968
969
  return injected({
@@ -1040,6 +1041,7 @@ function BlinkProvider({
1040
1041
  privyAppId,
1041
1042
  minTransferAmountUsd,
1042
1043
  enableFullWidget = false,
1044
+ isMobileApp = false,
1043
1045
  children
1044
1046
  }) {
1045
1047
  const queryClientRef = useRef(null);
@@ -1078,9 +1080,10 @@ function BlinkProvider({
1078
1080
  minTransferAmountUsd: resolvedMinTransferAmountUsd,
1079
1081
  depositAmount,
1080
1082
  setDepositAmount,
1081
- enableFullWidget
1083
+ enableFullWidget,
1084
+ isMobileApp
1082
1085
  }),
1083
- [apiBaseUrl, theme, resolvedMinTransferAmountUsd, depositAmount, setDepositAmount, enableFullWidget]
1086
+ [apiBaseUrl, theme, resolvedMinTransferAmountUsd, depositAmount, setDepositAmount, enableFullWidget, isMobileApp]
1084
1087
  );
1085
1088
  return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClientRef.current, children: /* @__PURE__ */ jsx(WagmiProvider, { config: wagmiConfig, reconnectOnMount: false, children: /* @__PURE__ */ jsx(
1086
1089
  PrivyProvider,
@@ -2137,7 +2140,19 @@ async function getWalletCapabilities(walletClient, address, chainId) {
2137
2140
  params: chainScopedParams ?? legacyParams
2138
2141
  });
2139
2142
  if (result && typeof result === "object" && !Array.isArray(result)) {
2140
- return result;
2143
+ const caps = result;
2144
+ const hexKey = chainId != null ? `0x${chainId.toString(16)}` : null;
2145
+ const chainMissing = chainScopedParams && hexKey && !caps[hexKey] && !caps[String(chainId)];
2146
+ if (chainMissing) {
2147
+ const legacyResult = await walletClient.request({
2148
+ method: "wallet_getCapabilities",
2149
+ params: legacyParams
2150
+ });
2151
+ if (legacyResult && typeof legacyResult === "object" && !Array.isArray(legacyResult)) {
2152
+ return legacyResult;
2153
+ }
2154
+ }
2155
+ return caps;
2141
2156
  }
2142
2157
  return {};
2143
2158
  } catch (err) {
@@ -3458,8 +3473,54 @@ function isUserRejection(msg) {
3458
3473
  const lower = msg.toLowerCase();
3459
3474
  return lower.includes("rejected") || lower.includes("denied");
3460
3475
  }
3461
- function isTrustWalletAccount(account) {
3462
- return connectorMatchesWallet(account?.connector, { providerName: "trust" });
3476
+ function requiresExplicitEvmNonce(account) {
3477
+ return connectorMatchesWallet(account?.connector, { providerName: "trust" }) || connectorMatchesWallet(account?.connector, { providerName: "phantom" });
3478
+ }
3479
+ function getEvmNonceTrackerKey(sender, chainId) {
3480
+ return `${chainId ?? "unknown"}:${sender.toLowerCase()}`;
3481
+ }
3482
+ async function snapshotExplicitEvmNonce(params) {
3483
+ const {
3484
+ walletClient,
3485
+ sender,
3486
+ chainId,
3487
+ nonceTracker,
3488
+ logContext,
3489
+ actionId,
3490
+ extraDebug
3491
+ } = params;
3492
+ const trackerKey = getEvmNonceTrackerKey(sender, chainId);
3493
+ const trackedNonce = nonceTracker?.get(trackerKey) ?? null;
3494
+ try {
3495
+ const providerPendingNonce = await fetchLatestNonce(walletClient, sender, "pending");
3496
+ const nonce = trackedNonce == null ? providerPendingNonce : Math.max(providerPendingNonce, trackedNonce);
3497
+ appendDebug("info", `${logContext}: explicit nonce snapshot`, {
3498
+ actionId,
3499
+ sender,
3500
+ chainId: chainId ?? null,
3501
+ providerPendingNonce,
3502
+ trackedNonce,
3503
+ selectedNonce: nonce,
3504
+ ...extraDebug ?? {}
3505
+ });
3506
+ return { nonce, trackerKey };
3507
+ } catch (err) {
3508
+ appendDebug(trackedNonce == null ? "warn" : "info", `${logContext}: pre-send nonce snapshot failed`, {
3509
+ actionId,
3510
+ sender,
3511
+ chainId: chainId ?? null,
3512
+ trackedNonce,
3513
+ selectedNonce: trackedNonce,
3514
+ error: err instanceof Error ? err.message : String(err),
3515
+ ...extraDebug ?? {}
3516
+ });
3517
+ return { nonce: trackedNonce, trackerKey: trackedNonce == null ? null : trackerKey };
3518
+ }
3519
+ }
3520
+ function advanceTrackedEvmNonce(nonceTracker, trackerKey, nextNonce) {
3521
+ if (!nonceTracker || !trackerKey) return;
3522
+ const current = nonceTracker.get(trackerKey);
3523
+ nonceTracker.set(trackerKey, current == null ? nextNonce : Math.max(current, nextNonce));
3463
3524
  }
3464
3525
  async function waitForWalletClient(wagmiConfig, params = {}) {
3465
3526
  for (let i = 0; i < WALLET_CLIENT_MAX_ATTEMPTS; i++) {
@@ -4211,10 +4272,11 @@ function failBothActions(approveAction, bridgeAction, message) {
4211
4272
  ]
4212
4273
  };
4213
4274
  }
4214
- async function executeApprovePermit2(action, wagmiConfig) {
4275
+ async function executeApprovePermit2(action, wagmiConfig, options = {}) {
4215
4276
  let walletClient = null;
4216
4277
  let sender = null;
4217
4278
  let preSendNonce = null;
4279
+ let nonceTrackerKey = null;
4218
4280
  try {
4219
4281
  walletClient = await waitForWalletClient(wagmiConfig);
4220
4282
  const account = getAccount(wagmiConfig);
@@ -4238,19 +4300,20 @@ async function executeApprovePermit2(action, wagmiConfig) {
4238
4300
  "APPROVE_PERMIT2 metadata is missing transaction parameters (to, data)."
4239
4301
  );
4240
4302
  }
4241
- const shouldSnapshotPreSendNonce = isTrustWalletAccount(account);
4242
- if (shouldSnapshotPreSendNonce) {
4243
- try {
4244
- preSendNonce = await fetchLatestNonce(walletClient, sender, "pending");
4245
- } catch (err) {
4246
- appendDebug("warn", "APPROVE_PERMIT2: pre-send nonce snapshot failed", {
4247
- actionId: action.id,
4248
- sender,
4249
- error: err instanceof Error ? err.message : String(err)
4250
- });
4251
- }
4303
+ const shouldUseExplicitNonce = requiresExplicitEvmNonce(account);
4304
+ if (shouldUseExplicitNonce) {
4305
+ const snapshot = await snapshotExplicitEvmNonce({
4306
+ walletClient,
4307
+ sender,
4308
+ chainId: account.chainId,
4309
+ nonceTracker: options.nonceTracker,
4310
+ logContext: "APPROVE_PERMIT2",
4311
+ actionId: action.id
4312
+ });
4313
+ preSendNonce = snapshot.nonce;
4314
+ nonceTrackerKey = snapshot.trackerKey;
4252
4315
  }
4253
- const useExplicitNonce = shouldSnapshotPreSendNonce && preSendNonce != null;
4316
+ const useExplicitNonce = shouldUseExplicitNonce && preSendNonce != null;
4254
4317
  const txParams = {
4255
4318
  from: sender,
4256
4319
  to,
@@ -4280,6 +4343,9 @@ async function executeApprovePermit2(action, wagmiConfig) {
4280
4343
  ),
4281
4344
  approveLabel
4282
4345
  );
4346
+ if (preSendNonce != null) {
4347
+ advanceTrackedEvmNonce(options.nonceTracker, nonceTrackerKey, preSendNonce + 1);
4348
+ }
4283
4349
  appendDebug("info", "APPROVE_PERMIT2: tx sent, awaiting settlement", {
4284
4350
  actionId: action.id,
4285
4351
  txHash,
@@ -4370,6 +4436,7 @@ async function executeApprovePermit2(action, wagmiConfig) {
4370
4436
  actionId: action.id
4371
4437
  });
4372
4438
  if (recovery) {
4439
+ advanceTrackedEvmNonce(options.nonceTracker, nonceTrackerKey, recovery.latestNonce);
4373
4440
  return actionRecovery(
4374
4441
  action,
4375
4442
  "Approval transaction was submitted but the wallet did not return a confirmation. Verifying on-chain\u2026",
@@ -4556,10 +4623,11 @@ async function executeSignPermit2(action, wagmiConfig, apiBaseUrl, sessionId) {
4556
4623
  );
4557
4624
  }
4558
4625
  }
4559
- async function executeExecuteBridge(action, wagmiConfig) {
4626
+ async function executeExecuteBridge(action, wagmiConfig, options = {}) {
4560
4627
  let walletClient = null;
4561
4628
  let sender = null;
4562
4629
  let lastPreSendNonce = null;
4630
+ let lastNonceTrackerKey = null;
4563
4631
  try {
4564
4632
  walletClient = await waitForWalletClient(wagmiConfig);
4565
4633
  const account = getAccount(wagmiConfig);
@@ -4580,22 +4648,25 @@ async function executeExecuteBridge(action, wagmiConfig) {
4580
4648
  for (let i = 0; i < calls.length; i++) {
4581
4649
  const call = calls[i];
4582
4650
  const isIntermediateCall = i < calls.length - 1;
4583
- const shouldSnapshotPreSendNonce = isTrustWalletAccount(account);
4651
+ const shouldUseExplicitNonce = requiresExplicitEvmNonce(account);
4584
4652
  let preSendNonce = null;
4585
- if (shouldSnapshotPreSendNonce) {
4586
- try {
4587
- preSendNonce = await fetchLatestNonce(walletClient, sender, "pending");
4588
- lastPreSendNonce = preSendNonce;
4589
- } catch (err) {
4590
- appendDebug("warn", "EXECUTE_BRIDGE: pre-send nonce snapshot failed", {
4591
- actionId: action.id,
4592
- callIndex: i,
4593
- sender,
4594
- error: err instanceof Error ? err.message : String(err)
4595
- });
4596
- }
4653
+ let nonceTrackerKey = null;
4654
+ if (shouldUseExplicitNonce) {
4655
+ const snapshot = await snapshotExplicitEvmNonce({
4656
+ walletClient,
4657
+ sender,
4658
+ chainId: account.chainId,
4659
+ nonceTracker: options.nonceTracker,
4660
+ logContext: "EXECUTE_BRIDGE",
4661
+ actionId: action.id,
4662
+ extraDebug: { callIndex: i }
4663
+ });
4664
+ preSendNonce = snapshot.nonce;
4665
+ nonceTrackerKey = snapshot.trackerKey;
4666
+ lastPreSendNonce = preSendNonce;
4667
+ lastNonceTrackerKey = nonceTrackerKey;
4597
4668
  }
4598
- const useExplicitNonce = shouldSnapshotPreSendNonce && preSendNonce != null;
4669
+ const useExplicitNonce = shouldUseExplicitNonce && preSendNonce != null;
4599
4670
  const txParams = {
4600
4671
  from: sender,
4601
4672
  to: call.to,
@@ -4624,6 +4695,9 @@ async function executeExecuteBridge(action, wagmiConfig) {
4624
4695
  ),
4625
4696
  watchdogLabel
4626
4697
  );
4698
+ if (preSendNonce != null) {
4699
+ advanceTrackedEvmNonce(options.nonceTracker, nonceTrackerKey, preSendNonce + 1);
4700
+ }
4627
4701
  appendDebug("info", "EXECUTE_BRIDGE: tx sent", {
4628
4702
  actionId: action.id,
4629
4703
  callIndex: i,
@@ -4709,6 +4783,7 @@ async function executeExecuteBridge(action, wagmiConfig) {
4709
4783
  actionId: action.id
4710
4784
  });
4711
4785
  if (recovery) {
4786
+ advanceTrackedEvmNonce(options.nonceTracker, lastNonceTrackerKey, recovery.latestNonce);
4712
4787
  return actionRecovery(
4713
4788
  action,
4714
4789
  "Bridge transaction was submitted but the wallet did not return a confirmation. Verifying on-chain\u2026",
@@ -5253,6 +5328,7 @@ function useAuthorizationExecutor(options) {
5253
5328
  const walletConnectRuntimeRef = useRef(/* @__PURE__ */ new Map());
5254
5329
  const activeWalletConnectRuntimeKeyRef = useRef(void 0);
5255
5330
  const activeEvmTransportRef = useRef("wagmi");
5331
+ const evmNonceTrackerRef = useRef(/* @__PURE__ */ new Map());
5256
5332
  const [batchTxHash, setBatchTxHash] = useState(null);
5257
5333
  const externalAuthorizationAvailableRef = useRef(false);
5258
5334
  const setExternalAuthorizationAvailable = useCallback((available) => {
@@ -5308,6 +5384,7 @@ function useAuthorizationExecutor(options) {
5308
5384
  setApproveSplConfirming(null);
5309
5385
  activeEvmTransportRef.current = "wagmi";
5310
5386
  activeWalletConnectRuntimeKeyRef.current = void 0;
5387
+ evmNonceTrackerRef.current.clear();
5311
5388
  setExecuting(false);
5312
5389
  executingRef.current = false;
5313
5390
  }, []);
@@ -5333,6 +5410,7 @@ function useAuthorizationExecutor(options) {
5333
5410
  if (result2.status === "success" && result2.data?.transport === "wagmi") {
5334
5411
  activeEvmTransportRef.current = "wagmi";
5335
5412
  activeWalletConnectRuntimeKeyRef.current = void 0;
5413
+ evmNonceTrackerRef.current.clear();
5336
5414
  if (action.metadata?.chainFamily !== "svm") {
5337
5415
  walletCapabilitiesRef.current = await refreshWalletCapabilities(
5338
5416
  wagmiConfig,
@@ -5345,6 +5423,7 @@ function useAuthorizationExecutor(options) {
5345
5423
  walletCapabilitiesRef.current = {};
5346
5424
  walletCapabilitiesRefreshedRef.current = true;
5347
5425
  batchCapabilityDecisionRef.current = null;
5426
+ evmNonceTrackerRef.current.clear();
5348
5427
  }
5349
5428
  return result2;
5350
5429
  }
@@ -5354,6 +5433,7 @@ function useAuthorizationExecutor(options) {
5354
5433
  externalAuthorizationAvailable: externalAuthorizationAvailableRef.current
5355
5434
  });
5356
5435
  if (result.status === "success" && action.metadata?.chainFamily !== "svm") {
5436
+ evmNonceTrackerRef.current.clear();
5357
5437
  walletCapabilitiesRef.current = await refreshWalletCapabilities(
5358
5438
  wagmiConfig,
5359
5439
  "open-provider"
@@ -5377,11 +5457,13 @@ function useAuthorizationExecutor(options) {
5377
5457
  walletCapabilitiesRef.current = {};
5378
5458
  walletCapabilitiesRefreshedRef.current = true;
5379
5459
  batchCapabilityDecisionRef.current = null;
5460
+ evmNonceTrackerRef.current.clear();
5380
5461
  }
5381
5462
  return result2;
5382
5463
  }
5383
5464
  const result = await executeSwitchChain(action, wagmiConfig, switchChainAsync);
5384
5465
  if (result.status === "success" && action.metadata?.chainFamily !== "svm") {
5466
+ evmNonceTrackerRef.current.clear();
5385
5467
  walletCapabilitiesRef.current = await refreshWalletCapabilities(
5386
5468
  wagmiConfig,
5387
5469
  "switch-chain"
@@ -5399,7 +5481,9 @@ function useAuthorizationExecutor(options) {
5399
5481
  dispatchOptions?.onWalletConnectDisplayUri
5400
5482
  );
5401
5483
  }
5402
- return executeApprovePermit2(action, wagmiConfig);
5484
+ return executeApprovePermit2(action, wagmiConfig, {
5485
+ nonceTracker: evmNonceTrackerRef.current
5486
+ });
5403
5487
  case "DEPLOY_SMART_ACCOUNT":
5404
5488
  return actionSuccess(action, "Smart account deployment acknowledged.");
5405
5489
  case "SIGN_PERMIT2": {
@@ -5458,7 +5542,9 @@ function useAuthorizationExecutor(options) {
5458
5542
  dispatchOptions?.onWalletConnectDisplayUri
5459
5543
  );
5460
5544
  }
5461
- return executeExecuteBridge(action, wagmiConfig);
5545
+ return executeExecuteBridge(action, wagmiConfig, {
5546
+ nonceTracker: evmNonceTrackerRef.current
5547
+ });
5462
5548
  default:
5463
5549
  return actionError(action, `Unsupported action type: ${action.type}`);
5464
5550
  }
@@ -5611,6 +5697,7 @@ function useAuthorizationExecutor(options) {
5611
5697
  setError(null);
5612
5698
  setBatchTxHash(null);
5613
5699
  setApproveSplConfirming(null);
5700
+ evmNonceTrackerRef.current.clear();
5614
5701
  return true;
5615
5702
  }, []);
5616
5703
  const endExecution = useCallback(() => {
@@ -5619,6 +5706,7 @@ function useAuthorizationExecutor(options) {
5619
5706
  setApproveSplConfirming(null);
5620
5707
  activeEvmTransportRef.current = "wagmi";
5621
5708
  activeWalletConnectRuntimeKeyRef.current = void 0;
5709
+ evmNonceTrackerRef.current.clear();
5622
5710
  setExecuting(false);
5623
5711
  executingRef.current = false;
5624
5712
  }, []);
@@ -6041,6 +6129,8 @@ var ACTION_POLL_INTERVAL_MS2 = 500;
6041
6129
  var ACTION_POLL_MAX_RETRIES2 = 20;
6042
6130
  var REPORT_COMPLETION_TIMEOUT_MS = 9e4;
6043
6131
  var REPORT_COMPLETION_TIMEOUT_MESSAGE = "REPORT_COMPLETION_TIMEOUT";
6132
+ var APPROVE_PERMIT2_CONFIRMING_MESSAGE = "Your Permit2 approval transaction was submitted and is still confirming on-chain. Please wait a moment and retry. Do not approve again in your wallet.";
6133
+ var SIGN_PERMIT2_CONFIRMING_MESSAGE = "Your Permit2 signature was submitted and is still confirming on-chain. Please wait a moment and retry. Do not sign again in your wallet.";
6044
6134
  function useAuthorizationOrchestrator(deps) {
6045
6135
  const blinkConfig = useOptionalBlinkConfig();
6046
6136
  const resolvedApiBaseUrl = deps.apiBaseUrl ?? blinkConfig?.apiBaseUrl;
@@ -6054,6 +6144,8 @@ function useAuthorizationOrchestrator(deps) {
6054
6144
  const selectSourceRejectRef = useRef(null);
6055
6145
  const oneTapResolverRef = useRef(null);
6056
6146
  const oneTapRejectRef = useRef(null);
6147
+ const submittedApprovePermit2ActionIdsRef = useRef(/* @__PURE__ */ new Set());
6148
+ const submittedSignPermit2ActionIdsRef = useRef(/* @__PURE__ */ new Set());
6057
6149
  const oneTapPauseRequestedRef = useRef(false);
6058
6150
  const addSession = useCallback((sessionId) => {
6059
6151
  pendingSessionIdsRef.current.push(sessionId);
@@ -6476,6 +6568,12 @@ function useAuthorizationOrchestrator(deps) {
6476
6568
  completedIds.add(batchedAction.id);
6477
6569
  oneTapCompletedActionIds.delete(batchedAction.id);
6478
6570
  authExecutor.addResult(result2);
6571
+ if (isSubmittedApprovePermit2Result(batchedAction, result2)) {
6572
+ submittedApprovePermit2ActionIdsRef.current.add(batchedAction.id);
6573
+ }
6574
+ if (isSubmittedSignPermit2Result(batchedAction, result2)) {
6575
+ submittedSignPermit2ActionIdsRef.current.add(batchedAction.id);
6576
+ }
6479
6577
  const batchedOwnerSessionId = actionSessionMap.get(batchedAction.id) ?? ownerSessionId;
6480
6578
  const reportedSession2 = await reportActionCompletionWithLogging(
6481
6579
  apiBaseUrl,
@@ -6503,7 +6601,9 @@ function useAuthorizationOrchestrator(deps) {
6503
6601
  continue;
6504
6602
  }
6505
6603
  }
6506
- const isPrePromptProbableActionType = action.type === "SIGN_PERMIT2" || action.type === "APPROVE_PERMIT2" || action.type === "APPROVE_SPL";
6604
+ const approvePermit2WasSubmitted = action.type === "APPROVE_PERMIT2" && submittedApprovePermit2ActionIdsRef.current.has(action.id);
6605
+ const signPermit2WasSubmitted = action.type === "SIGN_PERMIT2" && submittedSignPermit2ActionIdsRef.current.has(action.id);
6606
+ const isPrePromptProbableActionType = action.type === "SIGN_PERMIT2" || action.type === "APPROVE_SPL" || approvePermit2WasSubmitted;
6507
6607
  if (isPrePromptProbableActionType && probeBeforePrompt && !preProbedIds.has(action.id)) {
6508
6608
  preProbedIds.add(action.id);
6509
6609
  appendDebug("info", `${action.type}: pre-prompt probe start`, {
@@ -6536,13 +6636,19 @@ function useAuthorizationOrchestrator(deps) {
6536
6636
  });
6537
6637
  continue;
6538
6638
  }
6539
- appendDebug("info", `${action.type}: pre-prompt probe did not detect; presenting wallet`, {
6639
+ appendDebug("info", approvePermit2WasSubmitted || signPermit2WasSubmitted ? `${action.type}: submitted action not detected yet; waiting for confirmation` : `${action.type}: pre-prompt probe did not detect; presenting wallet`, {
6540
6640
  actionId: action.id,
6541
6641
  ownerSessionId,
6542
6642
  reason: probe.reason,
6543
6643
  status: probe.status,
6544
6644
  code: probe.code
6545
6645
  });
6646
+ if (approvePermit2WasSubmitted) {
6647
+ throw new Error(APPROVE_PERMIT2_CONFIRMING_MESSAGE);
6648
+ }
6649
+ if (signPermit2WasSubmitted) {
6650
+ throw new Error(SIGN_PERMIT2_CONFIRMING_MESSAGE);
6651
+ }
6546
6652
  }
6547
6653
  appendDebug("info", `orchestrator:executeAction start ${action.type}`, {
6548
6654
  actionId: action.id,
@@ -6576,6 +6682,9 @@ function useAuthorizationOrchestrator(deps) {
6576
6682
  const probedIds = action.type === "APPROVE_PERMIT2" ? approvePermit2ProbedIds : action.type === "EXECUTE_BRIDGE" ? executeBridgeProbedIds : null;
6577
6683
  if (probedIds && !probedIds.has(action.id)) {
6578
6684
  probedIds.add(action.id);
6685
+ if (action.type === "APPROVE_PERMIT2") {
6686
+ submittedApprovePermit2ActionIdsRef.current.add(action.id);
6687
+ }
6579
6688
  appendDebug("warn", `${action.type}: client error with nonce advancement, probing on-chain`, {
6580
6689
  actionId: action.id,
6581
6690
  ownerSessionId,
@@ -6616,6 +6725,9 @@ function useAuthorizationOrchestrator(deps) {
6616
6725
  status: probe.status,
6617
6726
  code: probe.code
6618
6727
  });
6728
+ if (action.type === "APPROVE_PERMIT2" && probe.reason === "not-found") {
6729
+ throw new Error(APPROVE_PERMIT2_CONFIRMING_MESSAGE);
6730
+ }
6619
6731
  }
6620
6732
  }
6621
6733
  if (result.status === "error" && action.type === "EXECUTE_BRIDGE" && result.message === EXECUTE_BRIDGE_TX_TIMEOUT_MESSAGE && !executeBridgeProbedIds.has(action.id)) {
@@ -6677,6 +6789,12 @@ function useAuthorizationOrchestrator(deps) {
6677
6789
  completedIds.add(action.id);
6678
6790
  oneTapCompletedActionIds.delete(action.id);
6679
6791
  authExecutor.addResult(result);
6792
+ if (isSubmittedApprovePermit2Result(action, result)) {
6793
+ submittedApprovePermit2ActionIdsRef.current.add(action.id);
6794
+ }
6795
+ if (isSubmittedSignPermit2Result(action, result)) {
6796
+ submittedSignPermit2ActionIdsRef.current.add(action.id);
6797
+ }
6680
6798
  const reportedSession = await reportActionCompletionWithLogging(
6681
6799
  apiBaseUrl,
6682
6800
  action,
@@ -6764,6 +6882,25 @@ function createSelectSourceResult(action, selection) {
6764
6882
  }
6765
6883
  };
6766
6884
  }
6885
+ function isSubmittedApprovePermit2Result(action, result) {
6886
+ if (action.type !== "APPROVE_PERMIT2" || result.status !== "success") {
6887
+ return false;
6888
+ }
6889
+ if (!result.data || typeof result.data !== "object") {
6890
+ return false;
6891
+ }
6892
+ return typeof result.data.txHash === "string";
6893
+ }
6894
+ function isSubmittedSignPermit2Result(action, result) {
6895
+ if (action.type !== "SIGN_PERMIT2" || result.status !== "success") {
6896
+ return false;
6897
+ }
6898
+ if (!result.data || typeof result.data !== "object") {
6899
+ return false;
6900
+ }
6901
+ const data = result.data;
6902
+ return typeof data.signature === "string" || data.batchApprove === true;
6903
+ }
6767
6904
  function getLeadingBatchableActions(mergedPending) {
6768
6905
  const firstAction = mergedPending[0];
6769
6906
  if (!firstAction || !isBatchableAction(firstAction)) {
@@ -7131,6 +7268,9 @@ function resolveStickyPhase(state) {
7131
7268
  if (currentPhase.step === "manual-transfer" && !state.loginRequested) {
7132
7269
  return currentPhase;
7133
7270
  }
7271
+ if (currentPhase.step === "deposit-options" && !state.loginRequested) {
7272
+ return currentPhase;
7273
+ }
7134
7274
  if (!state.loginRequested && state.setupFlowScreen === "one-tap-setup") {
7135
7275
  return { step: "one-tap-setup", action: null };
7136
7276
  }
@@ -7648,6 +7788,8 @@ function applyAction(state, action) {
7648
7788
  pendingTransferId: null,
7649
7789
  creatingTransfer: false
7650
7790
  };
7791
+ case "CANCEL_LOGIN_REQUEST":
7792
+ return { ...state, loginRequested: false, error: null };
7651
7793
  case "SET_ERROR":
7652
7794
  return { ...state, error: action.error };
7653
7795
  case "AMOUNT_TOO_LOW":
@@ -7829,10 +7971,10 @@ function planConfirmSetupDeposit(input) {
7829
7971
  };
7830
7972
  }
7831
7973
  function ScreenLayout({ children, footer }) {
7832
- const { tokens, theme } = useBlinkConfig();
7974
+ const { tokens, theme, isMobileApp } = useBlinkConfig();
7833
7975
  const isRedesign = theme.endsWith("New");
7834
7976
  const useAccentWash = !isRedesign;
7835
- const sheetRadius = isRedesign ? tokens.radiusLg : void 0;
7977
+ const sheetRadius = isRedesign && !isMobileApp ? tokens.radiusLg : void 0;
7836
7978
  const sheetClass = sheetRadius ? "blink-screen-sheet blink-screen-sheet--responsive-radius" : "blink-screen-sheet";
7837
7979
  return /* @__PURE__ */ jsxs("div", { className: sheetClass, style: containerStyle(tokens.bgCard, useAccentWash, sheetRadius, tokens.fontFamily), children: [
7838
7980
  sheetRadius && /* @__PURE__ */ jsx("style", { children: responsiveRadiusCss }),
@@ -9236,7 +9378,7 @@ var labelStyle4 = (color, disabled) => ({
9236
9378
  var rightSlotStyle2 = {
9237
9379
  display: "inline-flex",
9238
9380
  alignItems: "center",
9239
- justifyContent: "center",
9381
+ justifyContent: "flex-end",
9240
9382
  minWidth: 40,
9241
9383
  minHeight: 40,
9242
9384
  flexShrink: 0,
@@ -9536,9 +9678,9 @@ function LoginScreen({
9536
9678
  const { tokens } = useBlinkConfig();
9537
9679
  const heading = heroTitle ?? "Deposit instantly\nwith Blink";
9538
9680
  const primaryAction = preferSignup ? onLoginWithPasskey : onSignupWithPasskey;
9539
- const primaryLabel = preferSignup ? "I already have a Blink Passkey" : "Create a Passkey";
9681
+ const primaryLabel = preferSignup ? "Sign in with Blink" : "Create a Passkey";
9540
9682
  const secondaryAction = preferSignup ? onSignupWithPasskey : onLoginWithPasskey;
9541
- const secondaryLabel = preferSignup ? " Create a Passkey" : "I already have a Blink Passkey";
9683
+ const secondaryLabel = preferSignup ? " Create a Passkey" : "Sign in with Blink";
9542
9684
  const headerRight = onClose ? /* @__PURE__ */ jsx(
9543
9685
  "button",
9544
9686
  {
@@ -9578,7 +9720,7 @@ function LoginScreen({
9578
9720
  /* @__PURE__ */ jsx(
9579
9721
  ScreenHeader,
9580
9722
  {
9581
- onBack: onClose ? void 0 : onBack,
9723
+ onBack,
9582
9724
  right: headerRight,
9583
9725
  left: /* @__PURE__ */ jsx(
9584
9726
  "img",
@@ -9734,9 +9876,13 @@ function DepositOptionsScreen({
9734
9876
  /* @__PURE__ */ jsx(
9735
9877
  SourceRow,
9736
9878
  {
9737
- name: "Wallet",
9879
+ name: "Connect Wallet",
9738
9880
  icon: /* @__PURE__ */ jsx(WalletIcon, { color: tokens.text }),
9739
- onClick: onFromWallet
9881
+ onClick: onFromWallet,
9882
+ right: /* @__PURE__ */ jsxs("span", { style: badgeWithArrowStyle, children: [
9883
+ /* @__PURE__ */ jsx(RecommendedBadge, { tokens }),
9884
+ /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M9 6l6 6-6 6", stroke: tokens.textMuted, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
9885
+ ] })
9740
9886
  }
9741
9887
  ),
9742
9888
  /* @__PURE__ */ jsx(
@@ -9764,38 +9910,14 @@ function DepositOptionsScreen({
9764
9910
  );
9765
9911
  }
9766
9912
  function DepositTypeToggle({ tokens }) {
9767
- return /* @__PURE__ */ jsxs(
9768
- "div",
9769
- {
9770
- role: "tablist",
9771
- "aria-label": "Deposit type",
9772
- "aria-disabled": "true",
9773
- style: toggleContainerStyle(tokens.bgRecessed),
9774
- children: [
9775
- /* @__PURE__ */ jsx(ToggleSegment, { selected: true, label: "Crypto", tokens }),
9776
- /* @__PURE__ */ jsx(ToggleSegment, { selected: false, label: "Cash", subLabel: "Coming soon", tokens })
9777
- ]
9778
- }
9779
- );
9780
- }
9781
- function ToggleSegment({ selected, label, subLabel, tokens }) {
9782
- return /* @__PURE__ */ jsxs(
9783
- "div",
9784
- {
9785
- role: "tab",
9786
- "aria-selected": selected,
9787
- "aria-disabled": "true",
9788
- style: toggleSegmentStyle(selected, tokens),
9789
- children: [
9790
- /* @__PURE__ */ jsx("span", { children: label }),
9791
- subLabel ? /* @__PURE__ */ jsx("span", { style: toggleSubLabelStyle, children: subLabel }) : null
9792
- ]
9793
- }
9794
- );
9913
+ return /* @__PURE__ */ jsx(Fragment, {});
9795
9914
  }
9796
9915
  function ComingSoonBadge({ tokens }) {
9797
9916
  return /* @__PURE__ */ jsx("span", { style: comingSoonBadgeStyle(tokens.bgRecessed, tokens.textMuted), children: "Coming soon" });
9798
9917
  }
9918
+ function RecommendedBadge({ tokens }) {
9919
+ return /* @__PURE__ */ jsx("span", { style: recommendedBadgeStyle(tokens.successBg, tokens.success), children: "Recommended" });
9920
+ }
9799
9921
  function WalletIcon({ color }) {
9800
9922
  return /* @__PURE__ */ jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
9801
9923
  /* @__PURE__ */ jsx(
@@ -9932,39 +10054,25 @@ var cardStyle = (bg) => ({
9932
10054
  borderRadius: 28,
9933
10055
  padding: "8px 8px 8px 20px"
9934
10056
  });
9935
- var toggleContainerStyle = (bg) => ({
9936
- display: "flex",
9937
- width: "100%",
9938
- background: bg,
9939
- borderRadius: 999,
9940
- padding: 4,
9941
- boxSizing: "border-box"
9942
- });
9943
- var toggleSegmentStyle = (selected, tokens) => ({
9944
- flex: 1,
9945
- display: "flex",
9946
- flexDirection: "column",
10057
+ var comingSoonBadgeStyle = (bg, color) => ({
10058
+ display: "inline-flex",
9947
10059
  alignItems: "center",
9948
10060
  justifyContent: "center",
9949
- textAlign: "center",
9950
- padding: "10px 16px",
9951
- borderRadius: 999,
9952
- fontSize: "0.95rem",
9953
- fontWeight: 600,
9954
- lineHeight: 1.15,
9955
- color: selected ? tokens.text : tokens.textMuted,
9956
- background: selected ? tokens.bg : "transparent",
9957
- boxShadow: selected ? tokens.shadow : "none",
9958
- cursor: "default",
9959
- userSelect: "none"
9960
- });
9961
- var toggleSubLabelStyle = {
9962
- fontSize: "0.7rem",
10061
+ background: bg,
10062
+ color,
10063
+ fontSize: 10,
9963
10064
  fontWeight: 500,
9964
- marginTop: 2,
9965
- opacity: 0.85
10065
+ lineHeight: 1,
10066
+ padding: "4px 8px",
10067
+ borderRadius: 8,
10068
+ marginRight: 8,
10069
+ whiteSpace: "nowrap"
10070
+ });
10071
+ var badgeWithArrowStyle = {
10072
+ display: "flex",
10073
+ alignItems: "center"
9966
10074
  };
9967
- var comingSoonBadgeStyle = (bg, color) => ({
10075
+ var recommendedBadgeStyle = (bg, color) => ({
9968
10076
  display: "inline-flex",
9969
10077
  alignItems: "center",
9970
10078
  justifyContent: "center",
@@ -9975,7 +10083,6 @@ var comingSoonBadgeStyle = (bg, color) => ({
9975
10083
  lineHeight: 1,
9976
10084
  padding: "4px 8px",
9977
10085
  borderRadius: 8,
9978
- marginRight: 8,
9979
10086
  whiteSpace: "nowrap"
9980
10087
  });
9981
10088
  var linkIconImageStyle = (color) => ({
@@ -10901,70 +11008,59 @@ function WalletPickerScreen({
10901
11008
  ),
10902
11009
  /* @__PURE__ */ jsx("h1", { style: titleStyle3(tokens.text), children: "Link wallet" }),
10903
11010
  error && /* @__PURE__ */ jsx("div", { style: errorBannerStyle5(tokens), children: error }),
10904
- /* @__PURE__ */ jsxs("div", { style: sheetStackStyle, children: [
10905
- /* @__PURE__ */ jsx("div", { style: cardStyle2(tokens.bgCardTranslucent), children: showOtherWallets ? /* @__PURE__ */ jsx(
10906
- OtherWalletsPanel,
10907
- {
10908
- wallets: filteredReownWallets,
10909
- loading: reownLoading,
10910
- error: reownError,
10911
- search: reownSearch,
10912
- onSearchChange: setReownSearch,
10913
- onRetry: () => {
10914
- setReownWallets([]);
10915
- setReownFetchAttempt((attempt) => attempt + 1);
10916
- },
10917
- onSelectWallet: (wallet) => {
10918
- void onSelectWalletConnectWallet(wallet);
10919
- }
11011
+ /* @__PURE__ */ jsx("div", { style: sheetStackStyle, children: /* @__PURE__ */ jsx("div", { style: cardStyle2(tokens.bgCardTranslucent), children: showOtherWallets ? /* @__PURE__ */ jsx(
11012
+ OtherWalletsPanel,
11013
+ {
11014
+ wallets: filteredReownWallets,
11015
+ loading: reownLoading,
11016
+ error: reownError,
11017
+ search: reownSearch,
11018
+ onSearchChange: setReownSearch,
11019
+ onRetry: () => {
11020
+ setReownWallets([]);
11021
+ setReownFetchAttempt((attempt) => attempt + 1);
11022
+ },
11023
+ onSelectWallet: (wallet) => {
11024
+ void onSelectWalletConnectWallet(wallet);
10920
11025
  }
10921
- ) : showWalletListSpinner ? /* @__PURE__ */ jsx("div", { style: spinnerRowStyle, children: /* @__PURE__ */ jsx(Spinner, { label: providersLoading ? "Loading wallets..." : "Preparing wallet links..." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
10922
- visibleProviders.map((provider) => {
10923
- const logoSrc = "logoURI" in provider && provider.logoURI || KNOWN_LOGOS[provider.name.toLowerCase()];
10924
- const directPreparedSession = directPreparedSessions[provider.id];
10925
- const isRowPreparing = preparing && selectedProviderId === provider.id;
10926
- const rowLoader = isRowPreparing ? /* @__PURE__ */ jsx(Spinner, { size: 20 }) : void 0;
10927
- if (usesDirectLinkCards) {
10928
- if (directPreparedSession?.uri) {
10929
- const navigation = classifyWalletDeeplinkNavigation(directPreparedSession.uri);
10930
- const openWithJavaScript = shouldOpenWithJavaScript(navigation);
10931
- return /* @__PURE__ */ jsx(
10932
- SourceRow,
10933
- {
10934
- logo: logoSrc,
10935
- name: provider.name,
10936
- href: directPreparedSession.uri,
10937
- target: navigation.anchorTarget,
10938
- rel: navigation.anchorRel,
10939
- onClick: (e) => {
10940
- if (openWithJavaScript) {
10941
- e.preventDefault();
10942
- }
10943
- setSelectedProviderId(provider.id);
10944
- if (directPreparedSession.sessionId) {
10945
- void setAuthorizationSessionProvider(
10946
- apiBaseUrl,
10947
- directPreparedSession.sessionId,
10948
- provider.id
10949
- ).catch((err) => {
10950
- captureException(err);
10951
- });
10952
- }
10953
- if (openWithJavaScript) {
10954
- openDeeplink(directPreparedSession.uri);
10955
- }
10956
- void onSelectProvider(provider.id, directPreparedSession);
10957
- }
10958
- },
10959
- provider.id
10960
- );
10961
- }
11026
+ }
11027
+ ) : showWalletListSpinner ? /* @__PURE__ */ jsx("div", { style: spinnerRowStyle, children: /* @__PURE__ */ jsx(Spinner, { label: providersLoading ? "Loading wallets..." : "Preparing wallet links..." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
11028
+ visibleProviders.map((provider) => {
11029
+ const logoSrc = "logoURI" in provider && provider.logoURI || KNOWN_LOGOS[provider.name.toLowerCase()];
11030
+ const directPreparedSession = directPreparedSessions[provider.id];
11031
+ const isRowPreparing = preparing && selectedProviderId === provider.id;
11032
+ const rowLoader = isRowPreparing ? /* @__PURE__ */ jsx(Spinner, { size: 20 }) : void 0;
11033
+ if (usesDirectLinkCards) {
11034
+ if (directPreparedSession?.uri) {
11035
+ const navigation = classifyWalletDeeplinkNavigation(directPreparedSession.uri);
11036
+ const openWithJavaScript = shouldOpenWithJavaScript(navigation);
10962
11037
  return /* @__PURE__ */ jsx(
10963
11038
  SourceRow,
10964
11039
  {
10965
11040
  logo: logoSrc,
10966
11041
  name: provider.name,
10967
- disabled: true
11042
+ href: directPreparedSession.uri,
11043
+ target: navigation.anchorTarget,
11044
+ rel: navigation.anchorRel,
11045
+ onClick: (e) => {
11046
+ if (openWithJavaScript) {
11047
+ e.preventDefault();
11048
+ }
11049
+ setSelectedProviderId(provider.id);
11050
+ if (directPreparedSession.sessionId) {
11051
+ void setAuthorizationSessionProvider(
11052
+ apiBaseUrl,
11053
+ directPreparedSession.sessionId,
11054
+ provider.id
11055
+ ).catch((err) => {
11056
+ captureException(err);
11057
+ });
11058
+ }
11059
+ if (openWithJavaScript) {
11060
+ openDeeplink(directPreparedSession.uri);
11061
+ }
11062
+ void onSelectProvider(provider.id, directPreparedSession);
11063
+ }
10968
11064
  },
10969
11065
  provider.id
10970
11066
  );
@@ -10974,36 +11070,35 @@ function WalletPickerScreen({
10974
11070
  {
10975
11071
  logo: logoSrc,
10976
11072
  name: provider.name,
10977
- right: rowLoader,
10978
- onClick: () => {
10979
- void handleRowSelect(provider.id);
10980
- }
11073
+ disabled: true
10981
11074
  },
10982
11075
  provider.id
10983
11076
  );
10984
- }),
10985
- /* @__PURE__ */ jsx(
11077
+ }
11078
+ return /* @__PURE__ */ jsx(
10986
11079
  SourceRow,
10987
11080
  {
10988
- name: "Other",
10989
- icon: /* @__PURE__ */ jsx(OtherWalletsIcon, { color: tokens.textMuted }),
11081
+ logo: logoSrc,
11082
+ name: provider.name,
11083
+ right: rowLoader,
10990
11084
  onClick: () => {
10991
- setShowOtherWallets(true);
11085
+ void handleRowSelect(provider.id);
10992
11086
  }
10993
- }
10994
- )
10995
- ] }) }),
10996
- /* @__PURE__ */ jsx("div", { style: disabledCardStyle(tokens.bgRecessed), children: /* @__PURE__ */ jsx(
11087
+ },
11088
+ provider.id
11089
+ );
11090
+ }),
11091
+ /* @__PURE__ */ jsx(
10997
11092
  SourceRow,
10998
11093
  {
10999
- disabled: true,
11000
- disabledColor: tokens.textTertiary,
11001
- name: "Bank account",
11002
- icon: /* @__PURE__ */ jsx(BankIcon, { color: tokens.textTertiary }),
11003
- right: /* @__PURE__ */ jsx("span", { style: comingSoonStyle(tokens.textTertiary), children: "Coming soon" })
11094
+ name: "Other",
11095
+ icon: /* @__PURE__ */ jsx(OtherWalletsIcon, {}),
11096
+ onClick: () => {
11097
+ setShowOtherWallets(true);
11098
+ }
11004
11099
  }
11005
- ) })
11006
- ] })
11100
+ )
11101
+ ] }) }) })
11007
11102
  ] });
11008
11103
  }
11009
11104
  function OtherWalletsPanel({
@@ -11072,77 +11167,29 @@ function ReownWalletLogo({ wallet }) {
11072
11167
  }
11073
11168
  );
11074
11169
  }
11075
- function OtherWalletsIcon({ color }) {
11076
- return /* @__PURE__ */ jsxs("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
11077
- /* @__PURE__ */ jsx(
11078
- "path",
11079
- {
11080
- d: "M7.5 9.5C10 7.2 14 7.2 16.5 9.5",
11081
- stroke: color,
11082
- strokeWidth: "1.8",
11083
- strokeLinecap: "round"
11084
- }
11085
- ),
11086
- /* @__PURE__ */ jsx(
11087
- "path",
11088
- {
11089
- d: "M4.5 6.5C8.7 2.9 15.3 2.9 19.5 6.5",
11090
- stroke: color,
11091
- strokeWidth: "1.8",
11092
- strokeLinecap: "round"
11093
- }
11094
- ),
11095
- /* @__PURE__ */ jsx(
11096
- "path",
11097
- {
11098
- d: "M10 12.5C11.1 11.7 12.9 11.7 14 12.5",
11099
- stroke: color,
11100
- strokeWidth: "1.8",
11101
- strokeLinecap: "round"
11102
- }
11103
- ),
11104
- /* @__PURE__ */ jsx(
11105
- "path",
11106
- {
11107
- d: "M12 16H12.01",
11108
- stroke: color,
11109
- strokeWidth: "2.4",
11110
- strokeLinecap: "round"
11111
- }
11112
- )
11113
- ] });
11114
- }
11115
- function BankIcon({ color }) {
11116
- return /* @__PURE__ */ jsxs("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
11117
- /* @__PURE__ */ jsx(
11118
- "path",
11119
- {
11120
- d: "M3 10L12 4L21 10",
11121
- stroke: color,
11122
- strokeWidth: "1.8",
11123
- strokeLinecap: "round",
11124
- strokeLinejoin: "round"
11125
- }
11126
- ),
11127
- /* @__PURE__ */ jsx(
11128
- "path",
11129
- {
11130
- d: "M5 10V18M9 10V18M15 10V18M19 10V18",
11131
- stroke: color,
11132
- strokeWidth: "1.8",
11133
- strokeLinecap: "round"
11134
- }
11135
- ),
11136
- /* @__PURE__ */ jsx(
11137
- "path",
11138
- {
11139
- d: "M3 20H21",
11140
- stroke: color,
11141
- strokeWidth: "1.8",
11142
- strokeLinecap: "round"
11143
- }
11144
- )
11145
- ] });
11170
+ function OtherWalletsIcon() {
11171
+ return /* @__PURE__ */ jsxs(
11172
+ "svg",
11173
+ {
11174
+ width: "34",
11175
+ height: "34",
11176
+ viewBox: "0 0 400 400",
11177
+ fill: "none",
11178
+ xmlns: "http://www.w3.org/2000/svg",
11179
+ "aria-hidden": "true",
11180
+ style: { borderRadius: "50%" },
11181
+ children: [
11182
+ /* @__PURE__ */ jsx("circle", { cx: "200", cy: "200", fill: "#3396ff", r: "199.5", stroke: "#66b1ff" }),
11183
+ /* @__PURE__ */ jsx(
11184
+ "path",
11185
+ {
11186
+ d: "m122.519 148.965c42.791-41.729 112.171-41.729 154.962 0l5.15 5.022c2.14 2.086 2.14 5.469 0 7.555l-17.617 17.18c-1.07 1.043-2.804 1.043-3.874 0l-7.087-6.911c-29.853-29.111-78.253-29.111-108.106 0l-7.59 7.401c-1.07 1.043-2.804 1.043-3.874 0l-17.617-17.18c-2.14-2.086-2.14-5.469 0-7.555zm191.397 35.529 15.679 15.29c2.14 2.086 2.14 5.469 0 7.555l-70.7 68.944c-2.139 2.087-5.608 2.087-7.748 0l-50.178-48.931c-.535-.522-1.402-.522-1.937 0l-50.178 48.931c-2.139 2.087-5.608 2.087-7.748 0l-70.7015-68.945c-2.1396-2.086-2.1396-5.469 0-7.555l15.6795-15.29c2.1396-2.086 5.6085-2.086 7.7481 0l50.1789 48.932c.535.522 1.402.522 1.937 0l50.177-48.932c2.139-2.087 5.608-2.087 7.748 0l50.179 48.932c.535.522 1.402.522 1.937 0l50.179-48.931c2.139-2.087 5.608-2.087 7.748 0z",
11187
+ fill: "#fff"
11188
+ }
11189
+ )
11190
+ ]
11191
+ }
11192
+ );
11146
11193
  }
11147
11194
  function isAbortError(err) {
11148
11195
  return err instanceof DOMException && err.name === "AbortError";
@@ -11191,19 +11238,6 @@ var cardStyle2 = (bg) => ({
11191
11238
  borderRadius: 28,
11192
11239
  padding: "8px 8px 8px 20px"
11193
11240
  });
11194
- var disabledCardStyle = (bg) => ({
11195
- display: "flex",
11196
- flexDirection: "column",
11197
- background: bg,
11198
- borderRadius: 28,
11199
- padding: "8px 8px 8px 20px"
11200
- });
11201
- var comingSoonStyle = (color) => ({
11202
- fontSize: "1rem",
11203
- color,
11204
- paddingRight: 8,
11205
- whiteSpace: "nowrap"
11206
- });
11207
11241
  var spinnerRowStyle = {
11208
11242
  display: "flex",
11209
11243
  alignItems: "center",
@@ -12324,13 +12358,14 @@ function DepositScreen({
12324
12358
  (opt) => opt.balance == null || isSelectableDepositSourceAmountUsd(opt.balance, minDepositFloor)
12325
12359
  ) ?? [];
12326
12360
  const hasTokenDropdown = selectableTokenOptions.length > 0 && onPickToken != null;
12361
+ const canOpenInlineSheet = onPickToken != null && (hasTokenDropdown || (accounts?.length ?? 0) > 0);
12327
12362
  const handleOpenSourceSheet = useCallback(() => {
12328
- if (hasTokenDropdown) {
12363
+ if (canOpenInlineSheet) {
12329
12364
  setTokenPickerOpen((v) => !v);
12330
12365
  } else {
12331
12366
  onSelectToken?.();
12332
12367
  }
12333
- }, [hasTokenDropdown, onSelectToken]);
12368
+ }, [canOpenInlineSheet, onSelectToken]);
12334
12369
  const handleCloseSourceSheet = useCallback(() => {
12335
12370
  setTokenPickerOpen(false);
12336
12371
  }, []);
@@ -12342,9 +12377,9 @@ function DepositScreen({
12342
12377
  const exceedsLimit = remainingLimit != null && amount > remainingLimit && !isLowBalance && !needsAuthorization;
12343
12378
  const canDeposit = amount >= minDepositFloor && !exceedsLimit && !isLowBalance && !insufficientFunds && !needsAuthorization && !processing;
12344
12379
  const hasAccountPill = !!accounts && accounts.length > 0;
12345
- const pillClickable = hasTokenDropdown || !!onSelectToken;
12380
+ const pillClickable = canOpenInlineSheet || !!onSelectToken;
12346
12381
  const tokenAriaLabel = selectedTokenSymbol && selectedChainName ? `Selected token: ${selectedTokenSymbol} on ${selectedChainName}` : selectedTokenSymbol ? `Selected token: ${selectedTokenSymbol}` : "Select token";
12347
- if (tokenPickerOpen && hasTokenDropdown) {
12382
+ if (tokenPickerOpen && canOpenInlineSheet) {
12348
12383
  const depositSourceAccounts = (accounts ?? []).map((a) => {
12349
12384
  const preferred = getPreferredDepositWallet(a, amount);
12350
12385
  return {
@@ -12405,8 +12440,8 @@ function DepositScreen({
12405
12440
  onClick: handleOpenSourceSheet,
12406
12441
  style: redesignPillButtonStyle(pillClickable),
12407
12442
  "aria-label": tokenAriaLabel,
12408
- "aria-expanded": hasTokenDropdown ? tokenPickerOpen : void 0,
12409
- "aria-haspopup": hasTokenDropdown ? "listbox" : void 0,
12443
+ "aria-expanded": canOpenInlineSheet ? tokenPickerOpen : void 0,
12444
+ "aria-haspopup": canOpenInlineSheet ? "listbox" : void 0,
12410
12445
  children: /* @__PURE__ */ jsx(
12411
12446
  SourcePill,
12412
12447
  {
@@ -12519,8 +12554,8 @@ function SuccessScreen({
12519
12554
  onLogout,
12520
12555
  returnMessage
12521
12556
  }) {
12522
- const { tokens } = useBlinkConfig();
12523
- const headerRight = succeeded && onDone ? /* @__PURE__ */ jsx(
12557
+ const { tokens, isMobileApp } = useBlinkConfig();
12558
+ const headerRight = succeeded && onDone && !isMobileApp ? /* @__PURE__ */ jsx(
12524
12559
  "button",
12525
12560
  {
12526
12561
  type: "button",
@@ -12721,7 +12756,7 @@ function SelectSourceScreen({
12721
12756
  /* @__PURE__ */ jsxs("div", { style: optionContentStyle, children: [
12722
12757
  /* @__PURE__ */ jsxs("span", { style: optionNameStyle(tokens.text), children: [
12723
12758
  chain.chainName,
12724
- isRecommended && /* @__PURE__ */ jsx("span", { style: recommendedBadgeStyle(tokens.textMuted), children: " recommended" })
12759
+ isRecommended && /* @__PURE__ */ jsx("span", { style: recommendedBadgeStyle2(tokens.textMuted), children: " recommended" })
12725
12760
  ] }),
12726
12761
  /* @__PURE__ */ jsxs("span", { style: optionBalanceStyle(tokens.textMuted), children: [
12727
12762
  "$",
@@ -12817,7 +12852,7 @@ var optionNameStyle = (color) => ({
12817
12852
  fontWeight: 600,
12818
12853
  color
12819
12854
  });
12820
- var recommendedBadgeStyle = (color) => ({
12855
+ var recommendedBadgeStyle2 = (color) => ({
12821
12856
  fontSize: "0.7rem",
12822
12857
  fontWeight: 500,
12823
12858
  color,
@@ -15327,10 +15362,10 @@ function buildLoginScreenProps({ flow, handlers }) {
15327
15362
  onSignupWithPasskey: handlers.onSignupWithPasskey,
15328
15363
  loading: flow.passkeyLoading,
15329
15364
  error: flow.state.error,
15330
- // Login is the root screen, so "back" and "close" both dismiss the widget.
15331
- // Exposing onClose lets LoginScreen render the Figma-redesign top-right
15332
- // (X) button instead of the legacy back arrow.
15333
- onClose: flow.onBack,
15365
+ // Inside a native mobile in-app browser the host's chrome handles
15366
+ // dismissal, so suppress the in-screen (X) close button.
15367
+ onClose: flow.isMobileApp ? void 0 : flow.onBack,
15368
+ onBack: flow.state.enableFullWidget ? handlers.onCancelLogin : void 0,
15334
15369
  merchantInitials: flow.merchantName ? flow.merchantName.slice(0, 2).toUpperCase() : void 0
15335
15370
  };
15336
15371
  }
@@ -15345,8 +15380,9 @@ function buildDepositOptionsScreenProps({ flow, handlers }) {
15345
15380
  // Deposit-options is the root screen for the full-widget flow, so the
15346
15381
  // top-right (X) closes the widget through the same `onBack` the host
15347
15382
  // provides. Falling back to `undefined` hides the close button when the
15348
- // host did not pass an onBack (matches LoginScreen behavior).
15349
- onClose: flow.onBack
15383
+ // host did not pass an onBack (matches LoginScreen behavior). Inside a
15384
+ // native mobile in-app browser the host chrome handles dismissal.
15385
+ onClose: flow.isMobileApp ? void 0 : flow.onBack
15350
15386
  };
15351
15387
  }
15352
15388
  function buildPasskeyReadyScreenProps({ handlers }) {
@@ -15584,7 +15620,7 @@ function buildDepositScreenProps({
15584
15620
  error: state.error,
15585
15621
  onDeposit: handlers.onPay,
15586
15622
  onSwitchWallet: () => handlers.onSetPhase({ step: "wallet-picker", reason: "switch" }),
15587
- onBack: onBack ?? (() => handlers.onLogout()),
15623
+ onBack: state.enableFullWidget ? () => handlers.onSetPhase({ step: "deposit-options" }) : onBack ?? (() => handlers.onLogout()),
15588
15624
  onLogout: handlers.onLogout,
15589
15625
  onIncreaseLimit: handlers.onIncreaseLimit,
15590
15626
  increasingLimit: state.increasingLimit,
@@ -15597,7 +15633,7 @@ function buildDepositScreenProps({
15597
15633
  // the inline sheet can't render). Hosts with sources get the inline
15598
15634
  // SelectDepositSourceScreen via onPickToken below.
15599
15635
  onSelectToken: handlers.onSelectToken,
15600
- tokenOptions: depositTokenOptions.length > 0 ? depositTokenOptions : void 0,
15636
+ tokenOptions: depositTokenOptions,
15601
15637
  useDeeplink: !flow.isDesktop,
15602
15638
  onPickToken: (symbol, chainName, walletId) => {
15603
15639
  const match = depositTokenOptions.find(
@@ -15751,13 +15787,15 @@ function buildAmountTooLowScreenProps({
15751
15787
  flow,
15752
15788
  handlers
15753
15789
  }) {
15754
- const { state, onDismiss } = flow;
15790
+ const { state, onDismiss, isMobileApp } = flow;
15755
15791
  const minAmountUsd = state.phase.step === "amount-too-low" ? state.phase.minAmountUsd : state.amountTooLow?.minAmountUsd ?? flow.minTransferAmountUsd;
15756
15792
  const canRetry = flow.depositAmount == null;
15757
15793
  return {
15758
15794
  minAmountUsd,
15759
15795
  onRetry: canRetry ? handlers.onNewPayment : void 0,
15760
- onClose: onDismiss
15796
+ // Inside a native mobile in-app browser the host's chrome handles
15797
+ // dismissal, so suppress the in-screen (X) close button.
15798
+ onClose: isMobileApp ? void 0 : onDismiss
15761
15799
  };
15762
15800
  }
15763
15801
  function StepRenderer(props) {
@@ -18924,7 +18962,7 @@ function BlinkPaymentInner({
18924
18962
  onBack,
18925
18963
  onDismiss
18926
18964
  }) {
18927
- const { apiBaseUrl, depositAmount, minTransferAmountUsd, enableFullWidget } = useBlinkConfig();
18965
+ const { apiBaseUrl, depositAmount, minTransferAmountUsd, enableFullWidget, isMobileApp } = useBlinkConfig();
18928
18966
  const { ready, authenticated, logout, getAccessToken } = usePrivy();
18929
18967
  const popupAuthRef = useRef(loadPopupAuth());
18930
18968
  const popupAuthValid = (() => {
@@ -19436,6 +19474,11 @@ function BlinkPaymentInner({
19436
19474
  onNewPayment: handleNewPayment,
19437
19475
  onSetPhase: (phase) => {
19438
19476
  clearScreenErrors();
19477
+ if (phase.step === "deposit") {
19478
+ dispatch({ type: "SET_SETUP_DEPOSIT_AMOUNT", amount: null });
19479
+ dispatch({ type: "CLEAR_SETUP_DEPOSIT_TOKEN" });
19480
+ dispatch({ type: "SET_SETUP_FLOW_SCREEN", screen: null });
19481
+ }
19439
19482
  dispatch({ type: "SET_USER_INTENT", intent: phase });
19440
19483
  },
19441
19484
  onAddProviderFromDeposit: (amount) => {
@@ -19449,6 +19492,11 @@ function BlinkPaymentInner({
19449
19492
  authExecutor.cancelPendingExecution();
19450
19493
  clearScreenErrors();
19451
19494
  dispatch({ type: "RESTORE_SELECTION" });
19495
+ dispatch({ type: "SET_SETUP_DEPOSIT_AMOUNT", amount: null });
19496
+ dispatch({ type: "CLEAR_SETUP_DEPOSIT_TOKEN" });
19497
+ dispatch({ type: "SET_SETUP_FLOW_SCREEN", screen: null });
19498
+ dispatch({ type: "DESKTOP_WAIT_CLEARED" });
19499
+ dispatch({ type: "SET_STANDARD_DESKTOP_INLINE_OPEN_WALLET", value: false });
19452
19500
  dispatch({ type: "SET_USER_INTENT", intent: { step: "deposit" } });
19453
19501
  },
19454
19502
  onSelectSourceChainChange: sourceSelection.handleSelectSourceChainChange,
@@ -19461,6 +19509,7 @@ function BlinkPaymentInner({
19461
19509
  onPrepareTokenAuthorization: provider.handlePrepareTokenAuthorization,
19462
19510
  onCommitTokenAuthorization: provider.handleCommitTokenAuthorization,
19463
19511
  onLogin: () => dispatch({ type: "REQUEST_LOGIN" }),
19512
+ onCancelLogin: () => dispatch({ type: "CANCEL_LOGIN_REQUEST" }),
19464
19513
  onSetDepositAmount: handleSetDepositAmount,
19465
19514
  onSetDepositToken: handleSetDepositToken,
19466
19515
  onConfirmSetupDeposit: handleConfirmSetupDeposit
@@ -19492,6 +19541,7 @@ function BlinkPaymentInner({
19492
19541
  authenticated: effectiveAuthenticated,
19493
19542
  passkeyLoading: auth.passkeyLoginStatus !== "initial" && auth.passkeyLoginStatus !== "done" && auth.passkeyLoginStatus !== "error" || auth.passkeySignupStatus !== "initial" && auth.passkeySignupStatus !== "done" && auth.passkeySignupStatus !== "error" || auth.passkeySignupPopupActive,
19494
19543
  isDesktop,
19544
+ isMobileApp: isMobileApp ?? false,
19495
19545
  merchantName,
19496
19546
  onBack,
19497
19547
  onDismiss,