@rhinestone/deposit-modal 0.1.40 → 0.1.42

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.
Files changed (39) hide show
  1. package/README.md +1 -0
  2. package/dist/{DepositModalReown-3HNOCOOO.mjs → DepositModalReown-3GPEVG26.mjs} +15 -6
  3. package/dist/{DepositModalReown-ZZKRN6J3.cjs → DepositModalReown-EEXNSXI4.cjs} +17 -8
  4. package/dist/{WithdrawModalReown-XXCOZYVU.mjs → WithdrawModalReown-7CSCY55U.mjs} +4 -4
  5. package/dist/{WithdrawModalReown-2CWNDVJD.cjs → WithdrawModalReown-GCOVYZN2.cjs} +7 -7
  6. package/dist/{chunk-K7BHCDJQ.cjs → chunk-37CTMJMO.cjs} +181 -96
  7. package/dist/{chunk-3O37UPSC.cjs → chunk-CDHUGROM.cjs} +1630 -362
  8. package/dist/{chunk-CFLZYWX7.mjs → chunk-KWAFKVV6.mjs} +120 -35
  9. package/dist/{chunk-AHOFT42H.cjs → chunk-LT3QKJI2.cjs} +458 -115
  10. package/dist/{chunk-SJEIKMVO.mjs → chunk-MBOH6XW3.mjs} +26 -13
  11. package/dist/{chunk-FLXTBFMZ.cjs → chunk-NELAYNA3.cjs} +11 -0
  12. package/dist/{chunk-F5S6RHUI.mjs → chunk-NLL42V7D.mjs} +1568 -300
  13. package/dist/{chunk-V7I5T4SW.cjs → chunk-PWPW7GFB.cjs} +25 -12
  14. package/dist/{chunk-IC2M2DZ7.mjs → chunk-QIK6ONMQ.mjs} +392 -49
  15. package/dist/{chunk-I7RYTI4G.mjs → chunk-ZJQZEIHA.mjs} +11 -0
  16. package/dist/constants.cjs +2 -2
  17. package/dist/constants.d.cts +6 -6
  18. package/dist/constants.d.ts +6 -6
  19. package/dist/constants.mjs +1 -1
  20. package/dist/deposit.cjs +4 -4
  21. package/dist/deposit.d.cts +2 -2
  22. package/dist/deposit.d.ts +2 -2
  23. package/dist/deposit.mjs +3 -3
  24. package/dist/index.cjs +5 -5
  25. package/dist/index.d.cts +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.mjs +4 -4
  28. package/dist/reown.cjs +5 -5
  29. package/dist/reown.d.cts +1 -1
  30. package/dist/reown.d.ts +1 -1
  31. package/dist/reown.mjs +4 -4
  32. package/dist/styles.css +66 -0
  33. package/dist/{types-CIaQPR6F.d.cts → types-CyUiKQ4H.d.cts} +10 -7
  34. package/dist/{types-Bp2n2RQ3.d.ts → types-DQG7NEBI.d.ts} +10 -7
  35. package/dist/withdraw.cjs +4 -4
  36. package/dist/withdraw.d.cts +2 -2
  37. package/dist/withdraw.d.ts +2 -2
  38. package/dist/withdraw.mjs +3 -3
  39. package/package.json +25 -5
@@ -11,9 +11,10 @@ import {
11
11
  createDepositService,
12
12
  createSessionOwnerKey,
13
13
  currencyFormatter,
14
+ debugError,
15
+ debugLog,
14
16
  formatUserError,
15
17
  getAssetId,
16
- getEventSourceDetails,
17
18
  getEventTxHash,
18
19
  getPublicClient,
19
20
  isDepositEvent,
@@ -21,8 +22,10 @@ import {
21
22
  loadSessionOwnerFromStorage,
22
23
  portfolioToAssets,
23
24
  saveSessionOwnerToStorage,
24
- tokenFormatter
25
- } from "./chunk-IC2M2DZ7.mjs";
25
+ toEvmCaip2,
26
+ tokenFormatter,
27
+ txRefsMatch
28
+ } from "./chunk-QIK6ONMQ.mjs";
26
29
  import {
27
30
  DEFAULT_BACKEND_URL,
28
31
  DEFAULT_SIGNER_ADDRESS,
@@ -38,21 +41,22 @@ import {
38
41
  getTokenIcon,
39
42
  getTokenSymbol,
40
43
  isStablecoinSymbol
41
- } from "./chunk-I7RYTI4G.mjs";
44
+ } from "./chunk-ZJQZEIHA.mjs";
42
45
 
43
46
  // src/DepositModal.tsx
44
47
  import {
45
- useMemo as useMemo6,
46
- useEffect as useEffect8,
48
+ useMemo as useMemo8,
49
+ useEffect as useEffect9,
47
50
  useRef as useRef6,
48
- useState as useState8,
51
+ useState as useState11,
49
52
  useCallback as useCallback4,
50
53
  lazy,
51
54
  Suspense
52
55
  } from "react";
53
56
 
54
57
  // src/DepositFlow.tsx
55
- import { useState as useState7, useCallback as useCallback3, useMemo as useMemo5, useEffect as useEffect7, useRef as useRef5 } from "react";
58
+ import { useState as useState10, useCallback as useCallback3, useMemo as useMemo7, useEffect as useEffect8, useRef as useRef5 } from "react";
59
+ import { formatUnits as formatUnits5 } from "viem";
56
60
 
57
61
  // src/components/steps/SetupStep.tsx
58
62
  import { useState, useEffect, useRef, useCallback } from "react";
