@swype-org/react-sdk 0.2.226 → 0.2.233
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +293 -98
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -1
- package/dist/index.d.ts +40 -1
- package/dist/index.js +292 -99
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1616,6 +1616,93 @@ __export(api_exports, {
|
|
|
1616
1616
|
updateUserConfigBySession: () => updateUserConfigBySession,
|
|
1617
1617
|
waitForActionTransactionReceipt: () => waitForActionTransactionReceipt
|
|
1618
1618
|
});
|
|
1619
|
+
var DEBUG_BUFFER_CAPACITY = 200;
|
|
1620
|
+
var nextId = 1;
|
|
1621
|
+
var entries = [];
|
|
1622
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1623
|
+
function notify() {
|
|
1624
|
+
for (const listener of listeners) {
|
|
1625
|
+
try {
|
|
1626
|
+
listener();
|
|
1627
|
+
} catch (err) {
|
|
1628
|
+
console.error("[blink-sdk][debug-log] listener threw:", err);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
function appendDebug(level, message, data) {
|
|
1633
|
+
const entry = {
|
|
1634
|
+
id: nextId++,
|
|
1635
|
+
ts: Date.now(),
|
|
1636
|
+
level,
|
|
1637
|
+
message,
|
|
1638
|
+
data
|
|
1639
|
+
};
|
|
1640
|
+
const next = entries.length >= DEBUG_BUFFER_CAPACITY ? entries.slice(entries.length - DEBUG_BUFFER_CAPACITY + 1) : entries.slice();
|
|
1641
|
+
next.push(entry);
|
|
1642
|
+
entries = next;
|
|
1643
|
+
const prefix = "[blink-sdk][debug]";
|
|
1644
|
+
const sink = level === "error" ? console.error : level === "warn" ? console.warn : console.info;
|
|
1645
|
+
if (data !== void 0) {
|
|
1646
|
+
sink(`${prefix} ${message}`, data);
|
|
1647
|
+
} else {
|
|
1648
|
+
sink(`${prefix} ${message}`);
|
|
1649
|
+
}
|
|
1650
|
+
notify();
|
|
1651
|
+
}
|
|
1652
|
+
function subscribeDebug(listener) {
|
|
1653
|
+
listeners.add(listener);
|
|
1654
|
+
return () => {
|
|
1655
|
+
listeners.delete(listener);
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1658
|
+
function getDebugEntries() {
|
|
1659
|
+
return entries;
|
|
1660
|
+
}
|
|
1661
|
+
function clearDebugEntries() {
|
|
1662
|
+
entries = [];
|
|
1663
|
+
notify();
|
|
1664
|
+
}
|
|
1665
|
+
function useBlinkDebugLog() {
|
|
1666
|
+
return react.useSyncExternalStore(subscribeDebug, getDebugEntries, getDebugEntries);
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
// src/fetchWithRetry.ts
|
|
1670
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
1671
|
+
var DEFAULT_BASE_DELAY_MS = 500;
|
|
1672
|
+
var DEFAULT_MAX_JITTER_MS = 200;
|
|
1673
|
+
function isNetworkTypeError(err) {
|
|
1674
|
+
return err instanceof TypeError && /fetch|network|load failed/i.test(err.message);
|
|
1675
|
+
}
|
|
1676
|
+
async function fetchWithRetry(input, init, options) {
|
|
1677
|
+
const maxRetries = DEFAULT_MAX_RETRIES;
|
|
1678
|
+
const baseDelayMs = DEFAULT_BASE_DELAY_MS;
|
|
1679
|
+
const maxJitterMs = DEFAULT_MAX_JITTER_MS;
|
|
1680
|
+
const label = String(input).replace(/https?:\/\/[^/]+/, "");
|
|
1681
|
+
let lastError;
|
|
1682
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1683
|
+
try {
|
|
1684
|
+
return await fetch(input, init);
|
|
1685
|
+
} catch (err) {
|
|
1686
|
+
lastError = err;
|
|
1687
|
+
if (!isNetworkTypeError(err)) {
|
|
1688
|
+
throw err;
|
|
1689
|
+
}
|
|
1690
|
+
if (attempt < maxRetries) {
|
|
1691
|
+
const delay = baseDelayMs * Math.pow(2, attempt) + Math.random() * maxJitterMs;
|
|
1692
|
+
appendDebug("warn", `fetchWithRetry: network error, retrying ${label}`, {
|
|
1693
|
+
attempt: attempt + 1,
|
|
1694
|
+
maxRetries,
|
|
1695
|
+
delayMs: Math.round(delay),
|
|
1696
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1697
|
+
});
|
|
1698
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
throw lastError;
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
// src/api.ts
|
|
1619
1706
|
async function throwApiError(res) {
|
|
1620
1707
|
const body = await res.json().catch(() => null);
|
|
1621
1708
|
const detail = body?.error ?? body;
|
|
@@ -1628,13 +1715,13 @@ async function fetchProviders(apiBaseUrl, token) {
|
|
|
1628
1715
|
if (token) {
|
|
1629
1716
|
headers.Authorization = `Bearer ${token}`;
|
|
1630
1717
|
}
|
|
1631
|
-
const res = await
|
|
1718
|
+
const res = await fetchWithRetry(`${apiBaseUrl}/v1/providers`, { headers });
|
|
1632
1719
|
if (!res.ok) await throwApiError(res);
|
|
1633
1720
|
const data = await res.json();
|
|
1634
1721
|
return data.items;
|
|
1635
1722
|
}
|
|
1636
1723
|
async function fetchChains(apiBaseUrl, token) {
|
|
1637
|
-
const res = await
|
|
1724
|
+
const res = await fetchWithRetry(`${apiBaseUrl}/v1/chains`, {
|
|
1638
1725
|
headers: { Authorization: `Bearer ${token}` }
|
|
1639
1726
|
});
|
|
1640
1727
|
if (!res.ok) await throwApiError(res);
|
|
@@ -1643,7 +1730,7 @@ async function fetchChains(apiBaseUrl, token) {
|
|
|
1643
1730
|
}
|
|
1644
1731
|
async function fetchAccounts(apiBaseUrl, token, credentialId) {
|
|
1645
1732
|
const params = new URLSearchParams({ credentialId });
|
|
1646
|
-
const res = await
|
|
1733
|
+
const res = await fetchWithRetry(`${apiBaseUrl}/v1/accounts?${params.toString()}`, {
|
|
1647
1734
|
headers: { Authorization: `Bearer ${token}` }
|
|
1648
1735
|
});
|
|
1649
1736
|
if (!res.ok) await throwApiError(res);
|
|
@@ -1652,7 +1739,7 @@ async function fetchAccounts(apiBaseUrl, token, credentialId) {
|
|
|
1652
1739
|
}
|
|
1653
1740
|
async function fetchAccount(apiBaseUrl, token, accountId, credentialId) {
|
|
1654
1741
|
const params = new URLSearchParams({ credentialId });
|
|
1655
|
-
const res = await
|
|
1742
|
+
const res = await fetchWithRetry(`${apiBaseUrl}/v1/accounts/${accountId}?${params.toString()}`, {
|
|
1656
1743
|
headers: { Authorization: `Bearer ${token}` }
|
|
1657
1744
|
});
|
|
1658
1745
|
if (!res.ok) await throwApiError(res);
|
|
@@ -1794,7 +1881,7 @@ async function postTransferQuote(apiBaseUrl, bearerToken, params) {
|
|
|
1794
1881
|
return await res.json();
|
|
1795
1882
|
}
|
|
1796
1883
|
async function fetchMerchantPublicKey(apiBaseUrl, merchantId) {
|
|
1797
|
-
const res = await
|
|
1884
|
+
const res = await fetchWithRetry(
|
|
1798
1885
|
`${apiBaseUrl}/v1/merchants/${encodeURIComponent(merchantId)}/public-key`
|
|
1799
1886
|
);
|
|
1800
1887
|
if (!res.ok) await throwApiError(res);
|
|
@@ -1804,7 +1891,7 @@ async function fetchTransfer(apiBaseUrl, token, transferId, authorizationSession
|
|
|
1804
1891
|
if (!token && !authorizationSessionToken) {
|
|
1805
1892
|
throw new Error("Missing auth credentials for transfer fetch.");
|
|
1806
1893
|
}
|
|
1807
|
-
const res = await
|
|
1894
|
+
const res = await fetchWithRetry(`${apiBaseUrl}/v1/transfers/${transferId}`, {
|
|
1808
1895
|
headers: {
|
|
1809
1896
|
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
1810
1897
|
...authorizationSessionToken ? { "x-authorization-session-token": authorizationSessionToken } : {}
|
|
@@ -1832,14 +1919,14 @@ async function signTransfer(apiBaseUrl, token, transferId, signedTransfer, autho
|
|
|
1832
1919
|
return await res.json();
|
|
1833
1920
|
}
|
|
1834
1921
|
async function fetchAuthorizationSession(apiBaseUrl, sessionId) {
|
|
1835
|
-
const res = await
|
|
1922
|
+
const res = await fetchWithRetry(
|
|
1836
1923
|
`${apiBaseUrl}/v1/authorization-sessions/${sessionId}`
|
|
1837
1924
|
);
|
|
1838
1925
|
if (!res.ok) await throwApiError(res);
|
|
1839
1926
|
return await res.json();
|
|
1840
1927
|
}
|
|
1841
1928
|
async function fetchAuthorizationSessionByToken(apiBaseUrl, token) {
|
|
1842
|
-
const res = await
|
|
1929
|
+
const res = await fetchWithRetry(
|
|
1843
1930
|
`${apiBaseUrl}/v1/authorization-sessions?token=${encodeURIComponent(token)}`
|
|
1844
1931
|
);
|
|
1845
1932
|
if (!res.ok) await throwApiError(res);
|
|
@@ -1857,7 +1944,7 @@ async function registerPasskey(apiBaseUrl, token, credentialId, publicKey) {
|
|
|
1857
1944
|
if (!res.ok) await throwApiError(res);
|
|
1858
1945
|
}
|
|
1859
1946
|
async function reportPasskeyActivity(apiBaseUrl, token, credentialId) {
|
|
1860
|
-
const res = await
|
|
1947
|
+
const res = await fetchWithRetry(`${apiBaseUrl}/v1/users/config/passkey`, {
|
|
1861
1948
|
method: "PATCH",
|
|
1862
1949
|
headers: {
|
|
1863
1950
|
"Content-Type": "application/json",
|
|
@@ -1868,7 +1955,7 @@ async function reportPasskeyActivity(apiBaseUrl, token, credentialId) {
|
|
|
1868
1955
|
if (!res.ok) await throwApiError(res);
|
|
1869
1956
|
}
|
|
1870
1957
|
async function fetchUserConfig(apiBaseUrl, token) {
|
|
1871
|
-
const res = await
|
|
1958
|
+
const res = await fetchWithRetry(`${apiBaseUrl}/v1/users/config`, {
|
|
1872
1959
|
headers: { Authorization: `Bearer ${token}` }
|
|
1873
1960
|
});
|
|
1874
1961
|
if (!res.ok) await throwApiError(res);
|
|
@@ -1940,12 +2027,12 @@ async function createManualTransfer(apiBaseUrl, params) {
|
|
|
1940
2027
|
return await res.json();
|
|
1941
2028
|
}
|
|
1942
2029
|
async function fetchManualTransferSession(apiBaseUrl, sessionId) {
|
|
1943
|
-
const res = await
|
|
2030
|
+
const res = await fetchWithRetry(`${apiBaseUrl}/v1/manual-transfers/${sessionId}`);
|
|
1944
2031
|
if (!res.ok) await throwApiError(res);
|
|
1945
2032
|
return await res.json();
|
|
1946
2033
|
}
|
|
1947
2034
|
async function reportActionCompletion(apiBaseUrl, actionId, result) {
|
|
1948
|
-
const res = await
|
|
2035
|
+
const res = await fetchWithRetry(
|
|
1949
2036
|
`${apiBaseUrl}/v1/authorization-actions/${actionId}`,
|
|
1950
2037
|
{
|
|
1951
2038
|
method: "PATCH",
|
|
@@ -1969,7 +2056,7 @@ async function waitForActionTransactionReceipt(apiBaseUrl, actionId, txHash) {
|
|
|
1969
2056
|
return await res.json();
|
|
1970
2057
|
}
|
|
1971
2058
|
async function probeActionCompletion(apiBaseUrl, actionId) {
|
|
1972
|
-
const res = await
|
|
2059
|
+
const res = await fetchWithRetry(
|
|
1973
2060
|
`${apiBaseUrl}/v1/authorization-actions/${actionId}`,
|
|
1974
2061
|
{
|
|
1975
2062
|
method: "PATCH",
|
|
@@ -2809,55 +2896,6 @@ async function pollWalletCallsStatus(walletClient, callsId, options = {}) {
|
|
|
2809
2896
|
`Batch transaction did not confirm within ${maxAttempts * pollIntervalMs}ms. Last wallet status: ${lastStatusStr}. Please try again.`
|
|
2810
2897
|
);
|
|
2811
2898
|
}
|
|
2812
|
-
var DEBUG_BUFFER_CAPACITY = 200;
|
|
2813
|
-
var nextId = 1;
|
|
2814
|
-
var entries = [];
|
|
2815
|
-
var listeners = /* @__PURE__ */ new Set();
|
|
2816
|
-
function notify() {
|
|
2817
|
-
for (const listener of listeners) {
|
|
2818
|
-
try {
|
|
2819
|
-
listener();
|
|
2820
|
-
} catch (err) {
|
|
2821
|
-
console.error("[blink-sdk][debug-log] listener threw:", err);
|
|
2822
|
-
}
|
|
2823
|
-
}
|
|
2824
|
-
}
|
|
2825
|
-
function appendDebug(level, message, data) {
|
|
2826
|
-
const entry = {
|
|
2827
|
-
id: nextId++,
|
|
2828
|
-
ts: Date.now(),
|
|
2829
|
-
level,
|
|
2830
|
-
message,
|
|
2831
|
-
data
|
|
2832
|
-
};
|
|
2833
|
-
const next = entries.length >= DEBUG_BUFFER_CAPACITY ? entries.slice(entries.length - DEBUG_BUFFER_CAPACITY + 1) : entries.slice();
|
|
2834
|
-
next.push(entry);
|
|
2835
|
-
entries = next;
|
|
2836
|
-
const prefix = "[blink-sdk][debug]";
|
|
2837
|
-
const sink = level === "error" ? console.error : level === "warn" ? console.warn : console.info;
|
|
2838
|
-
if (data !== void 0) {
|
|
2839
|
-
sink(`${prefix} ${message}`, data);
|
|
2840
|
-
} else {
|
|
2841
|
-
sink(`${prefix} ${message}`);
|
|
2842
|
-
}
|
|
2843
|
-
notify();
|
|
2844
|
-
}
|
|
2845
|
-
function subscribeDebug(listener) {
|
|
2846
|
-
listeners.add(listener);
|
|
2847
|
-
return () => {
|
|
2848
|
-
listeners.delete(listener);
|
|
2849
|
-
};
|
|
2850
|
-
}
|
|
2851
|
-
function getDebugEntries() {
|
|
2852
|
-
return entries;
|
|
2853
|
-
}
|
|
2854
|
-
function clearDebugEntries() {
|
|
2855
|
-
entries = [];
|
|
2856
|
-
notify();
|
|
2857
|
-
}
|
|
2858
|
-
function useBlinkDebugLog() {
|
|
2859
|
-
return react.useSyncExternalStore(subscribeDebug, getDebugEntries, getDebugEntries);
|
|
2860
|
-
}
|
|
2861
2899
|
|
|
2862
2900
|
// src/withWatchdog.ts
|
|
2863
2901
|
var DEFAULT_WATCHDOG_INTERVAL_MS = 2e4;
|
|
@@ -3560,6 +3598,10 @@ function advanceTrackedEvmNonce(nonceTracker, trackerKey, nextNonce) {
|
|
|
3560
3598
|
nonceTracker.set(trackerKey, current == null ? nextNonce : Math.max(current, nextNonce));
|
|
3561
3599
|
}
|
|
3562
3600
|
async function waitForWalletClient(wagmiConfig, params = {}) {
|
|
3601
|
+
const initialAccount = core.getAccount(wagmiConfig);
|
|
3602
|
+
if (!initialAccount.isConnected) {
|
|
3603
|
+
await core.reconnect(wagmiConfig).catch(() => []);
|
|
3604
|
+
}
|
|
3563
3605
|
for (let i = 0; i < WALLET_CLIENT_MAX_ATTEMPTS; i++) {
|
|
3564
3606
|
try {
|
|
3565
3607
|
const account = core.getAccount(wagmiConfig);
|
|
@@ -6153,7 +6195,7 @@ function assertLinkedTransferBridgeExecuted(params) {
|
|
|
6153
6195
|
`Transfer session ${transferSessionId} has no EXECUTE_BRIDGE action. The bridge transaction was never presented to the wallet.`
|
|
6154
6196
|
);
|
|
6155
6197
|
}
|
|
6156
|
-
if (!completedIds.has(bridgeAction.id)) {
|
|
6198
|
+
if (!completedIds.has(bridgeAction.id) && bridgeAction.status !== "COMPLETED") {
|
|
6157
6199
|
throw new Error(
|
|
6158
6200
|
`Deposit flow finished without executing the bridge transaction (action ${bridgeAction.id} on session ${transferSessionId}).`
|
|
6159
6201
|
);
|
|
@@ -6161,6 +6203,47 @@ function assertLinkedTransferBridgeExecuted(params) {
|
|
|
6161
6203
|
}
|
|
6162
6204
|
}
|
|
6163
6205
|
|
|
6206
|
+
// src/authorizationOrchestratorOrdering.ts
|
|
6207
|
+
function getPendingActions2(session, completedIds) {
|
|
6208
|
+
return session.actions.filter((a) => a.status === "PENDING" && !completedIds.has(a.id)).sort((a, b) => a.orderIndex - b.orderIndex);
|
|
6209
|
+
}
|
|
6210
|
+
function isSvmSetupAction(action) {
|
|
6211
|
+
if (action.type === "APPROVE_SPL") {
|
|
6212
|
+
return true;
|
|
6213
|
+
}
|
|
6214
|
+
return action.type === "OPEN_PROVIDER" && action.metadata?.chainFamily === "svm";
|
|
6215
|
+
}
|
|
6216
|
+
function isSvmTransferBridgeAction(action) {
|
|
6217
|
+
return action.type === "EXECUTE_BRIDGE" && action.metadata?.chainFamily === "svm";
|
|
6218
|
+
}
|
|
6219
|
+
function isEvmBridgeAction(action) {
|
|
6220
|
+
return action.type === "EXECUTE_BRIDGE" && action.metadata?.chainFamily !== "svm";
|
|
6221
|
+
}
|
|
6222
|
+
function isEvmAccountAction(action) {
|
|
6223
|
+
return action.type === "SIGN_PERMIT2" || action.type === "APPROVE_PERMIT2";
|
|
6224
|
+
}
|
|
6225
|
+
function getMergedPending(sessions, completedIds) {
|
|
6226
|
+
const allActions = [];
|
|
6227
|
+
for (const { session } of sessions) {
|
|
6228
|
+
allActions.push(...getPendingActions2(session, completedIds));
|
|
6229
|
+
}
|
|
6230
|
+
const hasPendingSvmSetupAction = allActions.some((action) => isSvmSetupAction(action));
|
|
6231
|
+
const hasPendingEvmAccountAction = allActions.some((action) => isEvmAccountAction(action));
|
|
6232
|
+
return allActions.sort((a, b) => {
|
|
6233
|
+
const leftIsDeferredSvmBridge = hasPendingSvmSetupAction && isSvmTransferBridgeAction(a);
|
|
6234
|
+
const rightIsDeferredSvmBridge = hasPendingSvmSetupAction && isSvmTransferBridgeAction(b);
|
|
6235
|
+
if (leftIsDeferredSvmBridge !== rightIsDeferredSvmBridge) {
|
|
6236
|
+
return leftIsDeferredSvmBridge ? 1 : -1;
|
|
6237
|
+
}
|
|
6238
|
+
const leftIsDeferredEvmBridge = hasPendingEvmAccountAction && isEvmBridgeAction(a);
|
|
6239
|
+
const rightIsDeferredEvmBridge = hasPendingEvmAccountAction && isEvmBridgeAction(b);
|
|
6240
|
+
if (leftIsDeferredEvmBridge !== rightIsDeferredEvmBridge) {
|
|
6241
|
+
return leftIsDeferredEvmBridge ? 1 : -1;
|
|
6242
|
+
}
|
|
6243
|
+
return a.orderIndex - b.orderIndex;
|
|
6244
|
+
});
|
|
6245
|
+
}
|
|
6246
|
+
|
|
6164
6247
|
// src/hooks/useAuthorizationOrchestrator.ts
|
|
6165
6248
|
var ACTION_POLL_INTERVAL_MS2 = 500;
|
|
6166
6249
|
var ACTION_POLL_MAX_RETRIES2 = 20;
|
|
@@ -6174,6 +6257,7 @@ function useAuthorizationOrchestrator(deps) {
|
|
|
6174
6257
|
const { authExecutor } = deps;
|
|
6175
6258
|
const pendingSessionIdsRef = react.useRef([]);
|
|
6176
6259
|
const lastRunRef = react.useRef(null);
|
|
6260
|
+
const inflightRunRef = react.useRef(null);
|
|
6177
6261
|
const [pendingSelectSourceAction, setPendingSelectSourceAction] = react.useState(null);
|
|
6178
6262
|
const [pendingOneTapAction, setPendingOneTapAction] = react.useState(null);
|
|
6179
6263
|
const [orchestratorCompleted, setOrchestratorCompleted] = react.useState(false);
|
|
@@ -6249,7 +6333,7 @@ function useAuthorizationOrchestrator(deps) {
|
|
|
6249
6333
|
}
|
|
6250
6334
|
oneTapPauseRequestedRef.current = false;
|
|
6251
6335
|
}, []);
|
|
6252
|
-
const
|
|
6336
|
+
const runInternal = react.useCallback(
|
|
6253
6337
|
async (sessionId, options) => {
|
|
6254
6338
|
const apiBaseUrl = resolvedApiBaseUrl;
|
|
6255
6339
|
if (!apiBaseUrl) {
|
|
@@ -6881,6 +6965,21 @@ function useAuthorizationOrchestrator(deps) {
|
|
|
6881
6965
|
},
|
|
6882
6966
|
[resolvedApiBaseUrl, authExecutor, waitForOneTapPause, waitForSourceSelection]
|
|
6883
6967
|
);
|
|
6968
|
+
const run = react.useCallback(
|
|
6969
|
+
(sessionId, options) => {
|
|
6970
|
+
const promise = runInternal(sessionId, options);
|
|
6971
|
+
if (inflightRunRef.current === null) {
|
|
6972
|
+
inflightRunRef.current = promise;
|
|
6973
|
+
void promise.finally(() => {
|
|
6974
|
+
if (inflightRunRef.current === promise) {
|
|
6975
|
+
inflightRunRef.current = null;
|
|
6976
|
+
}
|
|
6977
|
+
});
|
|
6978
|
+
}
|
|
6979
|
+
return promise;
|
|
6980
|
+
},
|
|
6981
|
+
[runInternal]
|
|
6982
|
+
);
|
|
6884
6983
|
const restart = react.useCallback(async () => {
|
|
6885
6984
|
const lastRun = lastRunRef.current;
|
|
6886
6985
|
if (!lastRun) {
|
|
@@ -6889,12 +6988,20 @@ function useAuthorizationOrchestrator(deps) {
|
|
|
6889
6988
|
appendDebug("info", "orchestrator:restart", {
|
|
6890
6989
|
sessionId: lastRun.sessionId
|
|
6891
6990
|
});
|
|
6991
|
+
const inflight = inflightRunRef.current;
|
|
6992
|
+
if (inflight) {
|
|
6993
|
+
cancelPendingFlow();
|
|
6994
|
+
try {
|
|
6995
|
+
await inflight;
|
|
6996
|
+
} catch {
|
|
6997
|
+
}
|
|
6998
|
+
}
|
|
6892
6999
|
authExecutor.setError(null);
|
|
6893
7000
|
return run(lastRun.sessionId, {
|
|
6894
7001
|
...lastRun.options,
|
|
6895
7002
|
probeBeforePrompt: true
|
|
6896
7003
|
});
|
|
6897
|
-
}, [authExecutor, run]);
|
|
7004
|
+
}, [authExecutor, run, cancelPendingFlow]);
|
|
6898
7005
|
return {
|
|
6899
7006
|
run,
|
|
6900
7007
|
restart,
|
|
@@ -6984,30 +7091,6 @@ async function waitForBatchableActionsReady(options) {
|
|
|
6984
7091
|
}
|
|
6985
7092
|
return batchable.map((action) => updatedActions.get(action.id) ?? action);
|
|
6986
7093
|
}
|
|
6987
|
-
function getMergedPending(sessions, completedIds) {
|
|
6988
|
-
const allActions = [];
|
|
6989
|
-
for (const { session } of sessions) {
|
|
6990
|
-
allActions.push(...getPendingActions(session, completedIds));
|
|
6991
|
-
}
|
|
6992
|
-
const hasPendingSvmSetupAction = allActions.some((action) => isSvmSetupAction(action));
|
|
6993
|
-
return allActions.sort((a, b) => {
|
|
6994
|
-
const leftIsDeferredSvmBridge = hasPendingSvmSetupAction && isSvmTransferBridgeAction(a);
|
|
6995
|
-
const rightIsDeferredSvmBridge = hasPendingSvmSetupAction && isSvmTransferBridgeAction(b);
|
|
6996
|
-
if (leftIsDeferredSvmBridge !== rightIsDeferredSvmBridge) {
|
|
6997
|
-
return leftIsDeferredSvmBridge ? 1 : -1;
|
|
6998
|
-
}
|
|
6999
|
-
return a.orderIndex - b.orderIndex;
|
|
7000
|
-
});
|
|
7001
|
-
}
|
|
7002
|
-
function isSvmSetupAction(action) {
|
|
7003
|
-
if (action.type === "APPROVE_SPL") {
|
|
7004
|
-
return true;
|
|
7005
|
-
}
|
|
7006
|
-
return action.type === "OPEN_PROVIDER" && action.metadata?.chainFamily === "svm";
|
|
7007
|
-
}
|
|
7008
|
-
function isSvmTransferBridgeAction(action) {
|
|
7009
|
-
return action.type === "EXECUTE_BRIDGE" && action.metadata?.chainFamily === "svm";
|
|
7010
|
-
}
|
|
7011
7094
|
function getWalletConnectRuntimeKeyForAction(action, ownerSessionId, sessions) {
|
|
7012
7095
|
const metadataKey = action?.metadata?.walletConnectAccountId;
|
|
7013
7096
|
if (typeof metadataKey === "string" && metadataKey.length > 0) {
|
|
@@ -7536,6 +7619,7 @@ function createInitialState(config) {
|
|
|
7536
7619
|
loginRequested: false,
|
|
7537
7620
|
standardDesktopInlineOpenWallet: false,
|
|
7538
7621
|
desktopWait: null,
|
|
7622
|
+
setupAuthorizationSessionId: null,
|
|
7539
7623
|
mobileTokenAuthorizationPending: false,
|
|
7540
7624
|
privyReady: false,
|
|
7541
7625
|
privyAuthenticated: false,
|
|
@@ -7580,6 +7664,7 @@ function clearAuthenticatedSessionState(state) {
|
|
|
7580
7664
|
loginRequested: false,
|
|
7581
7665
|
standardDesktopInlineOpenWallet: false,
|
|
7582
7666
|
desktopWait: null,
|
|
7667
|
+
setupAuthorizationSessionId: null,
|
|
7583
7668
|
mobileTokenAuthorizationPending: false,
|
|
7584
7669
|
setupDepositAmount: null,
|
|
7585
7670
|
setupDepositToken: null,
|
|
@@ -7775,14 +7860,15 @@ function applyAction(state, action) {
|
|
|
7775
7860
|
case "TRANSFER_CREATED":
|
|
7776
7861
|
return { ...state, transfer: action.transfer, pendingTransferId: null };
|
|
7777
7862
|
case "TRANSFER_SIGNED":
|
|
7778
|
-
return { ...state, transfer: action.transfer };
|
|
7863
|
+
return { ...state, transfer: action.transfer, setupAuthorizationSessionId: null };
|
|
7779
7864
|
case "TRANSFER_COMPLETED":
|
|
7780
7865
|
return {
|
|
7781
7866
|
...state,
|
|
7782
7867
|
transfer: action.transfer,
|
|
7783
7868
|
pendingTransferId: null,
|
|
7784
7869
|
mobileFlow: false,
|
|
7785
|
-
deeplinkUri: null
|
|
7870
|
+
deeplinkUri: null,
|
|
7871
|
+
setupAuthorizationSessionId: null
|
|
7786
7872
|
};
|
|
7787
7873
|
case "TRANSFER_FAILED":
|
|
7788
7874
|
return {
|
|
@@ -7828,7 +7914,8 @@ function applyAction(state, action) {
|
|
|
7828
7914
|
deeplinkUri: null,
|
|
7829
7915
|
mobileTokenAuthorizationPending: false,
|
|
7830
7916
|
guestWalletPrepared: null,
|
|
7831
|
-
guestWalletDeeplinksPreparing: false
|
|
7917
|
+
guestWalletDeeplinksPreparing: false,
|
|
7918
|
+
setupAuthorizationSessionId: null
|
|
7832
7919
|
};
|
|
7833
7920
|
case "MOBILE_SIGN_READY":
|
|
7834
7921
|
return {
|
|
@@ -7949,6 +8036,10 @@ function applyAction(state, action) {
|
|
|
7949
8036
|
walletName: action.walletName,
|
|
7950
8037
|
walletLogoUrl: action.walletLogoUrl
|
|
7951
8038
|
},
|
|
8039
|
+
// Mirror sessionId into the longer-lived slice so the wallet
|
|
8040
|
+
// account switch listener stays armed after `desktopWait` is
|
|
8041
|
+
// cleared by the inline-connect effect.
|
|
8042
|
+
setupAuthorizationSessionId: action.sessionId,
|
|
7952
8043
|
standardDesktopInlineOpenWallet: true
|
|
7953
8044
|
};
|
|
7954
8045
|
case "DESKTOP_WAIT_CLEARED":
|
|
@@ -7978,6 +8069,7 @@ function applyAction(state, action) {
|
|
|
7978
8069
|
oneTapLimitSavedDuringSetup: false,
|
|
7979
8070
|
standardDesktopInlineOpenWallet: false,
|
|
7980
8071
|
desktopWait: null,
|
|
8072
|
+
setupAuthorizationSessionId: null,
|
|
7981
8073
|
savedSelection: null,
|
|
7982
8074
|
setupDepositAmount: null,
|
|
7983
8075
|
setupDepositToken: null,
|
|
@@ -8172,7 +8264,6 @@ function toTransfer(session) {
|
|
|
8172
8264
|
};
|
|
8173
8265
|
}
|
|
8174
8266
|
var SOLANA_CHAIN_ID = 792703809;
|
|
8175
|
-
var TRON_CHAIN_ID = 728126428;
|
|
8176
8267
|
var SOLANA_NATIVE_SOL_ADDRESS = "11111111111111111111111111111111";
|
|
8177
8268
|
function formatDepositUri(address, chainId, depToken) {
|
|
8178
8269
|
if (chainId === SOLANA_CHAIN_ID) {
|
|
@@ -8181,10 +8272,7 @@ function formatDepositUri(address, chainId, depToken) {
|
|
|
8181
8272
|
}
|
|
8182
8273
|
return `solana:${address}?spl-token=${depToken}`;
|
|
8183
8274
|
}
|
|
8184
|
-
|
|
8185
|
-
return address;
|
|
8186
|
-
}
|
|
8187
|
-
return `ethereum:${address}@${chainId}`;
|
|
8275
|
+
return address;
|
|
8188
8276
|
}
|
|
8189
8277
|
|
|
8190
8278
|
// src/hooks/useManualTransferSession.ts
|
|
@@ -17357,6 +17445,38 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
|
|
|
17357
17445
|
};
|
|
17358
17446
|
}
|
|
17359
17447
|
|
|
17448
|
+
// src/accountSwitchHelpers.ts
|
|
17449
|
+
var OPEN_PROVIDER_REPLACEMENT_CONFLICT_CODE = "OPEN_PROVIDER_REPLACEMENT_CONFLICT";
|
|
17450
|
+
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.";
|
|
17451
|
+
async function replaceOpenProviderForAccountSwitch(input) {
|
|
17452
|
+
try {
|
|
17453
|
+
const session = await fetchAuthorizationSession(
|
|
17454
|
+
input.apiBaseUrl,
|
|
17455
|
+
input.sessionId
|
|
17456
|
+
);
|
|
17457
|
+
const openProvider = session.actions.find((a) => a.type === "OPEN_PROVIDER");
|
|
17458
|
+
if (!openProvider) {
|
|
17459
|
+
return { status: "no-open-provider" };
|
|
17460
|
+
}
|
|
17461
|
+
const result = { accounts: [...input.accounts] };
|
|
17462
|
+
if (input.chainId != null) {
|
|
17463
|
+
result.chainId = `0x${input.chainId.toString(16)}`;
|
|
17464
|
+
}
|
|
17465
|
+
const updated = await reportActionCompletion(
|
|
17466
|
+
input.apiBaseUrl,
|
|
17467
|
+
openProvider.id,
|
|
17468
|
+
result
|
|
17469
|
+
);
|
|
17470
|
+
return { status: "success", session: updated };
|
|
17471
|
+
} catch (err) {
|
|
17472
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
17473
|
+
if (error.message.includes(OPEN_PROVIDER_REPLACEMENT_CONFLICT_CODE)) {
|
|
17474
|
+
return { status: "conflict" };
|
|
17475
|
+
}
|
|
17476
|
+
return { status: "error", error };
|
|
17477
|
+
}
|
|
17478
|
+
}
|
|
17479
|
+
|
|
17360
17480
|
// src/hooks/providerSelectionGuards.ts
|
|
17361
17481
|
function resolveSetupFlowDepositAmount({
|
|
17362
17482
|
hasActiveWallet: hasActiveWallet2,
|
|
@@ -18606,6 +18726,33 @@ function useProviderHandlers(deps) {
|
|
|
18606
18726
|
setupFlowDepositAmount,
|
|
18607
18727
|
dispatch
|
|
18608
18728
|
]);
|
|
18729
|
+
const handleWalletAccountSwitch = react.useCallback(async (change, sessionId) => {
|
|
18730
|
+
const outcome = await replaceOpenProviderForAccountSwitch({
|
|
18731
|
+
apiBaseUrl,
|
|
18732
|
+
sessionId,
|
|
18733
|
+
accounts: change.accounts,
|
|
18734
|
+
chainId: change.chainId
|
|
18735
|
+
});
|
|
18736
|
+
if (outcome.status === "success") {
|
|
18737
|
+
dispatch({ type: "CLEAR_SETUP_DEPOSIT_TOKEN" });
|
|
18738
|
+
try {
|
|
18739
|
+
await orchestrator.restart();
|
|
18740
|
+
} catch (err) {
|
|
18741
|
+
captureException(err);
|
|
18742
|
+
onError?.(err instanceof Error ? err.message : "Failed to refresh authorization session.");
|
|
18743
|
+
}
|
|
18744
|
+
return;
|
|
18745
|
+
}
|
|
18746
|
+
if (outcome.status === "conflict") {
|
|
18747
|
+
onError?.(ACCOUNT_SWITCH_CONFLICT_MESSAGE);
|
|
18748
|
+
return;
|
|
18749
|
+
}
|
|
18750
|
+
if (outcome.status === "error") {
|
|
18751
|
+
captureException(outcome.error);
|
|
18752
|
+
onError?.(outcome.error.message);
|
|
18753
|
+
return;
|
|
18754
|
+
}
|
|
18755
|
+
}, [apiBaseUrl, dispatch, orchestrator, onError]);
|
|
18609
18756
|
return {
|
|
18610
18757
|
handlePrepareProvider,
|
|
18611
18758
|
handleSelectProvider,
|
|
@@ -18618,7 +18765,8 @@ function useProviderHandlers(deps) {
|
|
|
18618
18765
|
handleAuthorizeToken,
|
|
18619
18766
|
handlePrepareTokenAuthorization,
|
|
18620
18767
|
handleCommitTokenAuthorization,
|
|
18621
|
-
handlePrepareGuestDeeplinks
|
|
18768
|
+
handlePrepareGuestDeeplinks,
|
|
18769
|
+
handleWalletAccountSwitch
|
|
18622
18770
|
};
|
|
18623
18771
|
}
|
|
18624
18772
|
function useOneTapSetupHandlers(deps) {
|
|
@@ -19682,6 +19830,40 @@ function useDepositFeeEstimate({
|
|
|
19682
19830
|
}, [fetchQuote]);
|
|
19683
19831
|
return { quoteId, quoteFee, quoteLoading, quoteError };
|
|
19684
19832
|
}
|
|
19833
|
+
function useWalletAccountSwitchEffect(deps) {
|
|
19834
|
+
const { enabled = true, isDesktop = true, onAccountChanged } = deps;
|
|
19835
|
+
const account = wagmi.useAccount();
|
|
19836
|
+
const address = account.address ?? null;
|
|
19837
|
+
const chainId = account.chainId ?? null;
|
|
19838
|
+
const connectorId = account.connector?.id ?? null;
|
|
19839
|
+
const addresses = account.addresses;
|
|
19840
|
+
const baselineRef = react.useRef(null);
|
|
19841
|
+
react.useEffect(() => {
|
|
19842
|
+
if (!enabled || !isDesktop) {
|
|
19843
|
+
baselineRef.current = null;
|
|
19844
|
+
return;
|
|
19845
|
+
}
|
|
19846
|
+
if (!address) {
|
|
19847
|
+
return;
|
|
19848
|
+
}
|
|
19849
|
+
if (baselineRef.current === null) {
|
|
19850
|
+
baselineRef.current = address;
|
|
19851
|
+
return;
|
|
19852
|
+
}
|
|
19853
|
+
if (baselineRef.current.toLowerCase() === address.toLowerCase()) {
|
|
19854
|
+
return;
|
|
19855
|
+
}
|
|
19856
|
+
const previous = baselineRef.current;
|
|
19857
|
+
baselineRef.current = address;
|
|
19858
|
+
void onAccountChanged({
|
|
19859
|
+
previousAddress: previous,
|
|
19860
|
+
nextAddress: address,
|
|
19861
|
+
connectorId: connectorId ?? "injected",
|
|
19862
|
+
chainId,
|
|
19863
|
+
accounts: addresses ?? [address]
|
|
19864
|
+
});
|
|
19865
|
+
}, [enabled, isDesktop, address, chainId, connectorId, addresses, onAccountChanged]);
|
|
19866
|
+
}
|
|
19685
19867
|
function usePersistAmountToActiveSession({
|
|
19686
19868
|
apiBaseUrl,
|
|
19687
19869
|
accounts,
|
|
@@ -19981,6 +20163,17 @@ function BlinkPaymentInner({
|
|
|
19981
20163
|
activeCredentialId: state.activeCredentialId ?? void 0,
|
|
19982
20164
|
idempotencyKey
|
|
19983
20165
|
});
|
|
20166
|
+
const accountSwitchSessionId = state.setupAuthorizationSessionId;
|
|
20167
|
+
const handleProviderWalletAccountSwitch = provider.handleWalletAccountSwitch;
|
|
20168
|
+
const onWalletAccountChanged = react.useCallback(async (change) => {
|
|
20169
|
+
if (!accountSwitchSessionId) return;
|
|
20170
|
+
await handleProviderWalletAccountSwitch(change, accountSwitchSessionId);
|
|
20171
|
+
}, [handleProviderWalletAccountSwitch, accountSwitchSessionId]);
|
|
20172
|
+
useWalletAccountSwitchEffect({
|
|
20173
|
+
enabled: accountSwitchSessionId != null,
|
|
20174
|
+
isDesktop,
|
|
20175
|
+
onAccountChanged: onWalletAccountChanged
|
|
20176
|
+
});
|
|
19984
20177
|
const clearLocalSessionArtifacts = react.useCallback(() => {
|
|
19985
20178
|
popupAuthRef.current = null;
|
|
19986
20179
|
clearPopupAuth();
|
|
@@ -20417,6 +20610,7 @@ function getDeviceBiometricUnlockText() {
|
|
|
20417
20610
|
return FALLBACK;
|
|
20418
20611
|
}
|
|
20419
20612
|
|
|
20613
|
+
exports.ACCOUNT_SWITCH_CONFLICT_MESSAGE = ACCOUNT_SWITCH_CONFLICT_MESSAGE;
|
|
20420
20614
|
exports.AdvancedSourceScreen = AdvancedSourceScreen;
|
|
20421
20615
|
exports.AuthorizationSessionCancelledError = AuthorizationSessionCancelledError;
|
|
20422
20616
|
exports.BLINK_ERROR_ILLUSTRATION = BLINK_ERROR_ILLUSTRATION;
|
|
@@ -20494,6 +20688,7 @@ exports.lightThemeNew = lightThemeNew;
|
|
|
20494
20688
|
exports.lightTransparentTheme = lightTransparentTheme;
|
|
20495
20689
|
exports.lightTransparentThemeNew = lightTransparentThemeNew;
|
|
20496
20690
|
exports.mapGuestPickerEntries = mapGuestPickerEntries;
|
|
20691
|
+
exports.replaceOpenProviderForAccountSwitch = replaceOpenProviderForAccountSwitch;
|
|
20497
20692
|
exports.resolvePasskeyRpId = resolvePasskeyRpId;
|
|
20498
20693
|
exports.screenForPhase = screenForPhase;
|
|
20499
20694
|
exports.subscribeDebug = subscribeDebug;
|