@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.
@@ -689,37 +689,40 @@ const Modal = ({
689
689
  }, [isOpen, onClose]);
690
690
  if (typeof document === "undefined") return null;
691
691
  return reactDom.createPortal(
692
- /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxRuntime.jsx(
692
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isOpen && /* @__PURE__ */ jsxRuntime.jsxs(
693
693
  framerMotion.motion.div,
694
694
  {
695
- 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",
695
+ 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",
696
696
  initial: { opacity: 0 },
697
697
  animate: { opacity: 1 },
698
698
  exit: { opacity: 0 },
699
- children: /* @__PURE__ */ jsxRuntime.jsx(
700
- framerMotion.motion.div,
701
- {
702
- ref: panelRef,
703
- role: "dialog",
704
- "aria-modal": "true",
705
- tabIndex: -1,
706
- className: cn(
707
- "outline-none overflow-auto w-screen h-screen rounded-none sm:w-full sm:h-full sm:rounded-3xl",
708
- className
709
- ),
710
- initial: { opacity: 0, scale: 0.9 },
711
- animate: { opacity: 1, scale: 1 },
712
- exit: { opacity: 0, scale: 0.9 },
713
- transition: {
714
- type: "spring",
715
- stiffness: 480,
716
- damping: 32,
717
- mass: 0.6
718
- },
719
- onMouseDown: (e) => e.stopPropagation(),
720
- children
721
- }
722
- )
699
+ children: [
700
+ /* @__PURE__ */ jsxRuntime.jsx(
701
+ framerMotion.motion.div,
702
+ {
703
+ ref: panelRef,
704
+ role: "dialog",
705
+ "aria-modal": "true",
706
+ tabIndex: -1,
707
+ className: cn(
708
+ "outline-none overflow-auto relative z-30 w-screen h-screen rounded-none sm:w-full sm:h-full sm:rounded-3xl",
709
+ className
710
+ ),
711
+ initial: { opacity: 0, scale: 0.9 },
712
+ animate: { opacity: 1, scale: 1 },
713
+ exit: { opacity: 0, scale: 0.9 },
714
+ transition: {
715
+ type: "spring",
716
+ stiffness: 480,
717
+ damping: 32,
718
+ mass: 0.6
719
+ },
720
+ onMouseDown: (e) => e.stopPropagation(),
721
+ children
722
+ }
723
+ ),
724
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 backdrop-blur-sm bg-background/10 z-10" })
725
+ ]
723
726
  }
724
727
  ) }),
725
728
  container
@@ -1472,7 +1475,7 @@ function sumFeeByTokenLD(fees, dstTokenAddr, dstChainKey) {
1472
1475
  }
1473
1476
  return acc.toString();
1474
1477
  }
