@swype-org/react-sdk 0.2.226 → 0.2.232

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
@@ -1592,6 +1592,93 @@ __export(api_exports, {
1592
1592
  updateUserConfigBySession: () => updateUserConfigBySession,
1593
1593
  waitForActionTransactionReceipt: () => waitForActionTransactionReceipt
1594
1594
  });
1595
+ var DEBUG_BUFFER_CAPACITY = 200;
1596
+ var nextId = 1;
1597
+ var entries = [];
1598
+ var listeners = /* @__PURE__ */ new Set();
1599
+ function notify() {
1600
+ for (const listener of listeners) {
1601
+ try {
1602
+ listener();
1603
+ } catch (err) {
1604
+ console.error("[blink-sdk][debug-log] listener threw:", err);
1605
+ }
1606
+ }
1607
+ }
1608
+ function appendDebug(level, message, data) {
1609
+ const entry = {
1610
+ id: nextId++,
1611
+ ts: Date.now(),
1612
+ level,
1613
+ message,
1614
+ data
1615
+ };
1616
+ const next = entries.length >= DEBUG_BUFFER_CAPACITY ? entries.slice(entries.length - DEBUG_BUFFER_CAPACITY + 1) : entries.slice();
1617
+ next.push(entry);
1618
+ entries = next;
1619
+ const prefix = "[blink-sdk][debug]";
1620
+ const sink = level === "error" ? console.error : level === "warn" ? console.warn : console.info;
1621
+ if (data !== void 0) {
1622
+ sink(`${prefix} ${message}`, data);
1623
+ } else {
1624
+ sink(`${prefix} ${message}`);
1625
+ }
1626
+ notify();
1627
+ }
1628
+ function subscribeDebug(listener) {
1629
+ listeners.add(listener);
1630
+ return () => {
1631
+ listeners.delete(listener);
1632
+ };
1633
+ }
1634
+ function getDebugEntries() {
1635
+ return entries;
1636
+ }
1637
+ function clearDebugEntries() {
1638
+ entries = [];
1639
+ notify();
1640
+ }
1641
+ function useBlinkDebugLog() {
1642
+ return useSyncExternalStore(subscribeDebug, getDebugEntries, getDebugEntries);
1643
+ }
1644
+
1645
+ // src/fetchWithRetry.ts
1646
+ var DEFAULT_MAX_RETRIES = 3;
1647
+ var DEFAULT_BASE_DELAY_MS = 500;
1648
+ var DEFAULT_MAX_JITTER_MS = 200;
1649
+ function isNetworkTypeError(err) {
1650
+ return err instanceof TypeError && /fetch|network|load failed/i.test(err.message);
1651
+ }
1652
+ async function fetchWithRetry(input, init, options) {
1653
+ const maxRetries = DEFAULT_MAX_RETRIES;
1654
+ const baseDelayMs = DEFAULT_BASE_DELAY_MS;
1655
+ const maxJitterMs = DEFAULT_MAX_JITTER_MS;
1656
+ const label = String(input).replace(/https?:\/\/[^/]+/, "");
1657
+ let lastError;
1658
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1659
+ try {
1660
+ return await fetch(input, init);
1661
+ } catch (err) {
1662
+ lastError = err;
1663
+ if (!isNetworkTypeError(err)) {
1664
+ throw err;
1665
+ }
1666
+ if (attempt < maxRetries) {
1667
+ const delay = baseDelayMs * Math.pow(2, attempt) + Math.random() * maxJitterMs;
1668
+ appendDebug("warn", `fetchWithRetry: network error, retrying ${label}`, {
1669
+ attempt: attempt + 1,
1670
+ maxRetries,
1671
+ delayMs: Math.round(delay),
1672
+ error: err instanceof Error ? err.message : String(err)
1673
+ });
1674
+ await new Promise((resolve) => setTimeout(resolve, delay));
1675
+ }
1676
+ }
1677
+ }
1678
+ throw lastError;
1679
+ }
1680
+
1681
+ // src/api.ts
1595
1682
  async function throwApiError(res) {
1596
1683
  const body = await res.json().catch(() => null);
1597
1684
  const detail = body?.error ?? body;
@@ -1604,13 +1691,13 @@ async function fetchProviders(apiBaseUrl, token) {
1604
1691
  if (token) {
1605
1692
  headers.Authorization = `Bearer ${token}`;
1606
1693
  }
1607
- const res = await fetch(`${apiBaseUrl}/v1/providers`, { headers });
1694
+ const res = await fetchWithRetry(`${apiBaseUrl}/v1/providers`, { headers });
1608
1695
  if (!res.ok) await throwApiError(res);
1609
1696
  const data = await res.json();
1610
1697
  return data.items;
1611
1698
  }
1612
1699
  async function fetchChains(apiBaseUrl, token) {
1613
- const res = await fetch(`${apiBaseUrl}/v1/chains`, {
1700
+ const res = await fetchWithRetry(`${apiBaseUrl}/v1/chains`, {
1614
1701
  headers: { Authorization: `Bearer ${token}` }
1615
1702
  });
1616
1703
  if (!res.ok) await throwApiError(res);
@@ -1619,7 +1706,7 @@ async function fetchChains(apiBaseUrl, token) {
1619
1706
  }
1620
1707
  async function fetchAccounts(apiBaseUrl, token, credentialId) {
1621
1708
  const params = new URLSearchParams({ credentialId });
1622
- const res = await fetch(`${apiBaseUrl}/v1/accounts?${params.toString()}`, {
1709
+ const res = await fetchWithRetry(`${apiBaseUrl}/v1/accounts?${params.toString()}`, {
1623
1710
  headers: { Authorization: `Bearer ${token}` }
1624
1711
  });
1625
1712
  if (!res.ok) await throwApiError(res);
@@ -1628,7 +1715,7 @@ async function fetchAccounts(apiBaseUrl, token, credentialId) {
1628
1715
  }
1629
1716
  async function fetchAccount(apiBaseUrl, token, accountId, credentialId) {
1630
1717
  const params = new URLSearchParams({ credentialId });
1631
- const res = await fetch(`${apiBaseUrl}/v1/accounts/${accountId}?${params.toString()}`, {
1718
+ const res = await fetchWithRetry(`${apiBaseUrl}/v1/accounts/${accountId}?${params.toString()}`, {
1632
1719
  headers: { Authorization: `Bearer ${token}` }
1633
1720
  });
1634
1721
  if (!res.ok) await throwApiError(res);
@@ -1770,7 +1857,7 @@ async function postTransferQuote(apiBaseUrl, bearerToken, params) {
1770
1857
  return await res.json();
1771
1858
  }
1772
1859
  async function fetchMerchantPublicKey(apiBaseUrl, merchantId) {
1773
- const res = await fetch(
1860
+ const res = await fetchWithRetry(
1774
1861
  `${apiBaseUrl}/v1/merchants/${encodeURIComponent(merchantId)}/public-key`
1775
1862
  );
1776
1863
  if (!res.ok) await throwApiError(res);
@@ -1780,7 +1867,7 @@ async function fetchTransfer(apiBaseUrl, token, transferId, authorizationSession
1780
1867
  if (!token && !authorizationSessionToken) {
1781
1868
  throw new Error("Missing auth credentials for transfer fetch.");
1782
1869
  }
1783
- const res = await fetch(`${apiBaseUrl}/v1/transfers/${transferId}`, {
1870
+ const res = await fetchWithRetry(`${apiBaseUrl}/v1/transfers/${transferId}`, {
1784
1871
  headers: {
1785
1872
  ...token ? { Authorization: `Bearer ${token}` } : {},
1786
1873
  ...authorizationSessionToken ? { "x-authorization-session-token": authorizationSessionToken } : {}
@@ -1808,14 +1895,14 @@ async function signTransfer(apiBaseUrl, token, transferId, signedTransfer, autho
1808
1895
  return await res.json();
1809
1896
  }
1810
1897
  async function fetchAuthorizationSession(apiBaseUrl, sessionId) {
1811
- const res = await fetch(
1898
+ const res = await fetchWithRetry(
1812
1899
  `${apiBaseUrl}/v1/authorization-sessions/${sessionId}`
1813
1900
  );
1814
1901
  if (!res.ok) await throwApiError(res);
1815
1902
  return await res.json();
1816
1903
  }
1817
1904
  async function fetchAuthorizationSessionByToken(apiBaseUrl, token) {
1818
- const res = await fetch(
1905
+ const res = await fetchWithRetry(
1819
1906
  `${apiBaseUrl}/v1/authorization-sessions?token=${encodeURIComponent(token)}`
1820
1907
  );
1821
1908
  if (!res.ok) await throwApiError(res);
@@ -1833,7 +1920,7 @@ async function registerPasskey(apiBaseUrl, token, credentialId, publicKey) {
1833
1920
  if (!res.ok) await throwApiError(res);
1834
1921
  }
1835
1922
  async function reportPasskeyActivity(apiBaseUrl, token, credentialId) {
1836
- const res = await fetch(`${apiBaseUrl}/v1/users/config/passkey`, {
1923
+ const res = await fetchWithRetry(`${apiBaseUrl}/v1/users/config/passkey`, {
1837
1924
  method: "PATCH",
1838
1925
  headers: {
1839
1926
  "Content-Type": "application/json",
@@ -1844,7 +1931,7 @@ async function reportPasskeyActivity(apiBaseUrl, token, credentialId) {
1844
1931
  if (!res.ok) await throwApiError(res);
1845
1932
  }
1846
1933
  async function fetchUserConfig(apiBaseUrl, token) {
1847
- const res = await fetch(`${apiBaseUrl}/v1/users/config`, {
1934
+ const res = await fetchWithRetry(`${apiBaseUrl}/v1/users/config`, {
1848
1935
  headers: { Authorization: `Bearer ${token}` }
1849
1936
  });
1850
1937
  if (!res.ok) await throwApiError(res);
@@ -1916,12 +2003,12 @@ async function createManualTransfer(apiBaseUrl, params) {
1916
2003
  return await res.json();
1917
2004
  }
1918
2005
  async function fetchManualTransferSession(apiBaseUrl, sessionId) {
1919
- const res = await fetch(`${apiBaseUrl}/v1/manual-transfers/${sessionId}`);
2006
+ const res = await fetchWithRetry(`${apiBaseUrl}/v1/manual-transfers/${sessionId}`);
1920
2007
  if (!res.ok) await throwApiError(res);
1921
2008
  return await res.json();
1922
2009
  }
1923
2010
  async function reportActionCompletion(apiBaseUrl, actionId, result) {
1924
- const res = await fetch(
2011
+ const res = await fetchWithRetry(
1925
2012
  `${apiBaseUrl}/v1/authorization-actions/${actionId}`,
1926
2013
  {
1927
2014
  method: "PATCH",
@@ -1945,7 +2032,7 @@ async function waitForActionTransactionReceipt(apiBaseUrl, actionId, txHash) {
1945
2032
  return await res.json();
1946
2033
  }
1947
2034
  async function probeActionCompletion(apiBaseUrl, actionId) {
1948
- const res = await fetch(
2035
+ const res = await fetchWithRetry(
1949
2036
  `${apiBaseUrl}/v1/authorization-actions/${actionId}`,
1950
2037
  {
1951
2038
  method: "PATCH",
@@ -2785,55 +2872,6 @@ async function pollWalletCallsStatus(walletClient, callsId, options = {}) {
2785
2872
  `Batch transaction did not confirm within ${maxAttempts * pollIntervalMs}ms. Last wallet status: ${lastStatusStr}. Please try again.`
2786
2873
  );
2787
2874
  }
2788
- var DEBUG_BUFFER_CAPACITY = 200;
2789
- var nextId = 1;
2790
- var entries = [];
2791
- var listeners = /* @__PURE__ */ new Set();
2792
- function notify() {
2793
- for (const listener of listeners) {
2794
- try {
2795
- listener();
2796
- } catch (err) {
2797
- console.error("[blink-sdk][debug-log] listener threw:", err);
2798
- }
2799
- }
2800
- }
2801
- function appendDebug(level, message, data) {
2802
- const entry = {
2803
- id: nextId++,
2804
- ts: Date.now(),
2805
- level,
2806
- message,
2807
- data
2808
- };
2809
- const next = entries.length >= DEBUG_BUFFER_CAPACITY ? entries.slice(entries.length - DEBUG_BUFFER_CAPACITY + 1) : entries.slice();
2810
- next.push(entry);
2811
- entries = next;
2812
- const prefix = "[blink-sdk][debug]";
2813
- const sink = level === "error" ? console.error : level === "warn" ? console.warn : console.info;
2814
- if (data !== void 0) {
2815
- sink(`${prefix} ${message}`, data);
2816
- } else {
2817
- sink(`${prefix} ${message}`);
2818
- }
2819
- notify();
2820
- }
2821
- function subscribeDebug(listener) {
2822
- listeners.add(listener);
2823
- return () => {
2824
- listeners.delete(listener);
2825
- };
2826
- }
2827
- function getDebugEntries() {
2828
- return entries;
2829
- }
2830
- function clearDebugEntries() {
2831
- entries = [];
2832
- notify();
2833
- }
2834
- function useBlinkDebugLog() {
2835
- return useSyncExternalStore(subscribeDebug, getDebugEntries, getDebugEntries);
2836
- }
2837
2875
 
2838
2876
  // src/withWatchdog.ts
2839
2877
  var DEFAULT_WATCHDOG_INTERVAL_MS = 2e4;
@@ -3536,6 +3574,10 @@ function advanceTrackedEvmNonce(nonceTracker, trackerKey, nextNonce) {
3536
3574
  nonceTracker.set(trackerKey, current == null ? nextNonce : Math.max(current, nextNonce));
3537
3575
  }
3538
3576
  async function waitForWalletClient(wagmiConfig, params = {}) {
3577
+ const initialAccount = getAccount(wagmiConfig);
3578
+ if (!initialAccount.isConnected) {
3579
+ await reconnect(wagmiConfig).catch(() => []);
3580
+ }
3539
3581
  for (let i = 0; i < WALLET_CLIENT_MAX_ATTEMPTS; i++) {
3540
3582
  try {
3541
3583
  const account = getAccount(wagmiConfig);
@@ -6129,7 +6171,7 @@ function assertLinkedTransferBridgeExecuted(params) {
6129
6171
  `Transfer session ${transferSessionId} has no EXECUTE_BRIDGE action. The bridge transaction was never presented to the wallet.`
6130
6172
  );
6131
6173
  }
6132
- if (!completedIds.has(bridgeAction.id)) {
6174
+ if (!completedIds.has(bridgeAction.id) && bridgeAction.status !== "COMPLETED") {
6133
6175
  throw new Error(
6134
6176
  `Deposit flow finished without executing the bridge transaction (action ${bridgeAction.id} on session ${transferSessionId}).`
6135
6177
  );
@@ -6137,6 +6179,47 @@ function assertLinkedTransferBridgeExecuted(params) {
6137
6179
  }
6138
6180
  }
6139
6181
 
6182
+ // src/authorizationOrchestratorOrdering.ts
6183
+ function getPendingActions2(session, completedIds) {
6184
+ return session.actions.filter((a) => a.status === "PENDING" && !completedIds.has(a.id)).sort((a, b) => a.orderIndex - b.orderIndex);
6185
+ }
6186
+ function isSvmSetupAction(action) {
6187
+ if (action.type === "APPROVE_SPL") {
6188
+ return true;
6189
+ }
6190
+ return action.type === "OPEN_PROVIDER" && action.metadata?.chainFamily === "svm";
6191
+ }
6192
+ function isSvmTransferBridgeAction(action) {
6193
+ return action.type === "EXECUTE_BRIDGE" && action.metadata?.chainFamily === "svm";
6194
+ }
6195
+ function isEvmBridgeAction(action) {
6196
+ return action.type === "EXECUTE_BRIDGE" && action.metadata?.chainFamily !== "svm";
6197
+ }
6198
+ function isEvmAccountAction(action) {
6199
+ return action.type === "SIGN_PERMIT2" || action.type === "APPROVE_PERMIT2";
6200
+ }
6201
+ function getMergedPending(sessions, completedIds) {
6202
+ const allActions = [];
6203
+ for (const { session } of sessions) {
6204
+ allActions.push(...getPendingActions2(session, completedIds));
6205
+ }
6206
+ const hasPendingSvmSetupAction = allActions.some((action) => isSvmSetupAction(action));
6207
+ const hasPendingEvmAccountAction = allActions.some((action) => isEvmAccountAction(action));
6208
+ return allActions.sort((a, b) => {
6209
+ const leftIsDeferredSvmBridge = hasPendingSvmSetupAction && isSvmTransferBridgeAction(a);
6210
+ const rightIsDeferredSvmBridge = hasPendingSvmSetupAction && isSvmTransferBridgeAction(b);
6211
+ if (leftIsDeferredSvmBridge !== rightIsDeferredSvmBridge) {
6212
+ return leftIsDeferredSvmBridge ? 1 : -1;
6213
+ }
6214
+ const leftIsDeferredEvmBridge = hasPendingEvmAccountAction && isEvmBridgeAction(a);
6215
+ const rightIsDeferredEvmBridge = hasPendingEvmAccountAction && isEvmBridgeAction(b);
6216
+ if (leftIsDeferredEvmBridge !== rightIsDeferredEvmBridge) {
6217
+ return leftIsDeferredEvmBridge ? 1 : -1;
6218
+ }
6219
+ return a.orderIndex - b.orderIndex;
6220
+ });
6221
+ }
6222
+
6140
6223
  // src/hooks/useAuthorizationOrchestrator.ts
6141
6224
  var ACTION_POLL_INTERVAL_MS2 = 500;
6142
6225
  var ACTION_POLL_MAX_RETRIES2 = 20;
@@ -6150,6 +6233,7 @@ function useAuthorizationOrchestrator(deps) {
6150
6233
  const { authExecutor } = deps;
6151
6234
  const pendingSessionIdsRef = useRef([]);
6152
6235
  const lastRunRef = useRef(null);
6236
+ const inflightRunRef = useRef(null);
6153
6237
  const [pendingSelectSourceAction, setPendingSelectSourceAction] = useState(null);
6154
6238
  const [pendingOneTapAction, setPendingOneTapAction] = useState(null);
6155
6239
  const [orchestratorCompleted, setOrchestratorCompleted] = useState(false);
@@ -6225,7 +6309,7 @@ function useAuthorizationOrchestrator(deps) {
6225
6309
  }
6226
6310
  oneTapPauseRequestedRef.current = false;
6227
6311
  }, []);
6228
- const run = useCallback(
6312
+ const runInternal = useCallback(
6229
6313
  async (sessionId, options) => {
6230
6314
  const apiBaseUrl = resolvedApiBaseUrl;
6231
6315
  if (!apiBaseUrl) {
@@ -6857,6 +6941,21 @@ function useAuthorizationOrchestrator(deps) {
6857
6941
  },
6858
6942
  [resolvedApiBaseUrl, authExecutor, waitForOneTapPause, waitForSourceSelection]
6859
6943
  );
6944
+ const run = useCallback(
6945
+ (sessionId, options) => {
6946
+ const promise = runInternal(sessionId, options);
6947
+ if (inflightRunRef.current === null) {
6948
+ inflightRunRef.current = promise;
6949
+ void promise.finally(() => {
6950
+ if (inflightRunRef.current === promise) {
6951
+ inflightRunRef.current = null;
6952
+ }
6953
+ });
6954
+ }
6955
+ return promise;
6956
+ },
6957
+ [runInternal]
6958
+ );
6860
6959
  const restart = useCallback(async () => {
6861
6960
  const lastRun = lastRunRef.current;
6862
6961
  if (!lastRun) {
@@ -6865,12 +6964,20 @@ function useAuthorizationOrchestrator(deps) {
6865
6964
  appendDebug("info", "orchestrator:restart", {
6866
6965
  sessionId: lastRun.sessionId
6867
6966
  });
6967
+ const inflight = inflightRunRef.current;
6968
+ if (inflight) {
6969
+ cancelPendingFlow();
6970
+ try {
6971
+ await inflight;
6972
+ } catch {
6973
+ }
6974
+ }
6868
6975
  authExecutor.setError(null);
6869
6976
  return run(lastRun.sessionId, {
6870
6977
  ...lastRun.options,
6871
6978
  probeBeforePrompt: true
6872
6979
  });
6873
- }, [authExecutor, run]);
6980
+ }, [authExecutor, run, cancelPendingFlow]);
6874
6981
  return {
6875
6982
  run,
6876
6983
  restart,
@@ -6960,30 +7067,6 @@ async function waitForBatchableActionsReady(options) {
6960
7067
  }
6961
7068
  return batchable.map((action) => updatedActions.get(action.id) ?? action);
6962
7069
  }
6963
- function getMergedPending(sessions, completedIds) {
6964
- const allActions = [];
6965
- for (const { session } of sessions) {
6966
- allActions.push(...getPendingActions(session, completedIds));
6967
- }
6968
- const hasPendingSvmSetupAction = allActions.some((action) => isSvmSetupAction(action));
6969
- return allActions.sort((a, b) => {
6970
- const leftIsDeferredSvmBridge = hasPendingSvmSetupAction && isSvmTransferBridgeAction(a);
6971
- const rightIsDeferredSvmBridge = hasPendingSvmSetupAction && isSvmTransferBridgeAction(b);
6972
- if (leftIsDeferredSvmBridge !== rightIsDeferredSvmBridge) {
6973
- return leftIsDeferredSvmBridge ? 1 : -1;
6974
- }
6975
- return a.orderIndex - b.orderIndex;
6976
- });
6977
- }
6978
- function isSvmSetupAction(action) {
6979
- if (action.type === "APPROVE_SPL") {
6980
- return true;
6981
- }
6982
- return action.type === "OPEN_PROVIDER" && action.metadata?.chainFamily === "svm";
6983
- }
6984
- function isSvmTransferBridgeAction(action) {
6985
- return action.type === "EXECUTE_BRIDGE" && action.metadata?.chainFamily === "svm";
6986
- }
6987
7070
  function getWalletConnectRuntimeKeyForAction(action, ownerSessionId, sessions) {
6988
7071
  const metadataKey = action?.metadata?.walletConnectAccountId;
6989
7072
  if (typeof metadataKey === "string" && metadataKey.length > 0) {
@@ -7512,6 +7595,7 @@ function createInitialState(config) {
7512
7595
  loginRequested: false,
7513
7596
  standardDesktopInlineOpenWallet: false,
7514
7597
  desktopWait: null,
7598
+ setupAuthorizationSessionId: null,
7515
7599
  mobileTokenAuthorizationPending: false,
7516
7600
  privyReady: false,
7517
7601
  privyAuthenticated: false,
@@ -7556,6 +7640,7 @@ function clearAuthenticatedSessionState(state) {
7556
7640
  loginRequested: false,
7557
7641
  standardDesktopInlineOpenWallet: false,
7558
7642
  desktopWait: null,
7643
+ setupAuthorizationSessionId: null,
7559
7644
  mobileTokenAuthorizationPending: false,
7560
7645
  setupDepositAmount: null,
7561
7646
  setupDepositToken: null,
@@ -7751,14 +7836,15 @@ function applyAction(state, action) {
7751
7836
  case "TRANSFER_CREATED":
7752
7837
  return { ...state, transfer: action.transfer, pendingTransferId: null };
7753
7838
  case "TRANSFER_SIGNED":
7754
- return { ...state, transfer: action.transfer };
7839
+ return { ...state, transfer: action.transfer, setupAuthorizationSessionId: null };
7755
7840
  case "TRANSFER_COMPLETED":
7756
7841
  return {
7757
7842
  ...state,
7758
7843
  transfer: action.transfer,
7759
7844
  pendingTransferId: null,
7760
7845
  mobileFlow: false,
7761
- deeplinkUri: null
7846
+ deeplinkUri: null,
7847
+ setupAuthorizationSessionId: null
7762
7848
  };
7763
7849
  case "TRANSFER_FAILED":
7764
7850
  return {
@@ -7804,7 +7890,8 @@ function applyAction(state, action) {
7804
7890
  deeplinkUri: null,
7805
7891
  mobileTokenAuthorizationPending: false,
7806
7892
  guestWalletPrepared: null,
7807
- guestWalletDeeplinksPreparing: false
7893
+ guestWalletDeeplinksPreparing: false,
7894
+ setupAuthorizationSessionId: null
7808
7895
  };
7809
7896
  case "MOBILE_SIGN_READY":
7810
7897
  return {
@@ -7925,6 +8012,10 @@ function applyAction(state, action) {
7925
8012
  walletName: action.walletName,
7926
8013
  walletLogoUrl: action.walletLogoUrl
7927
8014
  },
8015
+ // Mirror sessionId into the longer-lived slice so the wallet
8016
+ // account switch listener stays armed after `desktopWait` is
8017
+ // cleared by the inline-connect effect.
8018
+ setupAuthorizationSessionId: action.sessionId,
7928
8019
  standardDesktopInlineOpenWallet: true
7929
8020
  };
7930
8021
  case "DESKTOP_WAIT_CLEARED":
@@ -7954,6 +8045,7 @@ function applyAction(state, action) {
7954
8045
  oneTapLimitSavedDuringSetup: false,
7955
8046
  standardDesktopInlineOpenWallet: false,
7956
8047
  desktopWait: null,
8048
+ setupAuthorizationSessionId: null,
7957
8049
  savedSelection: null,
7958
8050
  setupDepositAmount: null,
7959
8051
  setupDepositToken: null,
@@ -17333,6 +17425,38 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
17333
17425
  };
17334
17426
  }
17335
17427
 
17428
+ // src/accountSwitchHelpers.ts
17429
+ var OPEN_PROVIDER_REPLACEMENT_CONFLICT_CODE = "OPEN_PROVIDER_REPLACEMENT_CONFLICT";
17430
+ var ACCOUNT_SWITCH_CONFLICT_MESSAGE = "You can't switch accounts after authorizing the source token. Please switch back to your previous account in your wallet.";
17431
+ async function replaceOpenProviderForAccountSwitch(input) {
17432
+ try {
17433
+ const session = await fetchAuthorizationSession(
17434
+ input.apiBaseUrl,
17435
+ input.sessionId
17436
+ );
17437
+ const openProvider = session.actions.find((a) => a.type === "OPEN_PROVIDER");
17438
+ if (!openProvider) {
17439
+ return { status: "no-open-provider" };
17440
+ }
17441
+ const result = { accounts: [...input.accounts] };
17442
+ if (input.chainId != null) {
17443
+ result.chainId = `0x${input.chainId.toString(16)}`;
17444
+ }
17445
+ const updated = await reportActionCompletion(
17446
+ input.apiBaseUrl,
17447
+ openProvider.id,
17448
+ result
17449
+ );
17450
+ return { status: "success", session: updated };
17451
+ } catch (err) {
17452
+ const error = err instanceof Error ? err : new Error(String(err));
17453
+ if (error.message.includes(OPEN_PROVIDER_REPLACEMENT_CONFLICT_CODE)) {
17454
+ return { status: "conflict" };
17455
+ }
17456
+ return { status: "error", error };
17457
+ }
17458
+ }
17459
+
17336
17460
  // src/hooks/providerSelectionGuards.ts
17337
17461
  function resolveSetupFlowDepositAmount({
17338
17462
  hasActiveWallet: hasActiveWallet2,
@@ -18582,6 +18706,33 @@ function useProviderHandlers(deps) {
18582
18706
  setupFlowDepositAmount,
18583
18707
  dispatch
18584
18708
  ]);
18709
+ const handleWalletAccountSwitch = useCallback(async (change, sessionId) => {
18710
+ const outcome = await replaceOpenProviderForAccountSwitch({
18711
+ apiBaseUrl,
18712
+ sessionId,
18713
+ accounts: change.accounts,
18714
+ chainId: change.chainId
18715
+ });
18716
+ if (outcome.status === "success") {
18717
+ dispatch({ type: "CLEAR_SETUP_DEPOSIT_TOKEN" });
18718
+ try {
18719
+ await orchestrator.restart();
18720
+ } catch (err) {
18721
+ captureException(err);
18722
+ onError?.(err instanceof Error ? err.message : "Failed to refresh authorization session.");
18723
+ }
18724
+ return;
18725
+ }
18726
+ if (outcome.status === "conflict") {
18727
+ onError?.(ACCOUNT_SWITCH_CONFLICT_MESSAGE);
18728
+ return;
18729
+ }
18730
+ if (outcome.status === "error") {
18731
+ captureException(outcome.error);
18732
+ onError?.(outcome.error.message);
18733
+ return;
18734
+ }
18735
+ }, [apiBaseUrl, dispatch, orchestrator, onError]);
18585
18736
  return {
18586
18737
  handlePrepareProvider,
18587
18738
  handleSelectProvider,
@@ -18594,7 +18745,8 @@ function useProviderHandlers(deps) {
18594
18745
  handleAuthorizeToken,
18595
18746
  handlePrepareTokenAuthorization,
18596
18747
  handleCommitTokenAuthorization,
18597
- handlePrepareGuestDeeplinks
18748
+ handlePrepareGuestDeeplinks,
18749
+ handleWalletAccountSwitch
18598
18750
  };
18599
18751
  }
18600
18752
  function useOneTapSetupHandlers(deps) {
@@ -19658,6 +19810,40 @@ function useDepositFeeEstimate({
19658
19810
  }, [fetchQuote]);
19659
19811
  return { quoteId, quoteFee, quoteLoading, quoteError };
19660
19812
  }
19813
+ function useWalletAccountSwitchEffect(deps) {
19814
+ const { enabled = true, isDesktop = true, onAccountChanged } = deps;
19815
+ const account = useAccount();
19816
+ const address = account.address ?? null;
19817
+ const chainId = account.chainId ?? null;
19818
+ const connectorId = account.connector?.id ?? null;
19819
+ const addresses = account.addresses;
19820
+ const baselineRef = useRef(null);
19821
+ useEffect(() => {
19822
+ if (!enabled || !isDesktop) {
19823
+ baselineRef.current = null;
19824
+ return;
19825
+ }
19826
+ if (!address) {
19827
+ return;
19828
+ }
19829
+ if (baselineRef.current === null) {
19830
+ baselineRef.current = address;
19831
+ return;
19832
+ }
19833
+ if (baselineRef.current.toLowerCase() === address.toLowerCase()) {
19834
+ return;
19835
+ }
19836
+ const previous = baselineRef.current;
19837
+ baselineRef.current = address;
19838
+ void onAccountChanged({
19839
+ previousAddress: previous,
19840
+ nextAddress: address,
19841
+ connectorId: connectorId ?? "injected",
19842
+ chainId,
19843
+ accounts: addresses ?? [address]
19844
+ });
19845
+ }, [enabled, isDesktop, address, chainId, connectorId, addresses, onAccountChanged]);
19846
+ }
19661
19847
  function usePersistAmountToActiveSession({
19662
19848
  apiBaseUrl,
19663
19849
  accounts,
@@ -19957,6 +20143,17 @@ function BlinkPaymentInner({
19957
20143
  activeCredentialId: state.activeCredentialId ?? void 0,
19958
20144
  idempotencyKey
19959
20145
  });
20146
+ const accountSwitchSessionId = state.setupAuthorizationSessionId;
20147
+ const handleProviderWalletAccountSwitch = provider.handleWalletAccountSwitch;
20148
+ const onWalletAccountChanged = useCallback(async (change) => {
20149
+ if (!accountSwitchSessionId) return;
20150
+ await handleProviderWalletAccountSwitch(change, accountSwitchSessionId);
20151
+ }, [handleProviderWalletAccountSwitch, accountSwitchSessionId]);
20152
+ useWalletAccountSwitchEffect({
20153
+ enabled: accountSwitchSessionId != null,
20154
+ isDesktop,
20155
+ onAccountChanged: onWalletAccountChanged
20156
+ });
19960
20157
  const clearLocalSessionArtifacts = useCallback(() => {
19961
20158
  popupAuthRef.current = null;
19962
20159
  clearPopupAuth();
@@ -20393,6 +20590,6 @@ function getDeviceBiometricUnlockText() {
20393
20590
  return FALLBACK;
20394
20591
  }
20395
20592
 
20396
- export { AdvancedSourceScreen, AuthorizationSessionCancelledError, BLINK_ERROR_ILLUSTRATION, BLINK_LOGO, BLINK_MASCOT, BLINK_PASSKEY_ILLUSTRATION, BLINK_SUCCESS_ILLUSTRATION, BlinkErrorScreen, BlinkInitialLoadingScreen, BlinkLoadingScreen, BlinkPayment, BlinkProvider, ConfirmSignScreen, DepositCompleteScreen, DepositScreen, DepositTransferStatusScreen, GuestTokenPickerScreen, IconCircle, InfoBanner, LoginScreen, OpenWalletScreen, OtpVerifyScreen, OutlineButton, PASSKEY_READY_ILLUSTRATION, PasskeyIframeBlockedError, PasskeyPopupWelcomeScreen, PasskeyReadyScreen, PasskeyScreen, PoweredByFooter, PrimaryButton, ScreenHeader, ScreenLayout, SelectDepositSourceScreen, SelectSourceScreen, SettingsMenu, SetupDepositScreen, SetupScreen, SetupSelectDepositSourceScreen, SetupTransferStatusScreen, Spinner, StepList, StepRenderer, SuccessScreen, TokenPickerScreen, VerifyPasskeyScreen, WalletPickerScreen, appendDebug, api_exports as blinkApi, clearDebugEntries, createInitialState, credentialIdBase64ToBytes, darkTheme, darkThemeNew, darkTransparentTheme, darkTransparentThemeNew, deviceHasPasskey, encodePermit2ApproveCalldata, findDevicePasskey, findDevicePasskeyViaPopup, getAtomicBatchSupportDebugInfo, getDebugEntries, getDeviceBiometricUnlockText, getTheme, getThemeBase, getWalletCapabilities, isAuthorizationSessionCancelled, isExpectedAuthorizationCancellation, isTerminalTransferStatus, isTransferAwaitingCompletion, isTransparentTheme, isUserDismissedAuthorizationError, isVisibleUsdAmountAtTwoDecimals, lightTheme, lightThemeNew, lightTransparentTheme, lightTransparentThemeNew, mapGuestPickerEntries, resolvePasskeyRpId, screenForPhase, subscribeDebug, supportsAtomicBatch, supportsPaymasterService, useAuthorizationExecutor, useAuthorizationOrchestrator, useBlinkConfig, useBlinkDebugLog, useBlinkDepositAmount, useTransferPolling, useTransferSigning };
20593
+ export { ACCOUNT_SWITCH_CONFLICT_MESSAGE, AdvancedSourceScreen, AuthorizationSessionCancelledError, BLINK_ERROR_ILLUSTRATION, BLINK_LOGO, BLINK_MASCOT, BLINK_PASSKEY_ILLUSTRATION, BLINK_SUCCESS_ILLUSTRATION, BlinkErrorScreen, BlinkInitialLoadingScreen, BlinkLoadingScreen, BlinkPayment, BlinkProvider, ConfirmSignScreen, DepositCompleteScreen, DepositScreen, DepositTransferStatusScreen, GuestTokenPickerScreen, IconCircle, InfoBanner, LoginScreen, OpenWalletScreen, OtpVerifyScreen, OutlineButton, PASSKEY_READY_ILLUSTRATION, PasskeyIframeBlockedError, PasskeyPopupWelcomeScreen, PasskeyReadyScreen, PasskeyScreen, PoweredByFooter, PrimaryButton, ScreenHeader, ScreenLayout, SelectDepositSourceScreen, SelectSourceScreen, SettingsMenu, SetupDepositScreen, SetupScreen, SetupSelectDepositSourceScreen, SetupTransferStatusScreen, Spinner, StepList, StepRenderer, SuccessScreen, TokenPickerScreen, VerifyPasskeyScreen, WalletPickerScreen, appendDebug, api_exports as blinkApi, clearDebugEntries, createInitialState, credentialIdBase64ToBytes, darkTheme, darkThemeNew, darkTransparentTheme, darkTransparentThemeNew, deviceHasPasskey, encodePermit2ApproveCalldata, findDevicePasskey, findDevicePasskeyViaPopup, getAtomicBatchSupportDebugInfo, getDebugEntries, getDeviceBiometricUnlockText, getTheme, getThemeBase, getWalletCapabilities, isAuthorizationSessionCancelled, isExpectedAuthorizationCancellation, isTerminalTransferStatus, isTransferAwaitingCompletion, isTransparentTheme, isUserDismissedAuthorizationError, isVisibleUsdAmountAtTwoDecimals, lightTheme, lightThemeNew, lightTransparentTheme, lightTransparentThemeNew, mapGuestPickerEntries, replaceOpenProviderForAccountSwitch, resolvePasskeyRpId, screenForPhase, subscribeDebug, supportsAtomicBatch, supportsPaymasterService, useAuthorizationExecutor, useAuthorizationOrchestrator, useBlinkConfig, useBlinkDebugLog, useBlinkDepositAmount, useTransferPolling, useTransferSigning };
20397
20594
  //# sourceMappingURL=index.js.map
20398
20595
  //# sourceMappingURL=index.js.map