@rash2x/bridge-widget 0.1.6 → 0.1.8

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.
@@ -647,37 +647,40 @@ const Modal = ({
647
647
  }, [isOpen, onClose]);
648
648
  if (typeof document === "undefined") return null;
649
649
  return createPortal(
650
- /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(
650
+ /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxs(
651
651
  motion.div,
652
652
  {
653
- className: "fixed inset-0 border border-border z-[100] bg-dialog sm:absolute sm:inset-0 sm:top-0 sm:bottom-0 sm:w-full sm:rounded-3xl",
653
+ className: "fixed m-auto border border-border max-w-md max-h-[80%] z-[100] bg-dialog sm:absolute sm:inset-0 sm:top-0 sm:bottom-0 sm:w-full rounded-xl",
654
654
  initial: { opacity: 0 },
655
655
  animate: { opacity: 1 },
656
656
  exit: { opacity: 0 },
657
- children: /* @__PURE__ */ jsx(
658
- motion.div,
659
- {
660
- ref: panelRef,
661
- role: "dialog",
662
- "aria-modal": "true",
663
- tabIndex: -1,
664
- className: cn(
665
- "outline-none overflow-auto w-screen h-screen rounded-none sm:w-full sm:h-full sm:rounded-3xl",
666
- className
667
- ),
668
- initial: { opacity: 0, scale: 0.9 },
669
- animate: { opacity: 1, scale: 1 },
670
- exit: { opacity: 0, scale: 0.9 },
671
- transition: {
672
- type: "spring",
673
- stiffness: 480,
674
- damping: 32,
675
- mass: 0.6
676
- },
677
- onMouseDown: (e) => e.stopPropagation(),
678
- children
679
- }
680
- )
657
+ children: [
658
+ /* @__PURE__ */ jsx(
659
+ motion.div,
660
+ {
661
+ ref: panelRef,
662
+ role: "dialog",
663
+ "aria-modal": "true",
664
+ tabIndex: -1,
665
+ className: cn(
666
+ "outline-none overflow-auto relative z-30 w-screen h-screen rounded-none sm:w-full sm:h-full sm:rounded-3xl",
667
+ className
668
+ ),
669
+ initial: { opacity: 0, scale: 0.9 },
670
+ animate: { opacity: 1, scale: 1 },
671
+ exit: { opacity: 0, scale: 0.9 },
672
+ transition: {
673
+ type: "spring",
674
+ stiffness: 480,
675
+ damping: 32,
676
+ mass: 0.6
677
+ },
678
+ onMouseDown: (e) => e.stopPropagation(),
679
+ children
680
+ }
681
+ ),
682
+ /* @__PURE__ */ jsx("div", { className: "fixed inset-0 backdrop-blur-sm bg-background/10 z-10" })
683
+ ]
681
684
  }
682
685
  ) }),
683
686
  container
@@ -1430,7 +1433,7 @@ function sumFeeByTokenLD(fees, dstTokenAddr, dstChainKey) {
1430
1433
  }
1431
1434
  return acc.toString();
1432
1435
  }