1475
- function useBalances(chainKey, address) {
1478
+ function useBalances(chainKey, address, priorityTokenSymbol) {
1476
1479
  const { chainRegistry } = useChainStrategies();
1477
1480
  const { assetMatrix } = useTokensStore();
1478
1481
  const tokensOnChain = require$$0.useMemo(() => {
@@ -1484,13 +1487,24 @@ function useBalances(chainKey, address) {
1484
1487
  }
1485
1488
  return tokensList;
1486
1489
  }, [assetMatrix, chainKey]);
1490
+ const priorityToken = require$$0.useMemo(() => {
1491
+ if (!priorityTokenSymbol || !chainKey || !assetMatrix) return void 0;
1492
+ const normalizedSymbol = normalizeTickerSymbol$1(priorityTokenSymbol);
1493
+ const token = assetMatrix[normalizedSymbol]?.[chainKey];
1494
+ return token;
1495
+ }, [priorityTokenSymbol, chainKey, assetMatrix]);
1487
1496
  const query = reactQuery.useQuery({
1488
- queryKey: ["balances", chainKey, address],
1497
+ queryKey: ["balances", chainKey, address, priorityTokenSymbol],
1489
1498
  queryFn: async () => {
1490
1499
  if (!address || !chainKey)
1491
1500
  return {};
1492
1501
  if (!isAddressValidForChain(chainKey, address)) return {};
1493
- return await chainRegistry.getBalances(chainKey, address, tokensOnChain);
1502
+ return await chainRegistry.getBalances(
1503
+ chainKey,
1504
+ address,
1505
+ tokensOnChain,
1506
+ priorityToken
1507
+ );
1494
1508
  },
1495
1509
  enabled: !!address && !!chainKey && tokensOnChain.length > 0 && isAddressValidForChain(chainKey, address),
1496
1510
  staleTime: 6e4,
@@ -1689,7 +1703,7 @@ const VirtualizedTokenList = ({
1689
1703
  getTokenUsdValue,
1690
1704
  onPick
1691
1705
  }) => {
1692
- const Row2 = ({ index, style }) => {
1706
+ const Row = ({ index, style }) => {
1693
1707
  const node = nodes[index];
1694
1708
  if (node.kind === "header") {
1695
1709
  const gap = index === 0 ? 0 : HEADER_TOP_GAP;
@@ -1736,7 +1750,7 @@ const VirtualizedTokenList = ({
1736
1750
  itemSize: getItemSize,
1737
1751
  overscanCount: 8,
1738
1752
  style: { willChange: "transform", paddingBottom: "40px" },
1739
- children: Row2
1753
+ children: Row
1740
1754
  }
1741
1755
  );
1742
1756
  };
@@ -2023,7 +2037,7 @@ function Card({ className, ...props }) {
2023
2037
  {
2024
2038
  "data-slot": "card",
2025
2039
  className: cn(
2026
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
2040
+ "bg-card text-card-foreground flex flex-col gap-4 rounded-xl border py-4 shadow-sm",
2027
2041
  className
2028
2042
  ),
2029
2043
  ...props
@@ -2036,7 +2050,7 @@ function CardHeader({ className, ...props }) {
2036
2050
  {
2037
2051
  "data-slot": "card-header",
2038
2052
  className: cn(
2039
- "@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",
2053
+ "@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",
2040
2054
  className
2041
2055
  ),
2042
2056
  ...props
@@ -2071,7 +2085,7 @@ function CardContent({ className, ...props }) {
2071
2085
  "div",
2072
2086
  {
2073
2087
  "data-slot": "card-content",
2074
- className: cn("px-6", className),
2088
+ className: cn("px-4", className),
2075
2089
  ...props
2076
2090
  }
2077
2091
  );
@@ -2081,7 +2095,7 @@ function CardFooter({ className, ...props }) {
2081
2095
  "div",
2082
2096
  {
2083
2097
  "data-slot": "card-footer",
2084
- className: cn("flex items-center px-6 [.border-t]:pt-6", className),
2098
+ className: cn("flex items-center px-4 [.border-t]:pt-4", className),
2085
2099
  ...props
2086
2100
  }
2087
2101
  );
@@ -2455,8 +2469,16 @@ function useSwapModel() {
2455
2469
  const tokensStore = useTokensStore();
2456
2470
  const { srcAddress, dstAddress } = useAddresses();
2457
2471
  const { allowedFromChains, allowedToChains, isLoadingToChains } = useChainDerivations();
2458
- const srcBalances = useBalances(chainsStore.fromChain?.chainKey, srcAddress);
2459
- const dstBalances = useBalances(chainsStore.toChain?.chainKey, dstAddress);
2472
+ const srcBalances = useBalances(
2473
+ chainsStore.fromChain?.chainKey,
2474
+ srcAddress,
2475
+ tokensStore.selectedAssetSymbol
2476
+ );
2477
+ const dstBalances = useBalances(
2478
+ chainsStore.toChain?.chainKey,
2479
+ dstAddress,
2480
+ tokensStore.selectedAssetSymbol
2481
+ );
2460
2482
  const { loading } = useBridgeQuote();
2461
2483
  const { inputAmount, setInputAmount, resetWithIdle } = useBridgeQuoteStore();
2462
2484
  const fromBalance = require$$0.useMemo(
@@ -2539,10 +2561,10 @@ const SwapButton = () => {
2539
2561
  {
2540
2562
  onClick: handleSwap,
2541
2563
  disabled: !canSwap || isSwapping,
2564
+ variant: "secondary",
2565
+ size: "sm",
2542
2566
  className: cn(
2543
- "has-[>svg]:p-0 h-9 bg-swap rounded-full p-2 max-w-9 w-full",
2544
2567
  "absolute top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2",
2545
- "hover:bg-swap transition-all duration-200 shadow-none select-none",
2546
2568
  !canSwap || isSwapping ? "opacity-50 cursor-not-allowed" : "hover:scale-110"
2547
2569
  ),
2548
2570
  children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2551,8 +2573,7 @@ const SwapButton = () => {
2551
2573
  style: {
2552
2574
  transform: `rotate(${turns * 180}deg)`,
2553
2575
  transition: "transform 300ms linear"
2554
- },
2555
- className: "size-5 text-swap-foreground will-change-transform"
2576
+ }
2556
2577
  }
2557
2578
  )
2558
2579
  }
@@ -2583,7 +2604,6 @@ const NetworkSymbol = ({
2583
2604
  };
2584
2605
  const SelectNetworkButton = ({
2585
2606
  onClick,
2586
- className,
2587
2607
  network
2588
2608
  }) => {
2589
2609
  const { t } = reactI18next.useTranslation();
@@ -2594,7 +2614,8 @@ const SelectNetworkButton = ({
2594
2614
  Button,
2595
2615
  {
2596
2616
  onClick,
2597
- 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 ?? ""}`,
2617
+ size: "sm",
2618
+ variant: "secondary",
2598
2619
  type: "button",
2599
2620
  "aria-label": label,
2600
2621
  children: [
@@ -2939,10 +2960,8 @@ const SwapSection = ({
2939
2960
  "div",
2940
2961
  {
2941
2962
  className: cn(
2942
- "p-4 flex flex-col gap-4 transition-colors bg-input",
2943
- {
2944
- "bg-input-focus": isSource && isFocused
2945
- },
2963
+ "p-4 flex flex-col gap-4 transition-colors bg-muted",
2964
+ isSource && isFocused ? "bg-accent" : "",
2946
2965
  className
2947
2966
  ),
2948
2967
  children: [
@@ -2961,8 +2980,7 @@ const SwapSection = ({
2961
2980
  SelectNetworkButton,
2962
2981
  {
2963
2982
  network: chain,
2964
- onClick: disableNetworkSelect ? void 0 : onOpen,
2965
- className: disableNetworkSelect ? "opacity-80 cursor-not-allowed" : ""
2983
+ onClick: disableNetworkSelect ? void 0 : onOpen
2966
2984
  }
2967
2985
  ),
2968
2986
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -3107,7 +3125,7 @@ const ToggleRow = ({ enabled, onToggle }) => {
3107
3125
  } catch {
3108
3126
  }
3109
3127
  };
3110
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 flex flex-col rounded-b-26 gap-2 bg-muted", children: [
3128
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 flex flex-col rounded-b-xl gap-2 bg-muted", children: [
3111
3129
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
3112
3130
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm leading-4.5 font-medium text-muted-foreground", children: t("bridge.sendToAnotherAddress") }),
3113
3131
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -3229,15 +3247,6 @@ function AccordionContent({
3229
3247
  }
3230
3248
  );
3231
3249
  }
3232
- function getRouteDisplayName(route) {
3233
- if (!route) return "Stargate Bridge";
3234
- const routeLower = route.toLowerCase();
3235
- if (routeLower.includes("taxi")) return "Stargate V2 Fast";
3236
- if (routeLower.includes("bus")) return "Stargate V2 Economy";
3237
- if (routeLower.includes("oft")) return "OFT Bridge";
3238
- if (routeLower.includes("v2")) return "Stargate V2";
3239
- return route.split(/[\/\-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
3240
- }
3241
3250
  function getQuoteAmounts(quote, srcToken, dstToken) {
3242
3251
  if (!quote || !srcToken || !dstToken) {
3243
3252
  return {
@@ -3330,12 +3339,21 @@ function getQuoteDetails(quote, srcToken, dstToken, tokens, chains, slippageBps)
3330
3339
  fees
3331
3340
  };
3332
3341
  }
3333
- const ReceiveRow = () => {
3342
+ function getRouteDisplayName(route) {
3343
+ if (!route) return "Stargate Bridge";
3344
+ const routeLower = route.toLowerCase();
3345
+ if (routeLower.includes("taxi")) return "Stargate V2 Fast";
3346
+ if (routeLower.includes("bus")) return "Stargate V2 Economy";
3347
+ if (routeLower.includes("oft")) return "OFT Bridge";
3348
+ if (routeLower.includes("v2")) return "Stargate V2";
3349
+ return route.split(/[/\-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
3350
+ }
3351
+ const Details = () => {
3334
3352
  const { t } = reactI18next.useTranslation();
3335
3353
  const { selectedAssetSymbol, assetMatrix, tokens } = useTokensStore();
3336
3354
  const { toChain, fromChain, chains } = useChainsStore();
3337
3355
  const { quote, status } = useBridgeQuoteStore();
3338
- const { slippageBps, routePriority, gasPreset } = useSettingsStore();
3356
+ const { slippageBps, routePriority } = useSettingsStore();
3339
3357
  const dstToken = resolveTokenOnChainFromMatrix$2(
3340
3358
  assetMatrix,
3341
3359
  selectedAssetSymbol,
@@ -3375,9 +3393,8 @@ const ReceiveRow = () => {
3375
3393
  })();
3376
3394
  const currentSlippageText = formatPercentage(slippageBps);
3377
3395
  const routeText = quote?.route ? getRouteDisplayName(quote.route) : t(`settings.routePresets.${routePriority}`);
3378
- const hasGasOnDestination = gasPreset !== "none";
3379
- return /* @__PURE__ */ jsxRuntime.jsx(Accordion, { type: "single", collapsible: true, className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsxs(AccordionItem, { value: "item-1", className: "bg-muted rounded-20", children: [
3380
- /* @__PURE__ */ jsxRuntime.jsx(AccordionTrigger, { className: "w-full gap-1 items-center py-6 px-5 rounded-b-16 data-[state=open]:pb-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full flex items-center justify-between", children: [
3396
+ return /* @__PURE__ */ jsxRuntime.jsx(Accordion, { type: "single", collapsible: true, className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsxs(AccordionItem, { value: "item-1", className: "bg-muted rounded-xl", children: [
3397
+ /* @__PURE__ */ jsxRuntime.jsx(AccordionTrigger, { className: "w-full gap-1 items-center py-6 px-5 rounded-b-xl data-[state=open]:pb-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full flex items-center justify-between", children: [
3381
3398
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-normal text-priority leading-3.5", children: t("bridge.youWillReceive", { defaultValue: "You will receive" }) }),
3382
3399
  /* @__PURE__ */ jsxRuntime.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: [
3383
3400
  /* @__PURE__ */ jsxRuntime.jsx(TokenSymbol, { symbol, className: "w-4 h-4", alt: "token" }),
@@ -3388,65 +3405,56 @@ const ReceiveRow = () => {
3388
3405
  ] })
3389
3406
  ] })
3390
3407
  ] }) }),
3391
- /* @__PURE__ */ jsxRuntime.jsxs(AccordionContent, { className: "text-balance text-foreground px-5 flex flex-col gap-3", children: [
3408
+ /* @__PURE__ */ jsxRuntime.jsxs(AccordionContent, { className: "px-5 flex flex-col gap-3", children: [
3392
3409
  /* @__PURE__ */ jsxRuntime.jsx(
3393
- Row,
3410
+ DetailsRow,
3394
3411
  {
3395
3412
  label: t("transaction.route"),
3396
- right: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
3413
+ value: /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "flex items-center gap-1.5", children: [
3397
3414
  /* @__PURE__ */ jsxRuntime.jsx(StargateIcon, { className: "size-4" }),
3398
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground font-normal text-sm leading-[100%]", children: routeText }),
3399
- hasGasOnDestination && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs bg-settings-active text-settings-active-foreground px-1.5 py-0.5 rounded", children: t(`settings.gasPresets.${gasPreset}`) })
3415
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "", children: routeText })
3400
3416
  ] })
3401
3417
  }
3402
3418
  ),
3403
3419
  /* @__PURE__ */ jsxRuntime.jsx(
3404
- Row,
3420
+ DetailsRow,
3405
3421
  {
3406
3422
  label: t("transaction.estTime"),
3407
3423
  value: etaText,
3408
3424
  isLoading
3409
3425
  }
3410
3426
  ),
3411
- /* @__PURE__ */ jsxRuntime.jsx(Row, { label: t("transaction.slippage"), value: currentSlippageText }),
3412
3427
  /* @__PURE__ */ jsxRuntime.jsx(
3413
- Row,
3428
+ DetailsRow,
3429
+ {
3430
+ label: t("transaction.slippage"),
3431
+ value: currentSlippageText
3432
+ }
3433
+ ),
3434
+ /* @__PURE__ */ jsxRuntime.jsx(
3435
+ DetailsRow,
3414
3436
  {
3415
3437
  label: t("transaction.totalFee"),
3416
- value: totalFeeDisplay,
3417
- isLoading,
3418
- className: "font-semibold",
3419
- token: /* @__PURE__ */ jsxRuntime.jsx(TokenSymbol, { symbol, className: "w-4 h-4", alt: "token" })
3438
+ value: /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "inline-flex items-center gap-1", children: [
3439
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: totalFeeDisplay }),
3440
+ /* @__PURE__ */ jsxRuntime.jsx(TokenSymbol, { symbol, className: "w-4 h-4", alt: "token" })
3441
+ ] }),
3442
+ isLoading
3420
3443
  }
3421
3444
  )
3422
3445
  ] })
3423
3446
  ] }) });
3424
3447
  };
3425
- const Row = ({
3448
+ const DetailsRow = ({
3426
3449
  label,
3427
3450
  value,
3428
- right,
3429
- className,
3430
- isLoading = false,
3431
- token
3451
+ isLoading = false
3432
3452
  }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
3433
3453
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
3434
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-priority font-normal font-display", children: label }),
3454
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-priority font-normal", children: label }),
3435
3455
  /* @__PURE__ */ jsxRuntime.jsx(Tip, { text: label, children: /* @__PURE__ */ jsxRuntime.jsx(TipIcon, { className: "size-4 text-receive-icon" }) })
3436
3456
  ] }),
3437
- right ?? (isLoading ? /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-4 w-16 rounded-md" }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1 items-center", children: [
3438
- /* @__PURE__ */ jsxRuntime.jsx(
3439
- "p",
3440
- {
3441
- className: cn(
3442
- "text-foreground text-sm font-display leading-[100%]",
3443
- className
3444
- ),
3445
- children: value ?? "—"
3446
- }
3447
- ),
3448
- token
3449
- ] }))
3457
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-4 w-16 rounded-md" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-foreground text-sm", children: value ?? "—" })
3450
3458
  ] });
3451
3459
  const useTransactionStore = zustand.create((set, get) => ({
3452
3460
  current: void 0,
@@ -4082,7 +4090,7 @@ const SubmitButton = () => {
4082
4090
  }
4083
4091
  };
4084
4092
  const disabled = isBusy || amountNum <= 0 || status === "loading" || isBalanceLoading || hasInsufficientBalance || hasAmountTooLarge || !gas.hasEnoughGas || noRoute || !isValidForTransfer;
4085
- return /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleClick, disabled, className: "w-full", children: label });
4093
+ return /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleClick, disabled, className: "w-full mt-4", children: label });
4086
4094
  };
4087
4095
  function short(addr) {
4088
4096
  return addr.slice(0, 4) + "…" + addr.slice(-4);
@@ -6289,10 +6297,10 @@ class ChainStrategyRegistry {
6289
6297
  const strategy = this.getStrategy(chainKey);
6290
6298
  return strategy?.isConnected() || false;
6291
6299
  }
6292
- async getBalances(chainKey, address, tokens) {
6300
+ async getBalances(chainKey, address, tokens, priorityToken) {
6293
6301
  const strategy = this.getStrategy(chainKey);
6294
6302
  if (!strategy) return {};
6295
- return await strategy.getBalances(address, tokens);
6303
+ return await strategy.getBalances(address, tokens, priorityToken);
6296
6304
  }
6297
6305
  isAddressValid(chainKey, address) {
6298
6306
  const strategy = this.getStrategy(chainKey);
@@ -6403,13 +6411,14 @@ function parseTonAddress(address) {
6403
6411
  }
6404
6412
  return ton.Address.parse(address);
6405
6413
  }
6406
- async function getEvmBalances(publicClient, address, tokens) {
6414
+ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
6407
6415
  const balances = {};
6408
6416
  try {
6409
6417
  console.log("start getEvmBalances");
6410
6418
  console.log("publicClient:", publicClient);
6411
6419
  console.log("isAddress:", viem.isAddress(address));
6412
6420
  console.log("tokens:", tokens);
6421
+ console.log("priorityToken:", priorityToken);
6413
6422
  if (!address || !viem.isAddress(address)) {
6414
6423
  console.warn(`Invalid EVM address provided: ${address}`);
6415
6424
  return balances;
@@ -6417,25 +6426,93 @@ async function getEvmBalances(publicClient, address, tokens) {
6417
6426
  if (!publicClient) {
6418
6427
  throw new Error("No public client provided");
6419
6428
  }
6420
- for (const token of tokens) {
6429
+ const nativeTokens = tokens.filter((t) => isNativeAddress(t.address));
6430
+ const erc20Tokens = tokens.filter((t) => !isNativeAddress(t.address) && viem.isAddress(t.address));
6431
+ if (priorityToken) {
6421
6432
  try {
6422
- let balance = 0;
6423
- const isNative = isNativeAddress(token.address);
6424
- if (isNative) {
6433
+ const isPriorityNative = isNativeAddress(priorityToken.address);
6434
+ if (isPriorityNative) {
6425
6435
  const ethBalance = await publicClient.getBalance({
6426
6436
  address
6427
6437
  });
6428
- balance = parseFloat(viem.formatUnits(ethBalance, token.decimals));
6429
- } else {
6430
- if (!viem.isAddress(token.address)) {
6431
- continue;
6438
+ const balance = parseFloat(viem.formatUnits(ethBalance, priorityToken.decimals));
6439
+ if (balance > 0) {
6440
+ balances[priorityToken.symbol] = { balance, address };
6432
6441
  }
6433
- const bytecode = await publicClient.getBytecode({
6434
- address: token.address
6442
+ } else if (viem.isAddress(priorityToken.address)) {
6443
+ const tokenBalance = await publicClient.readContract({
6444
+ address: priorityToken.address,
6445
+ abi: [
6446
+ {
6447
+ name: "balanceOf",
6448
+ type: "function",
6449
+ stateMutability: "view",
6450
+ inputs: [{ name: "owner", type: "address" }],
6451
+ outputs: [{ name: "balance", type: "uint256" }]
6452
+ }
6453
+ ],
6454
+ functionName: "balanceOf",
6455
+ args: [address]
6435
6456
  });
6436
- if (!bytecode || bytecode === "0x") {
6437
- continue;
6457
+ const balance = parseFloat(viem.formatUnits(tokenBalance, priorityToken.decimals));
6458
+ if (balance > 0) {
6459
+ balances[priorityToken.symbol] = { balance, address };
6438
6460
  }
6461
+ }
6462
+ } catch (error) {
6463
+ console.debug(`Failed to get priority token balance for ${priorityToken.symbol}:`, error);
6464
+ }
6465
+ }
6466
+ for (const token of nativeTokens) {
6467
+ try {
6468
+ const ethBalance = await publicClient.getBalance({
6469
+ address
6470
+ });
6471
+ const balance = parseFloat(viem.formatUnits(ethBalance, token.decimals));
6472
+ if (balance > 0) {
6473
+ balances[token.symbol] = { balance, address };
6474
+ }
6475
+ } catch (error) {
6476
+ console.debug(`Failed to get native balance for ${token.symbol}:`, error);
6477
+ }
6478
+ }
6479
+ if (erc20Tokens.length > 0) {
6480
+ try {
6481
+ const multicallContracts = erc20Tokens.map((token) => ({
6482
+ address: token.address,
6483
+ abi: [
6484
+ {
6485
+ name: "balanceOf",
6486
+ type: "function",
6487
+ stateMutability: "view",
6488
+ inputs: [{ name: "owner", type: "address" }],
6489
+ outputs: [{ name: "balance", type: "uint256" }]
6490
+ }
6491
+ ],
6492
+ functionName: "balanceOf",
6493
+ args: [address]
6494
+ }));
6495
+ const results = await publicClient.multicall({
6496
+ contracts: multicallContracts,
6497
+ allowFailure: true
6498
+ });
6499
+ results.forEach((result, index) => {
6500
+ const token = erc20Tokens[index];
6501
+ if (!token) return;
6502
+ if (result.status === "success" && result.result !== void 0) {
6503
+ try {
6504
+ const balance = parseFloat(viem.formatUnits(result.result, token.decimals));
6505
+ if (balance > 0) {
6506
+ balances[token.symbol] = { balance, address };
6507
+ }
6508
+ } catch (error) {
6509
+ console.debug(`Failed to parse balance for ${token.symbol}:`, error);
6510
+ }
6511
+ }
6512
+ });
6513
+ } catch (error) {
6514
+ console.warn("Multicall failed, falling back to individual calls:", error);
6515
+ for (const token of erc20Tokens) {
6439
6516
  try {
6440
6517
  const tokenBalance = await publicClient.readContract({
6441
6518
  address: token.address,
@@ -6451,23 +6528,16 @@ async function getEvmBalances(publicClient, address, tokens) {
6451
6528
  functionName: "balanceOf",
6452
6529
  args: [address]
6453
6530
  });
6454
- balance = parseFloat(
6531
+ const balance = parseFloat(
6455
6532
  viem.formatUnits(tokenBalance, token.decimals)
6456
6533
  );
6457
- } catch {
6458
- continue;
6534
+ if (balance > 0) {
6535
+ balances[token.symbol] = { balance, address };
6536
+ }
6537
+ } catch (error2) {
6538
+ console.debug(`Failed to get balance for ${token.symbol}:`, error2);
6459
6539
  }
6460
6540
  }
6461
- if (balance > 0) {
6462
- balances[token.symbol] = { balance, address };
6463
- }
6464
- } catch (error) {
6465
- if (error instanceof Error && !error.message.includes("could not decode")) {
6466
- console.warn(
6467
- `Network error fetching balance for ${token.symbol}:`,
6468
- error
6469
- );
6470
- }
6471
6541
  }
6472
6542
  }
6473
6543
  } catch (error) {
@@ -6529,7 +6599,11 @@ async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
6529
6599
  }
6530
6600
  }
6531
6601
  } catch (error) {
6532
- console.debug(`Failed to get balance for ${token.symbol}:`, error);
6602
+ const errorMessage = error instanceof Error ? error.message : String(error);
6603
+ const isNoWalletError = errorMessage.includes("exit_code: -13") || errorMessage.includes("exit_code:-13") || errorMessage.includes("exitCode: -13");
6604
+ if (!isNoWalletError) {
6605
+ console.debug(`Failed to get balance for ${token.symbol}:`, error);
6606
+ }
6533
6607
  }
6534
6608
  }
6535
6609
  } catch (error) {
@@ -6630,12 +6704,12 @@ class EvmChainStrategy {
6630
6704
  getConnectLabel(t) {
6631
6705
  return t("wallets.connectEvmWallet");
6632
6706
  }
6633
- async getBalances(address, tokens) {
6707
+ async getBalances(address, tokens, priorityToken) {
6634
6708
  if (!this.publicClient) {
6635
6709
  console.warn("No publicClient available for balance query");
6636
6710
  return {};
6637
6711
  }
6638
- return await getEvmBalances(this.publicClient, address, tokens);
6712
+ return await getEvmBalances(this.publicClient, address, tokens, priorityToken);
6639
6713
  }
6640
6714
  isAddressValid(address) {
6641
6715
  if (!address) return false;
@@ -8039,7 +8113,7 @@ const EvaaBridgeContent = ({
8039
8113
  /* @__PURE__ */ jsxRuntime.jsx(
8040
8114
  SwapSection,
8041
8115
  {
8042
- className: "rounded-t-16",
8116
+ className: "rounded-t-xl",
8043
8117
  label: t("bridge.sourceNetwork"),
8044
8118
  balance: fromBalance,
8045
8119
  chain: fromChain,
@@ -8074,7 +8148,7 @@ const EvaaBridgeContent = ({
8074
8148
  ),
8075
8149
  /* @__PURE__ */ jsxRuntime.jsx(SubmitButton, {})
8076
8150
  ] }),
8077
- /* @__PURE__ */ jsxRuntime.jsx(CardFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(ReceiveRow, {}) })
8151
+ /* @__PURE__ */ jsxRuntime.jsx(CardFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(Details, {}) })
8078
8152
  ]
8079
8153
  }
8080
8154
  ),