@@ -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 ( ) ;
@@ -164,20 +176,61 @@ export function AccountBalance({
164
176
chainToLoad ?. id || - 1 ,
165
177
address || "0x0" ,
166
178
{ tokenAddress } ,
179
+ showFiatValue ,
167
180
] as const ,
168
- queryFn : async ( ) => {
181
+ queryFn : async ( ) : Promise < AccountBalanceFormatParams > => {
169
182
if ( ! chainToLoad ) {
170
183
throw new Error ( "chain is required" ) ;
171
184
}
172
185
if ( ! client ) {
173
186
throw new Error ( "client is required" ) ;
174
187
}
175
- return getWalletBalance ( {
188
+ const tokenBalanceData = await getWalletBalance ( {
176
189
chain : chainToLoad ,
177
190
client,
178
191
address,
179
192
tokenAddress,
180
193
} ) ;
194
+
195
+ if ( ! tokenBalanceData ) {
196
+ throw new Error (
197
+ `Failed to retrieve ${ tokenAddress ? `token: ${ tokenAddress } ` : "native token" } balance for address: ${ address } on chainId:${ chainToLoad . id } ` ,
198
+ ) ;
199
+ }
200
+
201
+ if ( showFiatValue ) {
202
+ const fiatData = await convertCryptoToFiat ( {
203
+ fromAmount : Number ( tokenBalanceData . displayValue ) ,
204
+ fromTokenAddress : tokenAddress || NATIVE_TOKEN_ADDRESS ,
205
+ to : showFiatValue ,
206
+ chain : chainToLoad ,
207
+ client,
208
+ } ) . catch ( ( ) => undefined ) ;
209
+
210
+ // We can never support 100% of token out there, so if something fails to resolve, it's expected
211
+ // in that case just return the tokenBalance and symbol
212
+ return {
213
+ tokenBalance : Number ( tokenBalanceData . displayValue ) ,
214
+ tokenSymbol : tokenBalanceData . symbol ,
215
+ fiatBalance : fiatData ?. result ,
216
+ fiatSymbol : fiatData ?. result
217
+ ? new Intl . NumberFormat ( "en" , {
218
+ style : "currency" ,
219
+ currency : showFiatValue ,
220
+ minimumFractionDigits : 0 ,
221
+ maximumFractionDigits : 0 ,
222
+ } )
223
+ . formatToParts ( 0 )
224
+ . find ( ( p ) => p . type === "currency" ) ?. value ||
225
+ showFiatValue . toUpperCase ( )
226
+ : undefined ,
227
+ } ;
228
+ }
229
+
230
+ return {
231
+ tokenBalance : Number ( tokenBalanceData . displayValue ) ,
232
+ tokenSymbol : tokenBalanceData . symbol ,
233
+ } ;
181
234
} ,
182
235
...queryOptions ,
183
236
} ) ;
@@ -190,13 +243,24 @@ export function AccountBalance({
190
243
return fallbackComponent || null ;
191
244
}
192
245
193
- const displayValue = formatFn
194
- ? formatFn ( Number ( balanceQuery . data . displayValue ) )
195
- : balanceQuery . data . displayValue ;
246
+ if ( formatFn ) {
247
+ return < span { ...restProps } > { formatFn ( balanceQuery . data ) } </ span > ;
248
+ }
249
+
250
+ const { tokenBalance, tokenSymbol, fiatBalance, fiatSymbol } =
251
+ balanceQuery . data ;
252
+
253
+ if ( fiatBalance && fiatSymbol ) {
254
+ return (
255
+ < span { ...restProps } >
256
+ { `${ tokenBalance } ${ tokenSymbol } (${ fiatSymbol } ${ fiatBalance } )` }
257
+ </ span >
258
+ ) ;
259
+ }
196
260
197
261
return (
198
262
< span { ...restProps } >
199
- { displayValue } { balanceQuery . data . symbol }
263
+ { tokenBalance } { tokenSymbol }
200
264
</ span >
201
265
) ;
202
266
}
0 commit comments