@@ -3,14 +3,21 @@ import { isProd } from "@/constants/env-utils";
33import { useQuery } from "@tanstack/react-query" ;
44import { XIcon } from "lucide-react" ;
55import Link from "next/link" ;
6- import { type ThirdwebClient , defineChain , toTokens } from "thirdweb" ;
6+ import {
7+ NATIVE_TOKEN_ADDRESS ,
8+ type ThirdwebClient ,
9+ defineChain ,
10+ getAddress ,
11+ toTokens ,
12+ } from "thirdweb" ;
713import {
814 Blobbie ,
915 TokenIcon ,
1016 TokenProvider ,
1117 useActiveAccount ,
1218 useActiveWalletChain ,
1319} from "thirdweb/react" ;
20+ import { getWalletBalance } from "thirdweb/wallets" ;
1421import { ChainIconClient } from "../../../../../components/icons/ChainIcon" ;
1522import { useAllChainsData } from "../../../../../hooks/chains/allChains" ;
1623import { nebulaAppThirdwebClient } from "../../utils/nebulaThirdwebClient" ;
@@ -45,7 +52,7 @@ export function AssetsSectionUI(props: {
4552 { ! props . isPending &&
4653 props . data . map ( ( asset ) => (
4754 < AssetItem
48- key = { asset . token_address }
55+ key = { ` ${ asset . chain_id } - ${ asset . token_address } ` }
4956 asset = { asset }
5057 client = { props . client }
5158 />
@@ -78,6 +85,8 @@ function AssetItem(props: {
7885} ) {
7986 const { idToChain } = useAllChainsData ( ) ;
8087 const chainMeta = idToChain . get ( props . asset . chain_id ) ;
88+ const isNativeToken = props . asset . token_address === NATIVE_TOKEN_ADDRESS ;
89+
8190 return (
8291 < TokenProvider
8392 address = { props . asset . token_address }
@@ -88,7 +97,7 @@ function AssetItem(props: {
8897 < div className = "relative flex h-[48px] items-center gap-2.5 rounded-lg px-2 py-1 hover:bg-accent" >
8998 < div className = "relative" >
9099 < TokenIcon
91- className = "size-8 rounded-full"
100+ className = "size-8 rounded-full border "
92101 loadingComponent = {
93102 < Blobbie
94103 address = { props . asset . token_address }
@@ -102,25 +111,31 @@ function AssetItem(props: {
102111 />
103112 }
104113 />
105- < div className = "-right-0.5 -bottom-0.5 absolute rounded-full border bg-background p-0.5" >
106- < ChainIconClient
107- client = { props . client }
108- className = "size-3.5"
109- src = { chainMeta ?. icon ?. url || "" }
110- />
111- </ div >
114+ { ! isNativeToken && (
115+ < div className = "-right-0.5 -bottom-0.5 absolute rounded-full border bg-background p-0.5" >
116+ < ChainIconClient
117+ client = { props . client }
118+ className = "size-3.5"
119+ src = { chainMeta ?. icon ?. url || "" }
120+ />
121+ </ div >
122+ ) }
112123 </ div >
113124
114125 < div className = "flex min-w-0 flex-col text-sm" >
115126 < Link
116- href = { `https://thirdweb.com/${ props . asset . chain_id } /${ props . asset . token_address } ` }
127+ href = {
128+ isNativeToken
129+ ? `https://thirdweb.com/${ props . asset . chain_id } `
130+ : `https://thirdweb.com/${ props . asset . chain_id } /${ props . asset . token_address } `
131+ }
117132 target = "_blank"
118133 className = "truncate font-medium before:absolute before:inset-0"
119134 >
120135 { props . asset . name }
121136 </ Link >
122137
123- < p className = "text-muted-foreground text-sm" >
138+ < p className = "truncate text-muted-foreground text-sm" >
124139 { `${ toTokens ( BigInt ( props . asset . balance ) , props . asset . decimals ) } ${ props . asset . symbol } ` }
125140 </ p >
126141 </ div >
@@ -158,16 +173,85 @@ export function AssetsSection(props: {
158173 data : AssetBalance [ ] ;
159174 } ;
160175
161- return json . data ;
176+ const tokensToShowOnTop = new Set (
177+ [
178+ // base
179+ "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913" , // usdc,
180+ "0x0555E30da8f98308EdB960aa94C0Db47230d2B9c" , // wbtc
181+ "0x4200000000000000000000000000000000000006" , // wrapped eth
182+ // ethereum
183+ "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" , // usdc
184+ "0xdac17f958d2ee523a2206206994597c13d831ec7" , // usdt
185+ "0xB8c77482e45F1F44dE1745F52C74426C631bDD52" , // bnb
186+ "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" , // weth
187+ "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599" , // wbtc
188+ // optimism
189+ "0x4200000000000000000000000000000000000042" , // op token
190+ "0xdc6ff44d5d932cbd77b52e5612ba0529dc6226f1" , // world coin
191+ "0x94b008aa00579c1307b0ef2c499ad98a8ce58e58" , // usdt
192+ "0x0b2c639c533813f4aa9d7837caf62653d097ff85" , // usdc
193+ "0x4200000000000000000000000000000000000006" , // wrapped eth
194+ // polygon
195+ "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619" , // weth
196+ "0xc2132d05d31c914a87c6611c10748aeb04b58e8f" , // usdt
197+ "0x3BA4c387f786bFEE076A58914F5Bd38d668B42c3" , // bnb
198+ "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359" , // usdc
199+ "0x2791bca1f2de4661ed88a30c99a7a9449aa84174" , // usdc.e
200+ ] . map ( ( x ) => getAddress ( x ) ) ,
201+ ) ;
202+
203+ return json . data . sort ( ( a , b ) => {
204+ if ( tokensToShowOnTop . has ( getAddress ( a . token_address ) ) ) {
205+ return - 1 ;
206+ }
207+ if ( tokensToShowOnTop . has ( getAddress ( b . token_address ) ) ) {
208+ return 1 ;
209+ }
210+ return 0 ;
211+ } ) ;
162212 } ,
163213 enabled : ! ! account && ! ! activeChain ,
164214 } ) ;
165215
216+ const nativeBalances = useQuery ( {
217+ queryKey : [ "getWalletBalance" , account ?. address , activeChain ?. id ] ,
218+ queryFn : async ( ) => {
219+ if ( ! account || ! activeChain ) {
220+ return [ ] ;
221+ }
222+
223+ const chains = [ ...new Set ( [ 1 , 8453 , 10 , 137 , activeChain . id ] ) ] ;
224+
225+ const result = await Promise . allSettled (
226+ chains . map ( ( chain ) =>
227+ getWalletBalance ( {
228+ // eslint-disable-next-line no-restricted-syntax
229+ chain : defineChain ( chain ) ,
230+ client : props . client ,
231+ address : account . address ,
232+ } ) ,
233+ ) ,
234+ ) ;
235+
236+ return result
237+ . filter ( ( r ) => r . status === "fulfilled" )
238+ . map ( ( r ) => ( {
239+ chain_id : r . value . chainId ,
240+ token_address : r . value . tokenAddress ,
241+ balance : r . value . value . toString ( ) ,
242+ name : r . value . name ,
243+ symbol : r . value . symbol ,
244+ decimals : r . value . decimals ,
245+ } ) )
246+ . filter ( ( x ) => x . balance !== "0" ) as AssetBalance [ ] ;
247+ } ,
248+ } ) ;
249+
250+ const isPending = assetsQuery . isPending || nativeBalances . isPending ;
251+
252+ const data = [ ...( nativeBalances . data ?? [ ] ) , ...( assetsQuery . data ?? [ ] ) ] ;
253+
166254 return (
167- < AssetsSectionUI
168- data = { assetsQuery . data ?? [ ] }
169- isPending = { assetsQuery . isPending }
170- client = { props . client }
171- />
255+ < AssetsSectionUI data = { data } isPending = { isPending } client = { props . client } />
172256 ) ;
173257}
0 commit comments