Skip to content

Commit 0cfc6b3

Browse files
Enhance MarketSelector component with token balance fetching and default token management
- Added functionality to fetch balances for default tokens (USDC, WETH, ION) using the useBalance hook. - Introduced default token addresses based on the current chain. - Updated rewardTokensInfo to merge default tokens with those from the hook, ensuring accurate balance representation. - Improved debug logging for balance fetching and token management. - Refactored UI elements to streamline the incentivization process.
1 parent a80f8f8 commit 0cfc6b3

1 file changed

Lines changed: 196 additions & 116 deletions

File tree

packages/ui/components/veion/MarketSelector.tsx

Lines changed: 196 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import {
1515
CircleDollarSign,
1616
Loader2
1717
} from 'lucide-react';
18-
import { erc20Abi, isAddress } from 'viem';
19-
import { useAccount, useReadContract, useSwitchChain } from 'wagmi';
18+
import { erc20Abi, isAddress, formatUnits } from 'viem';
19+
import { useAccount, useReadContract, useSwitchChain, useBalance } from 'wagmi';
2020
import { base, mode } from 'wagmi/chains';
2121

2222
import { Button } from '@ui/components/ui/button';
@@ -53,7 +53,7 @@ const MarketSelector = ({ isAcknowledged }: MarketSelectorProps) => {
5353
const chainId = parseInt(currentChain);
5454
const poolId = currentChain === mode.id.toString() ? '1' : '0';
5555

56-
const { chain } = useAccount();
56+
const { chain, address } = useAccount();
5757
const { switchChain, isPending: isSwitchingNetwork } = useSwitchChain();
5858
const isWrongNetwork = chain?.id !== chainId;
5959

@@ -82,12 +82,110 @@ const MarketSelector = ({ isAcknowledged }: MarketSelectorProps) => {
8282
marketAddresses
8383
);
8484

85+
// Define default token addresses
86+
const defaultTokenAddresses = useMemo(
87+
() => ({
88+
USDC:
89+
chainId === 8453
90+
? '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
91+
: '0xd988097fb8612cc24eeC14542bC03424c656005f',
92+
WETH:
93+
chainId === 8453
94+
? '0x4200000000000000000000000000000000000006'
95+
: '0x4200000000000000000000000000000000000006',
96+
ION:
97+
chainId === 8453
98+
? '0x3eE5e23eEE121094f1cFc0Ccc79d6C809Ebd22e5'
99+
: '0x18470019bf0e94611f15852f7e93cf5d65bc34ca'
100+
}),
101+
[chainId]
102+
);
103+
104+
// Fetch balances for default tokens
105+
const { data: usdcBalance } = useBalance({
106+
address,
107+
token: defaultTokenAddresses.USDC as `0x${string}`,
108+
chainId,
109+
query: { enabled: !!address }
110+
});
111+
112+
const { data: wethBalance } = useBalance({
113+
address,
114+
token: defaultTokenAddresses.WETH as `0x${string}`,
115+
chainId,
116+
query: { enabled: !!address }
117+
});
118+
119+
const { data: ionBalance, error: ionBalanceError } = useBalance({
120+
address,
121+
token: defaultTokenAddresses.ION as `0x${string}`,
122+
chainId,
123+
query: { enabled: !!address }
124+
});
125+
126+
// Debug ION balance fetching
127+
useEffect(() => {
128+
console.log('=== ION BALANCE DEBUG ===');
129+
console.log('Chain ID:', chainId);
130+
console.log('ION Address:', defaultTokenAddresses.ION);
131+
console.log('User Address:', address);
132+
console.log('ION Balance Data:', ionBalance);
133+
console.log('ION Balance Error:', ionBalanceError);
134+
console.log('=== END ION DEBUG ===');
135+
}, [
136+
chainId,
137+
defaultTokenAddresses.ION,
138+
address,
139+
ionBalance,
140+
ionBalanceError
141+
]);
142+
143+
// Default reward tokens that are always available
144+
const defaultRewardTokens: RewardTokenInfo[] = useMemo(
145+
() => [
146+
{
147+
symbol: 'USDC',
148+
address: defaultTokenAddresses.USDC,
149+
balance: usdcBalance
150+
? formatUnits(usdcBalance.value, usdcBalance.decimals)
151+
: '0',
152+
name: 'USD Coin',
153+
cgId: 'usd-coin',
154+
decimals: 6,
155+
underlying_address: defaultTokenAddresses.USDC
156+
},
157+
{
158+
symbol: 'WETH',
159+
address: defaultTokenAddresses.WETH,
160+
balance: wethBalance
161+
? formatUnits(wethBalance.value, wethBalance.decimals)
162+
: '0',
163+
name: 'Wrapped Ether',
164+
cgId: 'weth',
165+
decimals: 18,
166+
underlying_address: defaultTokenAddresses.WETH
167+
},
168+
{
169+
symbol: 'ION',
170+
address: defaultTokenAddresses.ION,
171+
balance: ionBalance
172+
? formatUnits(ionBalance.value, ionBalance.decimals)
173+
: '0',
174+
name: 'Ionic Protocol',
175+
cgId: 'ionic-protocol',
176+
decimals: 18,
177+
underlying_address: defaultTokenAddresses.ION
178+
}
179+
],
180+
[defaultTokenAddresses, usdcBalance, wethBalance, ionBalance]
181+
);
182+
85183
// Update the useMarketIncentives hook usage to include getMarketIncentivesUsd
86184
const {
87185
getMarketIncentives,
88186
getMarketIncentivesUsd,
89187
getBribeAddress,
90-
rewardTokensInfo,
188+
rewardTokensInfo: hookRewardTokens,
91189
isLoading: isIncentivesLoading,
92190
fetchRewardTokensForBribe
93191
} = useMarketIncentives(
@@ -97,6 +195,63 @@ const MarketSelector = ({ isAcknowledged }: MarketSelectorProps) => {
97195
selectedMarket
98196
);
99197

198+
// Always ensure default tokens are available, supplement with hook tokens
199+
const rewardTokensInfo = useMemo(() => {
200+
// Always start with our default tokens
201+
let finalTokens = [...defaultRewardTokens];
202+
203+
// Debug logging
204+
console.log('=== TOKEN DEBUG ===');
205+
console.log('Default tokens count:', defaultRewardTokens.length);
206+
console.log(
207+
'Default tokens:',
208+
defaultRewardTokens.map((t) => `${t.symbol} (${t.balance})`)
209+
);
210+
console.log('Hook tokens count:', hookRewardTokens.length);
211+
console.log(
212+
'Hook tokens:',
213+
hookRewardTokens.map((t) => `${t.symbol} (${t.balance})`)
214+
);
215+
216+
// Only merge if hook has tokens, otherwise stick with defaults
217+
if (hookRewardTokens.length > 0) {
218+
const combinedTokens = [...defaultRewardTokens];
219+
220+
// Add additional tokens from the hook (e.g., EUSD)
221+
hookRewardTokens.forEach((hookToken) => {
222+
const existingIndex = combinedTokens.findIndex(
223+
(token) =>
224+
token.address.toLowerCase() === hookToken.address.toLowerCase()
225+
);
226+
227+
if (existingIndex >= 0) {
228+
// Update existing token with hook balance data, but preserve our token metadata
229+
combinedTokens[existingIndex] = {
230+
...combinedTokens[existingIndex],
231+
balance:
232+
hookToken.balance && hookToken.balance !== '0'
233+
? hookToken.balance
234+
: combinedTokens[existingIndex].balance
235+
};
236+
} else {
237+
// Add new token from hook (like EUSD)
238+
combinedTokens.push(hookToken);
239+
}
240+
});
241+
242+
finalTokens = combinedTokens;
243+
}
244+
245+
console.log('Final tokens count:', finalTokens.length);
246+
console.log(
247+
'Final tokens:',
248+
finalTokens.map((t) => `${t.symbol} (${t.balance})`)
249+
);
250+
console.log('=== END DEBUG ===');
251+
252+
return finalTokens;
253+
}, [defaultRewardTokens, hookRewardTokens]);
254+
100255
// Incentive submission hook
101256
const {
102257
submitIncentive,
@@ -440,124 +595,49 @@ const MarketSelector = ({ isAcknowledged }: MarketSelectorProps) => {
440595
</SelectContent>
441596
</Select>
442597

443-
{isIncentivesLoading ? (
444-
<div className="relative p-6 border border-white/10 rounded-md bg-grayone animate-pulse">
445-
<div className="flex items-center justify-center space-x-2">
598+
<MaxDeposit
599+
key={maxDepositKey}
600+
headerText="Incentivize Amount"
601+
tokenName={selectedToken?.symbol}
602+
tokenSelector={true}
603+
tokenArr={rewardTokensInfo.map((token) => token.symbol)}
604+
max={selectedToken?.balance || '0'}
605+
chain={+currentChain}
606+
handleInput={(val?: string) => handleInput(val || '')}
607+
onTokenChange={handleTokenChange}
608+
showUtilizationSlider
609+
amount={incentiveAmount}
610+
/>
611+
612+
<Button
613+
className="w-full bg-accent hover:bg-accent/90 text-black font-semibold relative overflow-hidden transition-all duration-300"
614+
disabled={isApproving || isSubmitting || isConfirming}
615+
onClick={handleSubmit}
616+
>
617+
{isApproving || isSubmitting || isConfirming ? (
618+
<div className="flex items-center justify-center">
446619
<Loader2
447-
size={20}
448-
className="text-accent animate-spin"
620+
size={18}
621+
className="mr-2 animate-spin"
449622
/>
450-
<div className="text-center text-white/60 text-sm">
451-
Loading reward tokens...
452-
</div>
623+
<span>
624+
{isApproving
625+
? 'Approving tokens...'
626+
: isSubmitting
627+
? 'Submitting incentive...'
628+
: 'Confirming transaction...'}
629+
</span>
453630
</div>
454-
</div>
455-
) : rewardTokensInfo.length === 0 ? (
456-
<div className="p-6 border border-white/10 rounded-md bg-grayone/80">
631+
) : (
457632
<div className="flex items-center justify-center">
458-
<Info
459-
size={20}
460-
className="text-yellow-400 mr-2"
633+
<CircleDollarSign
634+
size={18}
635+
className="mr-2"
461636
/>
462-
<span className="text-white/80 font-medium">
463-
No Reward Tokens Available
464-
</span>
637+
<span>Incentivize</span>
465638
</div>
466-
<p className="mt-2 text-center text-white/60 text-sm">
467-
There are currently no tokens available for incentives. Please
468-
check back later or contact the Ionic team.
469-
</p>
470-
</div>
471-
) : (
472-
<MaxDeposit
473-
key={maxDepositKey}
474-
headerText="Incentivize Amount"
475-
tokenName={selectedToken?.symbol}
476-
tokenSelector={true}
477-
tokenArr={rewardTokensInfo.map((token) => token.symbol)}
478-
max={selectedToken?.balance || '0'}
479-
chain={+currentChain}
480-
handleInput={(val?: string) => handleInput(val || '')}
481-
onTokenChange={handleTokenChange}
482-
showUtilizationSlider
483-
amount={incentiveAmount}
484-
/>
485-
)}
486-
487-
{isWrongNetwork ? (
488-
// Show network switch button when on wrong network
489-
<Button
490-
className="w-full bg-yellow-500 hover:bg-yellow-600 text-black font-semibold relative overflow-hidden transition-all duration-300"
491-
disabled={isSwitchingNetwork}
492-
onClick={() => switchChain({ chainId })}
493-
>
494-
{isSwitchingNetwork ? (
495-
<div className="flex items-center justify-center">
496-
<Loader2
497-
size={18}
498-
className="mr-2 animate-spin"
499-
/>
500-
<span>
501-
Switching to {chainId === 8453 ? 'Base' : 'Mode'}{' '}
502-
network...
503-
</span>
504-
</div>
505-
) : (
506-
<div className="flex items-center justify-center">
507-
<svg
508-
width="18"
509-
height="18"
510-
viewBox="0 0 24 24"
511-
fill="none"
512-
stroke="currentColor"
513-
strokeWidth="2"
514-
strokeLinecap="round"
515-
strokeLinejoin="round"
516-
className="mr-2"
517-
>
518-
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
519-
</svg>
520-
<span>
521-
Switch to {chainId === 8453 ? 'Base' : 'Mode'} Network
522-
First
523-
</span>
524-
</div>
525-
)}
526-
</Button>
527-
) : (
528-
// Show incentivize button when on correct network
529-
<Button
530-
className="w-full bg-accent hover:bg-accent/90 text-black font-semibold relative overflow-hidden transition-all duration-300"
531-
disabled={
532-
!isFormComplete || isLoading || rewardTokensInfo.length === 0
533-
}
534-
onClick={handleSubmit}
535-
>
536-
{isApproving || isSubmitting || isConfirming ? (
537-
<div className="flex items-center justify-center">
538-
<Loader2
539-
size={18}
540-
className="mr-2 animate-spin"
541-
/>
542-
<span>
543-
{isApproving
544-
? 'Approving tokens...'
545-
: isSubmitting
546-
? 'Submitting incentive...'
547-
: 'Confirming transaction...'}
548-
</span>
549-
</div>
550-
) : (
551-
<div className="flex items-center justify-center">
552-
<CircleDollarSign
553-
size={18}
554-
className="mr-2"
555-
/>
556-
<span>Incentivize</span>
557-
</div>
558-
)}
559-
</Button>
560-
)}
639+
)}
640+
</Button>
561641
</div>
562642

563643
{selectedMarket && selectedMarketData ? (

0 commit comments

Comments
 (0)