@rash2x/bridge-widget 0.1.6 → 0.1.7

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,
@@ -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: [
@@ -2919,8 +2940,7 @@ const SwapSection = ({
2919
2940
  SelectNetworkButton,
2920
2941
  {
2921
2942
  network: chain,
2922
- onClick: disableNetworkSelect ? void 0 : onOpen,
2923
- className: disableNetworkSelect ? "opacity-80 cursor-not-allowed" : ""
2943
+ onClick: disableNetworkSelect ? void 0 : onOpen
2924
2944
  }
2925
2945
  ),
2926
2946
  /* @__PURE__ */ jsx(
@@ -6247,10 +6267,10 @@ class ChainStrategyRegistry {
6247
6267
  const strategy = this.getStrategy(chainKey);
6248
6268
  return strategy?.isConnected() || false;
6249
6269
  }
6250
- async getBalances(chainKey, address, tokens) {
6270
+ async getBalances(chainKey, address, tokens, priorityToken) {
6251
6271
  const strategy = this.getStrategy(chainKey);
6252
6272
  if (!strategy) return {};
6253
- return await strategy.getBalances(address, tokens);
6273
+ return await strategy.getBalances(address, tokens, priorityToken);
6254
6274
  }
6255
6275
  isAddressValid(chainKey, address) {
6256
6276
  const strategy = this.getStrategy(chainKey);
@@ -6361,13 +6381,14 @@ function parseTonAddress(address) {
6361
6381
  }
6362
6382
  return Address$1.parse(address);
6363
6383
  }
6364
- async function getEvmBalances(publicClient, address, tokens) {
6384
+ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
6365
6385
  const balances = {};
6366
6386
  try {
6367
6387
  console.log("start getEvmBalances");
6368
6388
  console.log("publicClient:", publicClient);
6369
6389
  console.log("isAddress:", isAddress(address));
6370
6390
  console.log("tokens:", tokens);
6391
+ console.log("priorityToken:", priorityToken);
6371
6392
  if (!address || !isAddress(address)) {
6372
6393
  console.warn(`Invalid EVM address provided: ${address}`);
6373
6394
  return balances;
@@ -6375,25 +6396,93 @@ async function getEvmBalances(publicClient, address, tokens) {
6375
6396
  if (!publicClient) {
6376
6397
  throw new Error("No public client provided");
6377
6398
  }
6378
- for (const token of tokens) {
6399
+ const nativeTokens = tokens.filter((t2) => isNativeAddress(t2.address));
6400
+ const erc20Tokens = tokens.filter((t2) => !isNativeAddress(t2.address) && isAddress(t2.address));
6401
+ if (priorityToken) {
6379
6402
  try {
6380
- let balance = 0;
6381
- const isNative = isNativeAddress(token.address);
6382
- if (isNative) {
6403
+ const isPriorityNative = isNativeAddress(priorityToken.address);
6404
+ if (isPriorityNative) {
6383
6405
  const ethBalance = await publicClient.getBalance({
6384
6406
  address
6385
6407
  });
6386
- balance = parseFloat(formatUnits(ethBalance, token.decimals));
6387
- } else {
6388
- if (!isAddress(token.address)) {
6389
- continue;
6408
+ const balance = parseFloat(formatUnits(ethBalance, priorityToken.decimals));
6409
+ if (balance > 0) {
6410
+ balances[priorityToken.symbol] = { balance, address };
6390
6411
  }
6391
- const bytecode = await publicClient.getBytecode({
6392
- address: token.address
6412
+ } else if (isAddress(priorityToken.address)) {
6413
+ const tokenBalance = await publicClient.readContract({
6414
+ address: priorityToken.address,
6415
+ abi: [
6416
+ {
6417
+ name: "balanceOf",
6418
+ type: "function",
6419
+ stateMutability: "view",
6420
+ inputs: [{ name: "owner", type: "address" }],
6421
+ outputs: [{ name: "balance", type: "uint256" }]
6422
+ }
6423
+ ],
6424
+ functionName: "balanceOf",
6425
+ args: [address]
6393
6426
  });
6394
- if (!bytecode || bytecode === "0x") {
6395
- continue;
6427
+ const balance = parseFloat(formatUnits(tokenBalance, priorityToken.decimals));
6428
+ if (balance > 0) {
6429
+ balances[priorityToken.symbol] = { balance, address };
6396
6430
  }
6431
+ }
6432
+ } catch (error) {
6433
+ console.debug(`Failed to get priority token balance for ${priorityToken.symbol}:`, error);
6434
+ }
6435
+ }
6436
+ for (const token of nativeTokens) {
6437
+ try {
6438
+ const ethBalance = await publicClient.getBalance({
6439
+ address
6440
+ });
6441
+ const balance = parseFloat(formatUnits(ethBalance, token.decimals));
6442
+ if (balance > 0) {
6443
+ balances[token.symbol] = { balance, address };
6444
+ }
6445
+ } catch (error) {
6446
+ console.debug(`Failed to get native balance for ${token.symbol}:`, error);
6447
+ }
6448
+ }
6449
+ if (erc20Tokens.length > 0) {
6450
+ try {
6451
+ const multicallContracts = erc20Tokens.map((token) => ({
6452
+ address: token.address,
6453
+ abi: [
6454
+ {
6455
+ name: "balanceOf",
6456
+ type: "function",
6457
+ stateMutability: "view",
6458
+ inputs: [{ name: "owner", type: "address" }],
6459
+ outputs: [{ name: "balance", type: "uint256" }]
6460
+ }
6461
+ ],
6462
+ functionName: "balanceOf",
6463
+ args: [address]
6464
+ }));
6465
+ const results = await publicClient.multicall({
6466
+ contracts: multicallContracts,
6467
+ allowFailure: true
6468
+ });
6469
+ results.forEach((result, index) => {
6470
+ const token = erc20Tokens[index];
6471
+ if (!token) return;
6472
+ if (result.status === "success" && result.result !== void 0) {
6473
+ try {
6474
+ const balance = parseFloat(formatUnits(result.result, token.decimals));
6475
+ if (balance > 0) {
6476
+ balances[token.symbol] = { balance, address };
6477
+ }
6478
+ } catch (error) {
6479
+ console.debug(`Failed to parse balance for ${token.symbol}:`, error);
6480
+ }
6481
+ }
6482
+ });
6483
+ } catch (error) {
6484
+ console.warn("Multicall failed, falling back to individual calls:", error);
6485
+ for (const token of erc20Tokens) {
6397
6486
  try {
6398
6487
  const tokenBalance = await publicClient.readContract({
6399
6488
  address: token.address,
@@ -6409,23 +6498,16 @@ async function getEvmBalances(publicClient, address, tokens) {
6409
6498
  functionName: "balanceOf",
6410
6499
  args: [address]
6411
6500
  });
6412
- balance = parseFloat(
6501
+ const balance = parseFloat(
6413
6502
  formatUnits(tokenBalance, token.decimals)
6414
6503
  );
6415
- } catch {
6416
- continue;
6504
+ if (balance > 0) {
6505
+ balances[token.symbol] = { balance, address };
6506
+ }
6507
+ } catch (error2) {
6508
+ console.debug(`Failed to get balance for ${token.symbol}:`, error2);
6417
6509
  }
6418
6510
  }
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
6511
  }
6430
6512
  }
6431
6513
  } catch (error) {
@@ -6487,7 +6569,11 @@ async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
6487
6569
  }
6488
6570
  }
6489
6571
  } catch (error) {
6490
- console.debug(`Failed to get balance for ${token.symbol}:`, error);
6572
+ const errorMessage = error instanceof Error ? error.message : String(error);
6573
+ const isNoWalletError = errorMessage.includes("exit_code: -13") || errorMessage.includes("exit_code:-13") || errorMessage.includes("exitCode: -13");
6574
+ if (!isNoWalletError) {
6575
+ console.debug(`Failed to get balance for ${token.symbol}:`, error);
6576
+ }
6491
6577
  }
6492
6578
  }
6493
6579
  } catch (error) {
@@ -6588,12 +6674,12 @@ class EvmChainStrategy {
6588
6674
  getConnectLabel(t2) {
6589
6675
  return t2("wallets.connectEvmWallet");
6590
6676
  }
6591
- async getBalances(address, tokens) {
6677
+ async getBalances(address, tokens, priorityToken) {
6592
6678
  if (!this.publicClient) {
6593
6679
  console.warn("No publicClient available for balance query");
6594
6680
  return {};
6595
6681
  }
6596
- return await getEvmBalances(this.publicClient, address, tokens);
6682
+ return await getEvmBalances(this.publicClient, address, tokens, priorityToken);
6597
6683
  }
6598
6684
  isAddressValid(address) {
6599
6685
  if (!address) return false;