From a38b0c94e3b84ed4f65ccab53fee7b057f711f35 Mon Sep 17 00:00:00 2001 From: antoncoding Date: Thu, 8 Jan 2026 11:57:02 +0800 Subject: [PATCH 1/3] fix: dust amount --- .../components/from-markets-table.tsx | 16 ++++++-------- .../rebalance/rebalance-action-row.tsx | 5 ++++- .../components/rebalance/rebalance-modal.tsx | 22 +++++++++---------- src/utils/tokens.ts | 5 ++++- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/features/positions/components/from-markets-table.tsx b/src/features/positions/components/from-markets-table.tsx index 8bcb8994..8f52fb30 100644 --- a/src/features/positions/components/from-markets-table.tsx +++ b/src/features/positions/components/from-markets-table.tsx @@ -10,13 +10,13 @@ import { previewMarketState } from '@/utils/morpho'; import { convertApyToApr } from '@/utils/rateMath'; import type { MarketPosition } from '@/utils/types'; -type PositionWithPendingDelta = MarketPosition & { pendingDelta: number }; +type PositionWithPendingDelta = MarketPosition & { pendingDelta: bigint }; type FromMarketsTableProps = { positions: PositionWithPendingDelta[]; selectedMarketUniqueKey: string; onSelectMarket: (marketUniqueKey: string) => void; - onSelectMax?: (marketUniqueKey: string, amount: number) => void; + onSelectMax?: (marketUniqueKey: string, amount: bigint) => void; }; const PER_PAGE = 5; @@ -30,11 +30,10 @@ export function FromMarketsTable({ positions, selectedMarketUniqueKey, onSelectM const paginatedPositions = positions.slice((currentPage - 1) * PER_PAGE, currentPage * PER_PAGE); const getApyPreview = (position: PositionWithPendingDelta) => { - if (position.pendingDelta === 0) return null; + if (position.pendingDelta === 0n) return null; try { - const deltaBigInt = BigInt(Math.floor(position.pendingDelta)); - return previewMarketState(position.market, deltaBigInt, undefined); + return previewMarketState(position.market, position.pendingDelta, undefined); } catch { return null; } @@ -67,11 +66,10 @@ export function FromMarketsTable({ positions, selectedMarketUniqueKey, onSelectM {paginatedPositions.map((position) => { const userConfirmedSupply = BigInt(position.state.supplyAssets); - const pendingDeltaBigInt = BigInt(position.pendingDelta); - const userNetSupply = userConfirmedSupply + pendingDeltaBigInt; + const userNetSupply = userConfirmedSupply + position.pendingDelta; const rawMarketLiquidity = BigInt(position.market.state.liquidityAssets); - const adjustedMarketLiquidity = rawMarketLiquidity + pendingDeltaBigInt; + const adjustedMarketLiquidity = rawMarketLiquidity + position.pendingDelta; const maxTransferableAmount = userNetSupply < adjustedMarketLiquidity ? userNetSupply : adjustedMarketLiquidity; @@ -154,7 +152,7 @@ export function FromMarketsTable({ positions, selectedMarketUniqueKey, onSelectM e.stopPropagation(); onSelectMarket(position.market.uniqueKey); if (onSelectMax && maxTransferableAmount > 0n) { - onSelectMax(position.market.uniqueKey, Number(maxTransferableAmount)); + onSelectMax(position.market.uniqueKey, maxTransferableAmount); } }} > diff --git a/src/features/positions/components/rebalance/rebalance-action-row.tsx b/src/features/positions/components/rebalance/rebalance-action-row.tsx index 78ddd10c..7dda39a5 100644 --- a/src/features/positions/components/rebalance/rebalance-action-row.tsx +++ b/src/features/positions/components/rebalance/rebalance-action-row.tsx @@ -5,6 +5,7 @@ import { Button } from '@/components/ui/button'; import { MarketIdentity, MarketIdentityMode } from '@/features/markets/components/market-identity'; import { TokenIcon } from '@/components/shared/token-icon'; import { useRateLabel } from '@/hooks/useRateLabel'; +import { formatReadable } from '@/utils/balance'; import { previewMarketState } from '@/utils/morpho'; import type { GroupedPosition, Market } from '@/utils/types'; import { ApyPreview } from '../preview/apy-preview'; @@ -75,7 +76,9 @@ export function RebalanceActionRow({ }, [toMarket, amount, groupedPosition.loanAssetDecimals]); // Format amount for display - const displayAmount = typeof amount === 'string' ? amount : formatUnits(amount, groupedPosition.loanAssetDecimals); + const rawAmount = typeof amount === 'string' ? amount : formatUnits(amount, groupedPosition.loanAssetDecimals); + // In display mode (bigint), format nicely; in input mode (string), show raw value for editing + const displayAmount = typeof amount === 'string' ? rawAmount : formatReadable(rawAmount, 4); return (
diff --git a/src/features/positions/components/rebalance/rebalance-modal.tsx b/src/features/positions/components/rebalance/rebalance-modal.tsx index 2cdf683f..94a55e0d 100644 --- a/src/features/positions/components/rebalance/rebalance-modal.tsx +++ b/src/features/positions/components/rebalance/rebalance-modal.tsx @@ -54,16 +54,16 @@ export function RebalanceModal({ groupedPosition, isOpen, onOpenChange, refetch, }, [markets, groupedPosition.loanAssetAddress, groupedPosition.chainId]); const getPendingDelta = useCallback( - (marketUniqueKey: string) => { - return rebalanceActions.reduce((acc: number, action: RebalanceAction) => { + (marketUniqueKey: string): bigint => { + return rebalanceActions.reduce((acc: bigint, action: RebalanceAction) => { if (action.fromMarket.uniqueKey === marketUniqueKey) { - return acc - Number(action.amount); + return acc - BigInt(action.amount); } if (action.toMarket.uniqueKey === marketUniqueKey) { - return acc + Number(action.amount); + return acc + BigInt(action.amount); } return acc; - }, 0); + }, 0n); }, [rebalanceActions], ); @@ -107,7 +107,7 @@ export function RebalanceModal({ groupedPosition, isOpen, onOpenChange, refetch, const oldBalance = groupedPosition.markets.find((m) => m.market.uniqueKey === selectedFromMarketUniqueKey)?.state.supplyAssets; const pendingDelta = getPendingDelta(selectedFromMarketUniqueKey); - const pendingBalance = BigInt(oldBalance ?? 0) + BigInt(pendingDelta); + const pendingBalance = BigInt(oldBalance ?? 0) + pendingDelta; const scaledAmount = parseUnits(amount, groupedPosition.loanAssetDecimals); if (scaledAmount > pendingBalance) { @@ -147,13 +147,13 @@ export function RebalanceModal({ groupedPosition, isOpen, onOpenChange, refetch, }, []); const handleMaxSelect = useCallback( - (marketUniqueKey: string, maxAmount: number) => { + (marketUniqueKey: string, maxAmount: bigint) => { const market = eligibleMarkets.find((m) => m.uniqueKey === marketUniqueKey); if (!market) return; setSelectedFromMarketUniqueKey(marketUniqueKey); - // Convert the amount to a string with the correct number of decimals - const formattedAmount = formatUnits(BigInt(Math.floor(maxAmount)), groupedPosition.loanAssetDecimals); + // Convert the bigint amount to a string with the correct number of decimals + const formattedAmount = formatUnits(maxAmount, groupedPosition.loanAssetDecimals); setAmount(formattedAmount); }, [eligibleMarkets, groupedPosition.loanAssetDecimals], @@ -175,11 +175,11 @@ export function RebalanceModal({ groupedPosition, isOpen, onOpenChange, refetch, const selectedPosition = groupedPosition.markets.find((p) => p.market.uniqueKey === selectedFromMarketUniqueKey); // Get the pending delta for this market - const pendingDelta = selectedPosition ? getPendingDelta(selectedPosition.market.uniqueKey) : 0; + const pendingDelta = selectedPosition ? getPendingDelta(selectedPosition.market.uniqueKey) : 0n; // Check if this is a max amount considering pending delta const isMaxAmount = - selectedPosition !== undefined && BigInt(selectedPosition.state.supplyAssets) + BigInt(pendingDelta) === scaledAmount; + selectedPosition !== undefined && BigInt(selectedPosition.state.supplyAssets) + pendingDelta === scaledAmount; // Create the action using the helper function const action = createAction(fromMarket, toMarket, scaledAmount, isMaxAmount); diff --git a/src/utils/tokens.ts b/src/utils/tokens.ts index 4ba507e9..c8b78cf9 100644 --- a/src/utils/tokens.ts +++ b/src/utils/tokens.ts @@ -261,7 +261,10 @@ const supportedTokens = [ symbol: 'sDAI', img: require('../imgs/tokens/sdai.svg') as string, decimals: 18, - networks: [{ chain: mainnet, address: '0x83F20F44975D03b1b09e64809B757c47f942BEeA' }], + networks: [ + { chain: mainnet, address: '0x83F20F44975D03b1b09e64809B757c47f942BEeA' }, + { chain: base, address: '0x50c5725949a6f0c72e6c4a641f24049a917db0cb' }, + ], }, { symbol: 'wstETH', From 2060718704992ef9d50b7d7308e9e23fdcdf6019 Mon Sep 17 00:00:00 2001 From: antoncoding Date: Thu, 8 Jan 2026 12:09:12 +0800 Subject: [PATCH 2/3] fix: toast style --- src/components/providers/ThemeProvider.tsx | 8 ++------ src/components/ui/themed-toast-container.tsx | 17 +++++++++++++++++ src/hooks/useStyledToast.tsx | 1 - src/hooks/useTransactionWithToast.tsx | 1 - 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 src/components/ui/themed-toast-container.tsx diff --git a/src/components/providers/ThemeProvider.tsx b/src/components/providers/ThemeProvider.tsx index ef42ca5c..a78a952f 100644 --- a/src/components/providers/ThemeProvider.tsx +++ b/src/components/providers/ThemeProvider.tsx @@ -1,7 +1,7 @@ 'use client'; import { ThemeProvider as NextThemesProvider } from 'next-themes'; -import { ToastContainer } from 'react-toastify'; +import { ThemedToastContainer } from '@/components/ui/themed-toast-container'; import { TooltipProvider } from '@/components/ui/tooltip'; export function ThemeProviders({ children }: { children: React.ReactNode }) { @@ -14,11 +14,7 @@ export function ThemeProviders({ children }: { children: React.ReactNode }) { themes={['light', 'dark']} > {children} - + ); } diff --git a/src/components/ui/themed-toast-container.tsx b/src/components/ui/themed-toast-container.tsx new file mode 100644 index 00000000..bf82e4bb --- /dev/null +++ b/src/components/ui/themed-toast-container.tsx @@ -0,0 +1,17 @@ +'use client'; + +import { useTheme } from 'next-themes'; +import { ToastContainer } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; + +export function ThemedToastContainer() { + const { resolvedTheme } = useTheme(); + + return ( + + ); +} diff --git a/src/hooks/useStyledToast.tsx b/src/hooks/useStyledToast.tsx index dc3f509d..b55b8f02 100644 --- a/src/hooks/useStyledToast.tsx +++ b/src/hooks/useStyledToast.tsx @@ -1,6 +1,5 @@ import { useCallback } from 'react'; import { toast, type ToastOptions } from 'react-toastify'; -import 'react-toastify/dist/ReactToastify.css'; import { StyledToast } from '../components/ui/styled-toast'; export function useStyledToast() { diff --git a/src/hooks/useTransactionWithToast.tsx b/src/hooks/useTransactionWithToast.tsx index 6c71b56e..a4de4695 100644 --- a/src/hooks/useTransactionWithToast.tsx +++ b/src/hooks/useTransactionWithToast.tsx @@ -1,6 +1,5 @@ import { useCallback, useEffect, useRef } from 'react'; import { toast } from 'react-toastify'; -import 'react-toastify/dist/ReactToastify.css'; import { useSendTransaction, useWaitForTransactionReceipt } from 'wagmi'; import { StyledToast, TransactionToast } from '@/components/ui/styled-toast'; import { getExplorerTxURL } from '../utils/external'; From 6d722a2a61c05a754cb55da7bfd93f416acd6d97 Mon Sep 17 00:00:00 2001 From: antoncoding Date: Thu, 8 Jan 2026 12:15:18 +0800 Subject: [PATCH 3/3] fix: xdai --- src/utils/tokens.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/tokens.ts b/src/utils/tokens.ts index c8b78cf9..11766128 100644 --- a/src/utils/tokens.ts +++ b/src/utils/tokens.ts @@ -263,7 +263,7 @@ const supportedTokens = [ decimals: 18, networks: [ { chain: mainnet, address: '0x83F20F44975D03b1b09e64809B757c47f942BEeA' }, - { chain: base, address: '0x50c5725949a6f0c72e6c4a641f24049a917db0cb' }, + { chain: base, address: '0x99ac4484e8a1dbd6a185380b3a811913ac884d87' }, ], }, {