@@ -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' ;
2020import { base , mode } from 'wagmi/chains' ;
2121
2222import { 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