@swype-org/react-sdk 0.1.300 → 0.1.329
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/README.md +19 -0
- package/dist/index.cjs +1021 -345
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -9
- package/dist/index.d.ts +59 -9
- package/dist/index.js +1020 -347
- package/dist/index.js.map +1 -1
- package/package.json +11 -3
package/dist/index.cjs
CHANGED
|
@@ -78,14 +78,16 @@ function getTheme(mode) {
|
|
|
78
78
|
}
|
|
79
79
|
var BLINK_PRIVY_APP_ID = "cmlil87uv004n0ck0blwumwek";
|
|
80
80
|
var wagmiConfig = wagmi.createConfig({
|
|
81
|
-
|
|
81
|
+
// baseSepolia: guest/testnet flows (e.g. smokebox e2e) call switchChain to the source chain from the API.
|
|
82
|
+
chains: [chains.mainnet, chains.arbitrum, chains.base, chains.polygon, chains.bsc, chains.baseSepolia],
|
|
82
83
|
connectors: [connectors.injected({ shimDisconnect: true, unstable_shimAsyncInject: 2e3 })],
|
|
83
84
|
transports: {
|
|
84
85
|
[chains.mainnet.id]: wagmi.http(),
|
|
85
86
|
[chains.arbitrum.id]: wagmi.http(),
|
|
86
87
|
[chains.base.id]: wagmi.http(),
|
|
87
88
|
[chains.polygon.id]: wagmi.http(),
|
|
88
|
-
[chains.bsc.id]: wagmi.http()
|
|
89
|
+
[chains.bsc.id]: wagmi.http(),
|
|
90
|
+
[chains.baseSepolia.id]: wagmi.http()
|
|
89
91
|
}
|
|
90
92
|
});
|
|
91
93
|
var BlinkContext = react.createContext(null);
|
|
@@ -495,6 +497,7 @@ __export(api_exports, {
|
|
|
495
497
|
getGuestTransfer: () => getGuestTransfer,
|
|
496
498
|
getTransferByGuestToken: () => getTransferByGuestToken,
|
|
497
499
|
postGuestTransferFeeQuote: () => postGuestTransferFeeQuote,
|
|
500
|
+
postTransferQuote: () => postTransferQuote,
|
|
498
501
|
putGuestTransferSender: () => putGuestTransferSender,
|
|
499
502
|
registerPasskey: () => registerPasskey,
|
|
500
503
|
reportActionCompletion: () => reportActionCompletion,
|
|
@@ -610,7 +613,8 @@ async function createTransfer(apiBaseUrl, token, params) {
|
|
|
610
613
|
amount: {
|
|
611
614
|
amount: params.amount,
|
|
612
615
|
currency: params.currency ?? "USD"
|
|
613
|
-
}
|
|
616
|
+
},
|
|
617
|
+
...params.quoteId ? { quoteId: params.quoteId } : {}
|
|
614
618
|
};
|
|
615
619
|
const res = await fetch(`${apiBaseUrl}/v1/transfers`, {
|
|
616
620
|
method: "POST",
|
|
@@ -623,6 +627,28 @@ async function createTransfer(apiBaseUrl, token, params) {
|
|
|
623
627
|
if (!res.ok) await throwApiError(res);
|
|
624
628
|
return await res.json();
|
|
625
629
|
}
|
|
630
|
+
async function postTransferQuote(apiBaseUrl, bearerToken, params) {
|
|
631
|
+
const body = {
|
|
632
|
+
walletId: params.walletId,
|
|
633
|
+
...params.sourceTokenAddress ? { sourceTokenAddress: params.sourceTokenAddress } : {},
|
|
634
|
+
destination: {
|
|
635
|
+
chainId: params.destination.chainId,
|
|
636
|
+
token: { address: params.destination.token.address },
|
|
637
|
+
address: params.destination.address
|
|
638
|
+
},
|
|
639
|
+
amount: params.amount
|
|
640
|
+
};
|
|
641
|
+
const res = await fetch(`${apiBaseUrl}/v1/transfers/quotes`, {
|
|
642
|
+
method: "POST",
|
|
643
|
+
headers: {
|
|
644
|
+
"Content-Type": "application/json",
|
|
645
|
+
Authorization: `Bearer ${bearerToken}`
|
|
646
|
+
},
|
|
647
|
+
body: JSON.stringify(body)
|
|
648
|
+
});
|
|
649
|
+
if (!res.ok) await throwApiError(res);
|
|
650
|
+
return await res.json();
|
|
651
|
+
}
|
|
626
652
|
async function fetchMerchantPublicKey(apiBaseUrl, merchantId) {
|
|
627
653
|
const res = await fetch(
|
|
628
654
|
`${apiBaseUrl}/v1/merchants/${encodeURIComponent(merchantId)}/public-key`
|
|
@@ -964,6 +990,23 @@ function normalizeSignature(sig) {
|
|
|
964
990
|
);
|
|
965
991
|
}
|
|
966
992
|
|
|
993
|
+
// src/authorizationErrors.ts
|
|
994
|
+
var AuthorizationSessionCancelledError = class extends Error {
|
|
995
|
+
constructor() {
|
|
996
|
+
super("Authorization session cancelled");
|
|
997
|
+
this.name = "AuthorizationSessionCancelledError";
|
|
998
|
+
}
|
|
999
|
+
};
|
|
1000
|
+
function isAuthorizationSessionCancelled(err) {
|
|
1001
|
+
if (err instanceof AuthorizationSessionCancelledError) return true;
|
|
1002
|
+
return typeof err === "object" && err !== null && "name" in err && err.name === "AuthorizationSessionCancelledError";
|
|
1003
|
+
}
|
|
1004
|
+
function isUserDismissedAuthorizationError(err) {
|
|
1005
|
+
if (!(err instanceof Error)) return false;
|
|
1006
|
+
const m = err.message.toLowerCase();
|
|
1007
|
+
return m.includes("authorization session aborted") || m.includes("aborted by user");
|
|
1008
|
+
}
|
|
1009
|
+
|
|
967
1010
|
// src/hooks/authorizationExecutor.ts
|
|
968
1011
|
var WALLET_CLIENT_MAX_ATTEMPTS = 25;
|
|
969
1012
|
var WALLET_CLIENT_POLL_MS = 400;
|
|
@@ -1277,39 +1320,80 @@ function useAuthorizationExecutor(options) {
|
|
|
1277
1320
|
const [error, setError] = react.useState(null);
|
|
1278
1321
|
const [currentAction, setCurrentAction] = react.useState(null);
|
|
1279
1322
|
const executingRef = react.useRef(false);
|
|
1323
|
+
const oneTapPauseActiveRef = react.useRef(false);
|
|
1324
|
+
const sessionStackRef = react.useRef([]);
|
|
1325
|
+
const [authorizationSessionStackDepth, setAuthorizationSessionStackDepth] = react.useState(0);
|
|
1280
1326
|
const [pendingSelectSource, setPendingSelectSource] = react.useState(null);
|
|
1281
1327
|
const selectSourceResolverRef = react.useRef(null);
|
|
1328
|
+
const selectSourceRejectRef = react.useRef(null);
|
|
1282
1329
|
const sessionIdRef = react.useRef(null);
|
|
1283
1330
|
const resolveSelectSource = react.useCallback((selection) => {
|
|
1284
1331
|
if (selectSourceResolverRef.current) {
|
|
1285
1332
|
selectSourceResolverRef.current(selection);
|
|
1286
1333
|
selectSourceResolverRef.current = null;
|
|
1334
|
+
selectSourceRejectRef.current = null;
|
|
1287
1335
|
setPendingSelectSource(null);
|
|
1288
1336
|
}
|
|
1289
1337
|
}, []);
|
|
1290
1338
|
const waitForSelection = react.useCallback(
|
|
1291
|
-
(action) => new Promise((resolve) => {
|
|
1292
|
-
selectSourceResolverRef.current =
|
|
1339
|
+
(action) => new Promise((resolve, reject) => {
|
|
1340
|
+
selectSourceResolverRef.current = (selection) => {
|
|
1341
|
+
resolve(selection);
|
|
1342
|
+
selectSourceResolverRef.current = null;
|
|
1343
|
+
selectSourceRejectRef.current = null;
|
|
1344
|
+
};
|
|
1345
|
+
selectSourceRejectRef.current = reject;
|
|
1293
1346
|
setPendingSelectSource(action);
|
|
1294
1347
|
}),
|
|
1295
1348
|
[]
|
|
1296
1349
|
);
|
|
1297
1350
|
const [pendingOneTapSetup, setPendingOneTapSetup] = react.useState(null);
|
|
1298
1351
|
const oneTapSetupResolverRef = react.useRef(null);
|
|
1352
|
+
const oneTapSetupRejectRef = react.useRef(null);
|
|
1299
1353
|
const resolveOneTapSetup = react.useCallback(() => {
|
|
1300
1354
|
if (oneTapSetupResolverRef.current) {
|
|
1301
1355
|
oneTapSetupResolverRef.current();
|
|
1302
1356
|
oneTapSetupResolverRef.current = null;
|
|
1357
|
+
oneTapSetupRejectRef.current = null;
|
|
1303
1358
|
setPendingOneTapSetup(null);
|
|
1304
1359
|
}
|
|
1305
1360
|
}, []);
|
|
1306
1361
|
const waitForOneTapSetup = react.useCallback(
|
|
1307
|
-
(action) => new Promise((resolve) => {
|
|
1308
|
-
|
|
1362
|
+
(action) => new Promise((resolve, reject) => {
|
|
1363
|
+
oneTapPauseActiveRef.current = true;
|
|
1364
|
+
oneTapSetupResolverRef.current = () => {
|
|
1365
|
+
oneTapPauseActiveRef.current = false;
|
|
1366
|
+
resolve();
|
|
1367
|
+
oneTapSetupResolverRef.current = null;
|
|
1368
|
+
oneTapSetupRejectRef.current = null;
|
|
1369
|
+
};
|
|
1370
|
+
oneTapSetupRejectRef.current = (reason) => {
|
|
1371
|
+
oneTapPauseActiveRef.current = false;
|
|
1372
|
+
reject(reason);
|
|
1373
|
+
};
|
|
1309
1374
|
setPendingOneTapSetup(action);
|
|
1310
1375
|
}),
|
|
1311
1376
|
[]
|
|
1312
1377
|
);
|
|
1378
|
+
const cancelPendingExecution = react.useCallback(() => {
|
|
1379
|
+
if (selectSourceRejectRef.current) {
|
|
1380
|
+
selectSourceRejectRef.current(new AuthorizationSessionCancelledError());
|
|
1381
|
+
selectSourceRejectRef.current = null;
|
|
1382
|
+
selectSourceResolverRef.current = null;
|
|
1383
|
+
setPendingSelectSource(null);
|
|
1384
|
+
}
|
|
1385
|
+
if (oneTapSetupRejectRef.current) {
|
|
1386
|
+
oneTapPauseActiveRef.current = false;
|
|
1387
|
+
oneTapSetupRejectRef.current(new AuthorizationSessionCancelledError());
|
|
1388
|
+
oneTapSetupRejectRef.current = null;
|
|
1389
|
+
oneTapSetupResolverRef.current = null;
|
|
1390
|
+
setPendingOneTapSetup(null);
|
|
1391
|
+
}
|
|
1392
|
+
setError(null);
|
|
1393
|
+
setCurrentAction(null);
|
|
1394
|
+
setExecuting(false);
|
|
1395
|
+
executingRef.current = false;
|
|
1396
|
+
}, []);
|
|
1313
1397
|
const dispatchAction = react.useCallback(
|
|
1314
1398
|
async (action) => {
|
|
1315
1399
|
setCurrentAction(action);
|
|
@@ -1344,20 +1428,26 @@ function useAuthorizationExecutor(options) {
|
|
|
1344
1428
|
);
|
|
1345
1429
|
const executeSessionById = react.useCallback(
|
|
1346
1430
|
async (sessionId) => {
|
|
1347
|
-
if (executingRef.current) return;
|
|
1348
|
-
executingRef.current = true;
|
|
1349
1431
|
if (!sessionId) {
|
|
1350
|
-
executingRef.current = false;
|
|
1351
1432
|
throw new Error("No authorization session id provided.");
|
|
1352
1433
|
}
|
|
1353
1434
|
if (!apiBaseUrl) {
|
|
1354
|
-
executingRef.current = false;
|
|
1355
1435
|
throw new Error("Missing apiBaseUrl. Provide useAuthorizationExecutor({ apiBaseUrl }) or wrap in <BlinkProvider>.");
|
|
1356
1436
|
}
|
|
1357
|
-
|
|
1358
|
-
|
|
1437
|
+
const allowNested = executingRef.current && oneTapPauseActiveRef.current;
|
|
1438
|
+
if (executingRef.current && !allowNested) {
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
const isNestedRun = allowNested;
|
|
1442
|
+
if (!isNestedRun) {
|
|
1443
|
+
executingRef.current = true;
|
|
1444
|
+
setExecuting(true);
|
|
1445
|
+
setResults([]);
|
|
1446
|
+
}
|
|
1359
1447
|
setError(null);
|
|
1360
|
-
|
|
1448
|
+
sessionStackRef.current.push(sessionId);
|
|
1449
|
+
setAuthorizationSessionStackDepth(sessionStackRef.current.length);
|
|
1450
|
+
sessionIdRef.current = sessionId;
|
|
1361
1451
|
try {
|
|
1362
1452
|
let session = await fetchAuthorizationSession(apiBaseUrl, sessionId);
|
|
1363
1453
|
const allResults = [];
|
|
@@ -1393,13 +1483,23 @@ function useAuthorizationExecutor(options) {
|
|
|
1393
1483
|
pending = getPendingActions(session, completedIds);
|
|
1394
1484
|
}
|
|
1395
1485
|
} catch (err) {
|
|
1396
|
-
|
|
1397
|
-
|
|
1486
|
+
if (isAuthorizationSessionCancelled(err)) {
|
|
1487
|
+
setError(null);
|
|
1488
|
+
} else {
|
|
1489
|
+
const msg = err instanceof Error ? err.message : "Authorization failed";
|
|
1490
|
+
setError(msg);
|
|
1491
|
+
}
|
|
1398
1492
|
throw err;
|
|
1399
1493
|
} finally {
|
|
1494
|
+
sessionStackRef.current.pop();
|
|
1495
|
+
const depth = sessionStackRef.current.length;
|
|
1496
|
+
setAuthorizationSessionStackDepth(depth);
|
|
1497
|
+
sessionIdRef.current = depth > 0 ? sessionStackRef.current[depth - 1] : null;
|
|
1400
1498
|
setCurrentAction(null);
|
|
1401
|
-
|
|
1402
|
-
|
|
1499
|
+
if (depth === 0) {
|
|
1500
|
+
setExecuting(false);
|
|
1501
|
+
executingRef.current = false;
|
|
1502
|
+
}
|
|
1403
1503
|
}
|
|
1404
1504
|
},
|
|
1405
1505
|
[apiBaseUrl, dispatchAction]
|
|
@@ -1413,7 +1513,9 @@ function useAuthorizationExecutor(options) {
|
|
|
1413
1513
|
resolveSelectSource,
|
|
1414
1514
|
pendingOneTapSetup,
|
|
1415
1515
|
resolveOneTapSetup,
|
|
1416
|
-
executeSessionById
|
|
1516
|
+
executeSessionById,
|
|
1517
|
+
cancelPendingExecution,
|
|
1518
|
+
authorizationSessionStackDepth
|
|
1417
1519
|
};
|
|
1418
1520
|
}
|
|
1419
1521
|
var TRANSFER_SIGN_MAX_POLLS = 60;
|
|
@@ -1643,6 +1745,37 @@ function getPreferredDepositWallet(account, transferAmount) {
|
|
|
1643
1745
|
function getDepositEligibleAccounts(accounts) {
|
|
1644
1746
|
return accounts.filter((account) => getAddressableWallets(account).length > 0);
|
|
1645
1747
|
}
|
|
1748
|
+
function resolveDepositSelectionAfterRefresh(accounts, transferAmount, prev) {
|
|
1749
|
+
const { selectedAccountId, selectedWalletId, selectedTokenSymbol } = prev;
|
|
1750
|
+
if (selectedAccountId && selectedWalletId) {
|
|
1751
|
+
const acct = accounts.find((a) => a.id === selectedAccountId);
|
|
1752
|
+
const wallet = acct?.wallets.find((w) => w.id === selectedWalletId);
|
|
1753
|
+
if (wallet) {
|
|
1754
|
+
if (selectedTokenSymbol) {
|
|
1755
|
+
const hasToken = wallet.sources.some((s) => s.token.symbol === selectedTokenSymbol);
|
|
1756
|
+
if (hasToken) {
|
|
1757
|
+
return {
|
|
1758
|
+
defaults: { accountId: selectedAccountId, walletId: selectedWalletId },
|
|
1759
|
+
resetSelectedTokenSymbol: false
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
const fallback = resolveDepositSelection(accounts, transferAmount, selectedAccountId);
|
|
1763
|
+
return {
|
|
1764
|
+
defaults: fallback,
|
|
1765
|
+
resetSelectedTokenSymbol: true
|
|
1766
|
+
};
|
|
1767
|
+
}
|
|
1768
|
+
return {
|
|
1769
|
+
defaults: { accountId: selectedAccountId, walletId: selectedWalletId },
|
|
1770
|
+
resetSelectedTokenSymbol: false
|
|
1771
|
+
};
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
return {
|
|
1775
|
+
defaults: resolveDepositSelection(accounts, transferAmount, selectedAccountId),
|
|
1776
|
+
resetSelectedTokenSymbol: false
|
|
1777
|
+
};
|
|
1778
|
+
}
|
|
1646
1779
|
function resolveDepositSelection(accounts, transferAmount, selectedAccountId) {
|
|
1647
1780
|
const eligibleAccounts = getDepositEligibleAccounts(accounts);
|
|
1648
1781
|
if (eligibleAccounts.length === 0) return null;
|
|
@@ -1709,6 +1842,32 @@ function buildSelectSourceChoices(options) {
|
|
|
1709
1842
|
tokens: chain.tokens.filter((t) => t.balance > 0).sort((a, b) => b.balance - a.balance)
|
|
1710
1843
|
})).filter((chain) => chain.tokens.length > 0).sort((a, b) => b.balance - a.balance);
|
|
1711
1844
|
}
|
|
1845
|
+
function resolveSelectSourceAvailableBalance(choices, options, chainName, tokenSymbol, recommended) {
|
|
1846
|
+
const chain = chainName.trim();
|
|
1847
|
+
const token = tokenSymbol.trim();
|
|
1848
|
+
if (chain && token) {
|
|
1849
|
+
const chainChoice = choices.find((c) => c.chainName === chain);
|
|
1850
|
+
const row = chainChoice?.tokens.find((t) => t.tokenSymbol === token);
|
|
1851
|
+
if (row !== void 0) return row.balance;
|
|
1852
|
+
const direct = options.find(
|
|
1853
|
+
(opt) => opt.chainName === chain && opt.tokenSymbol === token
|
|
1854
|
+
);
|
|
1855
|
+
if (direct) return parseRawBalance(direct.rawBalance, direct.decimals);
|
|
1856
|
+
return 0;
|
|
1857
|
+
}
|
|
1858
|
+
if (recommended) {
|
|
1859
|
+
const match = options.find(
|
|
1860
|
+
(opt) => opt.chainName === recommended.chainName && opt.tokenSymbol === recommended.tokenSymbol
|
|
1861
|
+
);
|
|
1862
|
+
if (match) return parseRawBalance(match.rawBalance, match.decimals);
|
|
1863
|
+
}
|
|
1864
|
+
let max = 0;
|
|
1865
|
+
for (const opt of options) {
|
|
1866
|
+
const bal = parseRawBalance(opt.rawBalance, opt.decimals);
|
|
1867
|
+
if (bal > max) max = bal;
|
|
1868
|
+
}
|
|
1869
|
+
return max;
|
|
1870
|
+
}
|
|
1712
1871
|
|
|
1713
1872
|
// src/walletFlow.ts
|
|
1714
1873
|
var MOBILE_USER_AGENT_PATTERN = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
|
|
@@ -1793,10 +1952,11 @@ function resolvePhase(state) {
|
|
|
1793
1952
|
const walletPickerSwitchEligible = currentPhase.step === "wallet-picker" && currentPhase.reason === "switch" && !state.creatingTransfer && !(state.mobileFlow && state.deeplinkUri);
|
|
1794
1953
|
const missingActivePasskeyCredential = state.passkeyConfigLoaded && !state.activeCredentialId;
|
|
1795
1954
|
const shouldPromptPasskeyVerification = missingActivePasskeyCredential && state.knownCredentialIds.length > 0 && state.passkeyPopupNeeded;
|
|
1955
|
+
const guestPreauthClaimPending = state.guestPreauthAccountId != null && state.guestSessionToken != null && state.privyAuthenticated && state.activeCredentialId != null && !state.guestPreauthSetupCompletePending && !state.error;
|
|
1796
1956
|
const branchGuestSetupComplete = state.guestPreauthSetupCompletePending && state.privyReady && state.privyAuthenticated;
|
|
1797
1957
|
const branchKeepGuestPreauthPin = !branchGuestSetupComplete && guestPreauthPinsCurrentPhase;
|
|
1798
1958
|
const branchGuestPostPayLogin = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && guestPostPayLogin;
|
|
1799
|
-
const branchCompleted = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && transferCompleted && !state.verificationTarget && !needsPasskeyBootstrap;
|
|
1959
|
+
const branchCompleted = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && transferCompleted && !state.verificationTarget && !needsPasskeyBootstrap && !guestPreauthClaimPending && !state.loginRequested;
|
|
1800
1960
|
const branchFailed = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && state.transfer?.status === "FAILED";
|
|
1801
1961
|
const branchProcessing = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && !branchFailed && (state.creatingTransfer || isTransferAwaitingCompletion(state.transfer));
|
|
1802
1962
|
const branchStandardDesktopInlineOpenWallet = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && !branchFailed && !branchProcessing && state.standardDesktopInlineOpenWallet && state.privyAuthenticated && state.activeCredentialId != null && state.selectedAccountId != null && !state.loginRequested && !state.guestPreauthorizing;
|
|
@@ -1812,7 +1972,7 @@ function resolvePhase(state) {
|
|
|
1812
1972
|
const branchLoginRequested = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && !branchFailed && !branchProcessing && !branchKeepFundingSubflow && !branchMobileWalletSetup && !branchStandardDesktopInlineOpenWallet && !branchKeepGuestPreauthDesktopOpenWallet && !branchKeepGuestWalletSetup && !branchGuestTokenPicker && !branchKeepWalletPickerSwitch && !branchInitializingPrivy && !branchInitializingPasskeyConfig && !branchOtpVerify && state.loginRequested;
|
|
1813
1973
|
const branchPasskeyVerify = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && !branchFailed && !branchProcessing && !branchKeepFundingSubflow && !branchMobileWalletSetup && !branchStandardDesktopInlineOpenWallet && !branchKeepGuestPreauthDesktopOpenWallet && !branchKeepGuestWalletSetup && !branchGuestTokenPicker && !branchKeepWalletPickerSwitch && !branchInitializingPrivy && !branchInitializingPasskeyConfig && !branchOtpVerify && !branchLoginRequested && shouldPromptPasskeyVerification;
|
|
1814
1974
|
const branchPasskeyCreate = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && !branchFailed && !branchProcessing && !branchKeepFundingSubflow && !branchMobileWalletSetup && !branchStandardDesktopInlineOpenWallet && !branchKeepGuestPreauthDesktopOpenWallet && !branchKeepGuestWalletSetup && !branchGuestTokenPicker && !branchKeepWalletPickerSwitch && !branchInitializingPrivy && !branchInitializingPasskeyConfig && !branchOtpVerify && !branchLoginRequested && !branchPasskeyVerify && missingActivePasskeyCredential;
|
|
1815
|
-
const branchGuestPreauthClaiming = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && !branchFailed && !branchProcessing && !branchKeepFundingSubflow && !branchMobileWalletSetup && !branchStandardDesktopInlineOpenWallet && !branchKeepGuestPreauthDesktopOpenWallet && !branchKeepGuestWalletSetup && !branchGuestTokenPicker && !branchKeepWalletPickerSwitch && !branchInitializingPrivy && !branchInitializingPasskeyConfig && !branchOtpVerify && !branchLoginRequested && !branchPasskeyVerify && !branchPasskeyCreate &&
|
|
1975
|
+
const branchGuestPreauthClaiming = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && !branchFailed && !branchProcessing && !branchKeepFundingSubflow && !branchMobileWalletSetup && !branchStandardDesktopInlineOpenWallet && !branchKeepGuestPreauthDesktopOpenWallet && !branchKeepGuestWalletSetup && !branchGuestTokenPicker && !branchKeepWalletPickerSwitch && !branchInitializingPrivy && !branchInitializingPasskeyConfig && !branchOtpVerify && !branchLoginRequested && !branchPasskeyVerify && !branchPasskeyCreate && guestPreauthClaimPending;
|
|
1816
1976
|
const branchDataLoading = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && !branchFailed && !branchProcessing && !branchKeepFundingSubflow && !branchMobileWalletSetup && !branchStandardDesktopInlineOpenWallet && !branchKeepGuestPreauthDesktopOpenWallet && !branchKeepGuestWalletSetup && !branchGuestTokenPicker && !branchKeepWalletPickerSwitch && !branchInitializingPrivy && !branchInitializingPasskeyConfig && !branchOtpVerify && !branchLoginRequested && !branchPasskeyVerify && !branchPasskeyCreate && !branchGuestPreauthClaiming && state.loadingData && state.activeCredentialId != null && hasActiveWallet(state.accounts);
|
|
1817
1977
|
const branchWalletPickerLink = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && !branchFailed && !branchProcessing && !branchKeepFundingSubflow && !branchMobileWalletSetup && !branchStandardDesktopInlineOpenWallet && !branchKeepGuestPreauthDesktopOpenWallet && !branchKeepGuestWalletSetup && !branchGuestTokenPicker && !branchKeepWalletPickerSwitch && !branchInitializingPrivy && !branchInitializingPasskeyConfig && !branchOtpVerify && !branchLoginRequested && !branchPasskeyVerify && !branchPasskeyCreate && !branchGuestPreauthClaiming && !branchDataLoading && state.activeCredentialId != null && !hasActiveWallet(state.accounts) && !state.mobileFlow;
|
|
1818
1978
|
const branchDeposit = !branchGuestSetupComplete && !branchKeepGuestPreauthPin && !branchGuestPostPayLogin && !branchCompleted && !branchFailed && !branchProcessing && !branchKeepFundingSubflow && !branchMobileWalletSetup && !branchStandardDesktopInlineOpenWallet && !branchKeepGuestPreauthDesktopOpenWallet && !branchKeepGuestWalletSetup && !branchGuestTokenPicker && !branchKeepWalletPickerSwitch && !branchInitializingPrivy && !branchInitializingPasskeyConfig && !branchOtpVerify && !branchLoginRequested && !branchPasskeyVerify && !branchPasskeyCreate && !branchGuestPreauthClaiming && !branchDataLoading && !branchWalletPickerLink && state.activeCredentialId != null && hasActiveWallet(state.accounts) && !state.loadingData;
|
|
@@ -1983,6 +2143,7 @@ function createInitialState(config) {
|
|
|
1983
2143
|
selectedAccountId: null,
|
|
1984
2144
|
selectedWalletId: null,
|
|
1985
2145
|
selectedTokenSymbol: null,
|
|
2146
|
+
savedSelection: null,
|
|
1986
2147
|
amount: config.depositAmount != null ? config.depositAmount.toString() : "",
|
|
1987
2148
|
transfer: null,
|
|
1988
2149
|
creatingTransfer: false,
|
|
@@ -2009,7 +2170,8 @@ function createInitialState(config) {
|
|
|
2009
2170
|
standardDesktopInlineOpenWallet: false,
|
|
2010
2171
|
guestPreauthSetupCompletePending: false,
|
|
2011
2172
|
privyReady: false,
|
|
2012
|
-
privyAuthenticated: false
|
|
2173
|
+
privyAuthenticated: false,
|
|
2174
|
+
lastResumedAt: 0
|
|
2013
2175
|
};
|
|
2014
2176
|
}
|
|
2015
2177
|
function paymentReducer(state, action) {
|
|
@@ -2107,6 +2269,9 @@ function applyAction(state, action) {
|
|
|
2107
2269
|
next.mobileFlow = false;
|
|
2108
2270
|
next.deeplinkUri = null;
|
|
2109
2271
|
}
|
|
2272
|
+
if (action.resetSelectedTokenSymbol) {
|
|
2273
|
+
next.selectedTokenSymbol = null;
|
|
2274
|
+
}
|
|
2110
2275
|
return next;
|
|
2111
2276
|
}
|
|
2112
2277
|
case "DATA_LOAD_END":
|
|
@@ -2121,8 +2286,43 @@ function applyAction(state, action) {
|
|
|
2121
2286
|
next.selectedAccountId = action.defaults.accountId;
|
|
2122
2287
|
next.selectedWalletId = action.defaults.walletId;
|
|
2123
2288
|
}
|
|
2289
|
+
if (action.resetSelectedTokenSymbol) {
|
|
2290
|
+
next.selectedTokenSymbol = null;
|
|
2291
|
+
}
|
|
2124
2292
|
return next;
|
|
2125
2293
|
}
|
|
2294
|
+
case "SAVE_SELECTION":
|
|
2295
|
+
return {
|
|
2296
|
+
...state,
|
|
2297
|
+
savedSelection: {
|
|
2298
|
+
selectedProviderId: state.selectedProviderId,
|
|
2299
|
+
selectedAccountId: state.selectedAccountId,
|
|
2300
|
+
selectedWalletId: state.selectedWalletId,
|
|
2301
|
+
selectedTokenSymbol: state.selectedTokenSymbol
|
|
2302
|
+
}
|
|
2303
|
+
};
|
|
2304
|
+
case "RESTORE_SELECTION": {
|
|
2305
|
+
const snap = state.savedSelection;
|
|
2306
|
+
if (!snap) {
|
|
2307
|
+
return {
|
|
2308
|
+
...state,
|
|
2309
|
+
error: null,
|
|
2310
|
+
increasingLimit: false
|
|
2311
|
+
};
|
|
2312
|
+
}
|
|
2313
|
+
return {
|
|
2314
|
+
...state,
|
|
2315
|
+
selectedProviderId: snap.selectedProviderId,
|
|
2316
|
+
selectedAccountId: snap.selectedAccountId,
|
|
2317
|
+
selectedWalletId: snap.selectedWalletId,
|
|
2318
|
+
selectedTokenSymbol: snap.selectedTokenSymbol,
|
|
2319
|
+
savedSelection: null,
|
|
2320
|
+
error: null,
|
|
2321
|
+
increasingLimit: false
|
|
2322
|
+
};
|
|
2323
|
+
}
|
|
2324
|
+
case "DISCARD_SAVED_SELECTION":
|
|
2325
|
+
return { ...state, savedSelection: null };
|
|
2126
2326
|
// ── Source selection ──────────────────────────────────────────
|
|
2127
2327
|
case "SELECT_PROVIDER":
|
|
2128
2328
|
return {
|
|
@@ -2417,7 +2617,8 @@ function applyAction(state, action) {
|
|
|
2417
2617
|
oneTapLimitSavedDuringSetup: false,
|
|
2418
2618
|
guestPreauthorizing: false,
|
|
2419
2619
|
guestPreauthSetupCompletePending: false,
|
|
2420
|
-
standardDesktopInlineOpenWallet: false
|
|
2620
|
+
standardDesktopInlineOpenWallet: false,
|
|
2621
|
+
savedSelection: null
|
|
2421
2622
|
};
|
|
2422
2623
|
case "LOGOUT":
|
|
2423
2624
|
return {
|
|
@@ -2440,6 +2641,8 @@ function applyAction(state, action) {
|
|
|
2440
2641
|
};
|
|
2441
2642
|
case "SYNC_AMOUNT":
|
|
2442
2643
|
return { ...state, amount: action.amount };
|
|
2644
|
+
case "PAGE_RESUMED":
|
|
2645
|
+
return { ...state, lastResumedAt: Date.now() };
|
|
2443
2646
|
default:
|
|
2444
2647
|
return state;
|
|
2445
2648
|
}
|
|
@@ -2529,6 +2732,41 @@ function screenForPhase(phase) {
|
|
|
2529
2732
|
return "guest-preauth-linking";
|
|
2530
2733
|
}
|
|
2531
2734
|
}
|
|
2735
|
+
|
|
2736
|
+
// src/depositTokenSelection.ts
|
|
2737
|
+
function tokenOptionsForLinkedAccount(selectedAccount, chains) {
|
|
2738
|
+
if (!selectedAccount) return [];
|
|
2739
|
+
return selectedAccount.wallets.flatMap((w) => {
|
|
2740
|
+
const evmChainId = chains.find((c) => c.name === w.chain.name)?.commonId ?? void 0;
|
|
2741
|
+
return w.sources.filter((s) => s.balance.total.amount > 0).map((s) => ({
|
|
2742
|
+
symbol: s.token.symbol,
|
|
2743
|
+
chainName: w.chain.name,
|
|
2744
|
+
balance: s.balance.available.amount,
|
|
2745
|
+
walletId: w.id,
|
|
2746
|
+
status: s.token.status,
|
|
2747
|
+
tokenAddress: s.address,
|
|
2748
|
+
chainId: evmChainId
|
|
2749
|
+
}));
|
|
2750
|
+
});
|
|
2751
|
+
}
|
|
2752
|
+
function handleInlineTokenSelection(handlers, chains, selectedAccount, symbol, chainName, walletId) {
|
|
2753
|
+
if (walletId && selectedAccount) {
|
|
2754
|
+
const wallet = selectedAccount.wallets.find((w) => w.id === walletId);
|
|
2755
|
+
if (wallet && wallet.chain.name === chainName) {
|
|
2756
|
+
const source = wallet.sources.find((s) => s.token.symbol === symbol);
|
|
2757
|
+
const evmChainId = chains.find((c) => c.name === chainName)?.commonId ?? void 0;
|
|
2758
|
+
const authorized = !source?.token.status || source.token.status === "AUTHORIZED";
|
|
2759
|
+
if (source && !authorized && source.address && evmChainId != null) {
|
|
2760
|
+
void handlers.onAuthorizeToken(walletId, source.address, evmChainId, symbol);
|
|
2761
|
+
return;
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
handlers.onSelectAuthorizedToken(walletId, symbol);
|
|
2765
|
+
return;
|
|
2766
|
+
}
|
|
2767
|
+
handlers.onSelectSourceChainChange(chainName);
|
|
2768
|
+
handlers.onSetSelectSourceTokenSymbol(symbol);
|
|
2769
|
+
}
|
|
2532
2770
|
var MUTED = "#7fa4b0";
|
|
2533
2771
|
var LOGO_SIZE = 48;
|
|
2534
2772
|
function BlinkLoadingScreen() {
|
|
@@ -4081,6 +4319,22 @@ var loginButtonStyle = (accentColor) => ({
|
|
|
4081
4319
|
fontFamily: "inherit",
|
|
4082
4320
|
textDecoration: "underline"
|
|
4083
4321
|
});
|
|
4322
|
+
|
|
4323
|
+
// src/setupScreenSelection.ts
|
|
4324
|
+
function matchesSetupTokenSelection(opt, selectedTokenSymbol, selectedChainName, allOptions) {
|
|
4325
|
+
if (!selectedTokenSymbol || opt.symbol !== selectedTokenSymbol) {
|
|
4326
|
+
return false;
|
|
4327
|
+
}
|
|
4328
|
+
const chain = selectedChainName?.trim();
|
|
4329
|
+
if (chain) {
|
|
4330
|
+
return opt.chainName === chain;
|
|
4331
|
+
}
|
|
4332
|
+
const sameSymbol = allOptions.filter((o) => o.symbol === selectedTokenSymbol);
|
|
4333
|
+
if (sameSymbol.length === 1) {
|
|
4334
|
+
return opt.chainName === sameSymbol[0].chainName;
|
|
4335
|
+
}
|
|
4336
|
+
return false;
|
|
4337
|
+
}
|
|
4084
4338
|
var DEFAULT_MAX = 1e7;
|
|
4085
4339
|
var ABSOLUTE_MIN = 0.01;
|
|
4086
4340
|
var PRESETS = [100, 250, 1e3];
|
|
@@ -4096,13 +4350,16 @@ function SetupScreen({
|
|
|
4096
4350
|
loading,
|
|
4097
4351
|
error,
|
|
4098
4352
|
selectedTokenSymbol,
|
|
4353
|
+
selectedChainName,
|
|
4099
4354
|
tokenOptions,
|
|
4100
4355
|
onSelectToken
|
|
4101
4356
|
}) {
|
|
4102
4357
|
const { tokens } = useBlinkConfig();
|
|
4103
4358
|
const effectiveMax = DEFAULT_MAX;
|
|
4104
4359
|
const effectiveMin = Math.min(ABSOLUTE_MIN, effectiveMax);
|
|
4105
|
-
const
|
|
4360
|
+
const autoLimit = Math.min(Math.max(availableBalance, 0), effectiveMax);
|
|
4361
|
+
const [userChosenLimit, setUserChosenLimit] = react.useState(null);
|
|
4362
|
+
const limit = userChosenLimit ?? autoLimit;
|
|
4106
4363
|
const [activePreset, setActivePreset] = react.useState(null);
|
|
4107
4364
|
const [showAdvanced, setShowAdvanced] = react.useState(false);
|
|
4108
4365
|
const [editing, setEditing] = react.useState(false);
|
|
@@ -4141,20 +4398,22 @@ function SetupScreen({
|
|
|
4141
4398
|
const commitEdit = react.useCallback(() => {
|
|
4142
4399
|
const parsed = parseFloat(inputValue);
|
|
4143
4400
|
if (!isNaN(parsed)) {
|
|
4144
|
-
|
|
4401
|
+
setUserChosenLimit(
|
|
4402
|
+
Math.min(effectiveMax, Math.max(effectiveMin, Math.round(parsed * 100) / 100))
|
|
4403
|
+
);
|
|
4145
4404
|
}
|
|
4146
4405
|
setActivePreset(null);
|
|
4147
4406
|
setEditing(false);
|
|
4148
4407
|
}, [inputValue, effectiveMax, effectiveMin]);
|
|
4149
4408
|
const selectPreset = (value) => {
|
|
4150
|
-
|
|
4409
|
+
setUserChosenLimit(Math.min(value, effectiveMax));
|
|
4151
4410
|
setActivePreset(value);
|
|
4152
4411
|
};
|
|
4153
4412
|
const selectMax = () => {
|
|
4154
|
-
|
|
4413
|
+
setUserChosenLimit(autoLimit);
|
|
4155
4414
|
setActivePreset("max");
|
|
4156
4415
|
};
|
|
4157
|
-
const
|
|
4416
|
+
const options = tokenOptions ?? [];
|
|
4158
4417
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4159
4418
|
ScreenLayout,
|
|
4160
4419
|
{
|
|
@@ -4187,12 +4446,7 @@ function SetupScreen({
|
|
|
4187
4446
|
children: [
|
|
4188
4447
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenRowLabelStyle(tokens.text), children: "Token for one tap" }),
|
|
4189
4448
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenRowRightStyle, children: [
|
|
4190
|
-
|
|
4191
|
-
selectedOption.symbol,
|
|
4192
|
-
" \xB7 ",
|
|
4193
|
-
selectedOption.chainName
|
|
4194
|
-
] }),
|
|
4195
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenIconWrapStyle, children: selectedTokenSymbol && TOKEN_LOGOS[selectedTokenSymbol] ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: TOKEN_LOGOS[selectedTokenSymbol], alt: selectedTokenSymbol, width: 36, height: 36, style: { borderRadius: "50%" } }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
|
|
4449
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenIconWrapStyle, children: selectedTokenSymbol && TOKEN_LOGOS[selectedTokenSymbol] ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: TOKEN_LOGOS[selectedTokenSymbol], alt: "", width: 36, height: 36, style: { borderRadius: "50%" } }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
|
|
4196
4450
|
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "18", cy: "18", r: "18", fill: "#2DB84B" }),
|
|
4197
4451
|
/* @__PURE__ */ jsxRuntime.jsx("text", { x: "18", y: "23", textAnchor: "middle", fontSize: "18", fill: "#fff", fontWeight: "700", children: "$" })
|
|
4198
4452
|
] }) }),
|
|
@@ -4204,14 +4458,21 @@ function SetupScreen({
|
|
|
4204
4458
|
tokenDropdownOpen && tokenOptions && tokenOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: dropdownOuterStyle(tokens), children: [
|
|
4205
4459
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: dropdownLabelStyle(tokens.textMuted), children: "Choose token" }),
|
|
4206
4460
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: dropdownInnerStyle(tokens), children: tokenOptions.map((opt, index) => {
|
|
4207
|
-
const selected =
|
|
4461
|
+
const selected = matchesSetupTokenSelection(
|
|
4462
|
+
opt,
|
|
4463
|
+
selectedTokenSymbol,
|
|
4464
|
+
selectedChainName,
|
|
4465
|
+
options
|
|
4466
|
+
);
|
|
4208
4467
|
const isLast = index === tokenOptions.length - 1;
|
|
4468
|
+
const authorized = !opt.status || opt.status === "AUTHORIZED";
|
|
4209
4469
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4210
4470
|
"button",
|
|
4211
4471
|
{
|
|
4212
4472
|
type: "button",
|
|
4213
4473
|
onClick: () => handlePickToken(opt),
|
|
4214
4474
|
style: dropdownRowStyle(tokens, selected, isLast),
|
|
4475
|
+
"aria-label": opt.balance != null ? `${opt.symbol} on ${opt.chainName}, $${opt.balance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })} balance${!authorized ? ", not authorized" : ""}` : `${opt.symbol} on ${opt.chainName}${!authorized ? ", not authorized" : ""}`,
|
|
4215
4476
|
children: [
|
|
4216
4477
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: dropdownRowLeftStyle, children: [
|
|
4217
4478
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: dropdownTokenIconStyle(tokens, !!TOKEN_LOGOS[opt.symbol]), children: TOKEN_LOGOS[opt.symbol] ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: TOKEN_LOGOS[opt.symbol], alt: opt.symbol, style: dropdownTokenLogoStyle }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: dropdownTokenFallbackStyle(tokens.textMuted), children: "$" }) }),
|
|
@@ -4221,9 +4482,12 @@ function SetupScreen({
|
|
|
4221
4482
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: dropdownTokenDotStyle(tokens.textMuted), children: "\xB7" }),
|
|
4222
4483
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: dropdownTokenChainStyle(tokens.textMuted), children: opt.chainName })
|
|
4223
4484
|
] }),
|
|
4224
|
-
|
|
4225
|
-
"
|
|
4226
|
-
|
|
4485
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: dropdownTokenBalanceRowStyle, children: [
|
|
4486
|
+
opt.balance != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: dropdownTokenBalanceStyle(tokens.textMuted), children: [
|
|
4487
|
+
"$",
|
|
4488
|
+
opt.balance.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
|
4489
|
+
] }),
|
|
4490
|
+
!authorized && /* @__PURE__ */ jsxRuntime.jsx("span", { style: dropdownNotAuthorizedStyle(tokens.textMuted), children: "Not authorized" })
|
|
4227
4491
|
] })
|
|
4228
4492
|
] })
|
|
4229
4493
|
] }),
|
|
@@ -4343,11 +4607,6 @@ var tokenRowRightStyle = {
|
|
|
4343
4607
|
gap: 6,
|
|
4344
4608
|
flexShrink: 0
|
|
4345
4609
|
};
|
|
4346
|
-
var tokenRowSymbolStyle = (color) => ({
|
|
4347
|
-
fontSize: "0.84rem",
|
|
4348
|
-
fontWeight: 500,
|
|
4349
|
-
color
|
|
4350
|
-
});
|
|
4351
4610
|
var advancedToggleStyle = (accentColor) => ({
|
|
4352
4611
|
display: "block",
|
|
4353
4612
|
margin: "4px auto 24px",
|
|
@@ -4495,10 +4754,20 @@ var dropdownTokenChainStyle = (color) => ({
|
|
|
4495
4754
|
fontWeight: 400,
|
|
4496
4755
|
color
|
|
4497
4756
|
});
|
|
4757
|
+
var dropdownTokenBalanceRowStyle = {
|
|
4758
|
+
display: "flex",
|
|
4759
|
+
alignItems: "center",
|
|
4760
|
+
gap: 8
|
|
4761
|
+
};
|
|
4498
4762
|
var dropdownTokenBalanceStyle = (color) => ({
|
|
4499
4763
|
fontSize: "0.78rem",
|
|
4500
4764
|
color
|
|
4501
4765
|
});
|
|
4766
|
+
var dropdownNotAuthorizedStyle = (color) => ({
|
|
4767
|
+
fontSize: "0.7rem",
|
|
4768
|
+
fontWeight: 500,
|
|
4769
|
+
color
|
|
4770
|
+
});
|
|
4502
4771
|
var dropdownRadioEmptyStyle = (borderColor) => ({
|
|
4503
4772
|
width: 22,
|
|
4504
4773
|
height: 22,
|
|
@@ -4613,6 +4882,38 @@ var waitHintStyle = (color) => ({
|
|
|
4613
4882
|
color,
|
|
4614
4883
|
margin: 0
|
|
4615
4884
|
});
|
|
4885
|
+
|
|
4886
|
+
// src/feeFormat.ts
|
|
4887
|
+
function isPreciseMoneyNonPositive(fee) {
|
|
4888
|
+
const raw = fee.value.trim();
|
|
4889
|
+
if (!/^-?\d+(\.\d*)?$/.test(raw)) return false;
|
|
4890
|
+
const n = Number(raw);
|
|
4891
|
+
return Number.isFinite(n) && n <= 0;
|
|
4892
|
+
}
|
|
4893
|
+
function formatNonPositiveFeeDisplay(fee) {
|
|
4894
|
+
if (fee.currency === "USD") return "Under $0.01";
|
|
4895
|
+
return `Less than 0.01 ${fee.currency}`;
|
|
4896
|
+
}
|
|
4897
|
+
function formatPreciseMoneyForDisplay(fee) {
|
|
4898
|
+
const raw = fee.value.trim();
|
|
4899
|
+
if (fee.currency === "USD") {
|
|
4900
|
+
if (!/^\d+(\.\d*)?$/.test(raw)) {
|
|
4901
|
+
return `$${raw}`;
|
|
4902
|
+
}
|
|
4903
|
+
const [whole, frac = ""] = raw.split(".");
|
|
4904
|
+
const dec = `${frac}00`.slice(0, 2);
|
|
4905
|
+
const intFmt = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
4906
|
+
return `$${intFmt}.${dec}`;
|
|
4907
|
+
}
|
|
4908
|
+
return `${raw} ${fee.currency}`;
|
|
4909
|
+
}
|
|
4910
|
+
function formatUsdTwoDecimals(value) {
|
|
4911
|
+
const n = Number(value);
|
|
4912
|
+
return (Number.isFinite(n) ? n : 0).toLocaleString("en-US", {
|
|
4913
|
+
minimumFractionDigits: 2,
|
|
4914
|
+
maximumFractionDigits: 2
|
|
4915
|
+
});
|
|
4916
|
+
}
|
|
4616
4917
|
function DepositScreen({
|
|
4617
4918
|
merchantName,
|
|
4618
4919
|
availableBalance,
|
|
@@ -4620,6 +4921,8 @@ function DepositScreen({
|
|
|
4620
4921
|
tokenCount,
|
|
4621
4922
|
initialAmount,
|
|
4622
4923
|
minDepositFloor,
|
|
4924
|
+
quoteFee,
|
|
4925
|
+
quoteLoading,
|
|
4623
4926
|
processing,
|
|
4624
4927
|
error,
|
|
4625
4928
|
onDeposit,
|
|
@@ -4634,13 +4937,19 @@ function DepositScreen({
|
|
|
4634
4937
|
onAuthorizeAccount,
|
|
4635
4938
|
onAddProvider,
|
|
4636
4939
|
onSelectToken,
|
|
4940
|
+
tokenOptions,
|
|
4941
|
+
onPickToken,
|
|
4637
4942
|
selectedSourceLabel,
|
|
4638
|
-
selectedTokenSymbol
|
|
4943
|
+
selectedTokenSymbol,
|
|
4944
|
+
selectedChainName
|
|
4639
4945
|
}) {
|
|
4640
4946
|
const { tokens } = useBlinkConfig();
|
|
4641
4947
|
const amount = initialAmount;
|
|
4642
4948
|
const [accountPickerOpen, setAccountPickerOpen] = react.useState(false);
|
|
4949
|
+
const [tokenPickerOpen, setTokenPickerOpen] = react.useState(false);
|
|
4643
4950
|
const pickerRef = react.useRef(null);
|
|
4951
|
+
const tokenPickerRef = react.useRef(null);
|
|
4952
|
+
const hasTokenDropdown = tokenOptions != null && tokenOptions.length > 0 && onPickToken != null;
|
|
4644
4953
|
react.useEffect(() => {
|
|
4645
4954
|
if (!accountPickerOpen) return;
|
|
4646
4955
|
const handleClick = (e) => {
|
|
@@ -4651,6 +4960,28 @@ function DepositScreen({
|
|
|
4651
4960
|
document.addEventListener("mousedown", handleClick);
|
|
4652
4961
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
4653
4962
|
}, [accountPickerOpen]);
|
|
4963
|
+
react.useEffect(() => {
|
|
4964
|
+
if (!tokenPickerOpen) return;
|
|
4965
|
+
const handleMouseDown = (e) => {
|
|
4966
|
+
if (tokenPickerRef.current && !tokenPickerRef.current.contains(e.target)) {
|
|
4967
|
+
setTokenPickerOpen(false);
|
|
4968
|
+
}
|
|
4969
|
+
};
|
|
4970
|
+
document.addEventListener("mousedown", handleMouseDown);
|
|
4971
|
+
return () => document.removeEventListener("mousedown", handleMouseDown);
|
|
4972
|
+
}, [tokenPickerOpen]);
|
|
4973
|
+
const handleTokenBadgeClick = react.useCallback(() => {
|
|
4974
|
+
if (hasTokenDropdown) {
|
|
4975
|
+
setTokenPickerOpen((v) => !v);
|
|
4976
|
+
setAccountPickerOpen(false);
|
|
4977
|
+
} else {
|
|
4978
|
+
onSelectToken?.();
|
|
4979
|
+
}
|
|
4980
|
+
}, [hasTokenDropdown, onSelectToken]);
|
|
4981
|
+
const handlePickToken = react.useCallback((opt) => {
|
|
4982
|
+
onPickToken?.(opt.symbol, opt.chainName, opt.walletId);
|
|
4983
|
+
setTokenPickerOpen(false);
|
|
4984
|
+
}, [onPickToken]);
|
|
4654
4985
|
const selectedAccount = accounts?.find((a) => a.id === selectedAccountId);
|
|
4655
4986
|
const selectedProviderName = selectedAccount?.name ?? "Wallet";
|
|
4656
4987
|
const selectedProviderLogo = KNOWN_LOGOS[selectedProviderName.toLowerCase()];
|
|
@@ -4662,36 +4993,95 @@ function DepositScreen({
|
|
|
4662
4993
|
ScreenLayout,
|
|
4663
4994
|
{
|
|
4664
4995
|
footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4665
|
-
!accountPickerOpen && (exceedsLimit && onIncreaseLimit ? /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onIncreaseLimit, loading: increasingLimit, children: "Increase limit" }) : /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: "Confirm" })),
|
|
4996
|
+
!accountPickerOpen && !tokenPickerOpen && (exceedsLimit && onIncreaseLimit ? /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onIncreaseLimit, loading: increasingLimit, children: "Increase limit" }) : /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: () => onDeposit(amount), disabled: !canDeposit, loading: processing, children: "Confirm" })),
|
|
4666
4997
|
/* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
|
|
4667
4998
|
] }),
|
|
4668
4999
|
children: [
|
|
4669
5000
|
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onBack, onLogout }),
|
|
4670
5001
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { ref: pickerRef, style: depositCardWrapStyle, children: [
|
|
4671
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5002
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: depositCardStyle(tokens), children: [
|
|
4672
5003
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: depositLabelStyle(tokens.textMuted), children: "Depositing" }),
|
|
4673
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
4674
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style:
|
|
4675
|
-
"
|
|
4676
|
-
|
|
5004
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { ref: tokenPickerRef, children: [
|
|
5005
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: amountRowStyle, children: [
|
|
5006
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: amountValueStyle(tokens.text), children: [
|
|
5007
|
+
"$",
|
|
5008
|
+
formatUsdTwoDecimals(amount)
|
|
5009
|
+
] }),
|
|
5010
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
5011
|
+
"button",
|
|
5012
|
+
{
|
|
5013
|
+
type: "button",
|
|
5014
|
+
"data-testid": "deposit-token-badge",
|
|
5015
|
+
onClick: handleTokenBadgeClick,
|
|
5016
|
+
style: tokenIconButtonStyle(hasTokenDropdown || !!onSelectToken),
|
|
5017
|
+
"aria-expanded": hasTokenDropdown ? tokenPickerOpen : void 0,
|
|
5018
|
+
"aria-haspopup": hasTokenDropdown ? "listbox" : void 0,
|
|
5019
|
+
children: [
|
|
5020
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenIconWrapStyle2, children: selectedTokenSymbol && TOKEN_LOGOS[selectedTokenSymbol] ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: TOKEN_LOGOS[selectedTokenSymbol], alt: selectedTokenSymbol, width: 36, height: 36, style: { borderRadius: "50%" } }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", children: [
|
|
5021
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "18", cy: "18", r: "18", fill: "#2DB84B" }),
|
|
5022
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: "18", y: "23", textAnchor: "middle", fontSize: "18", fill: "#fff", fontWeight: "700", children: "$" })
|
|
5023
|
+
] }) }),
|
|
5024
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", style: { opacity: 0.5 }, children: tokenPickerOpen ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 15l-6-6-6 6", stroke: tokens.textMuted, strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }) : /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 9l6 6 6-6", stroke: tokens.textMuted, strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
5025
|
+
]
|
|
5026
|
+
}
|
|
5027
|
+
)
|
|
4677
5028
|
] }),
|
|
4678
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4679
|
-
"
|
|
4680
|
-
{
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
5029
|
+
tokenPickerOpen && tokenOptions && tokenOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenDropdownStyle(tokens), children: [
|
|
5030
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenDropdownLabelStyle(tokens.textMuted), children: "Choose token" }),
|
|
5031
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenDropdownInnerStyle(tokens), children: tokenOptions.map((opt, index) => {
|
|
5032
|
+
const selected = opt.symbol === selectedTokenSymbol && (!selectedChainName || opt.chainName === selectedChainName);
|
|
5033
|
+
const isLast = index === tokenOptions.length - 1;
|
|
5034
|
+
const authorized = !opt.status || opt.status === "AUTHORIZED";
|
|
5035
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5036
|
+
"button",
|
|
5037
|
+
{
|
|
5038
|
+
type: "button",
|
|
5039
|
+
onClick: () => handlePickToken(opt),
|
|
5040
|
+
style: tokenDropdownRowStyle(tokens, selected, isLast),
|
|
5041
|
+
"aria-label": opt.balance != null ? `${opt.symbol} on ${opt.chainName}, $${formatUsdTwoDecimals(opt.balance)} balance${!authorized ? ", not authorized" : ""}` : `${opt.symbol} on ${opt.chainName}${!authorized ? ", not authorized" : ""}`,
|
|
5042
|
+
children: [
|
|
5043
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenDropdownRowLeftStyle, children: [
|
|
5044
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenDropdownIconStyle(tokens, !!TOKEN_LOGOS[opt.symbol]), children: TOKEN_LOGOS[opt.symbol] ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: TOKEN_LOGOS[opt.symbol], alt: opt.symbol, style: tokenDropdownLogoStyle }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDropdownFallbackStyle(tokens.textMuted), children: "$" }) }),
|
|
5045
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenDropdownInfoStyle, children: [
|
|
5046
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenDropdownNameRowStyle, children: [
|
|
5047
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDropdownSymbolStyle(tokens.text), children: opt.symbol }),
|
|
5048
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDropdownDotStyle(tokens.textMuted), children: "\xB7" }),
|
|
5049
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDropdownChainStyle(tokens.textMuted), children: opt.chainName })
|
|
5050
|
+
] }),
|
|
5051
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenDropdownBalanceRowStyle, children: [
|
|
5052
|
+
opt.balance != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: tokenDropdownBalanceStyle(tokens.textMuted), children: [
|
|
5053
|
+
"$",
|
|
5054
|
+
formatUsdTwoDecimals(opt.balance)
|
|
5055
|
+
] }),
|
|
5056
|
+
!authorized && /* @__PURE__ */ jsxRuntime.jsx("span", { style: tokenDropdownNotAuthStyle(tokens.textMuted), children: "Not authorized" })
|
|
5057
|
+
] })
|
|
5058
|
+
] })
|
|
5059
|
+
] }),
|
|
5060
|
+
selected ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 22 22", fill: "none", children: [
|
|
5061
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "11", fill: tokens.success }),
|
|
5062
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 11l3 3 5-5", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
5063
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenDropdownRadioStyle(tokens.border) })
|
|
5064
|
+
]
|
|
5065
|
+
},
|
|
5066
|
+
`${opt.chainName}-${opt.symbol}`
|
|
5067
|
+
);
|
|
5068
|
+
}) })
|
|
5069
|
+
] })
|
|
4693
5070
|
] }),
|
|
4694
|
-
!accountPickerOpen &&
|
|
5071
|
+
!accountPickerOpen && !tokenPickerOpen && (() => {
|
|
5072
|
+
if (quoteLoading) {
|
|
5073
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: feeRowContainerStyle, "aria-live": "polite", children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: feeRowLabelStyle(tokens.textMuted), children: "Getting fee estimate\u2026" }) });
|
|
5074
|
+
}
|
|
5075
|
+
if (quoteFee) {
|
|
5076
|
+
const feeText = isPreciseMoneyNonPositive(quoteFee) ? formatNonPositiveFeeDisplay(quoteFee) : formatPreciseMoneyForDisplay(quoteFee);
|
|
5077
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: feeRowContainerStyle, "aria-live": "polite", children: [
|
|
5078
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: feeRowLabelStyle(tokens.textMuted), children: "Fee estimate: " }),
|
|
5079
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: feeRowAmountStyle(tokens.textSecondary), children: feeText })
|
|
5080
|
+
] });
|
|
5081
|
+
}
|
|
5082
|
+
return null;
|
|
5083
|
+
})(),
|
|
5084
|
+
!accountPickerOpen && !tokenPickerOpen && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4695
5085
|
"button",
|
|
4696
5086
|
{
|
|
4697
5087
|
type: "button",
|
|
@@ -4701,7 +5091,7 @@ function DepositScreen({
|
|
|
4701
5091
|
selectedProviderLogo ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: selectedProviderLogo, alt: selectedProviderName, style: providerLogoStyle }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: providerFallbackStyle(tokens.textMuted), children: selectedProviderName.charAt(0) }),
|
|
4702
5092
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: walletBalanceStyle(tokens.text), children: [
|
|
4703
5093
|
"$",
|
|
4704
|
-
totalAccountBalance
|
|
5094
|
+
formatUsdTwoDecimals(totalAccountBalance)
|
|
4705
5095
|
] }),
|
|
4706
5096
|
/* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", style: { opacity: 0.4 }, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 10l5-5 5 5M7 14l5 5 5-5", stroke: tokens.textMuted, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
4707
5097
|
]
|
|
@@ -4742,7 +5132,7 @@ function DepositScreen({
|
|
|
4742
5132
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: accountAddressStyle(tokens.text), children: truncatedAddress ?? account.nickname ?? account.name }),
|
|
4743
5133
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: accountBalanceTextStyle(tokens.textMuted), children: [
|
|
4744
5134
|
"$",
|
|
4745
|
-
accountBalance
|
|
5135
|
+
formatUsdTwoDecimals(accountBalance)
|
|
4746
5136
|
] })
|
|
4747
5137
|
] })
|
|
4748
5138
|
] }),
|
|
@@ -4778,21 +5168,21 @@ function DepositScreen({
|
|
|
4778
5168
|
" ",
|
|
4779
5169
|
/* @__PURE__ */ jsxRuntime.jsxs("strong", { style: { color: tokens.text }, children: [
|
|
4780
5170
|
"$",
|
|
4781
|
-
remainingLimit
|
|
5171
|
+
formatUsdTwoDecimals(remainingLimit)
|
|
4782
5172
|
] }),
|
|
4783
5173
|
exceedsLimit && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: limitExceededHintStyle(tokens.warning), children: [
|
|
4784
5174
|
"Your deposit of $",
|
|
4785
|
-
amount
|
|
5175
|
+
formatUsdTwoDecimals(amount),
|
|
4786
5176
|
" exceeds your One-Tap limit of $",
|
|
4787
|
-
remainingLimit
|
|
5177
|
+
remainingLimit != null ? formatUsdTwoDecimals(remainingLimit) : "0.00",
|
|
4788
5178
|
". Increase your limit to continue."
|
|
4789
5179
|
] })
|
|
4790
5180
|
] }),
|
|
4791
5181
|
!accountPickerOpen && isLowBalance && /* @__PURE__ */ jsxRuntime.jsxs(WarningBanner, { title: "Not enough funds", children: [
|
|
4792
5182
|
"Your wallet balance is $",
|
|
4793
|
-
availableBalance
|
|
5183
|
+
formatUsdTwoDecimals(availableBalance),
|
|
4794
5184
|
" \u2014 you need at least $",
|
|
4795
|
-
minDepositFloor
|
|
5185
|
+
formatUsdTwoDecimals(minDepositFloor),
|
|
4796
5186
|
" to deposit via One-Tap."
|
|
4797
5187
|
] }),
|
|
4798
5188
|
error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle6(tokens), children: error })
|
|
@@ -4804,6 +5194,11 @@ var depositCardWrapStyle = {
|
|
|
4804
5194
|
position: "relative",
|
|
4805
5195
|
marginBottom: 20
|
|
4806
5196
|
};
|
|
5197
|
+
var depositCardStyle = (tokens) => ({
|
|
5198
|
+
border: `1px solid ${tokens.border}`,
|
|
5199
|
+
borderRadius: tokens.radiusLg,
|
|
5200
|
+
padding: "16px 20px"
|
|
5201
|
+
});
|
|
4807
5202
|
var depositLabelStyle = (color) => ({
|
|
4808
5203
|
fontSize: "0.75rem",
|
|
4809
5204
|
fontWeight: 500,
|
|
@@ -4837,6 +5232,116 @@ var tokenIconWrapStyle2 = {
|
|
|
4837
5232
|
width: 36,
|
|
4838
5233
|
height: 36
|
|
4839
5234
|
};
|
|
5235
|
+
var tokenDropdownStyle = (t) => ({
|
|
5236
|
+
marginTop: 4,
|
|
5237
|
+
marginBottom: 12,
|
|
5238
|
+
background: t.bgCard,
|
|
5239
|
+
border: `1px solid ${t.border}`,
|
|
5240
|
+
borderRadius: t.radiusLg,
|
|
5241
|
+
boxShadow: t.shadowLg,
|
|
5242
|
+
padding: "12px 14px 14px"
|
|
5243
|
+
});
|
|
5244
|
+
var tokenDropdownLabelStyle = (color) => ({
|
|
5245
|
+
fontSize: "0.78rem",
|
|
5246
|
+
fontWeight: 500,
|
|
5247
|
+
color,
|
|
5248
|
+
marginBottom: 8
|
|
5249
|
+
});
|
|
5250
|
+
var tokenDropdownInnerStyle = (t) => ({
|
|
5251
|
+
background: t.bgInput,
|
|
5252
|
+
border: `1px solid ${t.border}`,
|
|
5253
|
+
borderRadius: t.radiusLg,
|
|
5254
|
+
overflow: "hidden"
|
|
5255
|
+
});
|
|
5256
|
+
var tokenDropdownRowStyle = (t, isSelected, isLast) => ({
|
|
5257
|
+
display: "flex",
|
|
5258
|
+
alignItems: "center",
|
|
5259
|
+
justifyContent: "space-between",
|
|
5260
|
+
width: "100%",
|
|
5261
|
+
padding: "14px 16px",
|
|
5262
|
+
background: isSelected ? `${t.accent}18` : "transparent",
|
|
5263
|
+
border: "none",
|
|
5264
|
+
borderBottom: isLast ? "none" : `1px solid ${t.border}`,
|
|
5265
|
+
cursor: "pointer",
|
|
5266
|
+
fontFamily: "inherit",
|
|
5267
|
+
textAlign: "left",
|
|
5268
|
+
outline: "none"
|
|
5269
|
+
});
|
|
5270
|
+
var tokenDropdownRowLeftStyle = {
|
|
5271
|
+
display: "flex",
|
|
5272
|
+
alignItems: "center",
|
|
5273
|
+
gap: 12,
|
|
5274
|
+
minWidth: 0,
|
|
5275
|
+
flex: 1
|
|
5276
|
+
};
|
|
5277
|
+
var tokenDropdownIconStyle = (t, hasLogo) => ({
|
|
5278
|
+
width: 36,
|
|
5279
|
+
height: 36,
|
|
5280
|
+
borderRadius: "50%",
|
|
5281
|
+
border: hasLogo ? "none" : `1.5px solid ${t.border}`,
|
|
5282
|
+
display: "flex",
|
|
5283
|
+
alignItems: "center",
|
|
5284
|
+
justifyContent: "center",
|
|
5285
|
+
flexShrink: 0,
|
|
5286
|
+
overflow: "hidden"
|
|
5287
|
+
});
|
|
5288
|
+
var tokenDropdownLogoStyle = {
|
|
5289
|
+
width: 36,
|
|
5290
|
+
height: 36,
|
|
5291
|
+
borderRadius: "50%",
|
|
5292
|
+
objectFit: "cover"
|
|
5293
|
+
};
|
|
5294
|
+
var tokenDropdownFallbackStyle = (color) => ({
|
|
5295
|
+
fontSize: "1rem",
|
|
5296
|
+
fontWeight: 700,
|
|
5297
|
+
color
|
|
5298
|
+
});
|
|
5299
|
+
var tokenDropdownInfoStyle = {
|
|
5300
|
+
display: "flex",
|
|
5301
|
+
flexDirection: "column",
|
|
5302
|
+
gap: 2,
|
|
5303
|
+
minWidth: 0
|
|
5304
|
+
};
|
|
5305
|
+
var tokenDropdownNameRowStyle = {
|
|
5306
|
+
display: "flex",
|
|
5307
|
+
alignItems: "center",
|
|
5308
|
+
gap: 4
|
|
5309
|
+
};
|
|
5310
|
+
var tokenDropdownSymbolStyle = (color) => ({
|
|
5311
|
+
fontSize: "0.92rem",
|
|
5312
|
+
fontWeight: 600,
|
|
5313
|
+
color
|
|
5314
|
+
});
|
|
5315
|
+
var tokenDropdownDotStyle = (color) => ({
|
|
5316
|
+
fontSize: "0.8rem",
|
|
5317
|
+
color
|
|
5318
|
+
});
|
|
5319
|
+
var tokenDropdownChainStyle = (color) => ({
|
|
5320
|
+
fontSize: "0.84rem",
|
|
5321
|
+
fontWeight: 400,
|
|
5322
|
+
color
|
|
5323
|
+
});
|
|
5324
|
+
var tokenDropdownBalanceRowStyle = {
|
|
5325
|
+
display: "flex",
|
|
5326
|
+
alignItems: "center",
|
|
5327
|
+
gap: 8
|
|
5328
|
+
};
|
|
5329
|
+
var tokenDropdownBalanceStyle = (color) => ({
|
|
5330
|
+
fontSize: "0.78rem",
|
|
5331
|
+
color
|
|
5332
|
+
});
|
|
5333
|
+
var tokenDropdownNotAuthStyle = (color) => ({
|
|
5334
|
+
fontSize: "0.7rem",
|
|
5335
|
+
fontWeight: 500,
|
|
5336
|
+
color
|
|
5337
|
+
});
|
|
5338
|
+
var tokenDropdownRadioStyle = (borderColor) => ({
|
|
5339
|
+
width: 22,
|
|
5340
|
+
height: 22,
|
|
5341
|
+
borderRadius: "50%",
|
|
5342
|
+
border: `2px solid ${borderColor}`,
|
|
5343
|
+
flexShrink: 0
|
|
5344
|
+
});
|
|
4840
5345
|
var walletBalanceRowStyle = {
|
|
4841
5346
|
display: "flex",
|
|
4842
5347
|
alignItems: "center",
|
|
@@ -4998,9 +5503,20 @@ var limitExceededHintStyle = (color) => ({
|
|
|
4998
5503
|
margin: "12px 0 2px",
|
|
4999
5504
|
lineHeight: 1.5
|
|
5000
5505
|
});
|
|
5506
|
+
var feeRowContainerStyle = {
|
|
5507
|
+
fontSize: "0.84rem",
|
|
5508
|
+
fontWeight: 500,
|
|
5509
|
+
marginTop: 6,
|
|
5510
|
+
marginBottom: 4
|
|
5511
|
+
};
|
|
5512
|
+
var feeRowLabelStyle = (color) => ({ color });
|
|
5513
|
+
var feeRowAmountStyle = (color) => ({
|
|
5514
|
+
color,
|
|
5515
|
+
fontVariantNumeric: "tabular-nums"
|
|
5516
|
+
});
|
|
5001
5517
|
function SuccessScreen({
|
|
5002
5518
|
amount,
|
|
5003
|
-
currency,
|
|
5519
|
+
currency: _currency,
|
|
5004
5520
|
succeeded,
|
|
5005
5521
|
error,
|
|
5006
5522
|
merchantName,
|
|
@@ -5013,22 +5529,30 @@ function SuccessScreen({
|
|
|
5013
5529
|
onPreauthorize
|
|
5014
5530
|
}) {
|
|
5015
5531
|
const { tokens } = useBlinkConfig();
|
|
5532
|
+
const isGuestDepositSuccess = succeeded && onPreauthorize != null;
|
|
5016
5533
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5017
5534
|
ScreenLayout,
|
|
5018
5535
|
{
|
|
5019
5536
|
footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5020
|
-
|
|
5021
|
-
/* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onPreauthorize, children: "
|
|
5022
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onDone, style: skipButtonStyle(tokens.textMuted), children: "
|
|
5537
|
+
isGuestDepositSuccess ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5538
|
+
/* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onPreauthorize, children: "Set up one tap" }),
|
|
5539
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onDone, style: skipButtonStyle(tokens.textMuted), children: "Return to app" })
|
|
5023
5540
|
] }) : /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: onDone, children: succeeded ? "Done" : "Try again" }),
|
|
5024
5541
|
onManageAccount && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onManageAccount, style: manageStyle(tokens.textMuted), children: "Manage Blink account \u2192" }),
|
|
5025
5542
|
/* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {})
|
|
5026
5543
|
] }),
|
|
5027
5544
|
children: [
|
|
5028
5545
|
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onLogout }),
|
|
5029
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style:
|
|
5030
|
-
|
|
5031
|
-
/* @__PURE__ */ jsxRuntime.
|
|
5546
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: screenContentStyle, children: [
|
|
5547
|
+
isGuestDepositSuccess ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyleCompact, children: [
|
|
5548
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h2", { style: headingStyle7(tokens.text), children: [
|
|
5549
|
+
"$",
|
|
5550
|
+
amount.toFixed(2),
|
|
5551
|
+
" deposited"
|
|
5552
|
+
] }),
|
|
5553
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { ...subtitleStyle7(tokens.text), fontWeight: 600, margin: "0 0 8px" }, children: "Next time, do it in one tap" }),
|
|
5554
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle7(tokens.textSecondary), children: "Set up one tap for this wallet and skip the extra steps." })
|
|
5555
|
+
] }) : succeeded ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyleCompact, children: [
|
|
5032
5556
|
/* @__PURE__ */ jsxRuntime.jsxs("h2", { style: headingStyle7(tokens.text), children: [
|
|
5033
5557
|
"$",
|
|
5034
5558
|
amount.toFixed(2),
|
|
@@ -5040,10 +5564,10 @@ function SuccessScreen({
|
|
|
5040
5564
|
] })
|
|
5041
5565
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5042
5566
|
/* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "error", size: 64, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z", fill: tokens.error }) }) }),
|
|
5043
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { style:
|
|
5044
|
-
error && /* @__PURE__ */ jsxRuntime.jsx("p", { style:
|
|
5567
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: failureHeadingStyle(tokens.text), children: "Transfer failed" }),
|
|
5568
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: failureSubtitleStyle(tokens.error), children: error })
|
|
5045
5569
|
] }),
|
|
5046
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryCardStyle(tokens), children: [
|
|
5570
|
+
!isGuestDepositSuccess && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryCardStyle(tokens), children: [
|
|
5047
5571
|
sourceName && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: summaryRowStyle, children: [
|
|
5048
5572
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryLabelStyle(tokens.textMuted), children: "From" }),
|
|
5049
5573
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: summaryValueStyle(tokens.text), children: sourceName })
|
|
@@ -5060,7 +5584,7 @@ function SuccessScreen({
|
|
|
5060
5584
|
] })
|
|
5061
5585
|
] })
|
|
5062
5586
|
] }),
|
|
5063
|
-
succeeded && onIncreaseLimits && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: upsellCardStyle(tokens), children: [
|
|
5587
|
+
succeeded && onIncreaseLimits && !isGuestDepositSuccess && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: upsellCardStyle(tokens), children: [
|
|
5064
5588
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: upsellHeaderStyle, children: [
|
|
5065
5589
|
/* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", style: { marginRight: 6 }, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 14l5-5 5 5", stroke: tokens.accent, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
5066
5590
|
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Want higher limits?" })
|
|
@@ -5073,21 +5597,42 @@ function SuccessScreen({
|
|
|
5073
5597
|
}
|
|
5074
5598
|
);
|
|
5075
5599
|
}
|
|
5076
|
-
var
|
|
5600
|
+
var screenContentStyle = {
|
|
5077
5601
|
flex: 1,
|
|
5078
5602
|
display: "flex",
|
|
5079
5603
|
flexDirection: "column",
|
|
5080
5604
|
alignItems: "center",
|
|
5081
5605
|
paddingTop: 16
|
|
5082
5606
|
};
|
|
5607
|
+
var contentStyleCompact = {
|
|
5608
|
+
textAlign: "center",
|
|
5609
|
+
display: "flex",
|
|
5610
|
+
flexDirection: "column",
|
|
5611
|
+
alignItems: "center",
|
|
5612
|
+
width: "100%"
|
|
5613
|
+
};
|
|
5083
5614
|
var headingStyle7 = (color) => ({
|
|
5615
|
+
fontSize: "1.45rem",
|
|
5616
|
+
fontWeight: 700,
|
|
5617
|
+
letterSpacing: "-0.02em",
|
|
5618
|
+
color,
|
|
5619
|
+
margin: "20px 0 8px"
|
|
5620
|
+
});
|
|
5621
|
+
var subtitleStyle7 = (color) => ({
|
|
5622
|
+
fontSize: "0.9rem",
|
|
5623
|
+
color,
|
|
5624
|
+
margin: "0 0 28px",
|
|
5625
|
+
lineHeight: 1.5,
|
|
5626
|
+
maxWidth: 280
|
|
5627
|
+
});
|
|
5628
|
+
var failureHeadingStyle = (color) => ({
|
|
5084
5629
|
fontSize: "1.5rem",
|
|
5085
5630
|
fontWeight: 700,
|
|
5086
5631
|
letterSpacing: "-0.02em",
|
|
5087
5632
|
color,
|
|
5088
5633
|
margin: "20px 0 4px"
|
|
5089
5634
|
});
|
|
5090
|
-
var
|
|
5635
|
+
var failureSubtitleStyle = (color) => ({
|
|
5091
5636
|
fontSize: "0.9rem",
|
|
5092
5637
|
color,
|
|
5093
5638
|
margin: "0 0 20px"
|
|
@@ -5603,7 +6148,7 @@ function TransferStatusScreen({
|
|
|
5603
6148
|
const steps = buildSteps(phase);
|
|
5604
6149
|
return /* @__PURE__ */ jsxRuntime.jsxs(ScreenLayout, { footer: /* @__PURE__ */ jsxRuntime.jsx(PoweredByFooter, {}), children: [
|
|
5605
6150
|
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onLogout }),
|
|
5606
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style:
|
|
6151
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle6, children: [
|
|
5607
6152
|
/* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 64 }),
|
|
5608
6153
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle9(tokens.text), children: "Depositing your money..." }),
|
|
5609
6154
|
error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: errorBannerStyle7(tokens), children: error }),
|
|
@@ -5611,7 +6156,7 @@ function TransferStatusScreen({
|
|
|
5611
6156
|
] })
|
|
5612
6157
|
] });
|
|
5613
6158
|
}
|
|
5614
|
-
var
|
|
6159
|
+
var contentStyle6 = {
|
|
5615
6160
|
flex: 1,
|
|
5616
6161
|
display: "flex",
|
|
5617
6162
|
flexDirection: "column",
|
|
@@ -5681,7 +6226,7 @@ function OpenWalletScreen({
|
|
|
5681
6226
|
] }),
|
|
5682
6227
|
children: [
|
|
5683
6228
|
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onLogout }),
|
|
5684
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style:
|
|
6229
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle7, children: [
|
|
5685
6230
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: logoCircleStyle(tokens.bgInput), children: logoSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoSrc, alt: displayName, style: logoStyle2 }) : /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 32 }) }),
|
|
5686
6231
|
/* @__PURE__ */ jsxRuntime.jsxs("h2", { style: headingStyle10(tokens.text), children: [
|
|
5687
6232
|
"Setting up ",
|
|
@@ -5714,7 +6259,7 @@ function OpenWalletScreen({
|
|
|
5714
6259
|
] }),
|
|
5715
6260
|
children: [
|
|
5716
6261
|
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onBack, onLogout }),
|
|
5717
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style:
|
|
6262
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle7, children: [
|
|
5718
6263
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: logoCircleStyle(tokens.bgInput), children: logoSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoSrc, alt: displayName, style: logoStyle2 }) : /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 32 }) }),
|
|
5719
6264
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle10(tokens.text), children: loading ? "Connecting..." : `Open ${displayName}` }),
|
|
5720
6265
|
/* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle10(tokens.textSecondary), children: loading ? "Creating transfer and preparing your wallet link..." : `Continue in ${displayName} to authorize this connection.` }),
|
|
@@ -5727,7 +6272,7 @@ function OpenWalletScreen({
|
|
|
5727
6272
|
}
|
|
5728
6273
|
);
|
|
5729
6274
|
}
|
|
5730
|
-
var
|
|
6275
|
+
var contentStyle7 = {
|
|
5731
6276
|
flex: 1,
|
|
5732
6277
|
display: "flex",
|
|
5733
6278
|
flexDirection: "column",
|
|
@@ -5813,7 +6358,7 @@ function ConfirmSignScreen({
|
|
|
5813
6358
|
] }),
|
|
5814
6359
|
children: [
|
|
5815
6360
|
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onLogout }),
|
|
5816
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style:
|
|
6361
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle8, children: [
|
|
5817
6362
|
logoSrc ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoSrc, alt: displayName, style: logoStyle3 }) : /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
|
|
5818
6363
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle11(tokens.text), children: "Wallet authorized" }),
|
|
5819
6364
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { style: subtitleStyle11(tokens.textSecondary), children: [
|
|
@@ -5829,7 +6374,7 @@ function ConfirmSignScreen({
|
|
|
5829
6374
|
}
|
|
5830
6375
|
);
|
|
5831
6376
|
}
|
|
5832
|
-
var
|
|
6377
|
+
var contentStyle8 = {
|
|
5833
6378
|
flex: 1,
|
|
5834
6379
|
display: "flex",
|
|
5835
6380
|
flexDirection: "column",
|
|
@@ -6124,29 +6669,6 @@ var selectCircleSelectedStyle = (color) => ({
|
|
|
6124
6669
|
function entryKey(entry) {
|
|
6125
6670
|
return `${entry.sourceChainId}-${entry.tokenAddress.toLowerCase()}`;
|
|
6126
6671
|
}
|
|
6127
|
-
function isPreciseMoneyNonPositive(fee) {
|
|
6128
|
-
const raw = fee.value.trim();
|
|
6129
|
-
if (!/^-?\d+(\.\d*)?$/.test(raw)) return false;
|
|
6130
|
-
const n = Number(raw);
|
|
6131
|
-
return Number.isFinite(n) && n <= 0;
|
|
6132
|
-
}
|
|
6133
|
-
function formatNonPositiveFeeDisplay(fee) {
|
|
6134
|
-
if (fee.currency === "USD") return "Under $0.01";
|
|
6135
|
-
return `Less than 0.01 ${fee.currency}`;
|
|
6136
|
-
}
|
|
6137
|
-
function formatPreciseMoneyForDisplay(fee) {
|
|
6138
|
-
const raw = fee.value.trim();
|
|
6139
|
-
if (fee.currency === "USD") {
|
|
6140
|
-
if (!/^\d+(\.\d*)?$/.test(raw)) {
|
|
6141
|
-
return `$${raw}`;
|
|
6142
|
-
}
|
|
6143
|
-
const [whole, frac = ""] = raw.split(".");
|
|
6144
|
-
const dec = `${frac}00`.slice(0, 2);
|
|
6145
|
-
const intFmt = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
6146
|
-
return `$${intFmt}.${dec}`;
|
|
6147
|
-
}
|
|
6148
|
-
return `${raw} ${fee.currency}`;
|
|
6149
|
-
}
|
|
6150
6672
|
function GuestTokenPickerScreen({
|
|
6151
6673
|
entries,
|
|
6152
6674
|
loading,
|
|
@@ -6186,13 +6708,13 @@ function GuestTokenPickerScreen({
|
|
|
6186
6708
|
const canConfirm = Boolean(quoteFee && pendingEntry && !quoteLoading);
|
|
6187
6709
|
const feeLine = (() => {
|
|
6188
6710
|
if (quoteLoading && pendingEntry) {
|
|
6189
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { style:
|
|
6711
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: feeRowContainerStyle2, "aria-live": "polite", children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: feeRowLabelStyle2(t.textMuted), children: "Getting fee estimate\u2026" }) });
|
|
6190
6712
|
}
|
|
6191
6713
|
if (quoteFee) {
|
|
6192
6714
|
const feeText = isPreciseMoneyNonPositive(quoteFee) ? formatNonPositiveFeeDisplay(quoteFee) : formatPreciseMoneyForDisplay(quoteFee);
|
|
6193
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style:
|
|
6194
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style:
|
|
6195
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style:
|
|
6715
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: feeRowContainerStyle2, "aria-live": "polite", children: [
|
|
6716
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: feeRowLabelStyle2(t.textMuted), children: "Fee estimate: " }),
|
|
6717
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: feeRowAmountStyle2(t.textSecondary), children: feeText })
|
|
6196
6718
|
] });
|
|
6197
6719
|
}
|
|
6198
6720
|
return null;
|
|
@@ -6214,7 +6736,7 @@ function GuestTokenPickerScreen({
|
|
|
6214
6736
|
depositAmount != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: depositAmountStyle2(t.text), children: [
|
|
6215
6737
|
"$",
|
|
6216
6738
|
depositAmount.toLocaleString("en-US", {
|
|
6217
|
-
minimumFractionDigits:
|
|
6739
|
+
minimumFractionDigits: 2,
|
|
6218
6740
|
maximumFractionDigits: 2
|
|
6219
6741
|
})
|
|
6220
6742
|
] }),
|
|
@@ -6296,7 +6818,7 @@ function GuestTokenPickerScreen({
|
|
|
6296
6818
|
] }),
|
|
6297
6819
|
tokenListOpen && entries.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tokenDropdownOuterStyle(t), children: [
|
|
6298
6820
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: accountDropdownLabelStyle2(t.textMuted), children: "Choose token" }),
|
|
6299
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style:
|
|
6821
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: tokenDropdownInnerStyle2(t), children: entries.map((entry, index) => {
|
|
6300
6822
|
const selected = pendingKey === entryKey(entry);
|
|
6301
6823
|
const isLast = index === entries.length - 1;
|
|
6302
6824
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -6397,13 +6919,13 @@ var depositAmountStyle2 = (color) => ({
|
|
|
6397
6919
|
color,
|
|
6398
6920
|
lineHeight: 1.05
|
|
6399
6921
|
});
|
|
6400
|
-
var
|
|
6922
|
+
var feeRowContainerStyle2 = {
|
|
6401
6923
|
fontSize: "0.84rem",
|
|
6402
6924
|
fontWeight: 500,
|
|
6403
6925
|
marginTop: 6
|
|
6404
6926
|
};
|
|
6405
|
-
var
|
|
6406
|
-
var
|
|
6927
|
+
var feeRowLabelStyle2 = (color) => ({ color });
|
|
6928
|
+
var feeRowAmountStyle2 = (color) => ({
|
|
6407
6929
|
color,
|
|
6408
6930
|
fontVariantNumeric: "tabular-nums"
|
|
6409
6931
|
});
|
|
@@ -6449,7 +6971,7 @@ var accountDropdownLabelStyle2 = (color) => ({
|
|
|
6449
6971
|
color,
|
|
6450
6972
|
marginBottom: 8
|
|
6451
6973
|
});
|
|
6452
|
-
var
|
|
6974
|
+
var tokenDropdownInnerStyle2 = (tokens) => ({
|
|
6453
6975
|
background: tokens.bgInput,
|
|
6454
6976
|
border: `1px solid ${tokens.border}`,
|
|
6455
6977
|
borderRadius: tokens.radiusLg,
|
|
@@ -6561,7 +7083,7 @@ function GuestPreauthSetupCompleteScreen({
|
|
|
6561
7083
|
] }),
|
|
6562
7084
|
children: [
|
|
6563
7085
|
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onLogout }),
|
|
6564
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style:
|
|
7086
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle9, children: [
|
|
6565
7087
|
/* @__PURE__ */ jsxRuntime.jsx(IconCircle, { variant: "success", size: 64, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6566
7088
|
"path",
|
|
6567
7089
|
{
|
|
@@ -6570,13 +7092,13 @@ function GuestPreauthSetupCompleteScreen({
|
|
|
6570
7092
|
}
|
|
6571
7093
|
) }) }),
|
|
6572
7094
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle12(tokens.text), children: "Setup complete" }),
|
|
6573
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle12(tokens.textSecondary), children: "Your account is linked and ready. You can close this window
|
|
7095
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle12(tokens.textSecondary), children: "Your account is linked and ready. You can close this window." })
|
|
6574
7096
|
] })
|
|
6575
7097
|
]
|
|
6576
7098
|
}
|
|
6577
7099
|
);
|
|
6578
7100
|
}
|
|
6579
|
-
var
|
|
7101
|
+
var contentStyle9 = {
|
|
6580
7102
|
display: "flex",
|
|
6581
7103
|
flexDirection: "column",
|
|
6582
7104
|
alignItems: "center",
|
|
@@ -6605,14 +7127,14 @@ function GuestPreauthLinkingScreen({ onLogout }) {
|
|
|
6605
7127
|
const { tokens } = useBlinkConfig();
|
|
6606
7128
|
return /* @__PURE__ */ jsxRuntime.jsxs(ScreenLayout, { children: [
|
|
6607
7129
|
/* @__PURE__ */ jsxRuntime.jsx(ScreenHeader, { onLogout }),
|
|
6608
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style:
|
|
7130
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: contentStyle10, children: [
|
|
6609
7131
|
/* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 48 }),
|
|
6610
7132
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: headingStyle13(tokens.text), children: "Setting up your account..." }),
|
|
6611
7133
|
/* @__PURE__ */ jsxRuntime.jsx("p", { style: subtitleStyle13(tokens.textSecondary), children: "Linking your wallet to your Blink account. This usually takes a few seconds." })
|
|
6612
7134
|
] })
|
|
6613
7135
|
] });
|
|
6614
7136
|
}
|
|
6615
|
-
var
|
|
7137
|
+
var contentStyle10 = {
|
|
6616
7138
|
flex: 1,
|
|
6617
7139
|
display: "flex",
|
|
6618
7140
|
flexDirection: "column",
|
|
@@ -6669,6 +7191,10 @@ function resolveHeaderFlowPhase(screen, phase, authenticated) {
|
|
|
6669
7191
|
return raw;
|
|
6670
7192
|
}
|
|
6671
7193
|
var DEFAULT_MIN_DEPOSIT_USD = 0.25;
|
|
7194
|
+
var GUEST_PREAUTH_LOGIN_HERO_TITLE = "Create an account to complete one tap setup";
|
|
7195
|
+
function isGuestPreauthLogin(state) {
|
|
7196
|
+
return state.isGuestFlow && (state.guestPreauthSessionId != null || state.guestPreauthAccountId != null);
|
|
7197
|
+
}
|
|
6672
7198
|
function StepRenderer(props) {
|
|
6673
7199
|
const screen = screenForPhase(props.flow.state.phase);
|
|
6674
7200
|
const flowPhase = resolveHeaderFlowPhase(
|
|
@@ -6748,7 +7274,8 @@ function StepRendererContent({
|
|
|
6748
7274
|
sending: activeOtpStatus === "sending-code",
|
|
6749
7275
|
error: state.error,
|
|
6750
7276
|
onBack,
|
|
6751
|
-
merchantInitials: merchantName ? merchantName.slice(0, 2).toUpperCase() : void 0
|
|
7277
|
+
merchantInitials: merchantName ? merchantName.slice(0, 2).toUpperCase() : void 0,
|
|
7278
|
+
heroTitle: isGuestPreauthLogin(state) ? GUEST_PREAUTH_LOGIN_HERO_TITLE : void 0
|
|
6752
7279
|
}
|
|
6753
7280
|
);
|
|
6754
7281
|
case "otp-verify":
|
|
@@ -6847,15 +7374,11 @@ function StepRendererContent({
|
|
|
6847
7374
|
0
|
|
6848
7375
|
);
|
|
6849
7376
|
const effectiveTokenCount = tokenCount > 0 ? tokenCount : selectSourceTokenCount;
|
|
6850
|
-
const
|
|
6851
|
-
const
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
balance: s.balance.available.amount,
|
|
6856
|
-
walletId: w.id
|
|
6857
|
-
}))
|
|
6858
|
-
) : selectSourceChoices.flatMap(
|
|
7377
|
+
const setupFromPendingSelectSource = pendingSelectSource != null;
|
|
7378
|
+
const setupSelectedTokenSymbol = setupFromPendingSelectSource ? selectSourceTokenSymbol || selectSourceRecommended?.tokenSymbol || "" : selectedSource?.token.symbol ?? selectSourceTokenSymbol;
|
|
7379
|
+
const setupSelectedChainName = setupFromPendingSelectSource ? selectSourceChainName || selectSourceRecommended?.chainName || "" : selectedWallet?.chain.name ?? selectSourceChainName;
|
|
7380
|
+
const effectiveSourceLabel = setupFromPendingSelectSource ? setupSelectedTokenSymbol && setupSelectedChainName ? `${setupSelectedTokenSymbol} on ${setupSelectedChainName}` : void 0 : selectedSourceLabel ?? (selectSourceChainName && selectSourceTokenSymbol ? `${selectSourceTokenSymbol} on ${selectSourceChainName}` : void 0);
|
|
7381
|
+
const setupTokenOptions = selectedAccount ? tokenOptionsForLinkedAccount(selectedAccount, state.chains) : selectSourceChoices.flatMap(
|
|
6859
7382
|
(chain) => chain.tokens.map((t) => ({
|
|
6860
7383
|
symbol: t.tokenSymbol,
|
|
6861
7384
|
chainName: chain.chainName,
|
|
@@ -6863,9 +7386,8 @@ function StepRendererContent({
|
|
|
6863
7386
|
}))
|
|
6864
7387
|
);
|
|
6865
7388
|
const handleSetupSelectToken = (symbol, chainName, walletId) => {
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
} else {
|
|
7389
|
+
handleInlineTokenSelection(handlers, state.chains, selectedAccount, symbol, chainName, walletId);
|
|
7390
|
+
if (pendingSelectSource) {
|
|
6869
7391
|
handlers.onSelectSourceChainChange(chainName);
|
|
6870
7392
|
handlers.onSetSelectSourceTokenSymbol(symbol);
|
|
6871
7393
|
}
|
|
@@ -6873,17 +7395,18 @@ function StepRendererContent({
|
|
|
6873
7395
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6874
7396
|
SetupScreen,
|
|
6875
7397
|
{
|
|
6876
|
-
availableBalance: selectedSource ? selectedSource.balance.available.amount : selectSourceAvailableBalance > 0 ? selectSourceAvailableBalance : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
|
|
7398
|
+
availableBalance: selectedSource ? selectedSource.balance.available.amount : setupFromPendingSelectSource ? selectSourceAvailableBalance : selectSourceAvailableBalance > 0 ? selectSourceAvailableBalance : selectedAccount ? selectedAccount.wallets.reduce((sum, w) => sum + w.balance.available.amount, 0) : maxSourceBalance,
|
|
6877
7399
|
tokenCount: effectiveTokenCount,
|
|
6878
7400
|
sourceName,
|
|
6879
7401
|
onSetupOneTap: handlers.onSetupOneTap,
|
|
6880
|
-
onBack:
|
|
7402
|
+
onBack: handlers.onBackFromSubflow,
|
|
6881
7403
|
onLogout: handlers.onLogout,
|
|
6882
7404
|
onAdvanced: handlers.onSelectToken,
|
|
6883
7405
|
selectedSourceLabel: effectiveSourceLabel,
|
|
6884
7406
|
loading: savingOneTapLimit,
|
|
6885
7407
|
error: state.error,
|
|
6886
|
-
selectedTokenSymbol:
|
|
7408
|
+
selectedTokenSymbol: setupSelectedTokenSymbol,
|
|
7409
|
+
selectedChainName: setupSelectedChainName,
|
|
6887
7410
|
tokenOptions: setupTokenOptions,
|
|
6888
7411
|
onSelectToken: handleSetupSelectToken
|
|
6889
7412
|
}
|
|
@@ -6905,6 +7428,7 @@ function StepRendererContent({
|
|
|
6905
7428
|
case "deposit": {
|
|
6906
7429
|
const parsedAmt = depositAmount != null ? depositAmount : 5;
|
|
6907
7430
|
const minDepositFloor = depositAmount != null ? depositAmount : DEFAULT_MIN_DEPOSIT_USD;
|
|
7431
|
+
const depositTokenOptions = tokenOptionsForLinkedAccount(selectedAccount, state.chains);
|
|
6908
7432
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6909
7433
|
DepositScreen,
|
|
6910
7434
|
{
|
|
@@ -6913,6 +7437,8 @@ function StepRendererContent({
|
|
|
6913
7437
|
remainingLimit: selectedSource != null ? selectedSource.remainingAllowance ?? null : selectedAccount?.remainingAllowance ?? null,
|
|
6914
7438
|
tokenCount,
|
|
6915
7439
|
initialAmount: parsedAmt,
|
|
7440
|
+
quoteFee: forms.depositQuoteFee,
|
|
7441
|
+
quoteLoading: forms.depositQuoteLoading,
|
|
6916
7442
|
processing: state.creatingTransfer,
|
|
6917
7443
|
error: state.error,
|
|
6918
7444
|
onDeposit: handlers.onPay,
|
|
@@ -6927,8 +7453,13 @@ function StepRendererContent({
|
|
|
6927
7453
|
onAuthorizeAccount: handlers.onContinueConnection,
|
|
6928
7454
|
onAddProvider: () => handlers.onSetPhase({ step: "wallet-picker", reason: "switch" }),
|
|
6929
7455
|
onSelectToken: handlers.onSelectToken,
|
|
7456
|
+
tokenOptions: depositTokenOptions,
|
|
7457
|
+
onPickToken: (symbol, chainName, walletId) => {
|
|
7458
|
+
handleInlineTokenSelection(handlers, state.chains, selectedAccount, symbol, chainName, walletId);
|
|
7459
|
+
},
|
|
6930
7460
|
selectedSourceLabel,
|
|
6931
7461
|
selectedTokenSymbol: selectedSource?.token.symbol,
|
|
7462
|
+
selectedChainName: selectedWallet?.chain.name,
|
|
6932
7463
|
minDepositFloor
|
|
6933
7464
|
}
|
|
6934
7465
|
);
|
|
@@ -6969,7 +7500,7 @@ function StepRendererContent({
|
|
|
6969
7500
|
chains: state.chains,
|
|
6970
7501
|
onSelectAuthorized: handlers.onSelectAuthorizedToken,
|
|
6971
7502
|
onAuthorizeToken: handlers.onAuthorizeToken,
|
|
6972
|
-
onBack:
|
|
7503
|
+
onBack: handlers.onBackFromSubflow,
|
|
6973
7504
|
onLogout: handlers.onLogout,
|
|
6974
7505
|
depositAmount: depositAmount ?? void 0,
|
|
6975
7506
|
selectedTokenSymbol: selectedSource?.token.symbol,
|
|
@@ -7048,7 +7579,7 @@ function StepRendererContent({
|
|
|
7048
7579
|
})() : void 0,
|
|
7049
7580
|
onDone: onDismiss ?? handlers.onNewPayment,
|
|
7050
7581
|
onLogout: authenticated ? handlers.onLogout : void 0,
|
|
7051
|
-
onPreauthorize: state.isGuestFlow ? handlers.onPreauthorize : void 0
|
|
7582
|
+
onPreauthorize: state.isGuestFlow && isDesktop ? handlers.onPreauthorize : void 0
|
|
7052
7583
|
}
|
|
7053
7584
|
);
|
|
7054
7585
|
}
|
|
@@ -7447,6 +7978,9 @@ function useTransferHandlers(deps) {
|
|
|
7447
7978
|
sourceTokenAddress,
|
|
7448
7979
|
activeCredentialId,
|
|
7449
7980
|
selectedAccountId,
|
|
7981
|
+
selectedWalletId,
|
|
7982
|
+
selectedTokenSymbol,
|
|
7983
|
+
quoteId,
|
|
7450
7984
|
transfer,
|
|
7451
7985
|
accounts
|
|
7452
7986
|
} = deps;
|
|
@@ -7460,9 +7994,32 @@ function useTransferHandlers(deps) {
|
|
|
7460
7994
|
fetchProviders(apiBaseUrl, token)
|
|
7461
7995
|
]);
|
|
7462
7996
|
const parsedAmt = depositAmount != null ? depositAmount : 0;
|
|
7463
|
-
const defaults =
|
|
7464
|
-
|
|
7465
|
-
|
|
7997
|
+
const { defaults, resetSelectedTokenSymbol } = resolveDepositSelectionAfterRefresh(
|
|
7998
|
+
accts,
|
|
7999
|
+
parsedAmt,
|
|
8000
|
+
{
|
|
8001
|
+
selectedAccountId,
|
|
8002
|
+
selectedWalletId,
|
|
8003
|
+
selectedTokenSymbol
|
|
8004
|
+
}
|
|
8005
|
+
);
|
|
8006
|
+
dispatch({
|
|
8007
|
+
type: "ACCOUNTS_RELOADED",
|
|
8008
|
+
accounts: accts,
|
|
8009
|
+
providers: prov,
|
|
8010
|
+
defaults,
|
|
8011
|
+
resetSelectedTokenSymbol
|
|
8012
|
+
});
|
|
8013
|
+
}, [
|
|
8014
|
+
getAccessToken,
|
|
8015
|
+
activeCredentialId,
|
|
8016
|
+
selectedAccountId,
|
|
8017
|
+
selectedWalletId,
|
|
8018
|
+
selectedTokenSymbol,
|
|
8019
|
+
apiBaseUrl,
|
|
8020
|
+
depositAmount,
|
|
8021
|
+
dispatch
|
|
8022
|
+
]);
|
|
7466
8023
|
const handlePay = react.useCallback(async (payAmount, sourceOverrides) => {
|
|
7467
8024
|
const minUsd = effectiveMinTransferAmountUsd(depositAmount);
|
|
7468
8025
|
if (isNaN(payAmount) || payAmount < minUsd) {
|
|
@@ -7506,7 +8063,8 @@ function useTransferHandlers(deps) {
|
|
|
7506
8063
|
sourceId: effectiveSourceId,
|
|
7507
8064
|
sourceTokenAddress,
|
|
7508
8065
|
destination,
|
|
7509
|
-
amount: payAmount
|
|
8066
|
+
amount: payAmount,
|
|
8067
|
+
...quoteId ? { quoteId } : {}
|
|
7510
8068
|
});
|
|
7511
8069
|
dispatch({ type: "TRANSFER_CREATED", transfer: t });
|
|
7512
8070
|
if (t.status === "COMPLETED") {
|
|
@@ -7538,6 +8096,7 @@ function useTransferHandlers(deps) {
|
|
|
7538
8096
|
accounts,
|
|
7539
8097
|
destination,
|
|
7540
8098
|
apiBaseUrl,
|
|
8099
|
+
quoteId,
|
|
7541
8100
|
getAccessToken,
|
|
7542
8101
|
transferSigning,
|
|
7543
8102
|
polling,
|
|
@@ -7588,20 +8147,20 @@ function useSourceSelectionHandlers(dispatch, authExecutor, options) {
|
|
|
7588
8147
|
const selectSourceAvailableBalance = react.useMemo(() => {
|
|
7589
8148
|
if (!pendingSelectSourceAction) return 0;
|
|
7590
8149
|
const options2 = pendingSelectSourceAction.metadata?.options ?? [];
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
8150
|
+
return resolveSelectSourceAvailableBalance(
|
|
8151
|
+
selectSourceChoices,
|
|
8152
|
+
options2,
|
|
8153
|
+
selectSourceChainName,
|
|
8154
|
+
selectSourceTokenSymbol,
|
|
8155
|
+
selectSourceRecommended
|
|
8156
|
+
);
|
|
8157
|
+
}, [
|
|
8158
|
+
pendingSelectSourceAction,
|
|
8159
|
+
selectSourceChoices,
|
|
8160
|
+
selectSourceChainName,
|
|
8161
|
+
selectSourceTokenSymbol,
|
|
8162
|
+
selectSourceRecommended
|
|
8163
|
+
]);
|
|
7605
8164
|
const handleSelectSourceChainChange = react.useCallback(
|
|
7606
8165
|
(chainName) => {
|
|
7607
8166
|
setSelectSourceChainName(chainName);
|
|
@@ -7652,7 +8211,7 @@ function useSourceSelectionHandlers(dispatch, authExecutor, options) {
|
|
|
7652
8211
|
initializedSelectSourceActionRef
|
|
7653
8212
|
};
|
|
7654
8213
|
}
|
|
7655
|
-
function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, guestCheckout, onComplete) {
|
|
8214
|
+
function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransferIdRef, stateTransfer, refs, guestCheckout, onComplete, lastResumedAt) {
|
|
7656
8215
|
const {
|
|
7657
8216
|
mobileSetupFlowRef,
|
|
7658
8217
|
handlingMobileReturnRef,
|
|
@@ -7663,6 +8222,8 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
|
|
|
7663
8222
|
onCompleteRef.current = onComplete;
|
|
7664
8223
|
const guestPollingActiveRef = react.useRef(false);
|
|
7665
8224
|
const guestPollingCleanupRef = react.useRef(null);
|
|
8225
|
+
const mobileFlowRef = react.useRef(guestCheckout.mobileFlow);
|
|
8226
|
+
mobileFlowRef.current = guestCheckout.mobileFlow;
|
|
7666
8227
|
const guestTransferIdRef = react.useRef(guestCheckout.guestTransferId);
|
|
7667
8228
|
guestTransferIdRef.current = guestCheckout.guestTransferId;
|
|
7668
8229
|
const guestSessionTokenRef = react.useRef(guestCheckout.guestSessionToken);
|
|
@@ -7718,27 +8279,15 @@ function useMobileFlowHandlers(dispatch, polling, reloadAccounts, pollingTransfe
|
|
|
7718
8279
|
startGuestPolling
|
|
7719
8280
|
]);
|
|
7720
8281
|
react.useEffect(() => {
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
}
|
|
7729
|
-
|
|
7730
|
-
if (document.visibilityState === "visible") tryStartPolling();
|
|
7731
|
-
};
|
|
7732
|
-
const handlePageShow = (e) => {
|
|
7733
|
-
if (e.persisted) tryStartPolling();
|
|
7734
|
-
};
|
|
7735
|
-
document.addEventListener("visibilitychange", handleVisibility);
|
|
7736
|
-
window.addEventListener("pageshow", handlePageShow);
|
|
7737
|
-
return () => {
|
|
7738
|
-
document.removeEventListener("visibilitychange", handleVisibility);
|
|
7739
|
-
window.removeEventListener("pageshow", handlePageShow);
|
|
7740
|
-
};
|
|
7741
|
-
}, [startGuestPolling]);
|
|
8282
|
+
if (!lastResumedAt) return;
|
|
8283
|
+
if (guestPollingActiveRef.current) return;
|
|
8284
|
+
if (!mobileFlowRef.current) return;
|
|
8285
|
+
const transferId = guestTransferIdRef.current;
|
|
8286
|
+
const token = guestSessionTokenRef.current;
|
|
8287
|
+
if (transferId && token) {
|
|
8288
|
+
startGuestPolling(transferId, token);
|
|
8289
|
+
}
|
|
8290
|
+
}, [lastResumedAt, startGuestPolling]);
|
|
7742
8291
|
const handleAuthorizedMobileReturn = react.useCallback(async (authorizedTransfer, isSetup) => {
|
|
7743
8292
|
if (handlingMobileReturnRef.current) return;
|
|
7744
8293
|
handlingMobileReturnRef.current = true;
|
|
@@ -7925,9 +8474,6 @@ function useProviderHandlers(deps) {
|
|
|
7925
8474
|
useWalletConnector: useWalletConnectorProp,
|
|
7926
8475
|
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
7927
8476
|
});
|
|
7928
|
-
if (!isMobile) {
|
|
7929
|
-
dispatch({ type: "PAY_STARTED" });
|
|
7930
|
-
}
|
|
7931
8477
|
try {
|
|
7932
8478
|
let accountId;
|
|
7933
8479
|
let sessionId;
|
|
@@ -7966,18 +8512,22 @@ function useProviderHandlers(deps) {
|
|
|
7966
8512
|
triggerDeeplink(sessionUri);
|
|
7967
8513
|
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: sessionUri });
|
|
7968
8514
|
} else {
|
|
8515
|
+
dispatch({
|
|
8516
|
+
type: "SELECT_ACCOUNT",
|
|
8517
|
+
accountId,
|
|
8518
|
+
walletId: null
|
|
8519
|
+
});
|
|
7969
8520
|
await authExecutor.executeSessionById(sessionId);
|
|
7970
8521
|
await reloadAccounts();
|
|
7971
8522
|
}
|
|
7972
8523
|
} catch (err) {
|
|
8524
|
+
if (isAuthorizationSessionCancelled(err) || isUserDismissedAuthorizationError(err)) {
|
|
8525
|
+
return;
|
|
8526
|
+
}
|
|
7973
8527
|
captureException(err);
|
|
7974
8528
|
const msg = err instanceof Error ? err.message : "Failed to set up wallet";
|
|
7975
8529
|
dispatch({ type: "PAY_ERROR", error: msg });
|
|
7976
8530
|
onError?.(msg);
|
|
7977
|
-
} finally {
|
|
7978
|
-
if (!isMobile) {
|
|
7979
|
-
dispatch({ type: "PAY_ENDED" });
|
|
7980
|
-
}
|
|
7981
8531
|
}
|
|
7982
8532
|
}, [
|
|
7983
8533
|
authenticated,
|
|
@@ -8040,7 +8590,12 @@ function useProviderHandlers(deps) {
|
|
|
8040
8590
|
}
|
|
8041
8591
|
const acct = accounts.find((a) => a.id === selectedAccountId);
|
|
8042
8592
|
const matchedProvider = acct ? providers.find((p) => p.name === acct.name) : void 0;
|
|
8043
|
-
|
|
8593
|
+
const isMobile = !shouldUseWalletConnector({
|
|
8594
|
+
useWalletConnector: useWalletConnectorProp,
|
|
8595
|
+
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
8596
|
+
});
|
|
8597
|
+
if (matchedProvider && isMobile) {
|
|
8598
|
+
dispatch({ type: "SAVE_SELECTION" });
|
|
8044
8599
|
dispatch({ type: "SELECT_PROVIDER", providerId: matchedProvider.id });
|
|
8045
8600
|
}
|
|
8046
8601
|
dispatch({ type: "SET_ERROR", error: null });
|
|
@@ -8060,10 +8615,6 @@ function useProviderHandlers(deps) {
|
|
|
8060
8615
|
activeCredentialId,
|
|
8061
8616
|
{ tokenAddress: source?.address, chainId: evmChainId }
|
|
8062
8617
|
);
|
|
8063
|
-
const isMobile = !shouldUseWalletConnector({
|
|
8064
|
-
useWalletConnector: useWalletConnectorProp,
|
|
8065
|
-
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
8066
|
-
});
|
|
8067
8618
|
if (isMobile) {
|
|
8068
8619
|
handlingMobileReturnRef.current = false;
|
|
8069
8620
|
mobileSetupFlowRef.current = true;
|
|
@@ -8080,12 +8631,20 @@ function useProviderHandlers(deps) {
|
|
|
8080
8631
|
});
|
|
8081
8632
|
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
|
|
8082
8633
|
triggerDeeplink(session.uri);
|
|
8634
|
+
dispatch({ type: "DISCARD_SAVED_SELECTION" });
|
|
8083
8635
|
} else {
|
|
8084
8636
|
await authExecutor.executeSessionById(session.id);
|
|
8085
8637
|
await reloadAccounts();
|
|
8638
|
+
dispatch({ type: "DISCARD_SAVED_SELECTION" });
|
|
8086
8639
|
}
|
|
8087
8640
|
} catch (err) {
|
|
8641
|
+
if (isAuthorizationSessionCancelled(err) || isUserDismissedAuthorizationError(err)) {
|
|
8642
|
+
return;
|
|
8643
|
+
}
|
|
8088
8644
|
captureException(err);
|
|
8645
|
+
if (isMobile) {
|
|
8646
|
+
dispatch({ type: "RESTORE_SELECTION" });
|
|
8647
|
+
}
|
|
8089
8648
|
const msg = err instanceof Error ? err.message : "Failed to increase limit";
|
|
8090
8649
|
dispatch({ type: "SET_ERROR", error: msg });
|
|
8091
8650
|
onError?.(msg);
|
|
@@ -8130,7 +8689,12 @@ function useProviderHandlers(deps) {
|
|
|
8130
8689
|
}
|
|
8131
8690
|
const acct = accounts.find((a) => a.id === selectedAccountId);
|
|
8132
8691
|
const matchedProvider = acct ? providers.find((p) => p.name === acct.name) : void 0;
|
|
8133
|
-
|
|
8692
|
+
const isMobile = !shouldUseWalletConnector({
|
|
8693
|
+
useWalletConnector: useWalletConnectorProp,
|
|
8694
|
+
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
8695
|
+
});
|
|
8696
|
+
if (matchedProvider && isMobile) {
|
|
8697
|
+
dispatch({ type: "SAVE_SELECTION" });
|
|
8134
8698
|
dispatch({ type: "SELECT_PROVIDER", providerId: matchedProvider.id });
|
|
8135
8699
|
}
|
|
8136
8700
|
dispatch({ type: "SET_ERROR", error: null });
|
|
@@ -8145,10 +8709,6 @@ function useProviderHandlers(deps) {
|
|
|
8145
8709
|
activeCredentialId,
|
|
8146
8710
|
{ tokenAddress, chainId }
|
|
8147
8711
|
);
|
|
8148
|
-
const isMobile = !shouldUseWalletConnector({
|
|
8149
|
-
useWalletConnector: useWalletConnectorProp,
|
|
8150
|
-
userAgent: typeof navigator === "undefined" ? void 0 : navigator.userAgent
|
|
8151
|
-
});
|
|
8152
8712
|
if (isMobile) {
|
|
8153
8713
|
handlingMobileReturnRef.current = false;
|
|
8154
8714
|
mobileSetupFlowRef.current = true;
|
|
@@ -8166,13 +8726,21 @@ function useProviderHandlers(deps) {
|
|
|
8166
8726
|
});
|
|
8167
8727
|
dispatch({ type: "MOBILE_DEEPLINK_READY", deeplinkUri: session.uri });
|
|
8168
8728
|
triggerDeeplink(session.uri);
|
|
8729
|
+
dispatch({ type: "DISCARD_SAVED_SELECTION" });
|
|
8169
8730
|
} else {
|
|
8170
8731
|
await authExecutor.executeSessionById(session.id);
|
|
8171
8732
|
await reloadAccounts();
|
|
8172
8733
|
dispatch({ type: "SELECT_TOKEN", walletId: _walletId, tokenSymbol });
|
|
8734
|
+
dispatch({ type: "DISCARD_SAVED_SELECTION" });
|
|
8173
8735
|
}
|
|
8174
8736
|
} catch (err) {
|
|
8737
|
+
if (isAuthorizationSessionCancelled(err) || isUserDismissedAuthorizationError(err)) {
|
|
8738
|
+
return;
|
|
8739
|
+
}
|
|
8175
8740
|
captureException(err);
|
|
8741
|
+
if (isMobile) {
|
|
8742
|
+
dispatch({ type: "RESTORE_SELECTION" });
|
|
8743
|
+
}
|
|
8176
8744
|
const msg = err instanceof Error ? err.message : "Failed to authorize token";
|
|
8177
8745
|
dispatch({ type: "SET_ERROR", error: msg });
|
|
8178
8746
|
onError?.(msg);
|
|
@@ -9109,7 +9677,15 @@ function useDataLoadEffect(deps) {
|
|
|
9109
9677
|
]);
|
|
9110
9678
|
if (cancelled) return;
|
|
9111
9679
|
const parsedAmt = depositAmount != null ? depositAmount : 0;
|
|
9112
|
-
const defaults =
|
|
9680
|
+
const { defaults, resetSelectedTokenSymbol } = resolveDepositSelectionAfterRefresh(
|
|
9681
|
+
accts,
|
|
9682
|
+
parsedAmt,
|
|
9683
|
+
{
|
|
9684
|
+
selectedAccountId: state.selectedAccountId,
|
|
9685
|
+
selectedWalletId: state.selectedWalletId,
|
|
9686
|
+
selectedTokenSymbol: state.selectedTokenSymbol
|
|
9687
|
+
}
|
|
9688
|
+
);
|
|
9113
9689
|
const persisted = loadMobileFlowState();
|
|
9114
9690
|
const clearMobile = persisted?.isSetup && accts.some((a) => a.wallets.some((w) => w.status === "ACTIVE"));
|
|
9115
9691
|
dispatch({
|
|
@@ -9118,7 +9694,8 @@ function useDataLoadEffect(deps) {
|
|
|
9118
9694
|
accounts: accts,
|
|
9119
9695
|
chains: chn,
|
|
9120
9696
|
defaults,
|
|
9121
|
-
clearMobileState: clearMobile
|
|
9697
|
+
clearMobileState: clearMobile,
|
|
9698
|
+
resetSelectedTokenSymbol
|
|
9122
9699
|
});
|
|
9123
9700
|
if (clearMobile) clearMobileFlowState();
|
|
9124
9701
|
} catch (err) {
|
|
@@ -9147,6 +9724,8 @@ function useDataLoadEffect(deps) {
|
|
|
9147
9724
|
apiBaseUrl,
|
|
9148
9725
|
state.activeCredentialId,
|
|
9149
9726
|
state.selectedAccountId,
|
|
9727
|
+
state.selectedWalletId,
|
|
9728
|
+
state.selectedTokenSymbol,
|
|
9150
9729
|
depositAmount
|
|
9151
9730
|
]);
|
|
9152
9731
|
react.useEffect(() => {
|
|
@@ -9375,25 +9954,16 @@ function useMobilePollingEffect(deps) {
|
|
|
9375
9954
|
const poll = isReauth ? pollReauthorization : pollWalletActive;
|
|
9376
9955
|
poll();
|
|
9377
9956
|
const intervalId = window.setInterval(poll, POLL_INTERVAL_MS);
|
|
9378
|
-
const handleVisibility = () => {
|
|
9379
|
-
if (document.visibilityState === "visible" && !cancelled) poll();
|
|
9380
|
-
};
|
|
9381
|
-
const handlePageShow = (e) => {
|
|
9382
|
-
if (e.persisted && !cancelled) poll();
|
|
9383
|
-
};
|
|
9384
|
-
document.addEventListener("visibilitychange", handleVisibility);
|
|
9385
|
-
window.addEventListener("pageshow", handlePageShow);
|
|
9386
9957
|
return () => {
|
|
9387
9958
|
cancelled = true;
|
|
9388
9959
|
window.clearInterval(intervalId);
|
|
9389
|
-
document.removeEventListener("visibilitychange", handleVisibility);
|
|
9390
|
-
window.removeEventListener("pageshow", handlePageShow);
|
|
9391
9960
|
};
|
|
9392
9961
|
}, [
|
|
9393
9962
|
state.mobileFlow,
|
|
9394
9963
|
state.isGuestFlow,
|
|
9395
9964
|
state.guestPreauthSessionId,
|
|
9396
9965
|
state.activeCredentialId,
|
|
9966
|
+
state.lastResumedAt,
|
|
9397
9967
|
apiBaseUrl,
|
|
9398
9968
|
reloadAccounts,
|
|
9399
9969
|
dispatch,
|
|
@@ -9410,28 +9980,13 @@ function useMobilePollingEffect(deps) {
|
|
|
9410
9980
|
const transferIdToResume = pollingTransferIdRef.current ?? state.transfer?.id;
|
|
9411
9981
|
if (!transferIdToResume) return;
|
|
9412
9982
|
if (!polling.isPolling) polling.startPolling(transferIdToResume);
|
|
9413
|
-
const handleVisibility = () => {
|
|
9414
|
-
if (document.visibilityState === "visible" && !handlingMobileReturnRef.current) {
|
|
9415
|
-
polling.startPolling(transferIdToResume);
|
|
9416
|
-
}
|
|
9417
|
-
};
|
|
9418
|
-
const handlePageShow = (e) => {
|
|
9419
|
-
if (e.persisted && !handlingMobileReturnRef.current) {
|
|
9420
|
-
polling.startPolling(transferIdToResume);
|
|
9421
|
-
}
|
|
9422
|
-
};
|
|
9423
|
-
document.addEventListener("visibilitychange", handleVisibility);
|
|
9424
|
-
window.addEventListener("pageshow", handlePageShow);
|
|
9425
|
-
return () => {
|
|
9426
|
-
document.removeEventListener("visibilitychange", handleVisibility);
|
|
9427
|
-
window.removeEventListener("pageshow", handlePageShow);
|
|
9428
|
-
};
|
|
9429
9983
|
}, [
|
|
9430
9984
|
state.mobileFlow,
|
|
9431
9985
|
state.transfer?.id,
|
|
9432
9986
|
state.isGuestFlow,
|
|
9433
9987
|
state.guestPreauthSessionId,
|
|
9434
9988
|
state.guestPreauthAccountId,
|
|
9989
|
+
state.lastResumedAt,
|
|
9435
9990
|
polling.isPolling,
|
|
9436
9991
|
polling.startPolling,
|
|
9437
9992
|
handlingMobileReturnRef,
|
|
@@ -9442,6 +9997,7 @@ function useGuestPreauthMobileRestoreEffect(deps) {
|
|
|
9442
9997
|
const {
|
|
9443
9998
|
dispatch,
|
|
9444
9999
|
privyReady,
|
|
10000
|
+
lastResumedAt,
|
|
9445
10001
|
mobileSetupFlowRef,
|
|
9446
10002
|
setupAccountIdRef,
|
|
9447
10003
|
startGuestAccountPolling
|
|
@@ -9452,68 +10008,43 @@ function useGuestPreauthMobileRestoreEffect(deps) {
|
|
|
9452
10008
|
console.info("[blink-sdk] guestPreauthMobileRestore: skipping, privyReady=false");
|
|
9453
10009
|
return;
|
|
9454
10010
|
}
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
|
|
9473
|
-
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
if (persisted.accountId) {
|
|
9478
|
-
dispatch({
|
|
9479
|
-
type: "GUEST_PREAUTH_DETECTED",
|
|
9480
|
-
accountId: persisted.accountId,
|
|
9481
|
-
sessionId: persisted.sessionId
|
|
9482
|
-
});
|
|
9483
|
-
}
|
|
10011
|
+
if (startedRef.current) {
|
|
10012
|
+
console.info("[blink-sdk] guestPreauthMobileRestore: already started");
|
|
10013
|
+
return;
|
|
10014
|
+
}
|
|
10015
|
+
const persisted = loadMobileFlowState();
|
|
10016
|
+
console.info("[blink-sdk] guestPreauthMobileRestore.tryStart", {
|
|
10017
|
+
trigger: lastResumedAt ? "page-resume" : "initial",
|
|
10018
|
+
hasPersistedState: !!persisted,
|
|
10019
|
+
isGuestPreauth: persisted?.isGuestPreauth ?? false,
|
|
10020
|
+
hasGuestSessionToken: !!persisted?.guestSessionToken,
|
|
10021
|
+
hasSessionId: !!persisted?.sessionId,
|
|
10022
|
+
accountId: persisted?.accountId ?? null
|
|
10023
|
+
});
|
|
10024
|
+
if (!persisted?.isGuestPreauth || !persisted.guestSessionToken || !persisted.sessionId) {
|
|
10025
|
+
return;
|
|
10026
|
+
}
|
|
10027
|
+
startedRef.current = true;
|
|
10028
|
+
mobileSetupFlowRef.current = true;
|
|
10029
|
+
if (persisted.accountId) {
|
|
10030
|
+
setupAccountIdRef.current = persisted.accountId;
|
|
10031
|
+
}
|
|
10032
|
+
if (persisted.accountId) {
|
|
9484
10033
|
dispatch({
|
|
9485
|
-
type: "
|
|
9486
|
-
|
|
9487
|
-
});
|
|
9488
|
-
console.info("[blink-sdk] guestPreauthMobileRestore: starting guest account polling", {
|
|
9489
|
-
trigger,
|
|
10034
|
+
type: "GUEST_PREAUTH_DETECTED",
|
|
10035
|
+
accountId: persisted.accountId,
|
|
9490
10036
|
sessionId: persisted.sessionId
|
|
9491
10037
|
});
|
|
9492
|
-
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
console.info("[blink-sdk] guestPreauthMobileRestore: pageshow fired", {
|
|
9503
|
-
persisted: e.persisted,
|
|
9504
|
-
visibilityState: document.visibilityState,
|
|
9505
|
-
startedRef: startedRef.current
|
|
9506
|
-
});
|
|
9507
|
-
if (document.visibilityState === "visible") tryStart("pageshow");
|
|
9508
|
-
};
|
|
9509
|
-
tryStart("initial");
|
|
9510
|
-
document.addEventListener("visibilitychange", onVisibility);
|
|
9511
|
-
window.addEventListener("pageshow", onPageShow);
|
|
9512
|
-
return () => {
|
|
9513
|
-
document.removeEventListener("visibilitychange", onVisibility);
|
|
9514
|
-
window.removeEventListener("pageshow", onPageShow);
|
|
9515
|
-
};
|
|
9516
|
-
}, [privyReady, dispatch, mobileSetupFlowRef, setupAccountIdRef, startGuestAccountPolling]);
|
|
10038
|
+
}
|
|
10039
|
+
dispatch({
|
|
10040
|
+
type: "MOBILE_DEEPLINK_READY",
|
|
10041
|
+
deeplinkUri: persisted.deeplinkUri
|
|
10042
|
+
});
|
|
10043
|
+
console.info("[blink-sdk] guestPreauthMobileRestore: starting guest account polling", {
|
|
10044
|
+
sessionId: persisted.sessionId
|
|
10045
|
+
});
|
|
10046
|
+
startGuestAccountPolling(persisted.guestSessionToken, persisted.sessionId);
|
|
10047
|
+
}, [privyReady, lastResumedAt, dispatch, mobileSetupFlowRef, setupAccountIdRef, startGuestAccountPolling]);
|
|
9517
10048
|
}
|
|
9518
10049
|
function useSelectSourceEffect(deps) {
|
|
9519
10050
|
const {
|
|
@@ -9714,7 +10245,9 @@ function useGuestDesktopPreauthSessionEffect(deps) {
|
|
|
9714
10245
|
function useGuestPreauthPhaseSyncEffect(deps) {
|
|
9715
10246
|
const { state, dispatch, authExecutor, isDesktop, privyAuthenticated } = deps;
|
|
9716
10247
|
react.useEffect(() => {
|
|
9717
|
-
if (!
|
|
10248
|
+
if (!isDesktop) return;
|
|
10249
|
+
const standardDesktopAuth = privyAuthenticated && state.activeCredentialId != null && !state.guestPreauthorizing;
|
|
10250
|
+
if (!state.guestPreauthorizing && !standardDesktopAuth) return;
|
|
9718
10251
|
const pending = authExecutor.pendingSelectSource;
|
|
9719
10252
|
if (pending) {
|
|
9720
10253
|
if (state.phase.step === "token-picker") {
|
|
@@ -9738,7 +10271,7 @@ function useGuestPreauthPhaseSyncEffect(deps) {
|
|
|
9738
10271
|
dispatch({ type: "SET_USER_INTENT", intent: { step: "one-tap-setup", action: null } });
|
|
9739
10272
|
return;
|
|
9740
10273
|
}
|
|
9741
|
-
if (!privyAuthenticated && authExecutor.executing && state.guestPreauthAccountId) {
|
|
10274
|
+
if (state.guestPreauthorizing && !privyAuthenticated && authExecutor.executing && state.guestPreauthAccountId) {
|
|
9742
10275
|
const accountId = state.guestPreauthAccountId;
|
|
9743
10276
|
const p = state.phase;
|
|
9744
10277
|
if (p.step === "wallet-setup" && p.mobile == null && p.guestDesktopExtension && p.accountId === accountId) {
|
|
@@ -9766,6 +10299,7 @@ function useGuestPreauthPhaseSyncEffect(deps) {
|
|
|
9766
10299
|
state.guestPreauthorizing,
|
|
9767
10300
|
state.phase,
|
|
9768
10301
|
state.guestPreauthAccountId,
|
|
10302
|
+
state.activeCredentialId,
|
|
9769
10303
|
isDesktop,
|
|
9770
10304
|
privyAuthenticated,
|
|
9771
10305
|
authExecutor.pendingSelectSource,
|
|
@@ -9814,7 +10348,7 @@ function useStandardDesktopInlineOpenWalletEffect(deps) {
|
|
|
9814
10348
|
react.useEffect(() => {
|
|
9815
10349
|
if (!isDesktop || state.guestPreauthorizing) return;
|
|
9816
10350
|
if (!state.privyAuthenticated || !state.activeCredentialId || !state.selectedAccountId) return;
|
|
9817
|
-
const shouldPin = authExecutor.executing && !authExecutor.pendingSelectSource && !authExecutor.pendingOneTapSetup;
|
|
10351
|
+
const shouldPin = authExecutor.executing && !authExecutor.pendingSelectSource && (!authExecutor.pendingOneTapSetup || authExecutor.authorizationSessionStackDepth > 1);
|
|
9818
10352
|
if (shouldPin && !state.standardDesktopInlineOpenWallet) {
|
|
9819
10353
|
dispatch({ type: "SET_STANDARD_DESKTOP_INLINE_OPEN_WALLET", value: true });
|
|
9820
10354
|
return;
|
|
@@ -9832,6 +10366,7 @@ function useStandardDesktopInlineOpenWalletEffect(deps) {
|
|
|
9832
10366
|
authExecutor.executing,
|
|
9833
10367
|
authExecutor.pendingSelectSource,
|
|
9834
10368
|
authExecutor.pendingOneTapSetup,
|
|
10369
|
+
authExecutor.authorizationSessionStackDepth,
|
|
9835
10370
|
dispatch
|
|
9836
10371
|
]);
|
|
9837
10372
|
}
|
|
@@ -9850,7 +10385,84 @@ function useGuestAccountAutoPollingEffect(deps) {
|
|
|
9850
10385
|
startPolling(guestSessionToken);
|
|
9851
10386
|
}, [mobileFlow, isGuestFlow, guestSessionToken, isPolling, guestAccount, startPolling]);
|
|
9852
10387
|
}
|
|
9853
|
-
|
|
10388
|
+
var WATCHDOG_INTERVAL_MS = 1e3;
|
|
10389
|
+
var WATCHDOG_THRESHOLD_MS = 3e3;
|
|
10390
|
+
var DEDUP_COOLDOWN_MS = 500;
|
|
10391
|
+
function usePageResume(callback) {
|
|
10392
|
+
const callbackRef = react.useRef(callback);
|
|
10393
|
+
callbackRef.current = callback;
|
|
10394
|
+
react.useEffect(() => {
|
|
10395
|
+
let lastTickAt = Date.now();
|
|
10396
|
+
let lastFiredAt = 0;
|
|
10397
|
+
const fire = (source, frozenDurationMs) => {
|
|
10398
|
+
const now = Date.now();
|
|
10399
|
+
if (now - lastFiredAt < DEDUP_COOLDOWN_MS) return;
|
|
10400
|
+
lastFiredAt = now;
|
|
10401
|
+
callbackRef.current({ frozenDurationMs, source });
|
|
10402
|
+
};
|
|
10403
|
+
const watchdogId = window.setInterval(() => {
|
|
10404
|
+
const now = Date.now();
|
|
10405
|
+
const elapsed = now - lastTickAt;
|
|
10406
|
+
lastTickAt = now;
|
|
10407
|
+
if (elapsed > WATCHDOG_THRESHOLD_MS) {
|
|
10408
|
+
fire("watchdog", elapsed);
|
|
10409
|
+
}
|
|
10410
|
+
}, WATCHDOG_INTERVAL_MS);
|
|
10411
|
+
const handleVisibility = () => {
|
|
10412
|
+
const now = Date.now();
|
|
10413
|
+
if (document.visibilityState === "visible") {
|
|
10414
|
+
fire("visibilitychange", now - lastTickAt);
|
|
10415
|
+
}
|
|
10416
|
+
lastTickAt = now;
|
|
10417
|
+
};
|
|
10418
|
+
const handlePageShow = (_e) => {
|
|
10419
|
+
const now = Date.now();
|
|
10420
|
+
if (document.visibilityState === "visible") {
|
|
10421
|
+
fire("pageshow", now - lastTickAt);
|
|
10422
|
+
}
|
|
10423
|
+
lastTickAt = now;
|
|
10424
|
+
};
|
|
10425
|
+
const handleFocus = () => {
|
|
10426
|
+
const now = Date.now();
|
|
10427
|
+
const elapsed = now - lastTickAt;
|
|
10428
|
+
lastTickAt = now;
|
|
10429
|
+
if (elapsed > WATCHDOG_THRESHOLD_MS) {
|
|
10430
|
+
fire("focus", elapsed);
|
|
10431
|
+
}
|
|
10432
|
+
};
|
|
10433
|
+
document.addEventListener("visibilitychange", handleVisibility);
|
|
10434
|
+
window.addEventListener("pageshow", handlePageShow);
|
|
10435
|
+
window.addEventListener("focus", handleFocus);
|
|
10436
|
+
return () => {
|
|
10437
|
+
window.clearInterval(watchdogId);
|
|
10438
|
+
document.removeEventListener("visibilitychange", handleVisibility);
|
|
10439
|
+
window.removeEventListener("pageshow", handlePageShow);
|
|
10440
|
+
window.removeEventListener("focus", handleFocus);
|
|
10441
|
+
};
|
|
10442
|
+
}, []);
|
|
10443
|
+
}
|
|
10444
|
+
var STUCK_REF_THRESHOLD_MS = 5e3;
|
|
10445
|
+
function usePageResumeEffect(deps) {
|
|
10446
|
+
const { dispatch, handlingMobileReturnRef } = deps;
|
|
10447
|
+
const dispatchRef = react.useRef(dispatch);
|
|
10448
|
+
dispatchRef.current = dispatch;
|
|
10449
|
+
usePageResume((info) => {
|
|
10450
|
+
console.info("[blink-sdk] PAGE_RESUMED", {
|
|
10451
|
+
source: info.source,
|
|
10452
|
+
frozenDurationMs: info.frozenDurationMs
|
|
10453
|
+
});
|
|
10454
|
+
dispatchRef.current({ type: "PAGE_RESUMED", frozenDurationMs: info.frozenDurationMs });
|
|
10455
|
+
if (info.frozenDurationMs > STUCK_REF_THRESHOLD_MS) {
|
|
10456
|
+
if (handlingMobileReturnRef.current) {
|
|
10457
|
+
console.info("[blink-sdk] PAGE_RESUMED: clearing stuck handlingMobileReturnRef", {
|
|
10458
|
+
frozenDurationMs: info.frozenDurationMs
|
|
10459
|
+
});
|
|
10460
|
+
handlingMobileReturnRef.current = false;
|
|
10461
|
+
}
|
|
10462
|
+
}
|
|
10463
|
+
});
|
|
10464
|
+
}
|
|
10465
|
+
function useGuestAccountPolling(intervalMs = 3e3, lastResumedAt = 0) {
|
|
9854
10466
|
const { apiBaseUrl } = useBlinkConfig();
|
|
9855
10467
|
const [guestAccount, setGuestAccount] = react.useState(null);
|
|
9856
10468
|
const [isPolling, setIsPolling] = react.useState(false);
|
|
@@ -9948,36 +10560,71 @@ function useGuestAccountPolling(intervalMs = 3e3) {
|
|
|
9948
10560
|
[poll, intervalMs, stopPolling]
|
|
9949
10561
|
);
|
|
9950
10562
|
react.useEffect(() => {
|
|
9951
|
-
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
|
|
9959
|
-
|
|
9960
|
-
|
|
9961
|
-
|
|
9962
|
-
|
|
9963
|
-
|
|
9964
|
-
|
|
9965
|
-
|
|
9966
|
-
|
|
10563
|
+
if (!lastResumedAt || !guestTokenRef.current) return;
|
|
10564
|
+
console.info("[blink-sdk] useGuestAccountPolling: page resumed, triggering poll", {
|
|
10565
|
+
lastResumedAt,
|
|
10566
|
+
hasToken: !!guestTokenRef.current,
|
|
10567
|
+
hasSessionId: !!sessionIdRef.current
|
|
10568
|
+
});
|
|
10569
|
+
void poll();
|
|
10570
|
+
}, [lastResumedAt, poll]);
|
|
10571
|
+
react.useEffect(() => () => stopPolling(), [stopPolling]);
|
|
10572
|
+
return { guestAccount, error, isPolling, startPolling, stopPolling };
|
|
10573
|
+
}
|
|
10574
|
+
function useDepositFeeEstimate({
|
|
10575
|
+
apiBaseUrl,
|
|
10576
|
+
getAccessToken,
|
|
10577
|
+
walletId,
|
|
10578
|
+
sourceTokenAddress,
|
|
10579
|
+
destination,
|
|
10580
|
+
amount,
|
|
10581
|
+
enabled
|
|
10582
|
+
}) {
|
|
10583
|
+
const [quoteId, setQuoteId] = react.useState(null);
|
|
10584
|
+
const [quoteFee, setQuoteFee] = react.useState(null);
|
|
10585
|
+
const [quoteLoading, setQuoteLoading] = react.useState(false);
|
|
10586
|
+
const abortRef = react.useRef(null);
|
|
10587
|
+
const fetchQuote = react.useCallback(async () => {
|
|
10588
|
+
if (!enabled || !walletId || !sourceTokenAddress) {
|
|
10589
|
+
setQuoteId(null);
|
|
10590
|
+
setQuoteFee(null);
|
|
10591
|
+
setQuoteLoading(false);
|
|
10592
|
+
return;
|
|
10593
|
+
}
|
|
10594
|
+
abortRef.current?.abort();
|
|
10595
|
+
const controller = new AbortController();
|
|
10596
|
+
abortRef.current = controller;
|
|
10597
|
+
setQuoteLoading(true);
|
|
10598
|
+
try {
|
|
10599
|
+
const token = await getAccessToken();
|
|
10600
|
+
if (!token || controller.signal.aborted) return;
|
|
10601
|
+
const quote = await postTransferQuote(apiBaseUrl, token, {
|
|
10602
|
+
walletId,
|
|
10603
|
+
sourceTokenAddress,
|
|
10604
|
+
destination,
|
|
10605
|
+
amount: { amount, currency: "USD" }
|
|
9967
10606
|
});
|
|
9968
|
-
if (
|
|
9969
|
-
|
|
10607
|
+
if (controller.signal.aborted) return;
|
|
10608
|
+
setQuoteId(quote.id);
|
|
10609
|
+
setQuoteFee(quote.fee);
|
|
10610
|
+
} catch (err) {
|
|
10611
|
+
if (controller.signal.aborted) return;
|
|
10612
|
+
console.warn("[blink-sdk] Fee quote failed:", err);
|
|
10613
|
+
setQuoteId(null);
|
|
10614
|
+
setQuoteFee(null);
|
|
10615
|
+
} finally {
|
|
10616
|
+
if (!controller.signal.aborted) {
|
|
10617
|
+
setQuoteLoading(false);
|
|
9970
10618
|
}
|
|
9971
|
-
}
|
|
9972
|
-
|
|
9973
|
-
|
|
10619
|
+
}
|
|
10620
|
+
}, [enabled, walletId, sourceTokenAddress, destination, amount, apiBaseUrl, getAccessToken]);
|
|
10621
|
+
react.useEffect(() => {
|
|
10622
|
+
fetchQuote();
|
|
9974
10623
|
return () => {
|
|
9975
|
-
|
|
9976
|
-
window.removeEventListener("pageshow", handlePageShow);
|
|
10624
|
+
abortRef.current?.abort();
|
|
9977
10625
|
};
|
|
9978
|
-
}, [
|
|
9979
|
-
|
|
9980
|
-
return { guestAccount, error, isPolling, startPolling, stopPolling };
|
|
10626
|
+
}, [fetchQuote]);
|
|
10627
|
+
return { quoteId, quoteFee, quoteLoading };
|
|
9981
10628
|
}
|
|
9982
10629
|
function BlinkPayment(props) {
|
|
9983
10630
|
const resetKey = react.useRef(0);
|
|
@@ -10017,7 +10664,7 @@ function BlinkPaymentInner({
|
|
|
10017
10664
|
);
|
|
10018
10665
|
const authExecutor = useAuthorizationExecutor();
|
|
10019
10666
|
const polling = useTransferPolling();
|
|
10020
|
-
const guestAccountPolling = useGuestAccountPolling();
|
|
10667
|
+
const guestAccountPolling = useGuestAccountPolling(3e3, state.lastResumedAt);
|
|
10021
10668
|
const transferSigning = useTransferSigning();
|
|
10022
10669
|
const mobileFlowRefs = {
|
|
10023
10670
|
mobileSetupFlowRef: react.useRef(false),
|
|
@@ -10035,6 +10682,15 @@ function BlinkPaymentInner({
|
|
|
10035
10682
|
state.accounts,
|
|
10036
10683
|
state.knownCredentialIds
|
|
10037
10684
|
);
|
|
10685
|
+
const depositFee = useDepositFeeEstimate({
|
|
10686
|
+
apiBaseUrl,
|
|
10687
|
+
getAccessToken,
|
|
10688
|
+
walletId: state.selectedWalletId,
|
|
10689
|
+
sourceTokenAddress: derived.selectedSource?.address,
|
|
10690
|
+
destination,
|
|
10691
|
+
amount: depositAmount ?? 5,
|
|
10692
|
+
enabled: state.phase.step === "deposit" && !state.isGuestFlow && authenticated
|
|
10693
|
+
});
|
|
10038
10694
|
const transfer = useTransferHandlers({
|
|
10039
10695
|
dispatch,
|
|
10040
10696
|
getAccessToken,
|
|
@@ -10052,6 +10708,9 @@ function BlinkPaymentInner({
|
|
|
10052
10708
|
sourceTokenAddress: derived.selectedSource?.address,
|
|
10053
10709
|
activeCredentialId: state.activeCredentialId,
|
|
10054
10710
|
selectedAccountId: state.selectedAccountId,
|
|
10711
|
+
selectedWalletId: state.selectedWalletId,
|
|
10712
|
+
selectedTokenSymbol: state.selectedTokenSymbol,
|
|
10713
|
+
quoteId: depositFee.quoteId,
|
|
10055
10714
|
transfer: state.transfer,
|
|
10056
10715
|
accounts: state.accounts
|
|
10057
10716
|
});
|
|
@@ -10068,7 +10727,8 @@ function BlinkPaymentInner({
|
|
|
10068
10727
|
guestTransferId: state.guestTransferId,
|
|
10069
10728
|
guestSessionToken: state.guestSessionToken
|
|
10070
10729
|
},
|
|
10071
|
-
onComplete
|
|
10730
|
+
onComplete,
|
|
10731
|
+
state.lastResumedAt
|
|
10072
10732
|
);
|
|
10073
10733
|
const sourceSelection = useSourceSelectionHandlers(dispatch, authExecutor, {
|
|
10074
10734
|
guestPreauthSessionId: state.guestPreauthSessionId,
|
|
@@ -10164,10 +10824,15 @@ function BlinkPaymentInner({
|
|
|
10164
10824
|
dispatch({ type: "SYNC_AMOUNT", amount: depositAmount.toString() });
|
|
10165
10825
|
}
|
|
10166
10826
|
}, [depositAmount, dispatch]);
|
|
10827
|
+
usePageResumeEffect({
|
|
10828
|
+
dispatch,
|
|
10829
|
+
handlingMobileReturnRef: mobileFlowRefs.handlingMobileReturnRef
|
|
10830
|
+
});
|
|
10167
10831
|
usePrivySessionSyncEffect({ dispatch, ready, authenticated });
|
|
10168
10832
|
useGuestPreauthMobileRestoreEffect({
|
|
10169
10833
|
dispatch,
|
|
10170
10834
|
privyReady: state.privyReady,
|
|
10835
|
+
lastResumedAt: state.lastResumedAt,
|
|
10171
10836
|
mobileSetupFlowRef: mobileFlowRefs.mobileSetupFlowRef,
|
|
10172
10837
|
setupAccountIdRef: mobileFlowRefs.setupAccountIdRef,
|
|
10173
10838
|
startGuestAccountPolling: guestAccountPolling.startPolling
|
|
@@ -10180,25 +10845,24 @@ function BlinkPaymentInner({
|
|
|
10180
10845
|
guestAccount: guestAccountPolling.guestAccount,
|
|
10181
10846
|
startPolling: guestAccountPolling.startPolling
|
|
10182
10847
|
});
|
|
10183
|
-
const guestSessionTokenRef = react.useRef(state.guestSessionToken);
|
|
10184
|
-
guestSessionTokenRef.current = state.guestSessionToken;
|
|
10185
|
-
const guestPreauthSessionIdRef = react.useRef(state.guestPreauthSessionId);
|
|
10186
|
-
guestPreauthSessionIdRef.current = state.guestPreauthSessionId;
|
|
10187
10848
|
react.useEffect(() => {
|
|
10188
|
-
|
|
10189
|
-
|
|
10190
|
-
|
|
10191
|
-
|
|
10192
|
-
|
|
10193
|
-
|
|
10194
|
-
|
|
10195
|
-
|
|
10196
|
-
|
|
10197
|
-
|
|
10198
|
-
|
|
10199
|
-
|
|
10200
|
-
|
|
10201
|
-
|
|
10849
|
+
if (!state.lastResumedAt) return;
|
|
10850
|
+
const token = state.guestSessionToken;
|
|
10851
|
+
const sessionId = state.guestPreauthSessionId;
|
|
10852
|
+
if (!token) return;
|
|
10853
|
+
if (guestAccountPolling.isPolling || guestAccountPolling.guestAccount) return;
|
|
10854
|
+
console.info("[blink-sdk] warm-return: restarting guest account polling from React state", {
|
|
10855
|
+
sessionId: sessionId ?? "(none \u2014 account-only mode)"
|
|
10856
|
+
});
|
|
10857
|
+
guestAccountPolling.startPolling(token, sessionId ?? void 0);
|
|
10858
|
+
}, [
|
|
10859
|
+
state.lastResumedAt,
|
|
10860
|
+
state.guestSessionToken,
|
|
10861
|
+
state.guestPreauthSessionId,
|
|
10862
|
+
guestAccountPolling.isPolling,
|
|
10863
|
+
guestAccountPolling.guestAccount,
|
|
10864
|
+
guestAccountPolling.startPolling
|
|
10865
|
+
]);
|
|
10202
10866
|
react.useEffect(() => {
|
|
10203
10867
|
console.info("[blink-sdk] guestPreauthCompletion effect", {
|
|
10204
10868
|
hasGuestAccount: !!guestAccountPolling.guestAccount,
|
|
@@ -10363,6 +11027,11 @@ function BlinkPaymentInner({
|
|
|
10363
11027
|
onLogout: handleLogout,
|
|
10364
11028
|
onNewPayment: handleNewPayment,
|
|
10365
11029
|
onSetPhase: (phase) => dispatch({ type: "SET_USER_INTENT", intent: phase }),
|
|
11030
|
+
onBackFromSubflow: () => {
|
|
11031
|
+
authExecutor.cancelPendingExecution();
|
|
11032
|
+
dispatch({ type: "RESTORE_SELECTION" });
|
|
11033
|
+
dispatch({ type: "SET_USER_INTENT", intent: { step: "deposit" } });
|
|
11034
|
+
},
|
|
10366
11035
|
onSetAuthInput: auth.setAuthInput,
|
|
10367
11036
|
onSetOtpCode: (code) => {
|
|
10368
11037
|
auth.setOtpCode(code);
|
|
@@ -10396,7 +11065,8 @@ function BlinkPaymentInner({
|
|
|
10396
11065
|
handleLogout,
|
|
10397
11066
|
handleNewPayment,
|
|
10398
11067
|
onDismiss,
|
|
10399
|
-
dispatch
|
|
11068
|
+
dispatch,
|
|
11069
|
+
authExecutor
|
|
10400
11070
|
]);
|
|
10401
11071
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10402
11072
|
StepRenderer,
|
|
@@ -10445,7 +11115,10 @@ function BlinkPaymentInner({
|
|
|
10445
11115
|
guestSettingSender: guestTransfer.settingSender,
|
|
10446
11116
|
guestPendingEntry: guestTransfer.pendingGuestEntry,
|
|
10447
11117
|
guestQuoteFee: guestTransfer.guestFee?.quote ?? null,
|
|
10448
|
-
guestQuoteLoading: guestTransfer.guestQuoteLoading
|
|
11118
|
+
guestQuoteLoading: guestTransfer.guestQuoteLoading,
|
|
11119
|
+
depositQuoteId: depositFee.quoteId,
|
|
11120
|
+
depositQuoteFee: depositFee.quoteFee,
|
|
11121
|
+
depositQuoteLoading: depositFee.quoteLoading
|
|
10449
11122
|
},
|
|
10450
11123
|
handlers
|
|
10451
11124
|
}
|
|
@@ -10453,6 +11126,7 @@ function BlinkPaymentInner({
|
|
|
10453
11126
|
}
|
|
10454
11127
|
|
|
10455
11128
|
exports.AdvancedSourceScreen = AdvancedSourceScreen;
|
|
11129
|
+
exports.AuthorizationSessionCancelledError = AuthorizationSessionCancelledError;
|
|
10456
11130
|
exports.BLINK_LOGO = BLINK_LOGO;
|
|
10457
11131
|
exports.BLINK_MASCOT = BLINK_MASCOT;
|
|
10458
11132
|
exports.BlinkLoadingScreen = BlinkLoadingScreen;
|
|
@@ -10497,6 +11171,8 @@ exports.findDevicePasskey = findDevicePasskey;
|
|
|
10497
11171
|
exports.findDevicePasskeyViaPopup = findDevicePasskeyViaPopup;
|
|
10498
11172
|
exports.getTheme = getTheme;
|
|
10499
11173
|
exports.guestEntryMatchingRecommended = guestEntryMatchingRecommended;
|
|
11174
|
+
exports.isAuthorizationSessionCancelled = isAuthorizationSessionCancelled;
|
|
11175
|
+
exports.isUserDismissedAuthorizationError = isUserDismissedAuthorizationError;
|
|
10500
11176
|
exports.lightTheme = lightTheme;
|
|
10501
11177
|
exports.mapGuestPickerEntries = mapGuestPickerEntries;
|
|
10502
11178
|
exports.resolvePasskeyRpId = resolvePasskeyRpId;
|