@@ -101,7 +105,7 @@ function SetupStep({
101
105
  const setup = await service.setupAccount({
102
106
  ownerAddress: address,
103
107
  sessionOwnerAddress: sessionOwner.address,
104
- targetChain,
108
+ targetChain: toEvmCaip2(targetChain),
105
109
  targetToken,
106
110
  signerAddress,
107
111
  sessionChainIds,
@@ -111,7 +115,7 @@ function SetupStep({
111
115
  if (!setup.needsRegistration) {
112
116
  setState({ type: "ready", smartAccount });
113
117
  onConnected?.(address, smartAccount);
114
- onSetupComplete(smartAccount);
118
+ onSetupComplete(smartAccount, setup.solanaDepositAddress);
115
119
  return;
116
120
  }
117
121
  setState({ type: "signing-session" });
@@ -130,7 +134,7 @@ function SetupStep({
130
134
  });
131
135
  const sessionDetails = buildSessionDetails(setup.sessionDetailsUnsigned, signature);
132
136
  setState({ type: "registering" });
133
- await service.registerAccount({
137
+ const registerResult = await service.registerAccount({
134
138
  address: smartAccount,
135
139
  accountParams: {
136
140
  factory: setup.accountParams.factory,
@@ -140,14 +144,14 @@ function SetupStep({
140
144
  eoaAddress: address,
141
145
  sessionOwner: sessionOwner.address,
142
146
  target: {
143
- chain: targetChain,
147
+ chain: toEvmCaip2(targetChain),
144
148
  token: targetToken,
145
149
  ...recipient && { recipient }
146
150
  }
147
151
  });
148
152
  setState({ type: "ready", smartAccount });
149
153
  onConnected?.(address, smartAccount);
150
- onSetupComplete(smartAccount);
154
+ onSetupComplete(smartAccount, registerResult.solanaDepositAddress);
151
155
  } catch (error) {
152
156
  const message = error instanceof Error ? error.message : "Setup failed";
153
157
  setState({ type: "error", message });
@@ -1234,28 +1238,223 @@ function QRCode({ value, size = 200, iconSrc, className }) {
1234
1238
  }
1235
1239
  QRCode.displayName = "QRCode";
1236
1240
 
1241
+ // src/core/solana.ts
1242
+ import {
1243
+ Connection,
1244
+ PublicKey,
1245
+ SystemProgram,
1246
+ Transaction
1247
+ } from "@solana/web3.js";
1248
+ import {
1249
+ getAssociatedTokenAddress,
1250
+ createAssociatedTokenAccountInstruction,
1251
+ createTransferInstruction
1252
+ } from "@solana/spl-token";
1253
+ var SOLANA_TOKENS = [
1254
+ { symbol: "SOL", mint: "native", decimals: 9 },
1255
+ {
1256
+ symbol: "USDC",
1257
+ mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
1258
+ decimals: 6
1259
+ },
1260
+ {
1261
+ symbol: "USDT",
1262
+ mint: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
1263
+ decimals: 6
1264
+ }
1265
+ ];
1266
+ var DEFAULT_SOLANA_RPC_URL = "https://api.mainnet.solana.com";
1267
+ var configuredSolanaRpcUrl = null;
1268
+ var cachedConnections = /* @__PURE__ */ new Map();
1269
+ function configureSolanaRpcUrl(rpcUrl) {
1270
+ const normalized = rpcUrl?.trim();
1271
+ configuredSolanaRpcUrl = normalized ? normalized : null;
1272
+ cachedConnections.clear();
1273
+ }
1274
+ function getSolanaRpcUrl() {
1275
+ return configuredSolanaRpcUrl ?? DEFAULT_SOLANA_RPC_URL;
1276
+ }
1277
+ function getSolanaConnection() {
1278
+ const rpcUrl = getSolanaRpcUrl();
1279
+ const cached = cachedConnections.get(rpcUrl);
1280
+ if (cached) {
1281
+ return cached;
1282
+ }
1283
+ const next = new Connection(rpcUrl, "confirmed");
1284
+ cachedConnections.set(rpcUrl, next);
1285
+ return next;
1286
+ }
1287
+ function isNativeSol(token) {
1288
+ return token.mint === "native";
1289
+ }
1290
+ async function buildSolTransferTransaction(connection, from, to, lamports) {
1291
+ const fromPubkey = new PublicKey(from);
1292
+ const toPubkey = new PublicKey(to);
1293
+ const tx = new Transaction().add(
1294
+ SystemProgram.transfer({
1295
+ fromPubkey,
1296
+ toPubkey,
1297
+ lamports
1298
+ })
1299
+ );
1300
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
1301
+ tx.recentBlockhash = blockhash;
1302
+ tx.lastValidBlockHeight = lastValidBlockHeight;
1303
+ tx.feePayer = fromPubkey;
1304
+ return tx;
1305
+ }
1306
+ async function buildSplTransferTransaction(connection, from, to, mint, amount) {
1307
+ const fromPubkey = new PublicKey(from);
1308
+ const toPubkey = new PublicKey(to);
1309
+ const mintPubkey = new PublicKey(mint);
1310
+ const fromAta = await getAssociatedTokenAddress(mintPubkey, fromPubkey);
1311
+ const toAta = await getAssociatedTokenAddress(mintPubkey, toPubkey, true);
1312
+ const tx = new Transaction();
1313
+ const toAtaInfo = await connection.getAccountInfo(toAta);
1314
+ if (!toAtaInfo) {
1315
+ tx.add(
1316
+ createAssociatedTokenAccountInstruction(
1317
+ fromPubkey,
1318
+ toAta,
1319
+ toPubkey,
1320
+ mintPubkey
1321
+ )
1322
+ );
1323
+ }
1324
+ tx.add(createTransferInstruction(fromAta, toAta, fromPubkey, amount));
1325
+ const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
1326
+ tx.recentBlockhash = blockhash;
1327
+ tx.lastValidBlockHeight = lastValidBlockHeight;
1328
+ tx.feePayer = fromPubkey;
1329
+ return tx;
1330
+ }
1331
+ function extractSignature(value) {
1332
+ if (typeof value === "string") {
1333
+ return value.length > 0 ? value : null;
1334
+ }
1335
+ if (typeof value.signature === "string" && value.signature.length > 0) {
1336
+ return value.signature;
1337
+ }
1338
+ if (typeof value.hash === "string" && value.hash.length > 0) {
1339
+ return value.hash;
1340
+ }
1341
+ if (typeof value.txid === "string" && value.txid.length > 0) {
1342
+ return value.txid;
1343
+ }
1344
+ if (typeof value.transactionId === "string" && value.transactionId.length > 0) {
1345
+ return value.transactionId;
1346
+ }
1347
+ return null;
1348
+ }
1349
+ async function sendSolanaTransaction(provider, _connection, transaction) {
1350
+ const result = await provider.signAndSendTransaction(transaction);
1351
+ const signature = extractSignature(result);
1352
+ if (!signature) {
1353
+ throw new Error("Transaction sent but wallet did not return a signature");
1354
+ }
1355
+ return signature;
1356
+ }
1357
+
1237
1358
  // src/components/steps/DepositAddressStep.tsx
1238
1359
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1239
1360
  var POLL_INTERVAL_MS = 4e3;
1361
+ function isRecord(value) {
1362
+ return typeof value === "object" && value !== null;
1363
+ }
1364
+ function asNumber(value) {
1365
+ if (typeof value === "number" && Number.isFinite(value)) return value;
1366
+ if (typeof value === "string" && value.trim() !== "") {
1367
+ const parsed = Number(value);
1368
+ return Number.isFinite(parsed) ? parsed : void 0;
1369
+ }
1370
+ return void 0;
1371
+ }
1372
+ function asChainId(value) {
1373
+ if (typeof value === "string") {
1374
+ if (value.startsWith("solana")) return "solana";
1375
+ const eip155Match = value.match(/^eip155:(\d+)$/);
1376
+ if (eip155Match) return Number(eip155Match[1]);
1377
+ }
1378
+ return asNumber(value);
1379
+ }
1380
+ function asAmount(value) {
1381
+ if (typeof value === "string") return value;
1382
+ if (typeof value === "number" && Number.isFinite(value)) {
1383
+ return value.toString();
1384
+ }
1385
+ return void 0;
1386
+ }
1387
+ function asString(value) {
1388
+ return typeof value === "string" ? value : void 0;
1389
+ }
1390
+ function resolveSolanaTokenMeta(token) {
1391
+ if (!token) return {};
1392
+ const normalized = token.toLowerCase();
1393
+ const matched = SOLANA_TOKENS.find(
1394
+ (entry) => entry.mint.toLowerCase() === normalized
1395
+ );
1396
+ if (matched) {
1397
+ return { sourceSymbol: matched.symbol, sourceDecimals: matched.decimals };
1398
+ }
1399
+ if (normalized === "native" || normalized === "11111111111111111111111111111111" || normalized === "so11111111111111111111111111111111111111112") {
1400
+ return { sourceSymbol: "SOL", sourceDecimals: 9 };
1401
+ }
1402
+ return {};
1403
+ }
1404
+ function getDepositEventDetails(event) {
1405
+ if (!event?.type || !isRecord(event.data)) return {};
1406
+ if (event.type === "deposit-received") {
1407
+ const chainId = asChainId(event.data.chain);
1408
+ const token = asString(event.data.token);
1409
+ const solanaMeta = chainId === "solana" ? resolveSolanaTokenMeta(token) : {};
1410
+ return {
1411
+ chainId,
1412
+ amount: asAmount(event.data.amount),
1413
+ token,
1414
+ ...solanaMeta
1415
+ };
1416
+ }
1417
+ if (event.type === "bridge-started") {
1418
+ const source = isRecord(event.data.source) ? event.data.source : void 0;
1419
+ const chainId = asChainId(source?.chain);
1420
+ const token = asString(source?.asset);
1421
+ const solanaMeta = chainId === "solana" ? resolveSolanaTokenMeta(token) : {};
1422
+ return {
1423
+ chainId,
1424
+ amount: asAmount(source?.amount),
1425
+ token,
1426
+ ...solanaMeta
1427
+ };
1428
+ }
1429
+ return {};
1430
+ }
1240
1431
  function DepositAddressStep({
1241
1432
  smartAccount,
1433
+ solanaDepositAddress,
1242
1434
  service,
1243
1435
  onDepositDetected,
1244
1436
  onError
1245
1437
  }) {
1246
- const supportedChainIds = useMemo4(() => getSupportedChainIds(), []);
1438
+ const hasSolana = Boolean(solanaDepositAddress);
1439
+ const evmChainIds = useMemo4(() => getSupportedChainIds(), []);
1440
+ const chainOptions = useMemo4(
1441
+ () => hasSolana ? [...evmChainIds, "solana"] : evmChainIds,
1442
+ [evmChainIds, hasSolana]
1443
+ );
1247
1444
  const BASE_CHAIN_ID = 8453;
1248
- const defaultChainId = supportedChainIds.includes(BASE_CHAIN_ID) ? BASE_CHAIN_ID : supportedChainIds[0];
1445
+ const defaultChainId = evmChainIds.includes(BASE_CHAIN_ID) ? BASE_CHAIN_ID : evmChainIds[0];
1249
1446
  const [sourceChainId, setSourceChainId] = useState6(defaultChainId);
1447
+ const isSolana = sourceChainId === "solana";
1250
1448
  const tokensForChain = useMemo4(
1251
- () => getTargetTokenSymbolsForChain(sourceChainId),
1252
- [sourceChainId]
1449
+ () => isSolana ? SOLANA_TOKENS.map((t) => t.symbol) : getTargetTokenSymbolsForChain(sourceChainId),
1450
+ [sourceChainId, isSolana]
1253
1451
  );
1254
1452
  const defaultToken = tokensForChain.includes("USDC") ? "USDC" : tokensForChain[0] ?? "USDC";
1255
1453
  const [sourceTokenSymbol, setSourceTokenSymbol] = useState6(defaultToken);
1256
1454
  useEffect6(() => {
1257
1455
  if (!tokensForChain.includes(sourceTokenSymbol)) {
1258
- setSourceTokenSymbol(tokensForChain[0] ?? "USDC");
1456
+ const fallback = tokensForChain.includes("USDC") ? "USDC" : tokensForChain[0] ?? "USDC";
1457
+ setSourceTokenSymbol(fallback);
1259
1458
  }
1260
1459
  }, [tokensForChain, sourceTokenSymbol]);
1261
1460
  const [copied, setCopied] = useState6(false);
@@ -1267,14 +1466,27 @@ function DepositAddressStep({
1267
1466
  const depositHandledRef = useRef4(false);
1268
1467
  const sourceSelectionRef = useRef4({
1269
1468
  chainId: defaultChainId,
1270
- tokenSymbol: defaultToken
1469
+ token: typeof defaultChainId === "number" ? getTokenAddress(defaultToken, defaultChainId) : void 0,
1470
+ sourceSymbol: defaultToken
1271
1471
  });
1272
1472
  useEffect6(() => {
1473
+ if (isSolana) {
1474
+ const matched = SOLANA_TOKENS.find((t) => t.symbol === sourceTokenSymbol) ?? SOLANA_TOKENS[0];
1475
+ sourceSelectionRef.current = {
1476
+ chainId: "solana",
1477
+ token: matched?.mint,
1478
+ sourceSymbol: matched?.symbol,
1479
+ sourceDecimals: matched?.decimals
1480
+ };
1481
+ return;
1482
+ }
1273
1483
  sourceSelectionRef.current = {
1274
1484
  chainId: sourceChainId,
1275
- tokenSymbol: sourceTokenSymbol
1485
+ token: getTokenAddress(sourceTokenSymbol, sourceChainId),
1486
+ sourceSymbol: sourceTokenSymbol
1276
1487
  };
1277
- }, [sourceChainId, sourceTokenSymbol]);
1488
+ }, [sourceChainId, sourceTokenSymbol, isSolana]);
1489
+ const displayAddress = isSolana && solanaDepositAddress ? solanaDepositAddress : smartAccount;
1278
1490
  useEffect6(() => {
1279
1491
  if (!chainDropdownOpen && !tokenDropdownOpen) return;
1280
1492
  function handlePointerDown(event) {
@@ -1295,12 +1507,12 @@ function DepositAddressStep({
1295
1507
  }, [chainDropdownOpen, tokenDropdownOpen]);
1296
1508
  const handleCopy = useCallback2(async () => {
1297
1509
  try {
1298
- await navigator.clipboard.writeText(smartAccount);
1510
+ await navigator.clipboard.writeText(displayAddress);
1299
1511
  setCopied(true);
1300
1512
  setTimeout(() => setCopied(false), 2e3);
1301
1513
  } catch {
1302
1514
  const textarea = document.createElement("textarea");
1303
- textarea.value = smartAccount;
1515
+ textarea.value = displayAddress;
1304
1516
  textarea.style.position = "fixed";
1305
1517
  textarea.style.opacity = "0";
1306
1518
  document.body.appendChild(textarea);
@@ -1310,7 +1522,12 @@ function DepositAddressStep({
1310
1522
  setCopied(true);
1311
1523
  setTimeout(() => setCopied(false), 2e3);
1312
1524
  }
1313
- }, [smartAccount]);
1525
+ }, [displayAddress]);
1526
+ useEffect6(() => {
1527
+ setCopied(false);
1528
+ setChainDropdownOpen(false);
1529
+ setTokenDropdownOpen(false);
1530
+ }, [sourceChainId]);
1314
1531
  useEffect6(() => {
1315
1532
  depositHandledRef.current = false;
1316
1533
  setPollingError(null);
@@ -1323,18 +1540,27 @@ function DepositAddressStep({
1323
1540
  const status = await service.fetchLatestStatus(smartAccount);
1324
1541
  if (cancelled || depositHandledRef.current) return;
1325
1542
  const event = status.lastEvent;
1326
- const eventTxHash = isDepositEvent(event) ? getEventTxHash(event)?.toLowerCase() ?? null : null;
1543
+ const eventTxHash = isDepositEvent(event) ? getEventTxHash(event) ?? null : null;
1327
1544
  if (baselineTxHash === void 0) {
1328
1545
  baselineTxHash = eventTxHash;
1329
- } else if (eventTxHash && eventTxHash !== baselineTxHash) {
1330
- const details = getEventSourceDetails(event);
1546
+ } else if (eventTxHash && (!baselineTxHash || !txRefsMatch(eventTxHash, baselineTxHash))) {
1547
+ const details = getDepositEventDetails(event);
1331
1548
  const fallback = sourceSelectionRef.current;
1332
1549
  const chainId = details.chainId ?? fallback.chainId;
1333
1550
  const amount = details.amount ?? "0";
1334
- const token = details.token ?? getTokenAddress(fallback.tokenSymbol, fallback.chainId);
1551
+ const token = details.token ?? fallback.token;
1552
+ const sourceSymbol = details.sourceSymbol ?? fallback.sourceSymbol;
1553
+ const sourceDecimals = details.sourceDecimals ?? fallback.sourceDecimals;
1335
1554
  if (token) {
1336
1555
  depositHandledRef.current = true;
1337
- onDepositDetected(eventTxHash, chainId, amount, token);
1556
+ onDepositDetected(
1557
+ eventTxHash,
1558
+ chainId,
1559
+ amount,
1560
+ token,
1561
+ sourceSymbol,
1562
+ sourceDecimals
1563
+ );
1338
1564
  return;
1339
1565
  }
1340
1566
  }
@@ -1356,31 +1582,31 @@ function DepositAddressStep({
1356
1582
  clearTimeout(timeoutId);
1357
1583
  };
1358
1584
  }, [smartAccount, service, onDepositDetected, onError]);
1359
- const chainIconSrc = getChainIcon(sourceChainId);
1585
+ const qrIconSrc = getChainIcon(sourceChainId);
1360
1586
  return /* @__PURE__ */ jsxs6("div", { className: "rs-step", children: [
1361
1587
  /* @__PURE__ */ jsx6("div", { className: "rs-step-body", children: /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address", children: [
1362
1588
  /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-selectors", children: [
1363
- /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-dropdown", ref: tokenDropdownRef, children: [
1364
- /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-label", children: "Supported token" }),
1589
+ /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-dropdown", ref: chainDropdownRef, children: [
1590
+ /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-label", children: "Chain" }),
1365
1591
  /* @__PURE__ */ jsxs6(
1366
1592
  "button",
1367
1593
  {
1368
1594
  type: "button",
1369
1595
  className: "rs-deposit-address-dropdown-trigger",
1370
1596
  onClick: () => {
1371
- setTokenDropdownOpen(!tokenDropdownOpen);
1372
- setChainDropdownOpen(false);
1597
+ setChainDropdownOpen(!chainDropdownOpen);
1598
+ setTokenDropdownOpen(false);
1373
1599
  },
1374
1600
  children: [
1375
- getTokenIcon(sourceTokenSymbol) && /* @__PURE__ */ jsx6(
1601
+ getChainIcon(sourceChainId) && /* @__PURE__ */ jsx6(
1376
1602
  "img",
1377
1603
  {
1378
- src: getTokenIcon(sourceTokenSymbol),
1604
+ src: getChainIcon(sourceChainId),
1379
1605
  alt: "",
1380
1606
  className: "rs-deposit-address-dropdown-icon"
1381
1607
  }
1382
1608
  ),
1383
- /* @__PURE__ */ jsx6("span", { children: sourceTokenSymbol }),
1609
+ /* @__PURE__ */ jsx6("span", { children: getChainName(sourceChainId) }),
1384
1610
  /* @__PURE__ */ jsx6(
1385
1611
  "svg",
1386
1612
  {
@@ -1402,51 +1628,51 @@ function DepositAddressStep({
1402
1628
  ]
1403
1629
  }
1404
1630
  ),
1405
- tokenDropdownOpen && /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-menu", children: tokensForChain.map((symbol) => /* @__PURE__ */ jsxs6(
1631
+ chainDropdownOpen && /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-menu", children: chainOptions.map((chainId) => /* @__PURE__ */ jsxs6(
1406
1632
  "button",
1407
1633
  {
1408
1634
  type: "button",
1409
- className: `rs-deposit-address-dropdown-item ${symbol === sourceTokenSymbol ? "rs-deposit-address-dropdown-item--active" : ""}`,
1635
+ className: `rs-deposit-address-dropdown-item ${chainId === sourceChainId ? "rs-deposit-address-dropdown-item--active" : ""}`,
1410
1636
  onClick: () => {
1411
- setSourceTokenSymbol(symbol);
1412
- setTokenDropdownOpen(false);
1637
+ setSourceChainId(chainId);
1638
+ setChainDropdownOpen(false);
1413
1639
  },
1414
1640
  children: [
1415
- getTokenIcon(symbol) && /* @__PURE__ */ jsx6(
1641
+ getChainIcon(chainId) && /* @__PURE__ */ jsx6(
1416
1642
  "img",
1417
1643
  {
1418
- src: getTokenIcon(symbol),
1644
+ src: getChainIcon(chainId),
1419
1645
  alt: "",
1420
1646
  className: "rs-deposit-address-dropdown-icon"
1421
1647
  }
1422
1648
  ),
1423
- /* @__PURE__ */ jsx6("span", { children: symbol })
1649
+ /* @__PURE__ */ jsx6("span", { children: getChainName(chainId) })
1424
1650
  ]
1425
1651
  },
1426
- symbol
1652
+ String(chainId)
1427
1653
  )) })
1428
1654
  ] }),
1429
- /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-dropdown", ref: chainDropdownRef, children: [
1430
- /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-label", children: "Supported chain" }),
1655
+ /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-dropdown", ref: tokenDropdownRef, children: [
1656
+ /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-label", children: "Token" }),
1431
1657
  /* @__PURE__ */ jsxs6(
1432
1658
  "button",
1433
1659
  {
1434
1660
  type: "button",
1435
1661
  className: "rs-deposit-address-dropdown-trigger",
1436
1662
  onClick: () => {
1437
- setChainDropdownOpen(!chainDropdownOpen);
1438
- setTokenDropdownOpen(false);
1663
+ setTokenDropdownOpen(!tokenDropdownOpen);
1664
+ setChainDropdownOpen(false);
1439
1665
  },
1440
1666
  children: [
1441
- getChainIcon(sourceChainId) && /* @__PURE__ */ jsx6(
1667
+ getTokenIcon(sourceTokenSymbol) && /* @__PURE__ */ jsx6(
1442
1668
  "img",
1443
1669
  {
1444
- src: getChainIcon(sourceChainId),
1670
+ src: getTokenIcon(sourceTokenSymbol),
1445
1671
  alt: "",
1446
1672
  className: "rs-deposit-address-dropdown-icon"
1447
1673
  }
1448
1674
  ),
1449
- /* @__PURE__ */ jsx6("span", { children: getChainName(sourceChainId) }),
1675
+ /* @__PURE__ */ jsx6("span", { children: sourceTokenSymbol }),
1450
1676
  /* @__PURE__ */ jsx6(
1451
1677
  "svg",
1452
1678
  {
@@ -1468,35 +1694,39 @@ function DepositAddressStep({
1468
1694
  ]
1469
1695
  }
1470
1696
  ),
1471
- chainDropdownOpen && /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-menu", children: supportedChainIds.map((chainId) => /* @__PURE__ */ jsxs6(
1697
+ tokenDropdownOpen && /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-menu", children: tokensForChain.map((symbol) => /* @__PURE__ */ jsxs6(
1472
1698
  "button",
1473
1699
  {
1474
1700
  type: "button",
1475
- className: `rs-deposit-address-dropdown-item ${chainId === sourceChainId ? "rs-deposit-address-dropdown-item--active" : ""}`,
1701
+ className: `rs-deposit-address-dropdown-item ${symbol === sourceTokenSymbol ? "rs-deposit-address-dropdown-item--active" : ""}`,
1476
1702
  onClick: () => {
1477
- setSourceChainId(chainId);
1478
- setChainDropdownOpen(false);
1703
+ setSourceTokenSymbol(symbol);
1704
+ setTokenDropdownOpen(false);
1479
1705
  },
1480
1706
  children: [
1481
- getChainIcon(chainId) && /* @__PURE__ */ jsx6(
1707
+ getTokenIcon(symbol) && /* @__PURE__ */ jsx6(
1482
1708
  "img",
1483
1709
  {
1484
- src: getChainIcon(chainId),
1710
+ src: getTokenIcon(symbol),
1485
1711
  alt: "",
1486
1712
  className: "rs-deposit-address-dropdown-icon"
1487
1713
  }
1488
1714
  ),
1489
- /* @__PURE__ */ jsx6("span", { children: getChainName(chainId) })
1715
+ /* @__PURE__ */ jsx6("span", { children: symbol })
1490
1716
  ]
1491
1717
  },
1492
- chainId
1718
+ symbol
1493
1719
  )) })
1494
1720
  ] })
1495
1721
  ] }),
1496
- /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-qr", children: /* @__PURE__ */ jsx6(QRCode, { value: smartAccount, size: 200, iconSrc: chainIconSrc }) }),
1722
+ /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-qr", children: /* @__PURE__ */ jsx6(QRCode, { value: displayAddress, size: 200, iconSrc: qrIconSrc }) }),
1497
1723
  /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-info", children: [
1498
- /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-label", children: "Your deposit address" }),
1499
- /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-value", children: smartAccount }),
1724
+ /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-label", children: [
1725
+ "Your ",
1726
+ isSolana ? "Solana" : "EVM",
1727
+ " deposit address"
1728
+ ] }),
1729
+ /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-value", children: displayAddress }),
1500
1730
  /* @__PURE__ */ jsxs6(
1501
1731
  "button",
1502
1732
  {
@@ -1541,170 +1771,890 @@ function DepositAddressStep({
1541
1771
  }
1542
1772
  DepositAddressStep.displayName = "DepositAddressStep";
1543
1773
 
1544
- // src/DepositFlow.tsx
1774
+ // src/components/steps/SolanaTokenSelectStep.tsx
1775
+ import { useState as useState7, useEffect as useEffect7, useMemo as useMemo5 } from "react";
1776
+ import { formatUnits as formatUnits3 } from "viem";
1545
1777
  import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1546
- function isSameRoute(sourceChain, sourceToken, targetChain, targetToken) {
1547
- return sourceChain === targetChain && sourceToken.toLowerCase() === targetToken.toLowerCase();
1548
- }
1549
- function getAddressKey(address) {
1550
- return address ? address.toLowerCase() : null;
1551
- }
1552
- function DepositFlow({
1553
- dappWalletClient,
1554
- dappPublicClient,
1555
- dappAddress,
1556
- targetChain,
1557
- targetToken,
1778
+ function SolanaTokenSelectStep({
1779
+ solanaAddress,
1558
1780
  service,
1559
- sourceChain: defaultSourceChain,
1560
- sourceToken: defaultSourceToken,
1561
- amount: defaultAmount,
1562
- recipient,
1563
- signerAddress = DEFAULT_SIGNER_ADDRESS,
1564
- sessionChainIds,
1565
- forceRegister = false,
1566
- waitForFinalTx = true,
1567
- reownWallet,
1568
- onConnect,
1569
- onDisconnect,
1570
- onRequestConnect,
1571
- connectButtonLabel,
1572
- uiConfig,
1573
- onStepChange,
1574
- onTotalBalanceChange,
1575
- onClose,
1576
- onConnected,
1577
- onDepositSubmitted,
1578
- onDepositComplete,
1579
- onDepositFailed,
1580
- onError,
1781
+ onContinue,
1782
+ onTotalBalanceComputed,
1581
1783
  debug
1582
1784
  }) {
1583
- const [step, setStep] = useState7({ type: "setup" });
1584
- const [flowMode, setFlowMode] = useState7(null);
1585
- const [totalBalanceUsd, setTotalBalanceUsd] = useState7(0);
1586
- const [isConnectSelectionConfirmed, setIsConnectSelectionConfirmed] = useState7(false);
1587
- const [selectedConnectAddress, setSelectedConnectAddress] = useState7(null);
1588
- const portfolioAssetsRef = useRef5([]);
1589
- const stableWalletSignerRef = useRef5(null);
1590
- const stableWalletSelectionKeyRef = useRef5(null);
1591
- const hasNavigatedBackRef = useRef5(false);
1592
- const handleAssetsLoaded = useCallback3((assets) => {
1593
- portfolioAssetsRef.current = assets;
1594
- }, []);
1595
- const getTokenPriceUsd = useCallback3((symbol) => {
1596
- const sym = symbol.toLowerCase();
1597
- for (const asset of portfolioAssetsRef.current) {
1598
- if (asset.symbol.toLowerCase() === sym && asset.balanceUsd && asset.balance) {
1599
- try {
1600
- const balanceUnits = Number(asset.balance) / 10 ** asset.decimals;
1601
- if (balanceUnits > 0) return asset.balanceUsd / balanceUnits;
1602
- } catch {
1785
+ const [tokenBalances, setTokenBalances] = useState7([]);
1786
+ const [selectedSymbol, setSelectedSymbol] = useState7(null);
1787
+ const [loading, setLoading] = useState7(true);
1788
+ const [error, setError] = useState7(null);
1789
+ useEffect7(() => {
1790
+ let active = true;
1791
+ async function loadBalances() {
1792
+ if (!solanaAddress) {
1793
+ setLoading(false);
1794
+ return;
1795
+ }
1796
+ setLoading(true);
1797
+ setError(null);
1798
+ const portfolioBySymbol = {};
1799
+ try {
1800
+ debugLog(debug, "solana-token-select", "portfolio:request", {
1801
+ solanaAddress
1802
+ });
1803
+ const portfolio = await service.fetchSolanaPortfolio(solanaAddress);
1804
+ if (!active) return;
1805
+ for (const t of portfolio.tokens) {
1806
+ const symbol = t.symbol.toUpperCase();
1807
+ if (!SOLANA_TOKENS.some((st) => st.symbol === symbol)) continue;
1808
+ let parsed = 0n;
1809
+ try {
1810
+ parsed = BigInt(t.balance || "0");
1811
+ } catch {
1812
+ parsed = 0n;
1813
+ }
1814
+ if (parsed <= 0n) continue;
1815
+ const existing = portfolioBySymbol[symbol];
1816
+ if (!existing || (t.balanceUsd ?? 0) > existing.balanceUsd) {
1817
+ portfolioBySymbol[symbol] = {
1818
+ balance: parsed,
1819
+ balanceUsd: t.balanceUsd ?? 0
1820
+ };
1821
+ }
1822
+ }
1823
+ debugLog(debug, "solana-token-select", "portfolio:success", {
1824
+ symbols: Object.keys(portfolioBySymbol)
1825
+ });
1826
+ } catch (err) {
1827
+ if (!active) return;
1828
+ debugError(debug, "solana-token-select", "portfolio:failure", err, {
1829
+ solanaAddress
1830
+ });
1831
+ setError(
1832
+ err instanceof Error ? err.message : "Failed to load balances"
1833
+ );
1834
+ setTokenBalances([]);
1835
+ setLoading(false);
1836
+ return;
1837
+ }
1838
+ const results = [];
1839
+ for (const token of SOLANA_TOKENS) {
1840
+ const fromPortfolio = portfolioBySymbol[token.symbol];
1841
+ if (fromPortfolio && fromPortfolio.balance > 0n) {
1842
+ results.push({
1843
+ token,
1844
+ balance: fromPortfolio.balance,
1845
+ balanceUsd: fromPortfolio.balanceUsd
1846
+ });
1603
1847
  }
1604
1848
  }
1849
+ if (!active) return;
1850
+ setTokenBalances(results);
1851
+ setLoading(false);
1852
+ const totalUsd = results.reduce((sum, r) => sum + r.balanceUsd, 0);
1853
+ onTotalBalanceComputed?.(totalUsd);
1605
1854
  }
1606
- return null;
1607
- }, []);
1608
- const dappSwitchChain = useMemo5(() => {
1609
- if (!dappWalletClient?.switchChain) return void 0;
1610
- return async (chainId) => {
1611
- await dappWalletClient.switchChain?.({ id: chainId });
1855
+ void loadBalances();
1856
+ return () => {
1857
+ active = false;
1612
1858
  };
1613
- }, [dappWalletClient]);
1614
- const connectedWalletAddress = dappWalletClient?.account?.address ?? null;
1615
- const walletOptions = useMemo5(() => {
1616
- const options = [];
1617
- const seen = /* @__PURE__ */ new Set();
1618
- if (connectedWalletAddress && dappAddress) {
1619
- options.push({
1620
- address: connectedWalletAddress,
1621
- label: "Connected Wallet",
1622
- kind: "connected"
1623
- });
1624
- seen.add(connectedWalletAddress.toLowerCase());
1625
- }
1626
- if (reownWallet?.address && reownWallet.isConnected && reownWallet.walletClient && reownWallet.publicClient && !seen.has(reownWallet.address.toLowerCase())) {
1627
- options.push({
1628
- address: reownWallet.address,
1629
- label: "External Wallet",
1630
- kind: "external",
1631
- icon: reownWallet.icon
1632
- });
1633
- }
1634
- return options;
1635
- }, [
1636
- connectedWalletAddress,
1637
- dappAddress,
1638
- reownWallet?.address,
1639
- reownWallet?.isConnected,
1640
- reownWallet?.walletClient,
1641
- reownWallet?.publicClient,
1642
- reownWallet?.icon
1643
- ]);
1644
- const canAutoLock = dappWalletClient?.account && dappAddress && !reownWallet;
1645
- const hasWalletOptions = walletOptions.length > 0;
1646
- const hasReownSession = Boolean(
1647
- reownWallet?.isConnected || reownWallet?.address
1859
+ }, [debug, solanaAddress, service, onTotalBalanceComputed]);
1860
+ const rows = useMemo5(
1861
+ () => [...tokenBalances].sort((a, b) => {
1862
+ if (a.balanceUsd !== b.balanceUsd) return b.balanceUsd - a.balanceUsd;
1863
+ if (b.balance > a.balance) return 1;
1864
+ if (b.balance < a.balance) return -1;
1865
+ return 0;
1866
+ }),
1867
+ [tokenBalances]
1648
1868
  );
1649
- const showConnectStep = flowMode === null && !canAutoLock && !isConnectSelectionConfirmed;
1650
- const walletSelectionKey = useMemo5(() => {
1651
- if (flowMode !== "wallet") return null;
1652
- if (canAutoLock) {
1653
- return getAddressKey(connectedWalletAddress);
1654
- }
1655
- if (!isConnectSelectionConfirmed) return null;
1656
- return getAddressKey(selectedConnectAddress);
1657
- }, [
1658
- flowMode,
1659
- canAutoLock,
1660
- connectedWalletAddress,
1661
- isConnectSelectionConfirmed,
1662
- selectedConnectAddress
1663
- ]);
1664
- const walletSignerContext = useMemo5(() => {
1665
- if (flowMode === "deposit-address") {
1666
- return null;
1667
- }
1668
- if (canAutoLock) {
1669
- const fallbackChainId = dappWalletClient?.chain?.id ?? targetChain;
1670
- return {
1671
- ownerAddress: dappWalletClient.account.address,
1672
- walletClient: dappWalletClient,
1673
- publicClient: dappPublicClient ?? getPublicClient(fallbackChainId),
1674
- switchChain: dappSwitchChain
1675
- };
1676
- }
1677
- if (!isConnectSelectionConfirmed || !selectedConnectAddress) return null;
1678
- if (dappWalletClient?.account && dappWalletClient.account.address.toLowerCase() === selectedConnectAddress.toLowerCase()) {
1679
- const fallbackChainId = dappWalletClient?.chain?.id ?? targetChain;
1680
- return {
1681
- ownerAddress: dappWalletClient.account.address,
1682
- walletClient: dappWalletClient,
1683
- publicClient: dappPublicClient ?? getPublicClient(fallbackChainId),
1684
- switchChain: dappSwitchChain
1685
- };
1686
- }
1687
- if (reownWallet?.address?.toLowerCase() === selectedConnectAddress.toLowerCase() && reownWallet.walletClient && reownWallet.publicClient) {
1688
- return {
1689
- ownerAddress: reownWallet.address,
1690
- walletClient: reownWallet.walletClient,
1691
- publicClient: reownWallet.publicClient,
1692
- switchChain: reownWallet.switchChain
1693
- };
1694
- }
1695
- return null;
1696
- }, [
1697
- canAutoLock,
1698
- isConnectSelectionConfirmed,
1699
- selectedConnectAddress,
1700
- dappWalletClient,
1701
- dappPublicClient,
1702
- dappSwitchChain,
1869
+ const selectedEntry = selectedSymbol ? rows.find((r) => r.token.symbol === selectedSymbol) : null;
1870
+ if (error) {
1871
+ return /* @__PURE__ */ jsx7("div", { className: "rs-step", children: /* @__PURE__ */ jsx7("div", { className: "rs-step-body", children: /* @__PURE__ */ jsx7("div", { className: "rs-alert rs-alert--error", children: /* @__PURE__ */ jsx7("span", { className: "rs-alert-text", children: error }) }) }) });
1872
+ }
1873
+ return /* @__PURE__ */ jsxs7("div", { className: "rs-step", children: [
1874
+ /* @__PURE__ */ jsx7("div", { style: { padding: "12px 12px 4px" }, children: /* @__PURE__ */ jsx7("div", { className: "rs-step-title", children: "Select source asset" }) }),
1875
+ /* @__PURE__ */ jsxs7(
1876
+ "div",
1877
+ {
1878
+ className: "rs-step-body",
1879
+ style: { paddingTop: 4, overflow: "auto", maxHeight: 340 },
1880
+ children: [
1881
+ loading && /* @__PURE__ */ jsxs7("div", { className: "rs-loading-state", style: { padding: "40px 12px" }, children: [
1882
+ /* @__PURE__ */ jsx7(Spinner, { className: "rs-text-tertiary" }),
1883
+ /* @__PURE__ */ jsx7("span", { className: "rs-text-sm rs-text-tertiary", children: "Loading balances" })
1884
+ ] }),
1885
+ !loading && rows.length === 0 && /* @__PURE__ */ jsxs7("div", { className: "rs-empty-state", children: [
1886
+ /* @__PURE__ */ jsx7(
1887
+ "svg",
1888
+ {
1889
+ className: "rs-empty-icon",
1890
+ viewBox: "0 0 24 24",
1891
+ fill: "none",
1892
+ stroke: "currentColor",
1893
+ strokeWidth: "1.5",
1894
+ children: /* @__PURE__ */ jsx7(
1895
+ "path",
1896
+ {
1897
+ strokeLinecap: "round",
1898
+ strokeLinejoin: "round",
1899
+ d: "M21 12a2.25 2.25 0 00-2.25-2.25H15a3 3 0 11-6 0H5.25A2.25 2.25 0 003 12m18 0v6a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 18v-6m18 0V9M3 12V9m18 0a2.25 2.25 0 00-2.25-2.25H5.25A2.25 2.25 0 003 9m18 0V6a2.25 2.25 0 00-2.25-2.25H5.25A2.25 2.25 0 003 6v3"
1900
+ }
1901
+ )
1902
+ }
1903
+ ),
1904
+ /* @__PURE__ */ jsx7("div", { className: "rs-empty-text", children: "No funds in connected wallet" }),
1905
+ /* @__PURE__ */ jsxs7("div", { className: "rs-empty-address", children: [
1906
+ solanaAddress.slice(0, 6),
1907
+ "...",
1908
+ solanaAddress.slice(-4)
1909
+ ] })
1910
+ ] }),
1911
+ !loading && rows.length > 0 && /* @__PURE__ */ jsx7("div", { className: "rs-asset-list", children: rows.map((entry) => {
1912
+ const isSelected = selectedSymbol === entry.token.symbol;
1913
+ const tokenIcon = getTokenIcon(entry.token.symbol);
1914
+ const chainIcon = getChainIcon("solana");
1915
+ let formattedBalance;
1916
+ try {
1917
+ const raw = formatUnits3(entry.balance, entry.token.decimals);
1918
+ const numeric = Number(raw);
1919
+ formattedBalance = Number.isFinite(numeric) ? tokenFormatter.format(numeric) : raw;
1920
+ } catch {
1921
+ formattedBalance = "...";
1922
+ }
1923
+ return /* @__PURE__ */ jsxs7(
1924
+ "button",
1925
+ {
1926
+ type: "button",
1927
+ onClick: () => setSelectedSymbol(entry.token.symbol),
1928
+ className: `rs-asset-row ${isSelected ? "rs-asset-row--selected" : ""}`,
1929
+ style: { textAlign: "left" },
1930
+ children: [
1931
+ /* @__PURE__ */ jsxs7("div", { className: "rs-asset-info", children: [
1932
+ /* @__PURE__ */ jsxs7("div", { className: "rs-asset-icon-wrapper", children: [
1933
+ tokenIcon ? /* @__PURE__ */ jsx7(
1934
+ "img",
1935
+ {
1936
+ src: tokenIcon,
1937
+ alt: entry.token.symbol,
1938
+ className: "rs-asset-icon",
1939
+ style: { background: "transparent" }
1940
+ }
1941
+ ) : /* @__PURE__ */ jsx7("div", { className: "rs-asset-icon", children: entry.token.symbol.slice(0, 4) }),
1942
+ chainIcon && /* @__PURE__ */ jsx7(
1943
+ "img",
1944
+ {
1945
+ src: chainIcon,
1946
+ alt: "Solana",
1947
+ className: "rs-asset-chain-badge"
1948
+ }
1949
+ )
1950
+ ] }),
1951
+ /* @__PURE__ */ jsxs7("div", { children: [
1952
+ /* @__PURE__ */ jsxs7("div", { className: "rs-asset-name", children: [
1953
+ entry.token.symbol,
1954
+ /* @__PURE__ */ jsx7("span", { className: "rs-asset-chain", children: " on Solana" })
1955
+ ] }),
1956
+ /* @__PURE__ */ jsxs7("div", { className: "rs-asset-balance-small", children: [
1957
+ formattedBalance,
1958
+ " ",
1959
+ entry.token.symbol
1960
+ ] })
1961
+ ] })
1962
+ ] }),
1963
+ /* @__PURE__ */ jsx7("div", { className: "rs-asset-balance", children: entry.balanceUsd > 0 ? currencyFormatter.format(entry.balanceUsd) : `${formattedBalance} ${entry.token.symbol}` })
1964
+ ]
1965
+ },
1966
+ entry.token.symbol
1967
+ );
1968
+ }) })
1969
+ ]
1970
+ }
1971
+ ),
1972
+ /* @__PURE__ */ jsx7("div", { className: "rs-step-footer", children: /* @__PURE__ */ jsx7(
1973
+ Button,
1974
+ {
1975
+ onClick: () => selectedEntry && onContinue(
1976
+ selectedEntry.token,
1977
+ selectedEntry.balance,
1978
+ selectedEntry.balanceUsd
1979
+ ),
1980
+ disabled: !selectedEntry,
1981
+ fullWidth: true,
1982
+ children: "Continue"
1983
+ }
1984
+ ) }),
1985
+ /* @__PURE__ */ jsx7(PoweredBy, {})
1986
+ ] });
1987
+ }
1988
+
1989
+ // src/components/steps/SolanaAmountStep.tsx
1990
+ import { useState as useState8, useMemo as useMemo6 } from "react";
1991
+ import { formatUnits as formatUnits4, parseUnits as parseUnits3 } from "viem";
1992
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1993
+ var SOL_FEE_RESERVE_LAMPORTS = 1000000n;
1994
+ function SolanaAmountStep({
1995
+ token,
1996
+ balance,
1997
+ balanceUsd,
1998
+ onContinue,
1999
+ debug
2000
+ }) {
2001
+ const [amount, setAmount] = useState8("");
2002
+ const [error, setError] = useState8(null);
2003
+ const formattedBalance = useMemo6(() => {
2004
+ try {
2005
+ const raw = formatUnits4(balance, token.decimals);
2006
+ const numeric = Number(raw);
2007
+ if (!Number.isFinite(numeric)) return raw;
2008
+ return tokenFormatter.format(numeric);
2009
+ } catch {
2010
+ return "...";
2011
+ }
2012
+ }, [balance, token.decimals]);
2013
+ const formattedBalanceUsd = useMemo6(() => {
2014
+ if (!Number.isFinite(balanceUsd) || balanceUsd <= 0) return null;
2015
+ return currencyFormatter.format(balanceUsd);
2016
+ }, [balanceUsd]);
2017
+ const spendableBalance = useMemo6(() => {
2018
+ if (!isNativeSol(token)) return balance;
2019
+ return balance > SOL_FEE_RESERVE_LAMPORTS ? balance - SOL_FEE_RESERVE_LAMPORTS : 0n;
2020
+ }, [balance, token]);
2021
+ const handlePresetClick = (percentage) => {
2022
+ try {
2023
+ const spendableUnits = Number(formatUnits4(spendableBalance, token.decimals));
2024
+ if (!Number.isFinite(spendableUnits) || spendableUnits <= 0) return;
2025
+ const value = spendableUnits * percentage / 100;
2026
+ const maxDecimals = token.decimals > 6 ? 6 : token.decimals;
2027
+ const factor = 10 ** maxDecimals;
2028
+ const truncated = Math.floor(value * factor) / factor;
2029
+ const formatted = truncated.toFixed(maxDecimals).replace(/\.?0+$/, "");
2030
+ debugLog(debug, "solana-amount", "amount:preset", {
2031
+ percentage,
2032
+ symbol: token.symbol,
2033
+ formatted
2034
+ });
2035
+ setAmount(formatted);
2036
+ } catch {
2037
+ return;
2038
+ }
2039
+ if (error) setError(null);
2040
+ };
2041
+ const handleContinue = () => {
2042
+ const numericAmount = parseFloat(amount);
2043
+ if (isNaN(numericAmount) || numericAmount <= 0) {
2044
+ debugLog(debug, "solana-amount", "amount:invalid", {
2045
+ amount,
2046
+ reason: "nan-or-non-positive"
2047
+ });
2048
+ setError("Please enter a valid amount");
2049
+ return;
2050
+ }
2051
+ let amountInUnits;
2052
+ try {
2053
+ amountInUnits = parseUnits3(amount, token.decimals);
2054
+ } catch {
2055
+ debugLog(debug, "solana-amount", "amount:invalid", {
2056
+ amount,
2057
+ reason: "parse-units-failed"
2058
+ });
2059
+ setError("Please enter a valid amount");
2060
+ return;
2061
+ }
2062
+ if (amountInUnits > spendableBalance) {
2063
+ const isReserveIssue = isNativeSol(token) && amountInUnits <= balance;
2064
+ debugLog(debug, "solana-amount", "amount:invalid", {
2065
+ amount,
2066
+ balance: balance.toString(),
2067
+ spendableBalance: spendableBalance.toString(),
2068
+ amountInUnits: amountInUnits.toString(),
2069
+ reason: isReserveIssue ? "native-buffer" : "insufficient-balance"
2070
+ });
2071
+ setError(
2072
+ isReserveIssue ? "Use a bit less than your full SOL balance" : "Insufficient balance"
2073
+ );
2074
+ return;
2075
+ }
2076
+ debugLog(debug, "solana-amount", "amount:continue", {
2077
+ symbol: token.symbol,
2078
+ amount,
2079
+ amountInUnits: amountInUnits.toString()
2080
+ });
2081
+ setError(null);
2082
+ onContinue(token, amount);
2083
+ };
2084
+ return /* @__PURE__ */ jsxs8("div", { className: "rs-step", children: [
2085
+ /* @__PURE__ */ jsx8("div", { style: { padding: "12px 12px 4px" }, children: /* @__PURE__ */ jsx8("div", { className: "rs-step-title", children: "Enter amount" }) }),
2086
+ /* @__PURE__ */ jsxs8("div", { className: "rs-step-body", style: { paddingTop: 0 }, children: [
2087
+ /* @__PURE__ */ jsxs8("div", { className: "rs-amount-display", children: [
2088
+ /* @__PURE__ */ jsxs8("div", { className: "rs-amount-input-wrapper", children: [
2089
+ /* @__PURE__ */ jsx8(
2090
+ "input",
2091
+ {
2092
+ type: "text",
2093
+ inputMode: "decimal",
2094
+ className: "rs-amount-input-large",
2095
+ placeholder: "0.00",
2096
+ value: amount,
2097
+ onChange: (e) => {
2098
+ const raw = e.target.value.replace(/[^0-9.]/g, "");
2099
+ const parts = raw.split(".");
2100
+ if (parts.length > 2) return;
2101
+ setAmount(raw);
2102
+ if (error) setError(null);
2103
+ },
2104
+ autoFocus: true
2105
+ }
2106
+ ),
2107
+ /* @__PURE__ */ jsx8("div", { className: "rs-amount-token-value", children: token.symbol })
2108
+ ] }),
2109
+ /* @__PURE__ */ jsxs8("div", { className: "rs-amount-available", children: [
2110
+ /* @__PURE__ */ jsxs8("span", { className: "rs-amount-available-value", children: [
2111
+ formattedBalance,
2112
+ " ",
2113
+ token.symbol,
2114
+ " available"
2115
+ ] }),
2116
+ formattedBalanceUsd && /* @__PURE__ */ jsx8("span", { className: "rs-amount-available-value", children: formattedBalanceUsd })
2117
+ ] })
2118
+ ] }),
2119
+ /* @__PURE__ */ jsxs8("div", { className: "rs-amount-presets", children: [
2120
+ [25, 50, 75].map((pct) => /* @__PURE__ */ jsxs8(
2121
+ "button",
2122
+ {
2123
+ type: "button",
2124
+ className: "rs-amount-preset-btn",
2125
+ onClick: () => handlePresetClick(pct),
2126
+ children: [
2127
+ pct,
2128
+ "%"
2129
+ ]
2130
+ },
2131
+ pct
2132
+ )),
2133
+ /* @__PURE__ */ jsx8(
2134
+ "button",
2135
+ {
2136
+ type: "button",
2137
+ className: "rs-amount-preset-btn",
2138
+ onClick: () => handlePresetClick(100),
2139
+ children: "Max"
2140
+ }
2141
+ )
2142
+ ] }),
2143
+ error && /* @__PURE__ */ jsxs8("div", { className: "rs-amount-error", children: [
2144
+ /* @__PURE__ */ jsx8(
2145
+ "svg",
2146
+ {
2147
+ viewBox: "0 0 24 24",
2148
+ fill: "none",
2149
+ stroke: "currentColor",
2150
+ strokeWidth: "2",
2151
+ style: { width: 16, height: 16, flexShrink: 0 },
2152
+ children: /* @__PURE__ */ jsx8(
2153
+ "path",
2154
+ {
2155
+ strokeLinecap: "round",
2156
+ strokeLinejoin: "round",
2157
+ d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
2158
+ }
2159
+ )
2160
+ }
2161
+ ),
2162
+ /* @__PURE__ */ jsx8("span", { children: error })
2163
+ ] })
2164
+ ] }),
2165
+ /* @__PURE__ */ jsx8("div", { className: "rs-step-footer", children: /* @__PURE__ */ jsx8(
2166
+ Button,
2167
+ {
2168
+ onClick: handleContinue,
2169
+ fullWidth: true,
2170
+ disabled: !amount,
2171
+ children: "Continue"
2172
+ }
2173
+ ) }),
2174
+ /* @__PURE__ */ jsx8(PoweredBy, {})
2175
+ ] });
2176
+ }
2177
+
2178
+ // src/components/steps/SolanaConfirmStep.tsx
2179
+ import { useState as useState9 } from "react";
2180
+ import { parseUnits as parseUnits4 } from "viem";
2181
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2182
+ function SolanaConfirmStep({
2183
+ smartAccount,
2184
+ solanaAddress,
2185
+ solanaDepositAddress,
2186
+ token,
2187
+ amount,
2188
+ targetAmount,
2189
+ targetTokenPriceUsd,
2190
+ targetChain,
2191
+ targetToken,
2192
+ service,
2193
+ solanaProvider,
2194
+ onConfirm,
2195
+ onError,
2196
+ debug
2197
+ }) {
2198
+ const [isSubmitting, setIsSubmitting] = useState9(false);
2199
+ const [error, setError] = useState9(null);
2200
+ const targetSymbol = getTokenSymbol(targetToken, targetChain);
2201
+ const isSameToken = token.symbol.toUpperCase() === targetSymbol.toUpperCase();
2202
+ const formattedAmount = amount && !Number.isNaN(Number(amount)) ? Number(amount).toLocaleString("en-US", { maximumFractionDigits: 6 }) : "0";
2203
+ const formattedReceiveAmount = (() => {
2204
+ if (isSameToken) return formattedAmount;
2205
+ const dollarValue = Number(targetAmount);
2206
+ if (!Number.isFinite(dollarValue) || dollarValue <= 0)
2207
+ return formattedAmount;
2208
+ if (targetTokenPriceUsd !== null && targetTokenPriceUsd > 0) {
2209
+ const tokenAmount = dollarValue / targetTokenPriceUsd;
2210
+ return tokenAmount.toLocaleString("en-US", { maximumFractionDigits: 6 });
2211
+ }
2212
+ return formattedAmount;
2213
+ })();
2214
+ const receiveAmount = isSameToken ? formattedReceiveAmount : `~ ${formattedReceiveAmount}`;
2215
+ const handleConfirm = async () => {
2216
+ if (!solanaProvider) {
2217
+ debugLog(debug, "solana-confirm", "submit:blocked", {
2218
+ reason: "missing-provider"
2219
+ });
2220
+ setError("Solana wallet not connected");
2221
+ return;
2222
+ }
2223
+ const parsedAmount = parseFloat(amount);
2224
+ if (isNaN(parsedAmount) || parsedAmount <= 0) {
2225
+ debugLog(debug, "solana-confirm", "submit:blocked", {
2226
+ reason: "invalid-amount",
2227
+ amount
2228
+ });
2229
+ setError("Please enter a valid amount");
2230
+ return;
2231
+ }
2232
+ setError(null);
2233
+ setIsSubmitting(true);
2234
+ debugLog(debug, "solana-confirm", "submit:start", {
2235
+ smartAccount,
2236
+ solanaAddress,
2237
+ solanaDepositAddress,
2238
+ token: token.symbol,
2239
+ amount
2240
+ });
2241
+ try {
2242
+ const check = await service.checkAccount(smartAccount);
2243
+ debugLog(debug, "solana-confirm", "check:success", {
2244
+ smartAccount,
2245
+ isRegistered: check.isRegistered,
2246
+ targetChain: check.targetChain,
2247
+ targetToken: check.targetToken
2248
+ });
2249
+ if (!check.isRegistered) {
2250
+ throw new Error(
2251
+ "Deposit account is not registered yet. Please restart setup and try again."
2252
+ );
2253
+ }
2254
+ const connection = getSolanaConnection();
2255
+ const amountUnits = parseUnits4(amount, token.decimals);
2256
+ debugLog(debug, "solana-confirm", "tx:build:start", {
2257
+ token: token.symbol,
2258
+ amount,
2259
+ amountUnits: amountUnits.toString()
2260
+ });
2261
+ const transaction = isNativeSol(token) ? await buildSolTransferTransaction(
2262
+ connection,
2263
+ solanaAddress,
2264
+ solanaDepositAddress,
2265
+ amountUnits
2266
+ ) : await buildSplTransferTransaction(
2267
+ connection,
2268
+ solanaAddress,
2269
+ solanaDepositAddress,
2270
+ token.mint,
2271
+ amountUnits
2272
+ );
2273
+ debugLog(debug, "solana-confirm", "tx:build:success", {
2274
+ token: token.symbol,
2275
+ instructionCount: transaction.instructions.length,
2276
+ feePayer: transaction.feePayer?.toBase58(),
2277
+ recentBlockhash: transaction.recentBlockhash
2278
+ });
2279
+ const txHash = await sendSolanaTransaction(
2280
+ solanaProvider,
2281
+ connection,
2282
+ transaction
2283
+ );
2284
+ debugLog(debug, "solana-confirm", "tx:sent", {
2285
+ txHash,
2286
+ amountUnits: amountUnits.toString()
2287
+ });
2288
+ onConfirm(txHash, amountUnits.toString());
2289
+ } catch (err) {
2290
+ const raw = err instanceof Error ? err.message : "Transfer failed";
2291
+ const message = formatUserError(raw);
2292
+ debugError(debug, "solana-confirm", "submit:failure", err, {
2293
+ smartAccount,
2294
+ token: token.symbol,
2295
+ amount
2296
+ });
2297
+ setError(message);
2298
+ onError?.(message, "SOLANA_TRANSFER_ERROR");
2299
+ } finally {
2300
+ setIsSubmitting(false);
2301
+ }
2302
+ };
2303
+ return /* @__PURE__ */ jsxs9("div", { className: "rs-step", children: [
2304
+ /* @__PURE__ */ jsx9("div", { style: { padding: "12px 12px 10px" }, children: /* @__PURE__ */ jsx9("div", { className: "rs-step-title", children: "Review order" }) }),
2305
+ /* @__PURE__ */ jsxs9("div", { className: "rs-step-body rs-space-y-3", style: { paddingTop: 0 }, children: [
2306
+ /* @__PURE__ */ jsxs9("div", { className: "rs-card", children: [
2307
+ /* @__PURE__ */ jsxs9("div", { className: "rs-card-row", children: [
2308
+ /* @__PURE__ */ jsx9("span", { className: "rs-card-label", children: "Source" }),
2309
+ /* @__PURE__ */ jsxs9(
2310
+ "span",
2311
+ {
2312
+ className: "rs-card-value",
2313
+ style: { display: "flex", alignItems: "center", gap: 8 },
2314
+ children: [
2315
+ getChainIcon("solana") && /* @__PURE__ */ jsx9(
2316
+ "img",
2317
+ {
2318
+ src: getChainIcon("solana"),
2319
+ alt: "",
2320
+ style: { width: 16, height: 16, borderRadius: 3 }
2321
+ }
2322
+ ),
2323
+ getChainName("solana")
2324
+ ]
2325
+ }
2326
+ )
2327
+ ] }),
2328
+ /* @__PURE__ */ jsxs9("div", { className: "rs-card-row", children: [
2329
+ /* @__PURE__ */ jsx9("span", { className: "rs-card-label", children: "Destination" }),
2330
+ /* @__PURE__ */ jsxs9(
2331
+ "span",
2332
+ {
2333
+ className: "rs-card-value",
2334
+ style: { display: "flex", alignItems: "center", gap: 8 },
2335
+ children: [
2336
+ getChainIcon(targetChain) && /* @__PURE__ */ jsx9(
2337
+ "img",
2338
+ {
2339
+ src: getChainIcon(targetChain),
2340
+ alt: "",
2341
+ style: { width: 16, height: 16, borderRadius: 3 }
2342
+ }
2343
+ ),
2344
+ getChainName(targetChain)
2345
+ ]
2346
+ }
2347
+ )
2348
+ ] }),
2349
+ /* @__PURE__ */ jsxs9("div", { className: "rs-card-row", children: [
2350
+ /* @__PURE__ */ jsx9("span", { className: "rs-card-label", children: "Estimated time" }),
2351
+ /* @__PURE__ */ jsx9("span", { className: "rs-card-value", children: "< 1 min" })
2352
+ ] })
2353
+ ] }),
2354
+ /* @__PURE__ */ jsxs9("div", { className: "rs-card", children: [
2355
+ /* @__PURE__ */ jsxs9("div", { className: "rs-card-row", children: [
2356
+ /* @__PURE__ */ jsx9("span", { className: "rs-card-label", children: "You send" }),
2357
+ /* @__PURE__ */ jsxs9(
2358
+ "span",
2359
+ {
2360
+ className: "rs-card-value",
2361
+ style: { display: "flex", alignItems: "center", gap: 6 },
2362
+ children: [
2363
+ getTokenIcon(token.symbol) && /* @__PURE__ */ jsx9(
2364
+ "img",
2365
+ {
2366
+ src: getTokenIcon(token.symbol),
2367
+ alt: "",
2368
+ style: { width: 16, height: 16, borderRadius: "50%" }
2369
+ }
2370
+ ),
2371
+ formattedAmount,
2372
+ " ",
2373
+ token.symbol
2374
+ ]
2375
+ }
2376
+ )
2377
+ ] }),
2378
+ /* @__PURE__ */ jsxs9("div", { className: "rs-card-row", children: [
2379
+ /* @__PURE__ */ jsx9("span", { className: "rs-card-label", children: "You receive" }),
2380
+ /* @__PURE__ */ jsxs9(
2381
+ "span",
2382
+ {
2383
+ className: "rs-card-value",
2384
+ style: { display: "flex", alignItems: "center", gap: 6 },
2385
+ children: [
2386
+ getTokenIcon(targetSymbol) && /* @__PURE__ */ jsx9(
2387
+ "img",
2388
+ {
2389
+ src: getTokenIcon(targetSymbol),
2390
+ alt: "",
2391
+ style: { width: 16, height: 16, borderRadius: "50%" }
2392
+ }
2393
+ ),
2394
+ receiveAmount,
2395
+ " ",
2396
+ targetSymbol
2397
+ ]
2398
+ }
2399
+ )
2400
+ ] })
2401
+ ] }),
2402
+ error && /* @__PURE__ */ jsxs9("div", { className: "rs-alert rs-alert--error", children: [
2403
+ /* @__PURE__ */ jsx9(
2404
+ "svg",
2405
+ {
2406
+ className: "rs-alert-icon",
2407
+ viewBox: "0 0 24 24",
2408
+ fill: "none",
2409
+ stroke: "currentColor",
2410
+ strokeWidth: "2",
2411
+ children: /* @__PURE__ */ jsx9(
2412
+ "path",
2413
+ {
2414
+ strokeLinecap: "round",
2415
+ strokeLinejoin: "round",
2416
+ d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
2417
+ }
2418
+ )
2419
+ }
2420
+ ),
2421
+ /* @__PURE__ */ jsx9("span", { className: "rs-alert-text", children: error })
2422
+ ] })
2423
+ ] }),
2424
+ /* @__PURE__ */ jsx9("div", { className: "rs-step-footer", children: /* @__PURE__ */ jsx9(
2425
+ Button,
2426
+ {
2427
+ onClick: handleConfirm,
2428
+ loading: isSubmitting,
2429
+ disabled: !amount || Number(amount) <= 0,
2430
+ fullWidth: true,
2431
+ children: "Confirm Order"
2432
+ }
2433
+ ) }),
2434
+ /* @__PURE__ */ jsx9(PoweredBy, {})
2435
+ ] });
2436
+ }
2437
+
2438
+ // src/DepositFlow.tsx
2439
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
2440
+ function isSameRoute(sourceChain, sourceToken, targetChain, targetToken) {
2441
+ return sourceChain === targetChain && sourceToken.toLowerCase() === targetToken.toLowerCase();
2442
+ }
2443
+ function getAddressKey(address) {
2444
+ return address ? address.toLowerCase() : null;
2445
+ }
2446
+ function DepositFlow({
2447
+ dappWalletClient,
2448
+ dappPublicClient,
2449
+ dappAddress,
2450
+ targetChain,
2451
+ targetToken,
2452
+ service,
2453
+ sourceChain: defaultSourceChain,
2454
+ sourceToken: defaultSourceToken,
2455
+ amount: defaultAmount,
2456
+ recipient,
2457
+ signerAddress = DEFAULT_SIGNER_ADDRESS,
2458
+ sessionChainIds,
2459
+ forceRegister = false,
2460
+ waitForFinalTx = true,
2461
+ reownWallet,
2462
+ onConnect,
2463
+ onDisconnect,
2464
+ onRequestConnect,
2465
+ connectButtonLabel,
2466
+ uiConfig,
2467
+ onStepChange,
2468
+ onTotalBalanceChange,
2469
+ onClose,
2470
+ onConnected,
2471
+ onDepositSubmitted,
2472
+ onDepositComplete,
2473
+ onDepositFailed,
2474
+ onError,
2475
+ debug
2476
+ }) {
2477
+ const [step, setStep] = useState10({ type: "setup" });
2478
+ const [flowMode, setFlowMode] = useState10(null);
2479
+ const [totalBalanceUsd, setTotalBalanceUsd] = useState10(0);
2480
+ const [isConnectSelectionConfirmed, setIsConnectSelectionConfirmed] = useState10(false);
2481
+ const [selectedWalletId, setSelectedWalletId] = useState10(null);
2482
+ const portfolioAssetsRef = useRef5([]);
2483
+ const stableWalletSignerRef = useRef5(null);
2484
+ const stableWalletSelectionKeyRef = useRef5(null);
2485
+ const logFlow = useCallback3(
2486
+ (message, data) => {
2487
+ debugLog(debug, "deposit-flow", message, data);
2488
+ },
2489
+ [debug]
2490
+ );
2491
+ const logFlowError = useCallback3(
2492
+ (message, error, data) => {
2493
+ debugError(debug, "deposit-flow", message, error, data);
2494
+ },
2495
+ [debug]
2496
+ );
2497
+ const handleAssetsLoaded = useCallback3((assets) => {
2498
+ portfolioAssetsRef.current = assets;
2499
+ }, []);
2500
+ const getTokenPriceUsd = useCallback3((symbol) => {
2501
+ const sym = symbol.toLowerCase();
2502
+ for (const asset of portfolioAssetsRef.current) {
2503
+ if (asset.symbol.toLowerCase() === sym && asset.balanceUsd && asset.balance) {
2504
+ try {
2505
+ const balanceUnits = Number(asset.balance) / 10 ** asset.decimals;
2506
+ if (balanceUnits > 0) return asset.balanceUsd / balanceUnits;
2507
+ } catch {
2508
+ }
2509
+ }
2510
+ }
2511
+ return null;
2512
+ }, []);
2513
+ const dappSwitchChain = useMemo7(() => {
2514
+ if (!dappWalletClient?.switchChain) return void 0;
2515
+ return async (chainId) => {
2516
+ await dappWalletClient.switchChain?.({ id: chainId });
2517
+ };
2518
+ }, [dappWalletClient]);
2519
+ const connectedWalletAddress = dappWalletClient?.account?.address ?? null;
2520
+ const walletOptions = useMemo7(() => {
2521
+ const options = [];
2522
+ const seen = /* @__PURE__ */ new Set();
2523
+ if (connectedWalletAddress && dappAddress) {
2524
+ const id = `evm:${connectedWalletAddress.toLowerCase()}`;
2525
+ options.push({
2526
+ id,
2527
+ address: connectedWalletAddress,
2528
+ label: "Connected Wallet",
2529
+ kind: "connected"
2530
+ });
2531
+ seen.add(id);
2532
+ }
2533
+ if (reownWallet?.isConnected && reownWallet.isSolana && reownWallet.solanaAddress && dappAddress) {
2534
+ const id = reownWallet.caipAddress ?? `solana:${reownWallet.solanaAddress}`;
2535
+ if (!seen.has(id)) {
2536
+ options.push({
2537
+ id,
2538
+ solanaAddress: reownWallet.solanaAddress,
2539
+ label: "Solana Wallet",
2540
+ kind: "solana",
2541
+ icon: reownWallet.icon
2542
+ });
2543
+ seen.add(id);
2544
+ }
2545
+ } else if (reownWallet?.address && reownWallet.isConnected && reownWallet.walletClient && reownWallet.publicClient && !seen.has(`evm:${reownWallet.address.toLowerCase()}`)) {
2546
+ const id = `evm:${reownWallet.address.toLowerCase()}`;
2547
+ if (!seen.has(id)) {
2548
+ options.push({
2549
+ id,
2550
+ address: reownWallet.address,
2551
+ label: "External Wallet",
2552
+ kind: "external",
2553
+ icon: reownWallet.icon
2554
+ });
2555
+ seen.add(id);
2556
+ }
2557
+ }
2558
+ return options;
2559
+ }, [
2560
+ connectedWalletAddress,
2561
+ dappAddress,
2562
+ reownWallet?.address,
2563
+ reownWallet?.isConnected,
2564
+ reownWallet?.walletClient,
2565
+ reownWallet?.publicClient,
2566
+ reownWallet?.icon,
2567
+ reownWallet?.isSolana,
2568
+ reownWallet?.solanaAddress,
2569
+ reownWallet?.caipAddress
2570
+ ]);
2571
+ const canAutoLock = dappWalletClient?.account && dappAddress && !reownWallet;
2572
+ const hasWalletOptions = walletOptions.length > 0;
2573
+ const hasReownSession = Boolean(
2574
+ reownWallet?.isConnected || reownWallet?.address
2575
+ );
2576
+ const showConnectStep = flowMode === null && !canAutoLock && !isConnectSelectionConfirmed;
2577
+ const walletSelectionKey = useMemo7(() => {
2578
+ if (flowMode !== "wallet") return null;
2579
+ if (canAutoLock) {
2580
+ return getAddressKey(connectedWalletAddress);
2581
+ }
2582
+ if (!isConnectSelectionConfirmed) return null;
2583
+ return selectedWalletId;
2584
+ }, [
2585
+ flowMode,
2586
+ canAutoLock,
2587
+ connectedWalletAddress,
2588
+ isConnectSelectionConfirmed,
2589
+ selectedWalletId
2590
+ ]);
2591
+ const walletSignerContext = useMemo7(() => {
2592
+ if (flowMode === "deposit-address") {
2593
+ return null;
2594
+ }
2595
+ if (flowMode === "solana-wallet") {
2596
+ if (!dappAddress) return null;
2597
+ return {
2598
+ ownerAddress: dappAddress,
2599
+ walletClient: void 0,
2600
+ publicClient: dappPublicClient ?? getPublicClient(targetChain),
2601
+ switchChain: void 0
2602
+ };
2603
+ }
2604
+ if (canAutoLock) {
2605
+ const fallbackChainId = dappWalletClient?.chain?.id ?? targetChain;
2606
+ return {
2607
+ ownerAddress: dappWalletClient.account.address,
2608
+ walletClient: dappWalletClient,
2609
+ publicClient: dappPublicClient ?? getPublicClient(fallbackChainId),
2610
+ switchChain: dappSwitchChain
2611
+ };
2612
+ }
2613
+ if (!isConnectSelectionConfirmed || !selectedWalletId) return null;
2614
+ const selectedOption = walletOptions.find(
2615
+ (option) => option.id === selectedWalletId
2616
+ );
2617
+ if (!selectedOption) return null;
2618
+ if (selectedOption.kind === "solana") {
2619
+ if (!dappAddress) return null;
2620
+ return {
2621
+ ownerAddress: dappAddress,
2622
+ walletClient: void 0,
2623
+ publicClient: dappPublicClient ?? getPublicClient(targetChain),
2624
+ switchChain: void 0
2625
+ };
2626
+ }
2627
+ if (selectedOption.kind === "connected" && dappWalletClient?.account && selectedOption.address && dappWalletClient.account.address.toLowerCase() === selectedOption.address.toLowerCase()) {
2628
+ const fallbackChainId = dappWalletClient?.chain?.id ?? targetChain;
2629
+ return {
2630
+ ownerAddress: dappWalletClient.account.address,
2631
+ walletClient: dappWalletClient,
2632
+ publicClient: dappPublicClient ?? getPublicClient(fallbackChainId),
2633
+ switchChain: dappSwitchChain
2634
+ };
2635
+ }
2636
+ if (selectedOption.kind === "external" && reownWallet?.address && selectedOption.address && reownWallet.address.toLowerCase() === selectedOption.address.toLowerCase()) {
2637
+ return {
2638
+ ownerAddress: reownWallet.address,
2639
+ walletClient: reownWallet.walletClient,
2640
+ publicClient: reownWallet.publicClient ?? getPublicClient(targetChain),
2641
+ switchChain: reownWallet.switchChain
2642
+ };
2643
+ }
2644
+ return null;
2645
+ }, [
2646
+ canAutoLock,
2647
+ isConnectSelectionConfirmed,
2648
+ selectedWalletId,
2649
+ walletOptions,
2650
+ dappWalletClient,
2651
+ dappPublicClient,
2652
+ dappSwitchChain,
1703
2653
  dappAddress,
1704
2654
  reownWallet,
1705
2655
  targetChain
1706
2656
  ]);
1707
- useEffect7(() => {
2657
+ useEffect8(() => {
1708
2658
  if (flowMode !== "wallet") {
1709
2659
  stableWalletSelectionKeyRef.current = null;
1710
2660
  stableWalletSignerRef.current = null;
@@ -1719,7 +2669,7 @@ function DepositFlow({
1719
2669
  stableWalletSignerRef.current = walletSignerContext;
1720
2670
  }
1721
2671
  }, [flowMode, walletSelectionKey, walletSignerContext]);
1722
- const signerContext = useMemo5(() => {
2672
+ const signerContext = useMemo7(() => {
1723
2673
  if (flowMode === "deposit-address") {
1724
2674
  if (!dappAddress) return null;
1725
2675
  return {
@@ -1749,7 +2699,7 @@ function DepositFlow({
1749
2699
  ]);
1750
2700
  const sessionKeyAddress = dappAddress ?? signerContext?.ownerAddress ?? null;
1751
2701
  const lastTargetRef = useRef5(null);
1752
- useEffect7(() => {
2702
+ useEffect8(() => {
1753
2703
  const prev = lastTargetRef.current;
1754
2704
  if (prev && (prev.chain !== targetChain || prev.token.toLowerCase() !== targetToken.toLowerCase())) {
1755
2705
  if (step.type !== "processing") {
@@ -1779,6 +2729,37 @@ function DepositFlow({
1779
2729
  setIsConnectSelectionConfirmed(false);
1780
2730
  }
1781
2731
  }, [hasWalletOptions, reownWallet]);
2732
+ const handleBackFromSolanaTokenSelect = useCallback3(() => {
2733
+ setFlowMode(null);
2734
+ setStep({ type: "setup" });
2735
+ if (hasWalletOptions || reownWallet) {
2736
+ hasNavigatedBackRef.current = true;
2737
+ setIsConnectSelectionConfirmed(false);
2738
+ }
2739
+ }, [hasWalletOptions, reownWallet]);
2740
+ const handleBackFromSolanaAmount = useCallback3(() => {
2741
+ setStep((prev) => {
2742
+ if (prev.type !== "solana-amount") return prev;
2743
+ return {
2744
+ type: "solana-token-select",
2745
+ smartAccount: prev.smartAccount,
2746
+ solanaDepositAddress: prev.solanaDepositAddress
2747
+ };
2748
+ });
2749
+ }, []);
2750
+ const handleBackFromSolanaConfirm = useCallback3(() => {
2751
+ setStep((prev) => {
2752
+ if (prev.type !== "solana-confirm") return prev;
2753
+ return {
2754
+ type: "solana-amount",
2755
+ smartAccount: prev.smartAccount,
2756
+ solanaDepositAddress: prev.solanaDepositAddress,
2757
+ token: prev.token,
2758
+ balance: prev.balance,
2759
+ balanceUsd: prev.balanceUsd
2760
+ };
2761
+ });
2762
+ }, []);
1782
2763
  const handleBackFromConfirm = useCallback3(() => {
1783
2764
  setStep((prev) => {
1784
2765
  if (prev.type !== "confirm") return prev;
@@ -1789,50 +2770,90 @@ function DepositFlow({
1789
2770
  };
1790
2771
  });
1791
2772
  }, []);
1792
- const stepIndex = step.type === "setup" ? 0 : step.type === "deposit-address" ? 1 : step.type === "select-asset" ? 1 : step.type === "amount" ? 2 : step.type === "confirm" ? 3 : 4;
1793
- const currentBackHandler = step.type === "deposit-address" ? handleBackFromDepositAddress : step.type === "select-asset" && signerContext && !canAutoLock ? handleBackFromSelectAsset : step.type === "amount" ? handleBackFromAmount : step.type === "confirm" ? handleBackFromConfirm : void 0;
1794
- useEffect7(() => {
2773
+ const stepIndex = step.type === "setup" ? 0 : step.type === "deposit-address" ? 1 : step.type === "select-asset" ? 1 : step.type === "solana-token-select" ? 1 : step.type === "solana-amount" ? 2 : step.type === "amount" ? 2 : step.type === "confirm" ? 3 : step.type === "solana-confirm" ? 3 : 4;
2774
+ const currentBackHandler = step.type === "deposit-address" ? handleBackFromDepositAddress : step.type === "select-asset" && signerContext && !canAutoLock ? handleBackFromSelectAsset : step.type === "solana-token-select" ? handleBackFromSolanaTokenSelect : step.type === "solana-amount" ? handleBackFromSolanaAmount : step.type === "solana-confirm" ? handleBackFromSolanaConfirm : step.type === "amount" ? handleBackFromAmount : step.type === "confirm" ? handleBackFromConfirm : void 0;
2775
+ useEffect8(() => {
1795
2776
  onStepChange?.(stepIndex, currentBackHandler);
1796
2777
  }, [stepIndex, currentBackHandler, onStepChange]);
1797
- useEffect7(() => {
2778
+ useEffect8(() => {
2779
+ logFlow("state:changed", {
2780
+ step: step.type,
2781
+ flowMode,
2782
+ targetChain,
2783
+ targetToken,
2784
+ selectedWalletId
2785
+ });
2786
+ }, [
2787
+ flowMode,
2788
+ logFlow,
2789
+ selectedWalletId,
2790
+ step.type,
2791
+ targetChain,
2792
+ targetToken
2793
+ ]);
2794
+ useEffect8(() => {
1798
2795
  onTotalBalanceChange?.(totalBalanceUsd);
1799
2796
  }, [totalBalanceUsd, onTotalBalanceChange]);
1800
2797
  const isDepositAddressMode = flowMode === "deposit-address";
2798
+ const isSolanaWalletMode = flowMode === "solana-wallet";
1801
2799
  const handleSelectProvider = useCallback3(() => {
1802
2800
  setFlowMode("wallet");
1803
2801
  }, []);
2802
+ const handleSelectSolanaWallet = useCallback3(() => {
2803
+ setFlowMode("solana-wallet");
2804
+ }, []);
1804
2805
  const handleSelectTransferCrypto = useCallback3(() => {
1805
2806
  setFlowMode("deposit-address");
1806
2807
  setStep({ type: "setup" });
1807
2808
  }, []);
1808
- const handleResetFlow = useCallback3(() => {
1809
- portfolioAssetsRef.current = [];
1810
- stableWalletSignerRef.current = null;
1811
- stableWalletSelectionKeyRef.current = null;
1812
- hasNavigatedBackRef.current = false;
1813
- setTotalBalanceUsd(0);
1814
- setSelectedConnectAddress(null);
1815
- setIsConnectSelectionConfirmed(false);
2809
+ const handleNewDeposit = useCallback3(() => {
1816
2810
  setFlowMode(null);
1817
2811
  setStep({ type: "setup" });
1818
2812
  }, []);
1819
- const handleNewDeposit = useCallback3(() => {
1820
- handleResetFlow();
1821
- }, [handleResetFlow]);
1822
2813
  const handleSetupComplete = useCallback3(
1823
- (smartAccount) => {
2814
+ (smartAccount, solanaDepositAddress) => {
2815
+ logFlow("setup:complete", {
2816
+ smartAccount,
2817
+ hasSolanaDepositAddress: Boolean(solanaDepositAddress),
2818
+ flowMode: isDepositAddressMode ? "deposit-address" : isSolanaWalletMode ? "solana-wallet" : "wallet"
2819
+ });
1824
2820
  if (isDepositAddressMode) {
1825
- setStep({ type: "deposit-address", smartAccount });
2821
+ setStep({
2822
+ type: "deposit-address",
2823
+ smartAccount,
2824
+ solanaDepositAddress
2825
+ });
2826
+ } else if (isSolanaWalletMode) {
2827
+ if (solanaDepositAddress) {
2828
+ setStep({
2829
+ type: "solana-token-select",
2830
+ smartAccount,
2831
+ solanaDepositAddress
2832
+ });
2833
+ } else {
2834
+ onError?.({
2835
+ message: "Solana deposit address not available. Please try again.",
2836
+ code: "SOLANA_SETUP_FAILED"
2837
+ });
2838
+ }
1826
2839
  } else {
1827
2840
  setStep({ type: "select-asset", smartAccount });
1828
2841
  }
1829
2842
  },
1830
- [isDepositAddressMode]
2843
+ [isDepositAddressMode, isSolanaWalletMode, logFlow]
1831
2844
  );
1832
2845
  const handleDepositAddressDetected = useCallback3(
1833
- (txHash, chainId, amount, token) => {
2846
+ (txHash, chainId, amount, token, sourceSymbol, sourceDecimals) => {
2847
+ logFlow("deposit-address:detected", {
2848
+ txHash,
2849
+ sourceChain: chainId,
2850
+ sourceToken: token,
2851
+ amount
2852
+ });
1834
2853
  setStep((prev) => {
1835
2854
  if (prev.type !== "deposit-address") return prev;
2855
+ const isEvmToken = /^0x[a-fA-F0-9]{40}$/.test(token);
2856
+ const directTransfer = typeof chainId === "number" && isEvmToken && isSameRoute(chainId, token, targetChain, targetToken);
1836
2857
  return {
1837
2858
  type: "processing",
1838
2859
  smartAccount: prev.smartAccount,
@@ -1840,13 +2861,94 @@ function DepositFlow({
1840
2861
  sourceChain: chainId,
1841
2862
  sourceToken: token,
1842
2863
  amount,
1843
- directTransfer: isSameRoute(chainId, token, targetChain, targetToken)
2864
+ sourceSymbol,
2865
+ sourceDecimals,
2866
+ directTransfer
1844
2867
  };
1845
2868
  });
1846
2869
  onDepositSubmitted?.({ txHash, sourceChain: chainId, amount });
1847
2870
  },
1848
2871
  [onDepositSubmitted, targetChain, targetToken]
1849
2872
  );
2873
+ const handleSolanaTokenContinue = useCallback3(
2874
+ (token, balance, balanceUsd) => {
2875
+ logFlow("solana:token:continue", { token: token.symbol });
2876
+ setStep((prev) => {
2877
+ if (prev.type !== "solana-token-select") return prev;
2878
+ return {
2879
+ type: "solana-amount",
2880
+ smartAccount: prev.smartAccount,
2881
+ solanaDepositAddress: prev.solanaDepositAddress,
2882
+ token,
2883
+ balance,
2884
+ balanceUsd
2885
+ };
2886
+ });
2887
+ },
2888
+ [logFlow]
2889
+ );
2890
+ const handleSolanaAmountContinue = useCallback3(
2891
+ (token, amount) => {
2892
+ const targetSym = getTokenSymbol(targetToken, targetChain);
2893
+ const isTargetStable = isStablecoinSymbol(targetSym);
2894
+ const targetTokenPriceUsd = isTargetStable ? 1 : getTokenPriceUsd(targetSym);
2895
+ logFlow("solana:amount:continue", {
2896
+ token: token.symbol,
2897
+ amount,
2898
+ targetSymbol: targetSym,
2899
+ targetTokenPriceUsd
2900
+ });
2901
+ setStep((prev) => {
2902
+ if (prev.type !== "solana-amount") return prev;
2903
+ const sourceBalance = Number(
2904
+ formatUnits5(prev.balance, prev.token.decimals)
2905
+ );
2906
+ const sourceTokenPriceUsd = Number.isFinite(sourceBalance) && sourceBalance > 0 && prev.balanceUsd > 0 ? prev.balanceUsd / sourceBalance : null;
2907
+ const parsedAmount = Number(amount);
2908
+ const targetAmount = sourceTokenPriceUsd !== null && Number.isFinite(parsedAmount) && parsedAmount > 0 ? (parsedAmount * sourceTokenPriceUsd).toString() : amount;
2909
+ return {
2910
+ type: "solana-confirm",
2911
+ smartAccount: prev.smartAccount,
2912
+ solanaDepositAddress: prev.solanaDepositAddress,
2913
+ token,
2914
+ amount,
2915
+ targetAmount,
2916
+ targetTokenPriceUsd,
2917
+ balance: prev.balance,
2918
+ balanceUsd: prev.balanceUsd
2919
+ };
2920
+ });
2921
+ },
2922
+ [targetToken, targetChain, getTokenPriceUsd, logFlow]
2923
+ );
2924
+ const handleSolanaConfirmed = useCallback3(
2925
+ (txHash, amountUnits) => {
2926
+ setStep((prev) => {
2927
+ if (prev.type !== "solana-confirm") return prev;
2928
+ logFlow("solana:submitted", {
2929
+ txHash,
2930
+ amountUnits,
2931
+ token: prev.token.symbol
2932
+ });
2933
+ return {
2934
+ type: "processing",
2935
+ smartAccount: prev.smartAccount,
2936
+ txHash,
2937
+ sourceChain: "solana",
2938
+ sourceToken: prev.token.mint,
2939
+ amount: amountUnits,
2940
+ sourceSymbol: prev.token.symbol,
2941
+ sourceDecimals: prev.token.decimals
2942
+ };
2943
+ });
2944
+ onDepositSubmitted?.({
2945
+ txHash,
2946
+ sourceChain: "solana",
2947
+ amount: amountUnits
2948
+ });
2949
+ },
2950
+ [logFlow, onDepositSubmitted]
2951
+ );
1850
2952
  const handleConnected = useCallback3(
1851
2953
  (addr, smartAccount) => {
1852
2954
  onConnected?.({ address: addr, smartAccount });
@@ -1889,6 +2991,12 @@ function DepositFlow({
1889
2991
  );
1890
2992
  const handleDepositSubmitted = useCallback3(
1891
2993
  (txHash, chainId, amount, token) => {
2994
+ logFlow("evm:submitted", {
2995
+ txHash,
2996
+ sourceChain: chainId,
2997
+ sourceToken: token,
2998
+ amount
2999
+ });
1892
3000
  setStep((prev) => {
1893
3001
  if (prev.type !== "confirm") return prev;
1894
3002
  return {
@@ -1912,48 +3020,69 @@ function DepositFlow({
1912
3020
  );
1913
3021
  const handleDepositComplete = useCallback3(
1914
3022
  (txHash, destinationTxHash) => {
3023
+ logFlow("deposit:complete", { txHash, destinationTxHash });
1915
3024
  onDepositComplete?.({ txHash, destinationTxHash });
1916
3025
  },
1917
- [onDepositComplete]
3026
+ [logFlow, onDepositComplete]
1918
3027
  );
1919
3028
  const handleDepositFailed = useCallback3(
1920
3029
  (txHash, error) => {
3030
+ logFlowError("deposit:failed", error, { txHash });
1921
3031
  onDepositFailed?.({ txHash, error });
1922
3032
  },
1923
- [onDepositFailed]
3033
+ [logFlowError, onDepositFailed]
1924
3034
  );
1925
3035
  const handleError = useCallback3(
1926
3036
  (message, code) => {
3037
+ logFlowError("flow:error", message, { code });
1927
3038
  onError?.({ message, code });
1928
3039
  },
1929
- [onError]
3040
+ [logFlowError, onError]
1930
3041
  );
1931
3042
  const handleTotalBalanceComputed = useCallback3((total) => {
1932
3043
  setTotalBalanceUsd(total);
1933
3044
  }, []);
1934
- const selectedConnectAddressEffective = useMemo5(() => {
1935
- if (selectedConnectAddress) return selectedConnectAddress;
3045
+ const selectedWalletIdEffective = useMemo7(() => {
3046
+ if (selectedWalletId) return selectedWalletId;
1936
3047
  if (walletOptions.length === 1) {
1937
- return walletOptions[0].address;
3048
+ return walletOptions[0].id;
1938
3049
  }
1939
3050
  return null;
1940
- }, [selectedConnectAddress, walletOptions]);
1941
- useEffect7(() => {
3051
+ }, [selectedWalletId, walletOptions]);
3052
+ const walletOptionsKey = useMemo7(
3053
+ () => walletOptions.map((option) => option.id).join(","),
3054
+ [walletOptions]
3055
+ );
3056
+ const hasNavigatedBackRef = useRef5(false);
3057
+ useEffect8(() => {
3058
+ setIsConnectSelectionConfirmed(false);
3059
+ setSelectedWalletId(null);
3060
+ setFlowMode(null);
3061
+ if (step.type !== "processing" && step.type !== "confirm" && step.type !== "solana-confirm" && step.type !== "amount" && step.type !== "solana-amount") {
3062
+ setStep({ type: "setup" });
3063
+ }
3064
+ }, [walletOptionsKey]);
3065
+ useEffect8(() => {
1942
3066
  if (!showConnectStep && isConnectSelectionConfirmed && flowMode === "wallet" && !signerContext) {
1943
- setSelectedConnectAddress(null);
3067
+ setSelectedWalletId(null);
1944
3068
  setIsConnectSelectionConfirmed(false);
1945
3069
  setFlowMode(null);
1946
3070
  }
1947
3071
  }, [showConnectStep, isConnectSelectionConfirmed, flowMode, signerContext]);
1948
- useEffect7(() => {
3072
+ useEffect8(() => {
1949
3073
  if (hasNavigatedBackRef.current || isConnectSelectionConfirmed || flowMode) {
1950
3074
  return;
1951
3075
  }
1952
3076
  if (hasWalletOptions) {
1953
- const address = selectedConnectAddressEffective;
1954
- if (address) {
1955
- setSelectedConnectAddress(address);
1956
- handleSelectProvider();
3077
+ const walletId = selectedWalletIdEffective;
3078
+ if (walletId) {
3079
+ const selectedOption = walletOptions.find((o) => o.id === walletId);
3080
+ setSelectedWalletId(walletId);
3081
+ if (selectedOption?.kind === "solana") {
3082
+ handleSelectSolanaWallet();
3083
+ } else {
3084
+ handleSelectProvider();
3085
+ }
1957
3086
  setIsConnectSelectionConfirmed(true);
1958
3087
  return;
1959
3088
  }
@@ -1967,18 +3096,20 @@ function DepositFlow({
1967
3096
  hasReownSession,
1968
3097
  isConnectSelectionConfirmed,
1969
3098
  flowMode,
1970
- selectedConnectAddressEffective,
3099
+ selectedWalletIdEffective,
1971
3100
  dappAddress,
3101
+ walletOptions,
1972
3102
  handleSelectProvider,
3103
+ handleSelectSolanaWallet,
1973
3104
  handleSelectTransferCrypto
1974
3105
  ]);
1975
3106
  if (showConnectStep) {
1976
- return /* @__PURE__ */ jsx7("div", { className: "rs-modal-body", children: /* @__PURE__ */ jsx7(
3107
+ return /* @__PURE__ */ jsx10("div", { className: "rs-modal-body", children: /* @__PURE__ */ jsx10(
1977
3108
  ConnectStep,
1978
3109
  {
1979
3110
  walletOptions,
1980
- selectedAddress: selectedConnectAddressEffective,
1981
- onSelectAddress: setSelectedConnectAddress,
3111
+ selectedWalletId: selectedWalletIdEffective,
3112
+ onSelectWallet: setSelectedWalletId,
1982
3113
  onSelectTransferCrypto: dappAddress ? () => {
1983
3114
  handleSelectTransferCrypto();
1984
3115
  setIsConnectSelectionConfirmed(true);
@@ -1987,10 +3118,17 @@ function DepositFlow({
1987
3118
  onConnect,
1988
3119
  onDisconnect,
1989
3120
  onContinue: () => {
1990
- if (selectedConnectAddressEffective) {
1991
- setSelectedConnectAddress(selectedConnectAddressEffective);
3121
+ if (selectedWalletIdEffective) {
3122
+ setSelectedWalletId(selectedWalletIdEffective);
3123
+ }
3124
+ const selectedOption = walletOptions.find(
3125
+ (o) => o.id === selectedWalletIdEffective
3126
+ );
3127
+ if (selectedOption?.kind === "solana") {
3128
+ handleSelectSolanaWallet();
3129
+ } else {
3130
+ handleSelectProvider();
1992
3131
  }
1993
- handleSelectProvider();
1994
3132
  setIsConnectSelectionConfirmed(true);
1995
3133
  },
1996
3134
  connectButtonLabel
@@ -1999,8 +3137,8 @@ function DepositFlow({
1999
3137
  }
2000
3138
  if (isDepositAddressMode) {
2001
3139
  if (!dappAddress || !sessionKeyAddress) return null;
2002
- return /* @__PURE__ */ jsxs7("div", { className: "rs-modal-body", children: [
2003
- step.type === "setup" && /* @__PURE__ */ jsx7(
3140
+ return /* @__PURE__ */ jsxs10("div", { className: "rs-modal-body", children: [
3141
+ step.type === "setup" && /* @__PURE__ */ jsx10(
2004
3142
  SetupStep,
2005
3143
  {
2006
3144
  address: sessionKeyAddress,
@@ -2016,16 +3154,134 @@ function DepositFlow({
2016
3154
  onError: handleError
2017
3155
  }
2018
3156
  ),
2019
- step.type === "deposit-address" && /* @__PURE__ */ jsx7(
3157
+ step.type === "deposit-address" && /* @__PURE__ */ jsx10(
2020
3158
  DepositAddressStep,
2021
3159
  {
2022
3160
  smartAccount: step.smartAccount,
3161
+ solanaDepositAddress: step.solanaDepositAddress,
2023
3162
  service,
2024
3163
  onDepositDetected: handleDepositAddressDetected,
2025
3164
  onError: handleError
2026
3165
  }
2027
3166
  ),
2028
- step.type === "processing" && /* @__PURE__ */ jsx7(
3167
+ step.type === "processing" && /* @__PURE__ */ jsx10(
3168
+ ProcessingStep,
3169
+ {
3170
+ smartAccount: step.smartAccount,
3171
+ txHash: step.txHash,
3172
+ sourceChain: step.sourceChain,
3173
+ sourceToken: step.sourceToken,
3174
+ targetChain,
3175
+ amount: step.amount,
3176
+ sourceSymbol: step.sourceSymbol,
3177
+ sourceDecimals: step.sourceDecimals,
3178
+ waitForFinalTx,
3179
+ service,
3180
+ directTransfer: step.directTransfer,
3181
+ onClose,
3182
+ onNewDeposit: handleNewDeposit,
3183
+ onDepositComplete: handleDepositComplete,
3184
+ onDepositFailed: handleDepositFailed,
3185
+ onError: handleError,
3186
+ debug
3187
+ }
3188
+ )
3189
+ ] });
3190
+ }
3191
+ if (isSolanaWalletMode) {
3192
+ if (!sessionKeyAddress) return null;
3193
+ const solanaAddr = reownWallet?.solanaAddress;
3194
+ const solanaProvider = reownWallet?.solanaProvider;
3195
+ return /* @__PURE__ */ jsxs10("div", { className: "rs-modal-body", children: [
3196
+ step.type === "setup" && /* @__PURE__ */ jsx10(
3197
+ SetupStep,
3198
+ {
3199
+ address: sessionKeyAddress,
3200
+ targetChain,
3201
+ targetToken,
3202
+ signerAddress,
3203
+ sessionChainIds,
3204
+ recipient,
3205
+ forceRegister,
3206
+ service,
3207
+ onSetupComplete: handleSetupComplete,
3208
+ onConnected: handleConnected,
3209
+ onError: handleError
3210
+ }
3211
+ ),
3212
+ step.type === "solana-token-select" && solanaAddr && /* @__PURE__ */ jsx10(
3213
+ SolanaTokenSelectStep,
3214
+ {
3215
+ solanaAddress: solanaAddr,
3216
+ service,
3217
+ onContinue: handleSolanaTokenContinue,
3218
+ onTotalBalanceComputed: handleTotalBalanceComputed,
3219
+ debug
3220
+ }
3221
+ ),
3222
+ step.type === "solana-amount" && /* @__PURE__ */ jsx10(
3223
+ SolanaAmountStep,
3224
+ {
3225
+ token: step.token,
3226
+ balance: step.balance,
3227
+ balanceUsd: step.balanceUsd,
3228
+ onContinue: handleSolanaAmountContinue,
3229
+ debug
3230
+ }
3231
+ ),
3232
+ step.type === "solana-confirm" && solanaAddr && solanaProvider ? /* @__PURE__ */ jsx10(
3233
+ SolanaConfirmStep,
3234
+ {
3235
+ smartAccount: step.smartAccount,
3236
+ solanaAddress: solanaAddr,
3237
+ solanaDepositAddress: step.solanaDepositAddress,
3238
+ token: step.token,
3239
+ amount: step.amount,
3240
+ targetAmount: step.targetAmount,
3241
+ targetTokenPriceUsd: step.targetTokenPriceUsd,
3242
+ targetChain,
3243
+ targetToken,
3244
+ service,
3245
+ solanaProvider,
3246
+ onConfirm: handleSolanaConfirmed,
3247
+ onError: handleError,
3248
+ debug
3249
+ }
3250
+ ) : step.type === "solana-confirm" ? /* @__PURE__ */ jsxs10("div", { className: "rs-step", children: [
3251
+ /* @__PURE__ */ jsxs10("div", { className: "rs-loading-state", children: [
3252
+ /* @__PURE__ */ jsx10("div", { className: "rs-step-icon rs-step-icon--error", children: /* @__PURE__ */ jsx10(
3253
+ "svg",
3254
+ {
3255
+ viewBox: "0 0 24 24",
3256
+ fill: "none",
3257
+ stroke: "currentColor",
3258
+ strokeWidth: "2",
3259
+ children: /* @__PURE__ */ jsx10(
3260
+ "path",
3261
+ {
3262
+ strokeLinecap: "round",
3263
+ strokeLinejoin: "round",
3264
+ d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
3265
+ }
3266
+ )
3267
+ }
3268
+ ) }),
3269
+ /* @__PURE__ */ jsxs10("div", { className: "rs-loading-text", children: [
3270
+ /* @__PURE__ */ jsx10("div", { className: "rs-loading-title rs-text-error", children: "Wallet disconnected" }),
3271
+ /* @__PURE__ */ jsx10("div", { className: "rs-loading-subtitle", children: "Please reconnect your Solana wallet to continue." })
3272
+ ] })
3273
+ ] }),
3274
+ /* @__PURE__ */ jsx10("div", { className: "rs-step-footer", children: /* @__PURE__ */ jsx10(
3275
+ "button",
3276
+ {
3277
+ type: "button",
3278
+ className: "rs-button rs-button--default rs-button--full-width",
3279
+ onClick: handleBackFromSolanaConfirm,
3280
+ children: /* @__PURE__ */ jsx10("span", { children: "Go Back" })
3281
+ }
3282
+ ) })
3283
+ ] }) : null,
3284
+ step.type === "processing" && /* @__PURE__ */ jsx10(
2029
3285
  ProcessingStep,
2030
3286
  {
2031
3287
  smartAccount: step.smartAccount,
@@ -2034,6 +3290,8 @@ function DepositFlow({
2034
3290
  sourceToken: step.sourceToken,
2035
3291
  targetChain,
2036
3292
  amount: step.amount,
3293
+ sourceSymbol: step.sourceSymbol,
3294
+ sourceDecimals: step.sourceDecimals,
2037
3295
  waitForFinalTx,
2038
3296
  service,
2039
3297
  directTransfer: step.directTransfer,
@@ -2048,7 +3306,7 @@ function DepositFlow({
2048
3306
  ] });
2049
3307
  }
2050
3308
  if (!signerContext?.walletClient || !signerContext?.publicClient) {
2051
- return null;
3309
+ return /* @__PURE__ */ jsx10("div", { className: "rs-modal-body", children: /* @__PURE__ */ jsx10("div", { className: "rs-step", children: /* @__PURE__ */ jsx10("div", { className: "rs-loading-state", children: /* @__PURE__ */ jsx10("div", { className: "rs-loading-text", children: /* @__PURE__ */ jsx10("div", { className: "rs-loading-title", children: "Connecting wallet..." }) }) }) }) });
2052
3310
  }
2053
3311
  const ownerAddress = signerContext.ownerAddress;
2054
3312
  const ownerChainId = signerContext.walletClient?.chain?.id ?? signerContext.publicClient.chain?.id ?? targetChain;
@@ -2058,8 +3316,8 @@ function DepositFlow({
2058
3316
  }
2059
3317
  return getPublicClient(chainId);
2060
3318
  };
2061
- return /* @__PURE__ */ jsxs7("div", { className: "rs-modal-body", children: [
2062
- step.type === "setup" && /* @__PURE__ */ jsx7(
3319
+ return /* @__PURE__ */ jsxs10("div", { className: "rs-modal-body", children: [
3320
+ step.type === "setup" && /* @__PURE__ */ jsx10(
2063
3321
  SetupStep,
2064
3322
  {
2065
3323
  walletClient: signerContext.walletClient,
@@ -2076,7 +3334,7 @@ function DepositFlow({
2076
3334
  onError: handleError
2077
3335
  }
2078
3336
  ),
2079
- step.type === "select-asset" && /* @__PURE__ */ jsx7(
3337
+ step.type === "select-asset" && /* @__PURE__ */ jsx10(
2080
3338
  AssetSelectStep,
2081
3339
  {
2082
3340
  address: ownerAddress,
@@ -2089,7 +3347,7 @@ function DepositFlow({
2089
3347
  onAssetsLoaded: handleAssetsLoaded
2090
3348
  }
2091
3349
  ),
2092
- step.type === "amount" && /* @__PURE__ */ jsx7(
3350
+ step.type === "amount" && /* @__PURE__ */ jsx10(
2093
3351
  AmountStep,
2094
3352
  {
2095
3353
  walletClient: signerContext.walletClient,
@@ -2104,7 +3362,7 @@ function DepositFlow({
2104
3362
  onContinue: handleAmountContinue
2105
3363
  }
2106
3364
  ),
2107
- step.type === "confirm" && /* @__PURE__ */ jsx7(
3365
+ step.type === "confirm" && /* @__PURE__ */ jsx10(
2108
3366
  ConfirmStep,
2109
3367
  {
2110
3368
  walletClient: signerContext.walletClient,
@@ -2124,7 +3382,7 @@ function DepositFlow({
2124
3382
  onError: handleError
2125
3383
  }
2126
3384
  ),
2127
- step.type === "processing" && /* @__PURE__ */ jsx7(
3385
+ step.type === "processing" && /* @__PURE__ */ jsx10(
2128
3386
  ProcessingStep,
2129
3387
  {
2130
3388
  smartAccount: step.smartAccount,
@@ -2133,6 +3391,8 @@ function DepositFlow({
2133
3391
  sourceToken: step.sourceToken,
2134
3392
  targetChain,
2135
3393
  amount: step.amount,
3394
+ sourceSymbol: step.sourceSymbol,
3395
+ sourceDecimals: step.sourceDecimals,
2136
3396
  waitForFinalTx,
2137
3397
  service,
2138
3398
  directTransfer: step.directTransfer,
@@ -2140,23 +3400,24 @@ function DepositFlow({
2140
3400
  onNewDeposit: handleNewDeposit,
2141
3401
  onDepositComplete: handleDepositComplete,
2142
3402
  onDepositFailed: handleDepositFailed,
2143
- onError: handleError
3403
+ onError: handleError,
3404
+ debug
2144
3405
  }
2145
3406
  )
2146
3407
  ] });
2147
3408
  }
2148
3409
 
2149
3410
  // src/DepositModal.tsx
2150
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
3411
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
2151
3412
  var ReownDepositInner = lazy(
2152
- () => import("./DepositModalReown-3HNOCOOO.mjs").then((m) => ({ default: m.DepositModalReown }))
3413
+ () => import("./DepositModalReown-3GPEVG26.mjs").then((m) => ({ default: m.DepositModalReown }))
2153
3414
  );
2154
3415
  function DepositModal(props) {
2155
3416
  const needsReown = !!props.reownAppId;
2156
3417
  if (needsReown) {
2157
- return /* @__PURE__ */ jsx8(Suspense, { fallback: null, children: /* @__PURE__ */ jsx8(ReownDepositInner, { ...props }) });
3418
+ return /* @__PURE__ */ jsx11(Suspense, { fallback: null, children: /* @__PURE__ */ jsx11(ReownDepositInner, { ...props }) });
2158
3419
  }
2159
- return /* @__PURE__ */ jsx8(DepositModalInner, { ...props });
3420
+ return /* @__PURE__ */ jsx11(DepositModalInner, { ...props });
2160
3421
  }
2161
3422
  DepositModal.displayName = "DepositModal";
2162
3423
  function DepositModalInner({
@@ -2173,6 +3434,7 @@ function DepositModalInner({
2173
3434
  defaultAmount,
2174
3435
  recipient,
2175
3436
  backendUrl = DEFAULT_BACKEND_URL,
3437
+ solanaRpcUrl,
2176
3438
  signerAddress = DEFAULT_SIGNER_ADDRESS,
2177
3439
  sessionChainIds,
2178
3440
  forceRegister = false,
@@ -2195,30 +3457,36 @@ function DepositModalInner({
2195
3457
  debug
2196
3458
  }) {
2197
3459
  const modalRef = useRef6(null);
2198
- const [currentStepIndex, setCurrentStepIndex] = useState8(0);
2199
- const [totalBalanceUsd, setTotalBalanceUsd] = useState8(null);
3460
+ const [currentStepIndex, setCurrentStepIndex] = useState11(0);
3461
+ const [totalBalanceUsd, setTotalBalanceUsd] = useState11(null);
2200
3462
  const backHandlerRef = useRef6(void 0);
2201
3463
  const targetChain = getChainId(targetChainProp);
2202
3464
  const sourceChain = sourceChainProp ? getChainId(sourceChainProp) : void 0;
2203
- const service = useMemo6(() => createDepositService(backendUrl), [backendUrl]);
2204
- useEffect8(() => {
3465
+ const service = useMemo8(
3466
+ () => createDepositService(backendUrl, {
3467
+ debug,
3468
+ debugScope: "service:deposit"
3469
+ }),
3470
+ [backendUrl, debug]
3471
+ );
3472
+ useEffect9(() => {
2205
3473
  if (isOpen && modalRef.current) {
2206
3474
  applyTheme(modalRef.current, theme);
2207
3475
  }
2208
3476
  }, [isOpen, theme]);
3477
+ useEffect9(() => {
3478
+ configureSolanaRpcUrl(solanaRpcUrl);
3479
+ }, [solanaRpcUrl]);
2209
3480
  const hasCalledReady = useRef6(false);
2210
- useEffect8(() => {
3481
+ useEffect9(() => {
2211
3482
  if (isOpen && !hasCalledReady.current) {
2212
3483
  hasCalledReady.current = true;
2213
3484
  onReady?.();
2214
3485
  }
2215
3486
  }, [isOpen, onReady]);
2216
- useEffect8(() => {
3487
+ useEffect9(() => {
2217
3488
  if (!isOpen) {
2218
3489
  setCurrentStepIndex(0);
2219
- setTotalBalanceUsd(null);
2220
- backHandlerRef.current = void 0;
2221
- hasCalledReady.current = false;
2222
3490
  }
2223
3491
  }, [isOpen]);
2224
3492
  const handleStepChange = useCallback4(
@@ -2241,30 +3509,30 @@ function DepositModalInner({
2241
3509
  const logoUrl = branding?.logoUrl ?? "https://github.com/rhinestonewtf.png";
2242
3510
  const title = branding?.title ?? "Deposit";
2243
3511
  const canGoBack = currentStepIndex > 0 && currentStepIndex < 4 && backHandlerRef.current !== void 0;
2244
- return /* @__PURE__ */ jsx8(
3512
+ return /* @__PURE__ */ jsx11(
2245
3513
  Modal,
2246
3514
  {
2247
3515
  isOpen,
2248
3516
  onClose,
2249
3517
  className,
2250
3518
  inline,
2251
- children: /* @__PURE__ */ jsxs8("div", { ref: modalRef, className: "rs-modal", children: [
2252
- /* @__PURE__ */ jsxs8("div", { className: "rs-modal-header--redesigned", children: [
2253
- /* @__PURE__ */ jsx8("div", { className: "rs-modal-header-nav-left", children: showBackButton && canGoBack && /* @__PURE__ */ jsx8(
3519
+ children: /* @__PURE__ */ jsxs11("div", { ref: modalRef, className: "rs-modal", children: [
3520
+ /* @__PURE__ */ jsxs11("div", { className: "rs-modal-header--redesigned", children: [
3521
+ /* @__PURE__ */ jsx11("div", { className: "rs-modal-header-nav-left", children: showBackButton && canGoBack && /* @__PURE__ */ jsx11(
2254
3522
  "button",
2255
3523
  {
2256
3524
  type: "button",
2257
3525
  className: "rs-modal-header-back",
2258
3526
  "aria-label": "Go back",
2259
3527
  onClick: handleBack,
2260
- children: /* @__PURE__ */ jsx8(
3528
+ children: /* @__PURE__ */ jsx11(
2261
3529
  "svg",
2262
3530
  {
2263
3531
  viewBox: "0 0 24 24",
2264
3532
  fill: "none",
2265
3533
  stroke: "currentColor",
2266
3534
  strokeWidth: "2",
2267
- children: /* @__PURE__ */ jsx8(
3535
+ children: /* @__PURE__ */ jsx11(
2268
3536
  "path",
2269
3537
  {
2270
3538
  strokeLinecap: "round",
@@ -2276,9 +3544,9 @@ function DepositModalInner({
2276
3544
  )
2277
3545
  }
2278
3546
  ) }),
2279
- /* @__PURE__ */ jsxs8("div", { className: "rs-modal-header-nav-center", children: [
2280
- /* @__PURE__ */ jsxs8("div", { className: "rs-modal-header-title-row", children: [
2281
- showLogo && logoUrl && /* @__PURE__ */ jsx8(
3547
+ /* @__PURE__ */ jsxs11("div", { className: "rs-modal-header-nav-center", children: [
3548
+ /* @__PURE__ */ jsxs11("div", { className: "rs-modal-header-title-row", children: [
3549
+ showLogo && logoUrl && /* @__PURE__ */ jsx11(
2282
3550
  "img",
2283
3551
  {
2284
3552
  src: logoUrl,
@@ -2289,8 +3557,8 @@ function DepositModalInner({
2289
3557
  }
2290
3558
  }
2291
3559
  ),
2292
- /* @__PURE__ */ jsx8("span", { className: "rs-modal-header-title", children: title }),
2293
- showStepper && /* @__PURE__ */ jsx8("div", { className: "rs-modal-progress", style: { marginLeft: 8 }, children: [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx8(
3560
+ /* @__PURE__ */ jsx11("span", { className: "rs-modal-header-title", children: title }),
3561
+ showStepper && /* @__PURE__ */ jsx11("div", { className: "rs-modal-progress", style: { marginLeft: 8 }, children: [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx11(
2294
3562
  "div",
2295
3563
  {
2296
3564
  className: `rs-modal-progress-dot ${i <= currentStepIndex ? "rs-modal-progress-dot--active" : "rs-modal-progress-dot--inactive"}`
@@ -2298,29 +3566,29 @@ function DepositModalInner({
2298
3566
  i
2299
3567
  )) })
2300
3568
  ] }),
2301
- balance && /* @__PURE__ */ jsxs8("div", { className: "rs-modal-header-balance", children: [
2302
- /* @__PURE__ */ jsxs8("span", { children: [
3569
+ balance && /* @__PURE__ */ jsxs11("div", { className: "rs-modal-header-balance", children: [
3570
+ /* @__PURE__ */ jsxs11("span", { children: [
2303
3571
  balance.title,
2304
3572
  ":"
2305
3573
  ] }),
2306
- /* @__PURE__ */ jsx8("span", { className: "rs-modal-header-balance-value", children: balance.amount ?? (totalBalanceUsd !== null ? currencyFormatter.format(totalBalanceUsd) : null) })
3574
+ /* @__PURE__ */ jsx11("span", { className: "rs-modal-header-balance-value", children: balance.amount ?? (totalBalanceUsd !== null ? currencyFormatter.format(totalBalanceUsd) : null) })
2307
3575
  ] })
2308
3576
  ] }),
2309
- /* @__PURE__ */ jsx8("div", { className: "rs-modal-header-nav-right", children: /* @__PURE__ */ jsx8(
3577
+ /* @__PURE__ */ jsx11("div", { className: "rs-modal-header-nav-right", children: /* @__PURE__ */ jsx11(
2310
3578
  "button",
2311
3579
  {
2312
3580
  type: "button",
2313
3581
  onClick: onClose,
2314
3582
  className: "rs-modal-close",
2315
3583
  "aria-label": "Close",
2316
- children: /* @__PURE__ */ jsx8(
3584
+ children: /* @__PURE__ */ jsx11(
2317
3585
  "svg",
2318
3586
  {
2319
3587
  viewBox: "0 0 24 24",
2320
3588
  fill: "none",
2321
3589
  stroke: "currentColor",
2322
3590
  strokeWidth: "2",
2323
- children: /* @__PURE__ */ jsx8(
3591
+ children: /* @__PURE__ */ jsx11(
2324
3592
  "path",
2325
3593
  {
2326
3594
  strokeLinecap: "round",
@@ -2333,7 +3601,7 @@ function DepositModalInner({
2333
3601
  }
2334
3602
  ) })
2335
3603
  ] }),
2336
- /* @__PURE__ */ jsx8(
3604
+ /* @__PURE__ */ jsx11(
2337
3605
  DepositFlow,
2338
3606
  {
2339
3607
  dappWalletClient,