@@ -1814,15 +1814,9 @@ export class AssetsController extends BaseController<
18141814 ) ;
18151815 }
18161816
1817- const chainId = extractChainId ( normalizedAssetId ) ;
1818-
1819- const assets = this . #getAssetsFromState(
1820- [ { id : accountId } ] ,
1821- [ chainId ] ,
1822- [ 'fungible' ] ,
1823- ) ;
1824-
1825- return assets [ accountId ] ?. [ normalizedAssetId ] ;
1817+ return this . #getAssetFromState( accountId , normalizedAssetId , {
1818+ assetTypeSet : new Set ( [ 'fungible' ] ) ,
1819+ } ) ;
18261820 }
18271821
18281822 async getAssetsPrice (
@@ -2762,70 +2756,103 @@ export class AssetsController extends BaseController<
27622756
27632757 const accountBalances = this . state . assetsBalance [ account . id ] ?? { } ;
27642758
2765- for ( const [ assetId , balance ] of Object . entries ( accountBalances ) ) {
2759+ for ( const assetId of Object . keys ( accountBalances ) ) {
27662760 const typedAssetId = assetId as Caip19AssetId ;
27672761
2768- const metadataRaw = this . state . assetsInfo [ typedAssetId ] ;
2762+ const asset = this . #getAssetFromState( account . id , typedAssetId , {
2763+ chainIdSet,
2764+ assetTypeSet,
2765+ } ) ;
27692766
2770- // Skip assets without metadata
2771- if ( ! metadataRaw ) {
2772- continue ;
2767+ if ( asset ) {
2768+ result [ account . id ] [ typedAssetId ] = asset ;
27732769 }
2770+ }
2771+ }
27742772
2775- const metadata = metadataRaw ;
2773+ return result ;
2774+ }
27762775
2777- // Skip hidden assets (assetPreferences)
2778- const prefs = this . state . assetPreferences [ typedAssetId ] ;
2779- if ( prefs ?. hidden ) {
2780- continue ;
2781- }
2776+ /**
2777+ * Compose a single combined `Asset` (balance + metadata + price + computed
2778+ * `fiatValue`) for an account/asset pair directly from controller state,
2779+ * applying the same filtering rules as `#getAssetsFromState`.
2780+ *
2781+ * @param accountId - The account ID (`InternalAccount.id`).
2782+ * @param assetId - The normalized CAIP-19 asset ID.
2783+ * @param filters - Optional filters applied before composing the asset.
2784+ * @param filters.chainIdSet - When provided, the asset's chain must be in this set.
2785+ * @param filters.assetTypeSet - When provided, the asset's type must be in this set.
2786+ * @returns The combined `Asset`, or `undefined` when the asset is missing a
2787+ * balance/metadata, is hidden/filtered out, or fails a provided filter.
2788+ */
2789+ #getAssetFromState(
2790+ accountId : AccountId ,
2791+ assetId : Caip19AssetId ,
2792+ filters ?: {
2793+ chainIdSet ?: Set < ChainId > ;
2794+ assetTypeSet ?: Set < AssetType > ;
2795+ } ,
2796+ ) : Asset | undefined {
2797+ const balance = this . state . assetsBalance [ accountId ] ?. [ assetId ] ;
27822798
2783- const assetChainId = extractChainId ( typedAssetId ) ;
2799+ // Skip assets without a balance entry
2800+ if ( ! balance ) {
2801+ return undefined ;
2802+ }
27842803
2785- // Skip native tokens on Tempo networks
2786- if ( this . #shouldHideNativeToken( assetChainId , metadata ) ) {
2787- continue ;
2788- }
2804+ const metadata = this . state . assetsInfo [ assetId ] ;
27892805
2790- if ( ! chainIdSet . has ( assetChainId ) ) {
2791- continue ;
2792- }
2806+ // Skip assets without metadata
2807+ if ( ! metadata ) {
2808+ return undefined ;
2809+ }
27932810
2794- // Filter by asset type
2795- const tokenAssetType = this . #tokenStandardToAssetType ( metadata . type ) ;
2796- if ( ! assetTypeSet . has ( tokenAssetType ) ) {
2797- continue ;
2798- }
2811+ // Skip hidden assets (assetPreferences)
2812+ const prefs = this . state . assetPreferences [ assetId ] ;
2813+ if ( prefs ?. hidden ) {
2814+ return undefined ;
2815+ }
27992816
2800- const typedBalance = balance ;
2801- const priceRaw = this . state . assetsPrice [ typedAssetId ] ;
2802- const price : AssetPrice = priceRaw ?? {
2803- price : 0 ,
2804- lastUpdated : 0 ,
2805- } ;
2817+ const assetChainId = extractChainId ( assetId ) ;
28062818
2807- // Compute fiat value using BigNumber for precision
2808- // Note: typedBalance.amount is already in human-readable format (e.g., "1" for 1 ETH)
2809- // so we do NOT divide by 10^decimals here
2810- const balanceAmount = new BigNumberJS ( typedBalance . amount || '0' ) ;
2811- const fiatValue = balanceAmount
2812- . multipliedBy ( price . price || 0 )
2813- . toNumber ( ) ;
2814-
2815- const asset : Asset = {
2816- id : typedAssetId ,
2817- chainId : assetChainId ,
2818- balance : typedBalance ,
2819- metadata,
2820- price,
2821- fiatValue,
2822- } ;
2819+ // Skip native tokens on Tempo networks
2820+ if ( this . #shouldHideNativeToken( assetChainId , metadata ) ) {
2821+ return undefined ;
2822+ }
2823+
2824+ if ( filters ?. chainIdSet && ! filters . chainIdSet . has ( assetChainId ) ) {
2825+ return undefined ;
2826+ }
28232827
2824- result [ account . id ] [ typedAssetId ] = asset ;
2828+ // Filter by asset type
2829+ if ( filters ?. assetTypeSet ) {
2830+ const tokenAssetType = this . #tokenStandardToAssetType( metadata . type ) ;
2831+ if ( ! filters . assetTypeSet . has ( tokenAssetType ) ) {
2832+ return undefined ;
28252833 }
28262834 }
28272835
2828- return result ;
2836+ const priceRaw = this . state . assetsPrice [ assetId ] ;
2837+ const price : AssetPrice = priceRaw ?? {
2838+ price : 0 ,
2839+ lastUpdated : 0 ,
2840+ } ;
2841+
2842+ // Compute fiat value using BigNumber for precision
2843+ // Note: balance.amount is already in human-readable format (e.g., "1" for 1 ETH)
2844+ // so we do NOT divide by 10^decimals here
2845+ const balanceAmount = new BigNumberJS ( balance . amount || '0' ) ;
2846+ const fiatValue = balanceAmount . multipliedBy ( price . price || 0 ) . toNumber ( ) ;
2847+
2848+ return {
2849+ id : assetId ,
2850+ chainId : assetChainId ,
2851+ balance,
2852+ metadata,
2853+ price,
2854+ fiatValue,
2855+ } ;
28292856 }
28302857
28312858 /**
0 commit comments