1433
- function useBalances(chainKey, address) {
1436
+ function useBalances(chainKey, address, priorityTokenSymbol) {
1434
1437
  const { chainRegistry } = useChainStrategies();
1435
1438
  const { assetMatrix } = useTokensStore();
1436
1439
  const tokensOnChain = useMemo(() => {
@@ -1442,13 +1445,24 @@ function useBalances(chainKey, address) {
1442
1445
  }
1443
1446
  return tokensList;
1444
1447
  }, [assetMatrix, chainKey]);
1448
+ const priorityToken = useMemo(() => {
1449
+ if (!priorityTokenSymbol || !chainKey || !assetMatrix) return void 0;
1450
+ const normalizedSymbol = normalizeTickerSymbol$1(priorityTokenSymbol);
1451
+ const token = assetMatrix[normalizedSymbol]?.[chainKey];
1452
+ return token;
1453
+ }, [priorityTokenSymbol, chainKey, assetMatrix]);
1445
1454
  const query = useQuery({
1446
- queryKey: ["balances", chainKey, address],
1455
+ queryKey: ["balances", chainKey, address, priorityTokenSymbol],
1447
1456
  queryFn: async () => {
1448
1457
  if (!address || !chainKey)
1449
1458
  return {};
1450
1459
  if (!isAddressValidForChain(chainKey, address)) return {};
1451
- return await chainRegistry.getBalances(chainKey, address, tokensOnChain);
1460
+ return await chainRegistry.getBalances(
1461
+ chainKey,
1462
+ address,
1463
+ tokensOnChain,
1464
+ priorityToken
1465
+ );
1452
1466
  },
1453
1467
  enabled: !!address && !!chainKey && tokensOnChain.length > 0 && isAddressValidForChain(chainKey, address),
1454
1468
  staleTime: 6e4,
@@ -1647,7 +1661,7 @@ const VirtualizedTokenList = ({
1647
1661
  getTokenUsdValue,
1648
1662
  onPick
1649
1663
  }) => {
1650
- const Row2 = ({ index, style }) => {
1664
+ const Row = ({ index, style }) => {
1651
1665
  const node = nodes[index];
1652
1666
  if (node.kind === "header") {
1653
1667
  const gap = index === 0 ? 0 : HEADER_TOP_GAP;
@@ -1694,7 +1708,7 @@ const VirtualizedTokenList = ({
1694
1708
  itemSize: getItemSize,
1695
1709
  overscanCount: 8,
1696
1710
  style: { willChange: "transform", paddingBottom: "40px" },
1697
- children: Row2
1711
+ children: Row
1698
1712
  }
1699
1713
  );
1700
1714
  };
@@ -1981,7 +1995,7 @@ function Card({ className, ...props }) {
1981
1995
  {
1982
1996
  "data-slot": "card",
1983
1997
  className: cn(
1984
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
1998
+ "bg-card text-card-foreground flex flex-col gap-4 rounded-xl border py-4 shadow-sm",
1985
1999
  className
1986
2000
  ),
1987
2001
  ...props
@@ -1994,7 +2008,7 @@ function CardHeader({ className, ...props }) {
1994
2008
  {
1995
2009
  "data-slot": "card-header",
1996
2010
  className: cn(
1997
- "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
2011
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-4",
1998
2012
  className
1999
2013
  ),
2000
2014
  ...props
@@ -2029,7 +2043,7 @@ function CardContent({ className, ...props }) {
2029
2043
  "div",
2030
2044
  {
2031
2045
  "data-slot": "card-content",
2032
- className: cn("px-6", className),
2046
+ className: cn("px-4", className),
2033
2047
  ...props
2034
2048
  }
2035
2049
  );
@@ -2039,7 +2053,7 @@ function CardFooter({ className, ...props }) {
2039
2053
  "div",
2040
2054
  {
2041
2055
  "data-slot": "card-footer",
2042
- className: cn("flex items-center px-6 [.border-t]:pt-6", className),
2056
+ className: cn("flex items-center px-4 [.border-t]:pt-4", className),
2043
2057
  ...props
2044
2058
  }
2045
2059
  );
@@ -2413,8 +2427,16 @@ function useSwapModel() {
2413
2427
  const tokensStore = useTokensStore();
2414
2428
  const { srcAddress, dstAddress } = useAddresses();
2415
2429
  const { allowedFromChains, allowedToChains, isLoadingToChains } = useChainDerivations();
2416
- const srcBalances = useBalances(chainsStore.fromChain?.chainKey, srcAddress);
2417
- const dstBalances = useBalances(chainsStore.toChain?.chainKey, dstAddress);
2430
+ const srcBalances = useBalances(
2431
+ chainsStore.fromChain?.chainKey,
2432
+ srcAddress,
2433
+ tokensStore.selectedAssetSymbol
2434
+ );
2435
+ const dstBalances = useBalances(
2436
+ chainsStore.toChain?.chainKey,
2437
+ dstAddress,
2438
+ tokensStore.selectedAssetSymbol
2439
+ );
2418
2440
  const { loading } = useBridgeQuote();
2419
2441
  const { inputAmount, setInputAmount, resetWithIdle } = useBridgeQuoteStore();
2420
2442
  const fromBalance = useMemo(
@@ -2497,10 +2519,10 @@ const SwapButton = () => {
2497
2519
  {
2498
2520
  onClick: handleSwap,
2499
2521
  disabled: !canSwap || isSwapping,
2522
+ variant: "secondary",
2523
+ size: "sm",
2500
2524
  className: cn(
2501
- "has-[>svg]:p-0 h-9 bg-swap rounded-full p-2 max-w-9 w-full",
2502
2525
  "absolute top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2",
2503
- "hover:bg-swap transition-all duration-200 shadow-none select-none",
2504
2526
  !canSwap || isSwapping ? "opacity-50 cursor-not-allowed" : "hover:scale-110"
2505
2527
  ),
2506
2528
  children: /* @__PURE__ */ jsx(
@@ -2509,8 +2531,7 @@ const SwapButton = () => {
2509
2531
  style: {
2510
2532
  transform: `rotate(${turns * 180}deg)`,
2511
2533
  transition: "transform 300ms linear"
2512
- },
2513
- className: "size-5 text-swap-foreground will-change-transform"
2534
+ }
2514
2535
  }
2515
2536
  )
2516
2537
  }
@@ -2541,7 +2562,6 @@ const NetworkSymbol = ({
2541
2562
  };
2542
2563
  const SelectNetworkButton = ({
2543
2564
  onClick,
2544
- className,
2545
2565
  network
2546
2566
  }) => {
2547
2567
  const { t: t2 } = useTranslation();
@@ -2552,7 +2572,8 @@ const SelectNetworkButton = ({
2552
2572
  Button,
2553
2573
  {
2554
2574
  onClick,
2555
- className: `cursor-pointer hover:scale-[1.1] p-1.5 h-8.5 pr-3 !pl-1.5 bg-secondary hover:bg-secondary shadow-none rounded-full flex items-center justify-between gap-3 w-fit shrink-0 ${className ?? ""}`,
2575
+ size: "sm",
2576
+ variant: "secondary",
2556
2577
  type: "button",
2557
2578
  "aria-label": label,
2558
2579
  children: [
@@ -2897,10 +2918,8 @@ const SwapSection = ({
2897
2918
  "div",
2898
2919
  {
2899
2920
  className: cn(
2900
- "p-4 flex flex-col gap-4 transition-colors bg-input",
2901
- {
2902
- "bg-input-focus": isSource && isFocused
2903
- },
2921
+ "p-4 flex flex-col gap-4 transition-colors bg-muted",
2922
+ isSource && isFocused ? "bg-accent" : "",
2904
2923
  className
2905
2924
  ),
2906
2925
  children: [
@@ -2919,8 +2938,7 @@ const SwapSection = ({
2919
2938
  SelectNetworkButton,
2920
2939
  {
2921
2940
  network: chain,
2922
- onClick: disableNetworkSelect ? void 0 : onOpen,
2923
- className: disableNetworkSelect ? "opacity-80 cursor-not-allowed" : ""
2941
+ onClick: disableNetworkSelect ? void 0 : onOpen
2924
2942
  }
2925
2943
  ),
2926
2944
  /* @__PURE__ */ jsx(
@@ -3065,7 +3083,7 @@ const ToggleRow = ({ enabled, onToggle }) => {
3065
3083
  } catch {
3066
3084
  }
3067
3085
  };
3068
- return /* @__PURE__ */ jsxs("div", { className: "p-4 flex flex-col rounded-b-26 gap-2 bg-muted", children: [
3086
+ return /* @__PURE__ */ jsxs("div", { className: "p-4 flex flex-col rounded-b-xl gap-2 bg-muted", children: [
3069
3087
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
3070
3088
  /* @__PURE__ */ jsx("p", { className: "text-sm leading-4.5 font-medium text-muted-foreground", children: t2("bridge.sendToAnotherAddress") }),
3071
3089
  /* @__PURE__ */ jsx(
@@ -3187,15 +3205,6 @@ function AccordionContent({
3187
3205
  }
3188
3206
  );
3189
3207
  }
3190
- function getRouteDisplayName(route) {
3191
- if (!route) return "Stargate Bridge";
3192
- const routeLower = route.toLowerCase();
3193
- if (routeLower.includes("taxi")) return "Stargate V2 Fast";
3194
- if (routeLower.includes("bus")) return "Stargate V2 Economy";
3195
- if (routeLower.includes("oft")) return "OFT Bridge";
3196
- if (routeLower.includes("v2")) return "Stargate V2";
3197
- return route.split(/[\/\-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
3198
- }
3199
3208
  function getQuoteAmounts(quote, srcToken, dstToken) {
3200
3209
  if (!quote || !srcToken || !dstToken) {
3201
3210
  return {
@@ -3288,12 +3297,21 @@ function getQuoteDetails(quote, srcToken, dstToken, tokens, chains, slippageBps)
3288
3297
  fees
3289
3298
  };
3290
3299
  }
3291
- const ReceiveRow = () => {
3300
+ function getRouteDisplayName(route) {
3301
+ if (!route) return "Stargate Bridge";
3302
+ const routeLower = route.toLowerCase();
3303
+ if (routeLower.includes("taxi")) return "Stargate V2 Fast";
3304
+ if (routeLower.includes("bus")) return "Stargate V2 Economy";
3305
+ if (routeLower.includes("oft")) return "OFT Bridge";
3306
+ if (routeLower.includes("v2")) return "Stargate V2";
3307
+ return route.split(/[/\-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
3308
+ }
3309
+ const Details = () => {
3292
3310
  const { t: t2 } = useTranslation();
3293
3311
  const { selectedAssetSymbol, assetMatrix, tokens } = useTokensStore();
3294
3312
  const { toChain, fromChain, chains } = useChainsStore();
3295
3313
  const { quote, status } = useBridgeQuoteStore();
3296
- const { slippageBps, routePriority, gasPreset } = useSettingsStore();
3314
+ const { slippageBps, routePriority } = useSettingsStore();
3297
3315
  const dstToken = resolveTokenOnChainFromMatrix$2(
3298
3316
  assetMatrix,
3299
3317
  selectedAssetSymbol,
@@ -3333,9 +3351,8 @@ const ReceiveRow = () => {
3333
3351
  })();
3334
3352
  const currentSlippageText = formatPercentage(slippageBps);
3335
3353
  const routeText = quote?.route ? getRouteDisplayName(quote.route) : t2(`settings.routePresets.${routePriority}`);
3336
- const hasGasOnDestination = gasPreset !== "none";
3337
- return /* @__PURE__ */ jsx(Accordion, { type: "single", collapsible: true, className: "w-full", children: /* @__PURE__ */ jsxs(AccordionItem, { value: "item-1", className: "bg-muted rounded-20", children: [
3338
- /* @__PURE__ */ jsx(AccordionTrigger, { className: "w-full gap-1 items-center py-6 px-5 rounded-b-16 data-[state=open]:pb-3", children: /* @__PURE__ */ jsxs("div", { className: "w-full flex items-center justify-between", children: [
3354
+ return /* @__PURE__ */ jsx(Accordion, { type: "single", collapsible: true, className: "w-full", children: /* @__PURE__ */ jsxs(AccordionItem, { value: "item-1", className: "bg-muted rounded-xl", children: [
3355
+ /* @__PURE__ */ jsx(AccordionTrigger, { className: "w-full gap-1 items-center py-6 px-5 rounded-b-xl data-[state=open]:pb-3", children: /* @__PURE__ */ jsxs("div", { className: "w-full flex items-center justify-between", children: [
3339
3356
  /* @__PURE__ */ jsx("p", { className: "text-sm font-normal text-priority leading-3.5", children: t2("bridge.youWillReceive", { defaultValue: "You will receive" }) }),
3340
3357
  /* @__PURE__ */ jsxs("div", { className: "bg-transparent hover:bg-transparent shadow-none h-4 p-0 px-0 py-0 flex items-center gap-1.5", children: [
3341
3358
  /* @__PURE__ */ jsx(TokenSymbol, { symbol, className: "w-4 h-4", alt: "token" }),
@@ -3346,65 +3363,56 @@ const ReceiveRow = () => {
3346
3363
  ] })
3347
3364
  ] })
3348
3365
  ] }) }),
3349
- /* @__PURE__ */ jsxs(AccordionContent, { className: "text-balance text-foreground px-5 flex flex-col gap-3", children: [
3366
+ /* @__PURE__ */ jsxs(AccordionContent, { className: "px-5 flex flex-col gap-3", children: [
3350
3367
  /* @__PURE__ */ jsx(
3351
- Row,
3368
+ DetailsRow,
3352
3369
  {
3353
3370
  label: t2("transaction.route"),
3354
- right: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
3371
+ value: /* @__PURE__ */ jsxs("strong", { className: "flex items-center gap-1.5", children: [
3355
3372
  /* @__PURE__ */ jsx(StargateIcon, { className: "size-4" }),
3356
- /* @__PURE__ */ jsx("p", { className: "text-foreground font-normal text-sm leading-[100%]", children: routeText }),
3357
- hasGasOnDestination && /* @__PURE__ */ jsx("span", { className: "text-xs bg-settings-active text-settings-active-foreground px-1.5 py-0.5 rounded", children: t2(`settings.gasPresets.${gasPreset}`) })
3373
+ /* @__PURE__ */ jsx("p", { className: "", children: routeText })
3358
3374
  ] })
3359
3375
  }
3360
3376
  ),
3361
3377
  /* @__PURE__ */ jsx(
3362
- Row,
3378
+ DetailsRow,
3363
3379
  {
3364
3380
  label: t2("transaction.estTime"),
3365
3381
  value: etaText,
3366
3382
  isLoading
3367
3383
  }
3368
3384
  ),
3369
- /* @__PURE__ */ jsx(Row, { label: t2("transaction.slippage"), value: currentSlippageText }),
3370
3385
  /* @__PURE__ */ jsx(
3371
- Row,
3386
+ DetailsRow,
3387
+ {
3388
+ label: t2("transaction.slippage"),
3389
+ value: currentSlippageText
3390
+ }
3391
+ ),
3392
+ /* @__PURE__ */ jsx(
3393
+ DetailsRow,
3372
3394
  {
3373
3395
  label: t2("transaction.totalFee"),
3374
- value: totalFeeDisplay,
3375
- isLoading,
3376
- className: "font-semibold",
3377
- token: /* @__PURE__ */ jsx(TokenSymbol, { symbol, className: "w-4 h-4", alt: "token" })
3396
+ value: /* @__PURE__ */ jsxs("strong", { className: "inline-flex items-center gap-1", children: [
3397
+ /* @__PURE__ */ jsx("span", { children: totalFeeDisplay }),
3398
+ /* @__PURE__ */ jsx(TokenSymbol, { symbol, className: "w-4 h-4", alt: "token" })
3399
+ ] }),
3400
+ isLoading
3378
3401
  }
3379
3402
  )
3380
3403
  ] })
3381
3404
  ] }) });
3382
3405
  };
3383
- const Row = ({
3406
+ const DetailsRow = ({
3384
3407
  label,
3385
3408
  value,
3386
- right,
3387
- className,
3388
- isLoading = false,
3389
- token
3409
+ isLoading = false
3390
3410
  }) => /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
3391
3411
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
3392
- /* @__PURE__ */ jsx("p", { className: "text-sm text-priority font-normal font-display", children: label }),
3412
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-priority font-normal", children: label }),
3393
3413
  /* @__PURE__ */ jsx(Tip, { text: label, children: /* @__PURE__ */ jsx(TipIcon, { className: "size-4 text-receive-icon" }) })
3394
3414
  ] }),
3395
- right ?? (isLoading ? /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-16 rounded-md" }) : /* @__PURE__ */ jsxs("div", { className: "flex gap-1 items-center", children: [
3396
- /* @__PURE__ */ jsx(
3397
- "p",
3398
- {
3399
- className: cn(
3400
- "text-foreground text-sm font-display leading-[100%]",
3401
- className
3402
- ),
3403
- children: value ?? "—"
3404
- }
3405
- ),
3406
- token
3407
- ] }))
3415
+ isLoading ? /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-16 rounded-md" }) : /* @__PURE__ */ jsx("div", { className: "text-foreground text-sm", children: value ?? "—" })
3408
3416
  ] });
3409
3417
  const useTransactionStore = create$1((set, get) => ({
3410
3418
  current: void 0,
@@ -4040,7 +4048,7 @@ const SubmitButton = () => {
4040
4048
  }
4041
4049
  };
4042
4050
  const disabled = isBusy || amountNum <= 0 || status === "loading" || isBalanceLoading || hasInsufficientBalance || hasAmountTooLarge || !gas.hasEnoughGas || noRoute || !isValidForTransfer;
4043
- return /* @__PURE__ */ jsx(Button, { onClick: handleClick, disabled, className: "w-full", children: label });
4051
+ return /* @__PURE__ */ jsx(Button, { onClick: handleClick, disabled, className: "w-full mt-4", children: label });
4044
4052
  };
4045
4053
  function short(addr) {
4046
4054
  return addr.slice(0, 4) + "…" + addr.slice(-4);
@@ -6247,10 +6255,10 @@ class ChainStrategyRegistry {
6247
6255
  const strategy = this.getStrategy(chainKey);
6248
6256
  return strategy?.isConnected() || false;
6249
6257
  }
6250
- async getBalances(chainKey, address, tokens) {
6258
+ async getBalances(chainKey, address, tokens, priorityToken) {
6251
6259
  const strategy = this.getStrategy(chainKey);
6252
6260
  if (!strategy) return {};
6253
- return await strategy.getBalances(address, tokens);
6261
+ return await strategy.getBalances(address, tokens, priorityToken);
6254
6262
  }
6255
6263
  isAddressValid(chainKey, address) {
6256
6264
  const strategy = this.getStrategy(chainKey);
@@ -6361,13 +6369,14 @@ function parseTonAddress(address) {
6361
6369
  }
6362
6370
  return Address$1.parse(address);
6363
6371
  }
6364
- async function getEvmBalances(publicClient, address, tokens) {
6372
+ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
6365
6373
  const balances = {};
6366
6374
  try {
6367
6375
  console.log("start getEvmBalances");
6368
6376
  console.log("publicClient:", publicClient);
6369
6377
  console.log("isAddress:", isAddress(address));
6370
6378
  console.log("tokens:", tokens);
6379
+ console.log("priorityToken:", priorityToken);
6371
6380
  if (!address || !isAddress(address)) {
6372
6381
  console.warn(`Invalid EVM address provided: ${address}`);
6373
6382
  return balances;
@@ -6375,25 +6384,93 @@ async function getEvmBalances(publicClient, address, tokens) {
6375
6384
  if (!publicClient) {
6376
6385
  throw new Error("No public client provided");
6377
6386
  }
6378
- for (const token of tokens) {
6387
+ const nativeTokens = tokens.filter((t2) => isNativeAddress(t2.address));
6388
+ const erc20Tokens = tokens.filter((t2) => !isNativeAddress(t2.address) && isAddress(t2.address));
6389
+ if (priorityToken) {
6379
6390
  try {
6380
- let balance = 0;
6381
- const isNative = isNativeAddress(token.address);
6382
- if (isNative) {
6391
+ const isPriorityNative = isNativeAddress(priorityToken.address);
6392
+ if (isPriorityNative) {
6383
6393
  const ethBalance = await publicClient.getBalance({
6384
6394
  address
6385
6395
  });
6386
- balance = parseFloat(formatUnits(ethBalance, token.decimals));
6387
- } else {
6388
- if (!isAddress(token.address)) {
6389
- continue;
6396
+ const balance = parseFloat(formatUnits(ethBalance, priorityToken.decimals));
6397
+ if (balance > 0) {
6398
+ balances[priorityToken.symbol] = { balance, address };
6390
6399
  }
6391
- const bytecode = await publicClient.getBytecode({
6392
- address: token.address
6400
+ } else if (isAddress(priorityToken.address)) {
6401
+ const tokenBalance = await publicClient.readContract({
6402
+ address: priorityToken.address,
6403
+ abi: [
6404
+ {
6405
+ name: "balanceOf",
6406
+ type: "function",
6407
+ stateMutability: "view",
6408
+ inputs: [{ name: "owner", type: "address" }],
6409
+ outputs: [{ name: "balance", type: "uint256" }]
6410
+ }
6411
+ ],
6412
+ functionName: "balanceOf",
6413
+ args: [address]
6393
6414
  });
6394
- if (!bytecode || bytecode === "0x") {
6395
- continue;
6415
+ const balance = parseFloat(formatUnits(tokenBalance, priorityToken.decimals));
6416
+ if (balance > 0) {
6417
+ balances[priorityToken.symbol] = { balance, address };
6396
6418
  }
6419
+ }
6420
+ } catch (error) {
6421
+ console.debug(`Failed to get priority token balance for ${priorityToken.symbol}:`, error);
6422
+ }
6423
+ }
6424
+ for (const token of nativeTokens) {
6425
+ try {
6426
+ const ethBalance = await publicClient.getBalance({
6427
+ address
6428
+ });
6429
+ const balance = parseFloat(formatUnits(ethBalance, token.decimals));
6430
+ if (balance > 0) {
6431
+ balances[token.symbol] = { balance, address };
6432
+ }
6433
+ } catch (error) {
6434
+ console.debug(`Failed to get native balance for ${token.symbol}:`, error);
6435
+ }
6436
+ }
6437
+ if (erc20Tokens.length > 0) {
6438
+ try {
6439
+ const multicallContracts = erc20Tokens.map((token) => ({
6440
+ address: token.address,
6441
+ abi: [
6442
+ {
6443
+ name: "balanceOf",
6444
+ type: "function",
6445
+ stateMutability: "view",
6446
+ inputs: [{ name: "owner", type: "address" }],
6447
+ outputs: [{ name: "balance", type: "uint256" }]
6448
+ }
6449
+ ],
6450
+ functionName: "balanceOf",
6451
+ args: [address]
6452
+ }));
6453
+ const results = await publicClient.multicall({
6454
+ contracts: multicallContracts,
6455
+ allowFailure: true
6456
+ });
6457
+ results.forEach((result, index) => {
6458
+ const token = erc20Tokens[index];
6459
+ if (!token) return;
6460
+ if (result.status === "success" && result.result !== void 0) {
6461
+ try {
6462
+ const balance = parseFloat(formatUnits(result.result, token.decimals));
6463
+ if (balance > 0) {
6464
+ balances[token.symbol] = { balance, address };
6465
+ }
6466
+ } catch (error) {
6467
+ console.debug(`Failed to parse balance for ${token.symbol}:`, error);
6468
+ }
6469
+ }
6470
+ });
6471
+ } catch (error) {
6472
+ console.warn("Multicall failed, falling back to individual calls:", error);
6473
+ for (const token of erc20Tokens) {
6397
6474
  try {
6398
6475
  const tokenBalance = await publicClient.readContract({
6399
6476
  address: token.address,
@@ -6409,23 +6486,16 @@ async function getEvmBalances(publicClient, address, tokens) {
6409
6486
  functionName: "balanceOf",
6410
6487
  args: [address]
6411
6488
  });
6412
- balance = parseFloat(
6489
+ const balance = parseFloat(
6413
6490
  formatUnits(tokenBalance, token.decimals)
6414
6491
  );
6415
- } catch {
6416
- continue;
6492
+ if (balance > 0) {
6493
+ balances[token.symbol] = { balance, address };
6494
+ }
6495
+ } catch (error2) {
6496
+ console.debug(`Failed to get balance for ${token.symbol}:`, error2);
6417
6497
  }
6418
6498
  }
6419
- if (balance > 0) {
6420
- balances[token.symbol] = { balance, address };
6421
- }
6422
- } catch (error) {
6423
- if (error instanceof Error && !error.message.includes("could not decode")) {
6424
- console.warn(
6425
- `Network error fetching balance for ${token.symbol}:`,
6426
- error
6427
- );
6428
- }
6429
6499
  }
6430
6500
  }
6431
6501
  } catch (error) {
@@ -6487,7 +6557,11 @@ async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
6487
6557
  }
6488
6558
  }
6489
6559
  } catch (error) {
6490
- console.debug(`Failed to get balance for ${token.symbol}:`, error);
6560
+ const errorMessage = error instanceof Error ? error.message : String(error);
6561
+ const isNoWalletError = errorMessage.includes("exit_code: -13") || errorMessage.includes("exit_code:-13") || errorMessage.includes("exitCode: -13");
6562
+ if (!isNoWalletError) {
6563
+ console.debug(`Failed to get balance for ${token.symbol}:`, error);
6564
+ }
6491
6565
  }
6492
6566
  }
6493
6567
  } catch (error) {
@@ -6588,12 +6662,12 @@ class EvmChainStrategy {
6588
6662
  getConnectLabel(t2) {
6589
6663
  return t2("wallets.connectEvmWallet");
6590
6664
  }
6591
- async getBalances(address, tokens) {
6665
+ async getBalances(address, tokens, priorityToken) {
6592
6666
  if (!this.publicClient) {
6593
6667
  console.warn("No publicClient available for balance query");
6594
6668
  return {};
6595
6669
  }
6596
- return await getEvmBalances(this.publicClient, address, tokens);
6670
+ return await getEvmBalances(this.publicClient, address, tokens, priorityToken);
6597
6671
  }
6598
6672
  isAddressValid(address) {
6599
6673
  if (!address) return false;
@@ -7997,7 +8071,7 @@ const EvaaBridgeContent = ({
7997
8071
  /* @__PURE__ */ jsx(
7998
8072
  SwapSection,
7999
8073
  {
8000
- className: "rounded-t-16",
8074
+ className: "rounded-t-xl",
8001
8075
  label: t2("bridge.sourceNetwork"),
8002
8076
  balance: fromBalance,
8003
8077
  chain: fromChain,
@@ -8032,7 +8106,7 @@ const EvaaBridgeContent = ({
8032
8106
  ),
8033
8107
  /* @__PURE__ */ jsx(SubmitButton, {})
8034
8108
  ] }),
8035
- /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(ReceiveRow, {}) })
8109
+ /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(Details, {}) })
8036
8110
  ]
8037
8111
  }
8038
8112
  ),