@@ -4,13 +4,22 @@ import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
4
4
import type React from "react" ;
5
5
import type { JSX } from "react" ;
6
6
import type { Chain } from "../../../../../chains/types.js" ;
7
+ import { NATIVE_TOKEN_ADDRESS } from "../../../../../constants/addresses.js" ;
8
+ import { convertCryptoToFiat } from "../../../../../exports/pay.js" ;
7
9
import { useActiveWalletChain } from "../../../../../react/core/hooks/wallets/useActiveWalletChain.js" ;
8
- import {
9
- type GetWalletBalanceResult ,
10
- getWalletBalance ,
11
- } from "../../../../../wallets/utils/getWalletBalance.js" ;
10
+ import { getWalletBalance } from "../../../../../wallets/utils/getWalletBalance.js" ;
12
11
import { useAccountContext } from "./provider.js" ;
13
12
13
+ /**
14
+ * @internal
15
+ */
16
+ export type AccountBalanceFormatParams = {
17
+ tokenBalance : number ;
18
+ tokenSymbol : string ;
19
+ fiatBalance ?: number ;
20
+ fiatSymbol ?: string ;
21
+ } ;
22
+
14
23
/**
15
24
* Props for the AccountBalance component
16
25
* @component
@@ -33,7 +42,7 @@ export interface AccountBalanceProps
33
42
* use this function to transform the balance display value like round up the number
34
43
* Particularly useful to avoid overflowing-UI issues
35
44
*/
36
- formatFn ?: ( num : number ) => number ;
45
+ formatFn ?: ( props : AccountBalanceFormatParams ) => string ;
37
46
/**
38
47
* This component will be shown while the balance of the account is being fetched
39
48
* If not passed, the component will return `null`.
@@ -67,9 +76,11 @@ export interface AccountBalanceProps
67
76
* Optional `useQuery` params
68
77
*/
69
78
queryOptions ?: Omit <
70
- UseQueryOptions < GetWalletBalanceResult > ,
79
+ UseQueryOptions < AccountBalanceFormatParams > ,
71
80
"queryFn" | "queryKey"
72
81
> ;
82
+
83
+ showFiatValue ?: "USD" ;
73
84
}
74
85
75
86
/**
@@ -149,10 +160,11 @@ export interface AccountBalanceProps
149
160
export function AccountBalance ( {
150
161
chain,
151
162
tokenAddress,
152
- formatFn,
153
163
loadingComponent,
154
164
fallbackComponent,
155
165
queryOptions,
166
+ formatFn,
167
+ showFiatValue,
156
168
...restProps
157
169
} : AccountBalanceProps ) {
158
170
const { address, client } = useAccountContext ( ) ;
@@ -165,19 +177,59 @@ export function AccountBalance({
165
177
address || "0x0" ,
166
178
{ tokenAddress } ,
167
179
] as const ,
168
- queryFn : async ( ) => {
180
+ queryFn : async ( ) : Promise < AccountBalanceFormatParams > => {
169
181
if ( ! chainToLoad ) {
170
182
throw new Error ( "chain is required" ) ;
171
183
}
172
184
if ( ! client ) {
173
185
throw new Error ( "client is required" ) ;
174
186
}
175
- return getWalletBalance ( {
187
+ const tokenBalanceData = await getWalletBalance ( {
176
188
chain : chainToLoad ,
177
189
client,
178
190
address,
179
191
tokenAddress,
180
192
} ) ;
193
+
194
+ if ( ! tokenBalanceData ) {
195
+ throw new Error (
196
+ `Failed to retrieve ${ tokenAddress ? `token: ${ tokenAddress } ` : "native token" } balance for address: ${ address } on chainId:${ chainToLoad . id } ` ,
197
+ ) ;
198
+ }
199
+
200
+ if ( showFiatValue ) {
201
+ const fiatData = await convertCryptoToFiat ( {
202
+ fromAmount : Number ( tokenBalanceData . displayValue ) ,
203
+ fromTokenAddress : tokenAddress || NATIVE_TOKEN_ADDRESS ,
204
+ to : showFiatValue ,
205
+ chain : chainToLoad ,
206
+ client,
207
+ } ) . catch ( ( ) => undefined ) ;
208
+
209
+ // We can never support 100% of token out there, so if something fails to resolve, it's expected
210
+ // in that case just return the tokenBalance and symbol
211
+ return {
212
+ tokenBalance : Number ( tokenBalanceData . displayValue ) ,
213
+ tokenSymbol : tokenBalanceData . symbol ,
214
+ fiatBalance : fiatData ?. result ,
215
+ fiatSymbol : fiatData ?. result
216
+ ? new Intl . NumberFormat ( "en" , {
217
+ style : "currency" ,
218
+ currency : showFiatValue ,
219
+ minimumFractionDigits : 0 ,
220
+ maximumFractionDigits : 0 ,
221
+ } )
222
+ . formatToParts ( 0 )
223
+ . find ( ( p ) => p . type === "currency" ) ?. value ||
224
+ showFiatValue . toUpperCase ( )
225
+ : undefined ,
226
+ } ;
227
+ }
228
+
229
+ return {
230
+ tokenBalance : Number ( tokenBalanceData . displayValue ) ,
231
+ tokenSymbol : tokenBalanceData . symbol ,
232
+ } ;
181
233
} ,
182
234
...queryOptions ,
183
235
} ) ;
@@ -190,13 +242,24 @@ export function AccountBalance({
190
242
return fallbackComponent || null ;
191
243
}
192
244
193
- const displayValue = formatFn
194
- ? formatFn ( Number ( balanceQuery . data . displayValue ) )
195
- : balanceQuery . data . displayValue ;
245
+ if ( formatFn ) {
246
+ return < span { ...restProps } > { formatFn ( balanceQuery . data ) } </ span > ;
247
+ }
248
+
249
+ const { tokenBalance, tokenSymbol, fiatBalance, fiatSymbol } =
250
+ balanceQuery . data ;
251
+
252
+ if ( fiatBalance && fiatSymbol ) {
253
+ return (
254
+ < span { ...restProps } >
255
+ { `${ tokenBalance } ${ tokenSymbol } (${ fiatSymbol } ${ fiatBalance } )` }
256
+ </ span >
257
+ ) ;
258
+ }
196
259
197
260
return (
198
261
< span { ...restProps } >
199
- { displayValue } { balanceQuery . data . symbol }
262
+ { tokenBalance } { tokenSymbol }
200
263
</ span >
201
264
) ;
202
265
}
0 commit comments