@rhinestone/deposit-modal 0.1.39 → 0.1.41

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