@metamask-previews/assets-controller 14.0.2-preview-4f4c98e → 14.0.2-preview-eb263b0ee
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -5
- package/dist/AssetsController-method-action-types.cjs +7 -0
- package/dist/AssetsController-method-action-types.cjs.map +1 -0
- package/dist/{AssetsController-method-action-types.d.ts → AssetsController-method-action-types.d.cts} +2 -2
- package/dist/AssetsController-method-action-types.d.cts.map +1 -0
- package/dist/AssetsController-method-action-types.d.mts +181 -0
- package/dist/AssetsController-method-action-types.d.mts.map +1 -0
- package/dist/{AssetsController-method-action-types.js → AssetsController-method-action-types.mjs} +1 -1
- package/dist/AssetsController-method-action-types.mjs.map +1 -0
- package/dist/AssetsController.cjs +2559 -0
- package/dist/AssetsController.cjs.map +1 -0
- package/dist/{AssetsController.d.ts → AssetsController.d.cts} +30 -30
- package/dist/AssetsController.d.cts.map +1 -0
- package/dist/AssetsController.d.mts +395 -0
- package/dist/AssetsController.d.mts.map +1 -0
- package/dist/{AssetsController.js → AssetsController.mjs} +29 -28
- package/dist/AssetsController.mjs.map +1 -0
- package/dist/data-sources/AbstractDataSource.cjs +111 -0
- package/dist/data-sources/AbstractDataSource.cjs.map +1 -0
- package/dist/data-sources/{AbstractDataSource.d.ts → AbstractDataSource.d.cts} +2 -2
- package/dist/data-sources/AbstractDataSource.d.cts.map +1 -0
- package/dist/data-sources/AbstractDataSource.d.mts +113 -0
- package/dist/data-sources/AbstractDataSource.d.mts.map +1 -0
- package/dist/data-sources/{AbstractDataSource.js → AbstractDataSource.mjs} +1 -1
- package/dist/data-sources/AbstractDataSource.mjs.map +1 -0
- package/dist/data-sources/AccountActivityDataSource.cjs +267 -0
- package/dist/data-sources/AccountActivityDataSource.cjs.map +1 -0
- package/dist/data-sources/{AccountActivityDataSource.d.ts → AccountActivityDataSource.d.cts} +6 -6
- package/dist/data-sources/AccountActivityDataSource.d.cts.map +1 -0
- package/dist/data-sources/AccountActivityDataSource.d.mts +80 -0
- package/dist/data-sources/AccountActivityDataSource.d.mts.map +1 -0
- package/dist/data-sources/{AccountActivityDataSource.js → AccountActivityDataSource.mjs} +11 -11
- package/dist/data-sources/AccountActivityDataSource.mjs.map +1 -0
- package/dist/data-sources/AccountsApiDataSource.cjs +586 -0
- package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -0
- package/dist/data-sources/{AccountsApiDataSource.d.ts → AccountsApiDataSource.d.cts} +7 -7
- package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -0
- package/dist/data-sources/AccountsApiDataSource.d.mts +82 -0
- package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -0
- package/dist/data-sources/{AccountsApiDataSource.js → AccountsApiDataSource.mjs} +8 -7
- package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -0
- package/dist/data-sources/PriceDataSource.cjs +466 -0
- package/dist/data-sources/PriceDataSource.cjs.map +1 -0
- package/dist/data-sources/{PriceDataSource.d.ts → PriceDataSource.d.cts} +5 -5
- package/dist/data-sources/PriceDataSource.d.cts.map +1 -0
- package/dist/data-sources/PriceDataSource.d.mts +100 -0
- package/dist/data-sources/PriceDataSource.d.mts.map +1 -0
- package/dist/data-sources/{PriceDataSource.js → PriceDataSource.mjs} +8 -7
- package/dist/data-sources/PriceDataSource.mjs.map +1 -0
- package/dist/data-sources/RpcDataSource.cjs +1021 -0
- package/dist/data-sources/RpcDataSource.cjs.map +1 -0
- package/dist/data-sources/{RpcDataSource.d.ts → RpcDataSource.d.cts} +10 -10
- package/dist/data-sources/RpcDataSource.d.cts.map +1 -0
- package/dist/data-sources/RpcDataSource.d.mts +174 -0
- package/dist/data-sources/RpcDataSource.d.mts.map +1 -0
- package/dist/data-sources/{RpcDataSource.js → RpcDataSource.mjs} +11 -11
- package/dist/data-sources/RpcDataSource.mjs.map +1 -0
- package/dist/data-sources/SnapDataSource.cjs +443 -0
- package/dist/data-sources/SnapDataSource.cjs.map +1 -0
- package/dist/data-sources/{SnapDataSource.d.ts → SnapDataSource.d.cts} +8 -8
- package/dist/data-sources/SnapDataSource.d.cts.map +1 -0
- package/dist/data-sources/SnapDataSource.d.mts +127 -0
- package/dist/data-sources/SnapDataSource.d.mts.map +1 -0
- package/dist/data-sources/{SnapDataSource.js → SnapDataSource.mjs} +6 -6
- package/dist/data-sources/SnapDataSource.mjs.map +1 -0
- package/dist/data-sources/StakedBalanceDataSource.cjs +616 -0
- package/dist/data-sources/StakedBalanceDataSource.cjs.map +1 -0
- package/dist/data-sources/{StakedBalanceDataSource.d.ts → StakedBalanceDataSource.d.cts} +5 -5
- package/dist/data-sources/StakedBalanceDataSource.d.cts.map +1 -0
- package/dist/data-sources/StakedBalanceDataSource.d.mts +72 -0
- package/dist/data-sources/StakedBalanceDataSource.d.mts.map +1 -0
- package/dist/data-sources/{StakedBalanceDataSource.js → StakedBalanceDataSource.mjs} +7 -7
- package/dist/data-sources/StakedBalanceDataSource.mjs.map +1 -0
- package/dist/data-sources/TokenDataSource.cjs +583 -0
- package/dist/data-sources/TokenDataSource.cjs.map +1 -0
- package/dist/data-sources/{TokenDataSource.d.ts → TokenDataSource.d.cts} +5 -5
- package/dist/data-sources/TokenDataSource.d.cts.map +1 -0
- package/dist/data-sources/TokenDataSource.d.mts +81 -0
- package/dist/data-sources/TokenDataSource.d.mts.map +1 -0
- package/dist/data-sources/{TokenDataSource.js → TokenDataSource.mjs} +8 -7
- package/dist/data-sources/TokenDataSource.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.cjs +705 -0
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/{MulticallClient.d.ts → MulticallClient.d.cts} +3 -3
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.mts +65 -0
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/{MulticallClient.js → MulticallClient.mjs} +5 -5
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.cjs +312 -0
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/{TokensApiClient.d.ts → TokensApiClient.d.cts} +2 -2
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.mts +61 -0
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/{TokensApiClient.js → TokensApiClient.mjs} +2 -2
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/index.cjs +10 -0
- package/dist/data-sources/evm-rpc-services/clients/index.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/index.d.cts +4 -0
- package/dist/data-sources/evm-rpc-services/clients/index.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/index.d.mts +4 -0
- package/dist/data-sources/evm-rpc-services/clients/index.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/clients/index.mjs +3 -0
- package/dist/data-sources/evm-rpc-services/clients/index.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/index.cjs +17 -0
- package/dist/data-sources/evm-rpc-services/index.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/{index.d.ts → index.d.cts} +5 -5
- package/dist/data-sources/evm-rpc-services/index.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/index.d.mts +5 -0
- package/dist/data-sources/evm-rpc-services/index.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/index.mjs +4 -0
- package/dist/data-sources/evm-rpc-services/index.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.cjs +247 -0
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/{BalanceFetcher.d.ts → BalanceFetcher.d.cts} +11 -11
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.mts +96 -0
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/{BalanceFetcher.js → BalanceFetcher.mjs} +5 -5
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.cjs +132 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/{StakedBalanceFetcher.d.ts → StakedBalanceFetcher.d.cts} +14 -13
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.mts +81 -0
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/{StakedBalanceFetcher.js → StakedBalanceFetcher.mjs} +6 -5
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs +230 -0
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/{TokenDetector.d.ts → TokenDetector.d.cts} +12 -12
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts +78 -0
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/{TokenDetector.js → TokenDetector.mjs} +4 -4
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/index.cjs +13 -0
- package/dist/data-sources/evm-rpc-services/services/index.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/{index.d.ts → index.d.cts} +4 -4
- package/dist/data-sources/evm-rpc-services/services/index.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/index.d.mts +4 -0
- package/dist/data-sources/evm-rpc-services/services/index.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/services/index.mjs +4 -0
- package/dist/data-sources/evm-rpc-services/services/index.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/assets.cjs +3 -0
- package/dist/data-sources/evm-rpc-services/types/assets.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/{assets.d.ts → assets.d.cts} +3 -3
- package/dist/data-sources/evm-rpc-services/types/assets.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/assets.d.mts +53 -0
- package/dist/data-sources/evm-rpc-services/types/assets.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/assets.mjs +2 -0
- package/dist/data-sources/evm-rpc-services/types/assets.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/config.cjs +3 -0
- package/dist/data-sources/evm-rpc-services/types/config.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/{config.d.ts → config.d.cts} +2 -2
- package/dist/data-sources/evm-rpc-services/types/config.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/config.d.mts +18 -0
- package/dist/data-sources/evm-rpc-services/types/config.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/config.mjs +2 -0
- package/dist/data-sources/evm-rpc-services/types/config.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/core.cjs +3 -0
- package/dist/data-sources/evm-rpc-services/types/core.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/{core.d.ts → core.d.cts} +2 -2
- package/dist/data-sources/evm-rpc-services/types/core.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/core.d.mts +19 -0
- package/dist/data-sources/evm-rpc-services/types/core.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/core.mjs +2 -0
- package/dist/data-sources/evm-rpc-services/types/core.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/index.cjs +3 -0
- package/dist/data-sources/evm-rpc-services/types/index.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/index.d.cts +7 -0
- package/dist/data-sources/evm-rpc-services/types/index.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/index.d.mts +7 -0
- package/dist/data-sources/evm-rpc-services/types/index.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/index.mjs +2 -0
- package/dist/data-sources/evm-rpc-services/types/index.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/multicall.cjs +3 -0
- package/dist/data-sources/evm-rpc-services/types/multicall.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/{multicall.d.ts → multicall.d.cts} +2 -2
- package/dist/data-sources/evm-rpc-services/types/multicall.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/multicall.d.mts +24 -0
- package/dist/data-sources/evm-rpc-services/types/multicall.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/multicall.mjs +2 -0
- package/dist/data-sources/evm-rpc-services/types/multicall.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/services.cjs +3 -0
- package/dist/data-sources/evm-rpc-services/types/services.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/{services.d.ts → services.d.cts} +3 -3
- package/dist/data-sources/evm-rpc-services/types/services.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/services.d.mts +70 -0
- package/dist/data-sources/evm-rpc-services/types/services.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/services.mjs +2 -0
- package/dist/data-sources/evm-rpc-services/types/services.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/state.cjs +3 -0
- package/dist/data-sources/evm-rpc-services/types/state.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/{state.d.ts → state.d.cts} +2 -2
- package/dist/data-sources/evm-rpc-services/types/state.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/state.d.mts +58 -0
- package/dist/data-sources/evm-rpc-services/types/state.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/types/state.mjs +2 -0
- package/dist/data-sources/evm-rpc-services/types/state.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/assets.cjs +9 -0
- package/dist/data-sources/evm-rpc-services/utils/assets.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/{assets.d.ts → assets.d.cts} +2 -2
- package/dist/data-sources/evm-rpc-services/utils/assets.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/assets.d.mts +3 -0
- package/dist/data-sources/evm-rpc-services/utils/assets.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/{assets.js → assets.mjs} +2 -2
- package/dist/data-sources/evm-rpc-services/utils/assets.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/batch.cjs +45 -0
- package/dist/data-sources/evm-rpc-services/utils/batch.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/{batch.d.ts → batch.d.cts} +1 -1
- package/dist/data-sources/evm-rpc-services/utils/batch.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/batch.d.mts +28 -0
- package/dist/data-sources/evm-rpc-services/utils/batch.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/{batch.js → batch.mjs} +1 -1
- package/dist/data-sources/evm-rpc-services/utils/batch.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/index.cjs +15 -0
- package/dist/data-sources/evm-rpc-services/utils/index.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/index.d.cts +4 -0
- package/dist/data-sources/evm-rpc-services/utils/index.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/index.d.mts +4 -0
- package/dist/data-sources/evm-rpc-services/utils/index.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/index.mjs +4 -0
- package/dist/data-sources/evm-rpc-services/utils/index.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.cjs +47 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/{parsing.d.ts → parsing.d.cts} +3 -3
- package/dist/data-sources/evm-rpc-services/utils/parsing.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.d.mts +25 -0
- package/dist/data-sources/evm-rpc-services/utils/parsing.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/{parsing.js → parsing.mjs} +3 -3
- package/dist/data-sources/evm-rpc-services/utils/parsing.mjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.cjs +68 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.cjs.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/{staking-contracts.d.ts → staking-contracts.d.cts} +1 -1
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.cts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.mts +25 -0
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.mts.map +1 -0
- package/dist/data-sources/evm-rpc-services/utils/{staking-contracts.js → staking-contracts.mjs} +3 -3
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.mjs.map +1 -0
- package/dist/data-sources/index.cjs +30 -0
- package/dist/data-sources/index.cjs.map +1 -0
- package/dist/data-sources/{index.d.ts → index.d.cts} +9 -9
- package/dist/data-sources/index.d.cts.map +1 -0
- package/dist/data-sources/index.d.mts +9 -0
- package/dist/data-sources/index.d.mts.map +1 -0
- package/dist/data-sources/index.mjs +14 -0
- package/dist/data-sources/index.mjs.map +1 -0
- package/dist/defaults.cjs +125 -0
- package/dist/defaults.cjs.map +1 -0
- package/dist/{defaults.d.ts → defaults.d.cts} +2 -2
- package/dist/defaults.d.cts.map +1 -0
- package/dist/defaults.d.mts +50 -0
- package/dist/defaults.d.mts.map +1 -0
- package/dist/{defaults.js → defaults.mjs} +1 -1
- package/dist/defaults.mjs.map +1 -0
- package/dist/errors.cjs +25 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/{errors.d.ts → errors.d.cts} +1 -1
- package/dist/errors.d.cts.map +1 -0
- package/dist/errors.d.mts +25 -0
- package/dist/errors.d.mts.map +1 -0
- package/dist/{errors.js → errors.mjs} +1 -1
- package/dist/errors.mjs.map +1 -0
- package/dist/index.cjs +67 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{index.d.ts → index.d.cts} +26 -26
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +26 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/{index.js → index.mjs} +13 -13
- package/dist/index.mjs.map +1 -0
- package/dist/logger.cjs +7 -0
- package/dist/logger.cjs.map +1 -0
- package/dist/logger.d.cts +5 -0
- package/dist/logger.d.cts.map +1 -0
- package/dist/logger.d.mts +5 -0
- package/dist/logger.d.mts.map +1 -0
- package/dist/logger.mjs +4 -0
- package/dist/logger.mjs.map +1 -0
- package/dist/middlewares/CustomAssetGraduationMiddleware.cjs +132 -0
- package/dist/middlewares/CustomAssetGraduationMiddleware.cjs.map +1 -0
- package/dist/middlewares/{CustomAssetGraduationMiddleware.d.ts → CustomAssetGraduationMiddleware.d.cts} +2 -2
- package/dist/middlewares/CustomAssetGraduationMiddleware.d.cts.map +1 -0
- package/dist/middlewares/CustomAssetGraduationMiddleware.d.mts +32 -0
- package/dist/middlewares/CustomAssetGraduationMiddleware.d.mts.map +1 -0
- package/dist/middlewares/{CustomAssetGraduationMiddleware.js → CustomAssetGraduationMiddleware.mjs} +5 -5
- package/dist/middlewares/CustomAssetGraduationMiddleware.mjs.map +1 -0
- package/dist/middlewares/DetectionMiddleware.cjs +154 -0
- package/dist/middlewares/DetectionMiddleware.cjs.map +1 -0
- package/dist/middlewares/{DetectionMiddleware.d.ts → DetectionMiddleware.d.cts} +2 -2
- package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -0
- package/dist/middlewares/DetectionMiddleware.d.mts +40 -0
- package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -0
- package/dist/middlewares/{DetectionMiddleware.js → DetectionMiddleware.mjs} +4 -4
- package/dist/middlewares/DetectionMiddleware.mjs.map +1 -0
- package/dist/middlewares/ParallelMiddleware.cjs +263 -0
- package/dist/middlewares/ParallelMiddleware.cjs.map +1 -0
- package/dist/middlewares/{ParallelMiddleware.d.ts → ParallelMiddleware.d.cts} +2 -2
- package/dist/middlewares/ParallelMiddleware.d.cts.map +1 -0
- package/dist/middlewares/ParallelMiddleware.d.mts +41 -0
- package/dist/middlewares/ParallelMiddleware.d.mts.map +1 -0
- package/dist/middlewares/{ParallelMiddleware.js → ParallelMiddleware.mjs} +9 -2
- package/dist/middlewares/{ParallelMiddleware.js.map → ParallelMiddleware.mjs.map} +1 -1
- package/dist/middlewares/RpcFallbackMiddleware.cjs +90 -0
- package/dist/middlewares/RpcFallbackMiddleware.cjs.map +1 -0
- package/dist/middlewares/{RpcFallbackMiddleware.d.ts → RpcFallbackMiddleware.d.cts} +2 -2
- package/dist/middlewares/RpcFallbackMiddleware.d.cts.map +1 -0
- package/dist/middlewares/RpcFallbackMiddleware.d.mts +23 -0
- package/dist/middlewares/RpcFallbackMiddleware.d.mts.map +1 -0
- package/dist/middlewares/{RpcFallbackMiddleware.js → RpcFallbackMiddleware.mjs} +4 -4
- package/dist/middlewares/RpcFallbackMiddleware.mjs.map +1 -0
- package/dist/middlewares/index.cjs +14 -0
- package/dist/middlewares/index.cjs.map +1 -0
- package/dist/middlewares/index.d.cts +9 -0
- package/dist/middlewares/index.d.cts.map +1 -0
- package/dist/middlewares/index.d.mts +9 -0
- package/dist/middlewares/index.d.mts.map +1 -0
- package/dist/middlewares/index.mjs +5 -0
- package/dist/middlewares/index.mjs.map +1 -0
- package/dist/migrations/healAssetsInfoMetadata.cjs +385 -0
- package/dist/migrations/healAssetsInfoMetadata.cjs.map +1 -0
- package/dist/migrations/{healAssetsInfoMetadata.d.ts → healAssetsInfoMetadata.d.cts} +4 -4
- package/dist/migrations/healAssetsInfoMetadata.d.cts.map +1 -0
- package/dist/migrations/healAssetsInfoMetadata.d.mts +106 -0
- package/dist/migrations/healAssetsInfoMetadata.d.mts.map +1 -0
- package/dist/migrations/{healAssetsInfoMetadata.js → healAssetsInfoMetadata.mjs} +5 -4
- package/dist/migrations/healAssetsInfoMetadata.mjs.map +1 -0
- package/dist/selectors/balance.cjs +532 -0
- package/dist/selectors/balance.cjs.map +1 -0
- package/dist/selectors/{balance.d.ts → balance.d.cts} +6 -6
- package/dist/selectors/balance.d.cts.map +1 -0
- package/dist/selectors/balance.d.mts +103 -0
- package/dist/selectors/balance.d.mts.map +1 -0
- package/dist/selectors/{balance.js → balance.mjs} +5 -5
- package/dist/selectors/balance.mjs.map +1 -0
- package/dist/types.cjs +39 -0
- package/dist/types.cjs.map +1 -0
- package/dist/{types.d.ts → types.d.cts} +4 -4
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +533 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/{types.js → types.mjs} +1 -1
- package/dist/types.mjs.map +1 -0
- package/dist/utils/constants.cjs +5 -0
- package/dist/utils/constants.cjs.map +1 -0
- package/dist/utils/constants.d.cts +2 -0
- package/dist/utils/constants.d.cts.map +1 -0
- package/dist/utils/constants.d.mts +2 -0
- package/dist/utils/constants.d.mts.map +1 -0
- package/dist/utils/{constants.js → constants.mjs} +1 -1
- package/dist/utils/constants.mjs.map +1 -0
- package/dist/utils/customAssetsRpcSupplement.cjs +72 -0
- package/dist/utils/customAssetsRpcSupplement.cjs.map +1 -0
- package/dist/utils/{customAssetsRpcSupplement.d.ts → customAssetsRpcSupplement.d.cts} +2 -2
- package/dist/utils/customAssetsRpcSupplement.d.cts.map +1 -0
- package/dist/utils/customAssetsRpcSupplement.d.mts +60 -0
- package/dist/utils/customAssetsRpcSupplement.d.mts.map +1 -0
- package/dist/utils/{customAssetsRpcSupplement.js → customAssetsRpcSupplement.mjs} +2 -2
- package/dist/utils/customAssetsRpcSupplement.mjs.map +1 -0
- package/dist/utils/dedupingBatchFetcher.cjs +168 -0
- package/dist/utils/dedupingBatchFetcher.cjs.map +1 -0
- package/dist/utils/{dedupingBatchFetcher.d.ts → dedupingBatchFetcher.d.cts} +1 -1
- package/dist/utils/dedupingBatchFetcher.d.cts.map +1 -0
- package/dist/utils/dedupingBatchFetcher.d.mts +72 -0
- package/dist/utils/dedupingBatchFetcher.d.mts.map +1 -0
- package/dist/utils/{dedupingBatchFetcher.js → dedupingBatchFetcher.mjs} +1 -1
- package/dist/utils/dedupingBatchFetcher.mjs.map +1 -0
- package/dist/utils/fetchWithTimeout.cjs +30 -0
- package/dist/utils/fetchWithTimeout.cjs.map +1 -0
- package/dist/utils/{fetchWithTimeout.d.ts → fetchWithTimeout.d.cts} +1 -1
- package/dist/utils/fetchWithTimeout.d.cts.map +1 -0
- package/dist/utils/fetchWithTimeout.d.mts +11 -0
- package/dist/utils/fetchWithTimeout.d.mts.map +1 -0
- package/dist/utils/{fetchWithTimeout.js → fetchWithTimeout.mjs} +1 -1
- package/dist/utils/fetchWithTimeout.mjs.map +1 -0
- package/dist/utils/formatExchangeRatesForBridge.cjs +161 -0
- package/dist/utils/formatExchangeRatesForBridge.cjs.map +1 -0
- package/dist/utils/{formatExchangeRatesForBridge.d.ts → formatExchangeRatesForBridge.d.cts} +3 -3
- package/dist/utils/formatExchangeRatesForBridge.d.cts.map +1 -0
- package/dist/utils/formatExchangeRatesForBridge.d.mts +43 -0
- package/dist/utils/formatExchangeRatesForBridge.d.mts.map +1 -0
- package/dist/utils/{formatExchangeRatesForBridge.js → formatExchangeRatesForBridge.mjs} +7 -6
- package/dist/utils/formatExchangeRatesForBridge.mjs.map +1 -0
- package/dist/utils/formatStateForTransactionPay.cjs +174 -0
- package/dist/utils/formatStateForTransactionPay.cjs.map +1 -0
- package/dist/utils/{formatStateForTransactionPay.d.ts → formatStateForTransactionPay.d.cts} +3 -3
- package/dist/utils/formatStateForTransactionPay.d.cts.map +1 -0
- package/dist/utils/formatStateForTransactionPay.d.mts +72 -0
- package/dist/utils/formatStateForTransactionPay.d.mts.map +1 -0
- package/dist/utils/{formatStateForTransactionPay.js → formatStateForTransactionPay.mjs} +8 -7
- package/dist/utils/formatStateForTransactionPay.mjs.map +1 -0
- package/dist/utils/index.cjs +21 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +9 -0
- package/dist/utils/index.d.cts.map +1 -0
- package/dist/utils/index.d.mts +9 -0
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/index.mjs +7 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/native-assets.cjs +64 -0
- package/dist/utils/native-assets.cjs.map +1 -0
- package/dist/utils/{native-assets.d.ts → native-assets.d.cts} +2 -2
- package/dist/utils/native-assets.d.cts.map +1 -0
- package/dist/utils/native-assets.d.mts +19 -0
- package/dist/utils/native-assets.d.mts.map +1 -0
- package/dist/utils/{native-assets.js → native-assets.mjs} +5 -5
- package/dist/utils/native-assets.mjs.map +1 -0
- package/dist/utils/normalizeAmountString.cjs +64 -0
- package/dist/utils/normalizeAmountString.cjs.map +1 -0
- package/dist/utils/{normalizeAmountString.d.ts → normalizeAmountString.d.cts} +1 -1
- package/dist/utils/normalizeAmountString.d.cts.map +1 -0
- package/dist/utils/normalizeAmountString.d.mts +35 -0
- package/dist/utils/normalizeAmountString.d.mts.map +1 -0
- package/dist/utils/{normalizeAmountString.js → normalizeAmountString.mjs} +2 -2
- package/dist/utils/normalizeAmountString.mjs.map +1 -0
- package/dist/utils/normalizeAssetId.cjs +60 -0
- package/dist/utils/normalizeAssetId.cjs.map +1 -0
- package/dist/utils/{normalizeAssetId.d.ts → normalizeAssetId.d.cts} +3 -3
- package/dist/utils/normalizeAssetId.d.cts.map +1 -0
- package/dist/utils/normalizeAssetId.d.mts +32 -0
- package/dist/utils/normalizeAssetId.d.mts.map +1 -0
- package/dist/utils/{normalizeAssetId.js → normalizeAssetId.mjs} +11 -4
- package/dist/utils/normalizeAssetId.mjs.map +1 -0
- package/dist/utils/snaps-assets-migration.cjs +171 -0
- package/dist/utils/snaps-assets-migration.cjs.map +1 -0
- package/dist/utils/{snaps-assets-migration.d.ts → snaps-assets-migration.d.cts} +5 -5
- package/dist/utils/snaps-assets-migration.d.cts.map +1 -0
- package/dist/utils/snaps-assets-migration.d.mts +113 -0
- package/dist/utils/snaps-assets-migration.d.mts.map +1 -0
- package/dist/utils/{snaps-assets-migration.js → snaps-assets-migration.mjs} +2 -2
- package/dist/utils/snaps-assets-migration.mjs.map +1 -0
- package/dist/utils/trace.cjs +120 -0
- package/dist/utils/trace.cjs.map +1 -0
- package/dist/utils/{trace.d.ts → trace.d.cts} +2 -2
- package/dist/utils/trace.d.cts.map +1 -0
- package/dist/utils/trace.d.mts +52 -0
- package/dist/utils/trace.d.mts.map +1 -0
- package/dist/utils/{trace.js → trace.mjs} +1 -1
- package/dist/utils/trace.mjs.map +1 -0
- package/package.json +18 -15
- package/dist/AssetsController-method-action-types.d.ts.map +0 -1
- package/dist/AssetsController-method-action-types.js.map +0 -1
- package/dist/AssetsController.d.ts.map +0 -1
- package/dist/AssetsController.js.map +0 -1
- package/dist/data-sources/AbstractDataSource.d.ts.map +0 -1
- package/dist/data-sources/AbstractDataSource.js.map +0 -1
- package/dist/data-sources/AccountActivityDataSource.d.ts.map +0 -1
- package/dist/data-sources/AccountActivityDataSource.js.map +0 -1
- package/dist/data-sources/AccountsApiDataSource.d.ts.map +0 -1
- package/dist/data-sources/AccountsApiDataSource.js.map +0 -1
- package/dist/data-sources/PriceDataSource.d.ts.map +0 -1
- package/dist/data-sources/PriceDataSource.js.map +0 -1
- package/dist/data-sources/RpcDataSource.d.ts.map +0 -1
- package/dist/data-sources/RpcDataSource.js.map +0 -1
- package/dist/data-sources/SnapDataSource.d.ts.map +0 -1
- package/dist/data-sources/SnapDataSource.js.map +0 -1
- package/dist/data-sources/StakedBalanceDataSource.d.ts.map +0 -1
- package/dist/data-sources/StakedBalanceDataSource.js.map +0 -1
- package/dist/data-sources/TokenDataSource.d.ts.map +0 -1
- package/dist/data-sources/TokenDataSource.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/clients/MulticallClient.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/clients/index.d.ts +0 -4
- package/dist/data-sources/evm-rpc-services/clients/index.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/clients/index.js +0 -3
- package/dist/data-sources/evm-rpc-services/clients/index.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/index.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/index.js +0 -4
- package/dist/data-sources/evm-rpc-services/index.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/services/TokenDetector.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/services/index.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/services/index.js +0 -4
- package/dist/data-sources/evm-rpc-services/services/index.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/assets.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/assets.js +0 -2
- package/dist/data-sources/evm-rpc-services/types/assets.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/config.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/config.js +0 -2
- package/dist/data-sources/evm-rpc-services/types/config.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/core.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/core.js +0 -2
- package/dist/data-sources/evm-rpc-services/types/core.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/index.d.ts +0 -7
- package/dist/data-sources/evm-rpc-services/types/index.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/index.js +0 -2
- package/dist/data-sources/evm-rpc-services/types/index.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/multicall.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/multicall.js +0 -2
- package/dist/data-sources/evm-rpc-services/types/multicall.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/services.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/services.js +0 -2
- package/dist/data-sources/evm-rpc-services/types/services.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/state.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/types/state.js +0 -2
- package/dist/data-sources/evm-rpc-services/types/state.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/utils/assets.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/utils/assets.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/utils/batch.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/utils/batch.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/utils/index.d.ts +0 -4
- package/dist/data-sources/evm-rpc-services/utils/index.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/utils/index.js +0 -4
- package/dist/data-sources/evm-rpc-services/utils/index.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/utils/parsing.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/utils/parsing.js.map +0 -1
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.ts.map +0 -1
- package/dist/data-sources/evm-rpc-services/utils/staking-contracts.js.map +0 -1
- package/dist/data-sources/index.d.ts.map +0 -1
- package/dist/data-sources/index.js +0 -14
- package/dist/data-sources/index.js.map +0 -1
- package/dist/defaults.d.ts.map +0 -1
- package/dist/defaults.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/logger.d.ts +0 -4
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -4
- package/dist/logger.js.map +0 -1
- package/dist/middlewares/CustomAssetGraduationMiddleware.d.ts.map +0 -1
- package/dist/middlewares/CustomAssetGraduationMiddleware.js.map +0 -1
- package/dist/middlewares/DetectionMiddleware.d.ts.map +0 -1
- package/dist/middlewares/DetectionMiddleware.js.map +0 -1
- package/dist/middlewares/ParallelMiddleware.d.ts.map +0 -1
- package/dist/middlewares/RpcFallbackMiddleware.d.ts.map +0 -1
- package/dist/middlewares/RpcFallbackMiddleware.js.map +0 -1
- package/dist/middlewares/index.d.ts +0 -9
- package/dist/middlewares/index.d.ts.map +0 -1
- package/dist/middlewares/index.js +0 -5
- package/dist/middlewares/index.js.map +0 -1
- package/dist/migrations/healAssetsInfoMetadata.d.ts.map +0 -1
- package/dist/migrations/healAssetsInfoMetadata.js.map +0 -1
- package/dist/selectors/balance.d.ts.map +0 -1
- package/dist/selectors/balance.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/constants.d.ts +0 -2
- package/dist/utils/constants.d.ts.map +0 -1
- package/dist/utils/constants.js.map +0 -1
- package/dist/utils/customAssetsRpcSupplement.d.ts.map +0 -1
- package/dist/utils/customAssetsRpcSupplement.js.map +0 -1
- package/dist/utils/dedupingBatchFetcher.d.ts.map +0 -1
- package/dist/utils/dedupingBatchFetcher.js.map +0 -1
- package/dist/utils/fetchWithTimeout.d.ts.map +0 -1
- package/dist/utils/fetchWithTimeout.js.map +0 -1
- package/dist/utils/formatExchangeRatesForBridge.d.ts.map +0 -1
- package/dist/utils/formatExchangeRatesForBridge.js.map +0 -1
- package/dist/utils/formatStateForTransactionPay.d.ts.map +0 -1
- package/dist/utils/formatStateForTransactionPay.js.map +0 -1
- package/dist/utils/index.d.ts +0 -9
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -7
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/native-assets.d.ts.map +0 -1
- package/dist/utils/native-assets.js.map +0 -1
- package/dist/utils/normalizeAmountString.d.ts.map +0 -1
- package/dist/utils/normalizeAmountString.js.map +0 -1
- package/dist/utils/normalizeAssetId.d.ts.map +0 -1
- package/dist/utils/normalizeAssetId.js.map +0 -1
- package/dist/utils/snaps-assets-migration.d.ts.map +0 -1
- package/dist/utils/snaps-assets-migration.js.map +0 -1
- package/dist/utils/trace.d.ts.map +0 -1
- package/dist/utils/trace.js.map +0 -1
|
@@ -0,0 +1,2559 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
8
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
11
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trace, _AssetsController_captureException, _AssetsController_firstInitFetchReported, _AssetsController_stateSizeReported, _AssetsController_emitStateSizeTrace, _AssetsController_uiOpen, _AssetsController_keyringUnlocked, _AssetsController_accountTreeInitialized, _AssetsController_controllerMutex, _AssetsController_accountRefreshMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_lastKnownAccountIds, _AssetsController_getSelectedAccounts, _AssetsController_accountActivityDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_stakedBalanceDataSource, _AssetsController_allBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_customAssetGraduationMiddleware, _AssetsController_rpcFallbackMiddleware, _AssetsController_tokenDataSource, _AssetsController_unsubscribeBasicFunctionality, _AssetsController_queryApiClient, _AssetsController_onActiveChainsUpdated, _AssetsController_initializeNativeAssetsMap, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_onUnapprovedTransactionAdded, _AssetsController_onTransactionConfirmed, _AssetsController_updateActive, _AssetsController_handleAccountTreeStateChange, _AssetsController_runAccountTreeRefresh, _AssetsController_runStartupRefresh, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _AssetsController_assertNonEmptyAccountId, _AssetsController_normalizeAssetIdOrThrow, _AssetsController_fetchMissingPricesWithoutCache, _AssetsController_getNativeAssetMap, _AssetsController_isNativeAsset, _AssetsController_getAssetType, _AssetsController_resolveNativeAssetIds, _AssetsController_getNativeAssetIdsForEnabledChains, _AssetsController_getNativeAssetIdsForAccount, _AssetsController_getSlowPipelineChainIds, _AssetsController_ensureNativeBalancesDefaultZero, _AssetsController_ensureDefaultTrackedAssetsSeeded, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_getAssetFromState, _AssetsController_shouldHideNativeToken, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_subscribeRpcCustomAssetsSupplement, _AssetsController_unsubscribeBySubscriptionKey, _AssetsController_subscribeStakedBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged, _AssetsController_handleNetworkAdded, _AssetsController_refreshActiveChainsOnNetworkSwitch, _AssetsController_getSelectedEvmChainIdFromNetworkState, _AssetsController_handleNetworkDidChange, _AssetsController_refreshAssetsAfterNetworkChange, _AssetsController_refreshAssetsAfterNetworkAdded;
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.AssetsController = exports.getDefaultAssetsControllerState = void 0;
|
|
19
|
+
const base_controller_1 = require("@metamask/base-controller");
|
|
20
|
+
const client_controller_1 = require("@metamask/client-controller");
|
|
21
|
+
const utils_1 = require("@metamask/utils");
|
|
22
|
+
const async_mutex_1 = require("async-mutex");
|
|
23
|
+
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
24
|
+
const lodash_1 = require("lodash");
|
|
25
|
+
const AccountActivityDataSource_js_1 = require("./data-sources/AccountActivityDataSource.cjs");
|
|
26
|
+
const AccountsApiDataSource_js_1 = require("./data-sources/AccountsApiDataSource.cjs");
|
|
27
|
+
const index_js_1 = require("./data-sources/evm-rpc-services/index.cjs");
|
|
28
|
+
const assets_js_1 = require("./data-sources/evm-rpc-services/utils/assets.cjs");
|
|
29
|
+
const PriceDataSource_js_1 = require("./data-sources/PriceDataSource.cjs");
|
|
30
|
+
const RpcDataSource_js_1 = require("./data-sources/RpcDataSource.cjs");
|
|
31
|
+
const SnapDataSource_js_1 = require("./data-sources/SnapDataSource.cjs");
|
|
32
|
+
const StakedBalanceDataSource_js_1 = require("./data-sources/StakedBalanceDataSource.cjs");
|
|
33
|
+
const TokenDataSource_js_1 = require("./data-sources/TokenDataSource.cjs");
|
|
34
|
+
const defaults_js_1 = require("./defaults.cjs");
|
|
35
|
+
const errors_js_1 = require("./errors.cjs");
|
|
36
|
+
const logger_js_1 = require("./logger.cjs");
|
|
37
|
+
const CustomAssetGraduationMiddleware_js_1 = require("./middlewares/CustomAssetGraduationMiddleware.cjs");
|
|
38
|
+
const DetectionMiddleware_js_1 = require("./middlewares/DetectionMiddleware.cjs");
|
|
39
|
+
const ParallelMiddleware_js_1 = require("./middlewares/ParallelMiddleware.cjs");
|
|
40
|
+
const RpcFallbackMiddleware_js_1 = require("./middlewares/RpcFallbackMiddleware.cjs");
|
|
41
|
+
const healAssetsInfoMetadata_js_1 = require("./migrations/healAssetsInfoMetadata.cjs");
|
|
42
|
+
const constants_js_1 = require("./utils/constants.cjs");
|
|
43
|
+
const customAssetsRpcSupplement_js_1 = require("./utils/customAssetsRpcSupplement.cjs");
|
|
44
|
+
const index_js_2 = require("./utils/index.cjs");
|
|
45
|
+
const trace_js_1 = require("./utils/trace.cjs");
|
|
46
|
+
const NATIVE_ASSETS_QUERY_KEY = ['nativeAssets'];
|
|
47
|
+
/** Stable empty map so memoized formatters are not busted by `?? {}` identity churn. */
|
|
48
|
+
const EMPTY_NATIVE_ASSET_MAP = {};
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// CONTROLLER CONSTANTS
|
|
51
|
+
// ============================================================================
|
|
52
|
+
const CONTROLLER_NAME = 'AssetsController';
|
|
53
|
+
/** Method names exposed as messenger actions (AssetsController:getAssets, etc.) */
|
|
54
|
+
const MESSENGER_EXPOSED_METHODS = [
|
|
55
|
+
'getAssets',
|
|
56
|
+
'getAssetsBalance',
|
|
57
|
+
'getAssetMetadata',
|
|
58
|
+
'getAccountAssetByID',
|
|
59
|
+
'getAccountAssetsByIDs',
|
|
60
|
+
'getAccountAssetsByScope',
|
|
61
|
+
'getAssetsPrice',
|
|
62
|
+
'getExchangeRatesForBridge',
|
|
63
|
+
'getStateForTransactionPay',
|
|
64
|
+
'addCustomAsset',
|
|
65
|
+
'removeCustomAsset',
|
|
66
|
+
'getCustomAssets',
|
|
67
|
+
'hideAsset',
|
|
68
|
+
'unhideAsset',
|
|
69
|
+
'setSelectedCurrency',
|
|
70
|
+
];
|
|
71
|
+
/** Default polling interval hint for data sources (30 seconds) */
|
|
72
|
+
const DEFAULT_POLLING_INTERVAL_MS = 30000;
|
|
73
|
+
// ============================================================================
|
|
74
|
+
// TRACE NAMES — used in Sentry spans (search these strings in Discover)
|
|
75
|
+
// ============================================================================
|
|
76
|
+
const TRACE_FIRST_INIT_FETCH = 'AssetsControllerFirstInitFetch';
|
|
77
|
+
const TRACE_FULL_FETCH = 'AssetsFullFetch';
|
|
78
|
+
/** Parent span that nests per-source timings; dashboard charts {@link TRACE_FULL_FETCH}. */
|
|
79
|
+
const TRACE_FETCH_PIPELINE = 'AssetsFetchPipeline';
|
|
80
|
+
const TRACE_BACKGROUND_FETCH = 'AssetsBackgroundFetch';
|
|
81
|
+
const TRACE_DATA_SOURCE_TIMING = 'AssetsDataSourceTiming';
|
|
82
|
+
const TRACE_DATA_SOURCE_ERROR = 'AssetsDataSourceError';
|
|
83
|
+
const TRACE_UPDATE_PIPELINE = 'AssetsUpdatePipeline';
|
|
84
|
+
/** Parent span that nests update enrichment; dashboard charts {@link TRACE_UPDATE_PIPELINE}. */
|
|
85
|
+
const TRACE_UPDATE_PARENT = 'AssetsUpdateEnrichment';
|
|
86
|
+
const TRACE_SUBSCRIPTION_ERROR = 'AssetsSubscriptionError';
|
|
87
|
+
const TRACE_STATE_SIZE = 'AssetsStateSize';
|
|
88
|
+
const log = (0, logger_js_1.createModuleLogger)(logger_js_1.projectLogger, CONTROLLER_NAME);
|
|
89
|
+
/**
|
|
90
|
+
* Returns the default state for AssetsController.
|
|
91
|
+
*
|
|
92
|
+
* @returns The default AssetsController state. Balance, price, and custom
|
|
93
|
+
* asset maps start empty; `assetsInfo` is pre-seeded for default tracked
|
|
94
|
+
* assets (see {@link buildDefaultAssetsInfo}).
|
|
95
|
+
*/
|
|
96
|
+
function getDefaultAssetsControllerState() {
|
|
97
|
+
return {
|
|
98
|
+
// Pre-populate metadata for controller-managed default tracked assets
|
|
99
|
+
// (e.g. mUSD on Ethereum mainnet, Linea, Monad) so they are
|
|
100
|
+
// immediately renderable in the UI before any RPC poll completes.
|
|
101
|
+
// Per-account zero-balance entries are filled into `assetsBalance`
|
|
102
|
+
// by `#ensureDefaultTrackedAssetsSeeded` once accounts are known.
|
|
103
|
+
assetsInfo: (0, defaults_js_1.buildDefaultAssetsInfo)(),
|
|
104
|
+
assetsBalance: {},
|
|
105
|
+
assetsPrice: {},
|
|
106
|
+
customAssets: {},
|
|
107
|
+
assetPreferences: {},
|
|
108
|
+
selectedCurrency: 'usd',
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
exports.getDefaultAssetsControllerState = getDefaultAssetsControllerState;
|
|
112
|
+
// ============================================================================
|
|
113
|
+
// STATE METADATA
|
|
114
|
+
// ============================================================================
|
|
115
|
+
const stateMetadata = {
|
|
116
|
+
assetsInfo: {
|
|
117
|
+
persist: true,
|
|
118
|
+
includeInStateLogs: false,
|
|
119
|
+
includeInDebugSnapshot: false,
|
|
120
|
+
usedInUi: true,
|
|
121
|
+
},
|
|
122
|
+
assetsBalance: {
|
|
123
|
+
persist: true,
|
|
124
|
+
includeInStateLogs: false,
|
|
125
|
+
includeInDebugSnapshot: false,
|
|
126
|
+
usedInUi: true,
|
|
127
|
+
},
|
|
128
|
+
assetsPrice: {
|
|
129
|
+
persist: true,
|
|
130
|
+
includeInStateLogs: false,
|
|
131
|
+
includeInDebugSnapshot: false,
|
|
132
|
+
usedInUi: true,
|
|
133
|
+
},
|
|
134
|
+
customAssets: {
|
|
135
|
+
persist: true,
|
|
136
|
+
includeInStateLogs: false,
|
|
137
|
+
includeInDebugSnapshot: false,
|
|
138
|
+
usedInUi: true,
|
|
139
|
+
},
|
|
140
|
+
assetPreferences: {
|
|
141
|
+
persist: true,
|
|
142
|
+
includeInStateLogs: false,
|
|
143
|
+
includeInDebugSnapshot: false,
|
|
144
|
+
usedInUi: true,
|
|
145
|
+
},
|
|
146
|
+
selectedCurrency: {
|
|
147
|
+
persist: true,
|
|
148
|
+
includeInStateLogs: false,
|
|
149
|
+
includeInDebugSnapshot: false,
|
|
150
|
+
usedInUi: true,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
// ============================================================================
|
|
154
|
+
// HELPER FUNCTIONS
|
|
155
|
+
// ============================================================================
|
|
156
|
+
function extractChainId(assetId) {
|
|
157
|
+
const parsed = (0, utils_1.parseCaipAssetType)(assetId);
|
|
158
|
+
return parsed.chainId;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Normalizes all asset IDs in a DataResponse.
|
|
162
|
+
* This is applied at the controller level to ensure consistent state
|
|
163
|
+
* regardless of how data sources format their asset IDs.
|
|
164
|
+
*
|
|
165
|
+
* @param response - The DataResponse to normalize.
|
|
166
|
+
* @returns The normalized DataResponse with checksummed EVM addresses.
|
|
167
|
+
*/
|
|
168
|
+
function normalizeResponse(response) {
|
|
169
|
+
const normalized = {};
|
|
170
|
+
if (response.assetsInfo) {
|
|
171
|
+
normalized.assetsInfo = {};
|
|
172
|
+
for (const [assetId, metadata] of Object.entries(response.assetsInfo)) {
|
|
173
|
+
const normalizedId = (0, index_js_2.normalizeAssetId)(assetId);
|
|
174
|
+
normalized.assetsInfo[normalizedId] = metadata;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (response.assetsPrice) {
|
|
178
|
+
normalized.assetsPrice = {};
|
|
179
|
+
for (const [assetId, price] of Object.entries(response.assetsPrice)) {
|
|
180
|
+
const normalizedId = (0, index_js_2.normalizeAssetId)(assetId);
|
|
181
|
+
normalized.assetsPrice[normalizedId] = price;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (response.assetsBalance) {
|
|
185
|
+
normalized.assetsBalance = {};
|
|
186
|
+
for (const [accountId, balances] of Object.entries(response.assetsBalance)) {
|
|
187
|
+
normalized.assetsBalance[accountId] = {};
|
|
188
|
+
for (const [assetId, balance] of Object.entries(balances)) {
|
|
189
|
+
const normalizedId = (0, index_js_2.normalizeAssetId)(assetId);
|
|
190
|
+
normalized.assetsBalance[accountId][normalizedId] = balance;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// Preserve detectedAssets with normalized asset IDs
|
|
195
|
+
if (response.detectedAssets) {
|
|
196
|
+
normalized.detectedAssets = {};
|
|
197
|
+
for (const [accountId, assetIds] of Object.entries(response.detectedAssets)) {
|
|
198
|
+
normalized.detectedAssets[accountId] = assetIds.map((assetId) => (0, index_js_2.normalizeAssetId)(assetId));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Preserve errors (chain IDs don't need normalization)
|
|
202
|
+
if (response.errors) {
|
|
203
|
+
normalized.errors = { ...response.errors };
|
|
204
|
+
}
|
|
205
|
+
if (response.updateMode) {
|
|
206
|
+
normalized.updateMode = response.updateMode;
|
|
207
|
+
}
|
|
208
|
+
if (response.replaceCoveredChainBalances) {
|
|
209
|
+
normalized.replaceCoveredChainBalances = true;
|
|
210
|
+
}
|
|
211
|
+
return normalized;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Merge account balances from a data-source response into prior state.
|
|
215
|
+
*
|
|
216
|
+
* @param previousBalances - Balances already in state for this account.
|
|
217
|
+
* @param accountBalances - Balances from the incoming response.
|
|
218
|
+
* @param customAssetIds - Custom assets to preserve when replacing covered chains.
|
|
219
|
+
* @param replaceCoveredChains - When true, drop prior balances on chains present
|
|
220
|
+
* in the response before applying it (authoritative chain slice).
|
|
221
|
+
* @returns The merged balance map for the account.
|
|
222
|
+
*/
|
|
223
|
+
function mergeAccountBalances(previousBalances, accountBalances, customAssetIds, replaceCoveredChains) {
|
|
224
|
+
if (!replaceCoveredChains) {
|
|
225
|
+
return { ...previousBalances, ...accountBalances };
|
|
226
|
+
}
|
|
227
|
+
const coveredChains = new Set(Object.keys(accountBalances).map((assetId) => assetId.split('/')[0]));
|
|
228
|
+
const next = {};
|
|
229
|
+
for (const [assetId, balance] of Object.entries(previousBalances)) {
|
|
230
|
+
if (!coveredChains.has(assetId.split('/')[0])) {
|
|
231
|
+
next[assetId] = balance;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
Object.assign(next, accountBalances);
|
|
235
|
+
for (const customId of customAssetIds) {
|
|
236
|
+
if (!Object.prototype.hasOwnProperty.call(next, customId)) {
|
|
237
|
+
const prev = previousBalances[customId];
|
|
238
|
+
next[customId] = prev ?? { amount: '0' };
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Staked vault balances are owned by StakedBalanceDataSource. When an
|
|
242
|
+
// Accounts API (or other) chain-slice replace omits them, keep the prior
|
|
243
|
+
// on-chain staked amount instead of clearing it to missing/0.
|
|
244
|
+
for (const [assetId, balance] of Object.entries(previousBalances)) {
|
|
245
|
+
if ((0, index_js_1.isStakingContractAssetId)(assetId) &&
|
|
246
|
+
!Object.prototype.hasOwnProperty.call(next, assetId)) {
|
|
247
|
+
next[assetId] = balance;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return next;
|
|
251
|
+
}
|
|
252
|
+
// ============================================================================
|
|
253
|
+
// CONTROLLER IMPLEMENTATION
|
|
254
|
+
// ============================================================================
|
|
255
|
+
/**
|
|
256
|
+
* AssetsController provides a unified interface for managing asset balances
|
|
257
|
+
* across all blockchain networks (EVM and non-EVM) and all asset types.
|
|
258
|
+
*
|
|
259
|
+
* ## Core Responsibilities
|
|
260
|
+
*
|
|
261
|
+
* 1. **One-Time Fetch (Sync)**: For initial load, force refresh, or on-demand queries.
|
|
262
|
+
* Uses `getAssets()`, `getAssetsBalance()`, etc. with `forceUpdate: true`.
|
|
263
|
+
*
|
|
264
|
+
* 2. **Async Subscriptions**: Subscribes to data sources for ongoing updates.
|
|
265
|
+
* Data sources push updates via callbacks; the controller updates state.
|
|
266
|
+
*
|
|
267
|
+
* 3. **Dynamic Source Selection**: Routes requests to appropriate data sources
|
|
268
|
+
* based on which chains they support. When active chains change, the controller
|
|
269
|
+
* dynamically adjusts subscriptions.
|
|
270
|
+
*
|
|
271
|
+
* 4. **Client + Keyring Lifecycle**: Starts subscriptions only when both the UI is
|
|
272
|
+
* open (ClientController) and the wallet is unlocked (KeyringController).
|
|
273
|
+
* Stops when either the UI closes or the keyring locks. See client-controller
|
|
274
|
+
* README for the combined pattern.
|
|
275
|
+
*
|
|
276
|
+
* ## Architecture
|
|
277
|
+
*
|
|
278
|
+
* - Data sources declare their supported chains (async, can change over time)
|
|
279
|
+
* - Data sources are responsible for their own update mechanisms (WebSocket, polling, events)
|
|
280
|
+
* - The controller does NOT manage polling - it simply receives pushed updates
|
|
281
|
+
*/
|
|
282
|
+
class AssetsController extends base_controller_1.BaseController {
|
|
283
|
+
constructor({ messenger, state = {}, defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS, isEnabled = () => true, isBasicFunctionality, subscribeToBasicFunctionalityChange, queryApiClient, rpcDataSourceConfig, trace, captureException, accountsApiDataSourceConfig, priceDataSourceConfig, stakedBalanceDataSourceConfig, isOnboarded, tempMigrateAssetsInfoMetadataAssets3346, }) {
|
|
284
|
+
super({
|
|
285
|
+
name: CONTROLLER_NAME,
|
|
286
|
+
messenger,
|
|
287
|
+
metadata: stateMetadata,
|
|
288
|
+
state: {
|
|
289
|
+
...getDefaultAssetsControllerState(),
|
|
290
|
+
...state,
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
_AssetsController_instances.add(this);
|
|
294
|
+
/** Whether the controller is enabled */
|
|
295
|
+
_AssetsController_isEnabled.set(this, void 0);
|
|
296
|
+
/** Getter for basic functionality (only balance fetch/subscribe use RPC; token/price API not used). No attribute stored. */
|
|
297
|
+
_AssetsController_isBasicFunctionality.set(this, void 0);
|
|
298
|
+
/** Default update interval hint passed to data sources */
|
|
299
|
+
_AssetsController_defaultUpdateInterval.set(this, void 0);
|
|
300
|
+
/** Optional trace callback for first init/fetch measurement (duration). */
|
|
301
|
+
_AssetsController_trace.set(this, void 0);
|
|
302
|
+
/** Optional reporter for Issue-style errors (e.g. Sentry.captureException). */
|
|
303
|
+
_AssetsController_captureException.set(this, void 0);
|
|
304
|
+
/** Whether we have already reported first init fetch for this session (reset on #stop). */
|
|
305
|
+
_AssetsController_firstInitFetchReported.set(this, false);
|
|
306
|
+
/** Whether we have already reported state size for this session (reset on #stop). */
|
|
307
|
+
_AssetsController_stateSizeReported.set(this, false);
|
|
308
|
+
/** Whether the client (UI) is open. Combined with #keyringUnlocked for #updateActive. */
|
|
309
|
+
_AssetsController_uiOpen.set(this, false);
|
|
310
|
+
/** Whether the keyring is unlocked. Combined with #uiOpen for #updateActive. */
|
|
311
|
+
_AssetsController_keyringUnlocked.set(this, false);
|
|
312
|
+
/**
|
|
313
|
+
* Whether `AccountTreeController` has finished `init()`. Unlock / UI-open
|
|
314
|
+
* alone must not start fetches — the tree can still be mid-build.
|
|
315
|
+
*/
|
|
316
|
+
_AssetsController_accountTreeInitialized.set(this, false);
|
|
317
|
+
_AssetsController_controllerMutex.set(this, new async_mutex_1.Mutex());
|
|
318
|
+
/** Serializes account-switch fetch + subscribe to prevent overlapping races. */
|
|
319
|
+
_AssetsController_accountRefreshMutex.set(this, new async_mutex_1.Mutex());
|
|
320
|
+
/**
|
|
321
|
+
* Active balance subscriptions keyed by account ID.
|
|
322
|
+
* Each account has one logical subscription that may span multiple data sources.
|
|
323
|
+
* For example, if WebSocket covers chains A,B and RPC covers chain C,
|
|
324
|
+
* the account subscribes to both data sources for its chains.
|
|
325
|
+
*/
|
|
326
|
+
_AssetsController_activeSubscriptions.set(this, new Map());
|
|
327
|
+
/** Currently enabled chains from NetworkEnablementController */
|
|
328
|
+
_AssetsController_enabledChains.set(this, new Set());
|
|
329
|
+
/**
|
|
330
|
+
* Snapshot of account IDs that were active when the last subscription/fetch
|
|
331
|
+
* cycle ran. Used by #handleAccountTreeStateChange to skip redundant
|
|
332
|
+
* re-subscriptions when the account set hasn't actually changed.
|
|
333
|
+
*/
|
|
334
|
+
_AssetsController_lastKnownAccountIds.set(this, new Set());
|
|
335
|
+
_AssetsController_accountActivityDataSource.set(this, void 0);
|
|
336
|
+
_AssetsController_accountsApiDataSource.set(this, void 0);
|
|
337
|
+
_AssetsController_snapDataSource.set(this, void 0);
|
|
338
|
+
_AssetsController_rpcDataSource.set(this, void 0);
|
|
339
|
+
_AssetsController_stakedBalanceDataSource.set(this, void 0);
|
|
340
|
+
_AssetsController_priceDataSource.set(this, void 0);
|
|
341
|
+
_AssetsController_detectionMiddleware.set(this, void 0);
|
|
342
|
+
_AssetsController_customAssetGraduationMiddleware.set(this, void 0);
|
|
343
|
+
_AssetsController_rpcFallbackMiddleware.set(this, void 0);
|
|
344
|
+
_AssetsController_tokenDataSource.set(this, void 0);
|
|
345
|
+
_AssetsController_unsubscribeBasicFunctionality.set(this, null);
|
|
346
|
+
_AssetsController_queryApiClient.set(this, void 0);
|
|
347
|
+
_AssetsController_onActiveChainsUpdated.set(this, void 0);
|
|
348
|
+
__classPrivateFieldSet(this, _AssetsController_isEnabled, isEnabled, "f");
|
|
349
|
+
__classPrivateFieldSet(this, _AssetsController_isBasicFunctionality, isBasicFunctionality ?? (() => true), "f");
|
|
350
|
+
__classPrivateFieldSet(this, _AssetsController_defaultUpdateInterval, defaultUpdateInterval, "f");
|
|
351
|
+
__classPrivateFieldSet(this, _AssetsController_trace, trace, "f");
|
|
352
|
+
__classPrivateFieldSet(this, _AssetsController_captureException, captureException, "f");
|
|
353
|
+
__classPrivateFieldSet(this, _AssetsController_queryApiClient, queryApiClient, "f");
|
|
354
|
+
const rpcConfig = rpcDataSourceConfig ?? {};
|
|
355
|
+
// TEMPORARY: heal assetsInfo metadata wiped by a prior defect
|
|
356
|
+
// (see extension migration #215 / ASSETS-3346). Remove in a future release.
|
|
357
|
+
if (tempMigrateAssetsInfoMetadataAssets3346) {
|
|
358
|
+
this.update(() => (0, healAssetsInfoMetadata_js_1.tempHealAssetsInfoMetadata)({
|
|
359
|
+
state: this.state,
|
|
360
|
+
getMigrationState: tempMigrateAssetsInfoMetadataAssets3346,
|
|
361
|
+
captureException,
|
|
362
|
+
}));
|
|
363
|
+
}
|
|
364
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_initializeNativeAssetsMap).call(this, queryApiClient);
|
|
365
|
+
__classPrivateFieldSet(this, _AssetsController_onActiveChainsUpdated, (dataSourceName, chains, previousChains) => {
|
|
366
|
+
try {
|
|
367
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleActiveChainsUpdate).call(this, dataSourceName, chains, previousChains);
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
log('Failed to handle active chains update', {
|
|
371
|
+
dataSourceName,
|
|
372
|
+
error,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}, "f");
|
|
376
|
+
__classPrivateFieldSet(this, _AssetsController_accountActivityDataSource, new AccountActivityDataSource_js_1.AccountActivityDataSource({
|
|
377
|
+
messenger: this.messenger,
|
|
378
|
+
onActiveChainsUpdated: __classPrivateFieldGet(this, _AssetsController_onActiveChainsUpdated, "f"),
|
|
379
|
+
getAssetType: (assetId) => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetType).call(this, assetId),
|
|
380
|
+
onAssetsUpdate: (response, request) => this.handleAssetsUpdate(response, __classPrivateFieldGet(this, _AssetsController_accountActivityDataSource, "f").getName(), request),
|
|
381
|
+
}), "f");
|
|
382
|
+
__classPrivateFieldSet(this, _AssetsController_accountsApiDataSource, new AccountsApiDataSource_js_1.AccountsApiDataSource({
|
|
383
|
+
messenger: this.messenger,
|
|
384
|
+
queryApiClient,
|
|
385
|
+
onActiveChainsUpdated: __classPrivateFieldGet(this, _AssetsController_onActiveChainsUpdated, "f"),
|
|
386
|
+
...accountsApiDataSourceConfig,
|
|
387
|
+
}), "f");
|
|
388
|
+
__classPrivateFieldSet(this, _AssetsController_snapDataSource, new SnapDataSource_js_1.SnapDataSource({
|
|
389
|
+
messenger: this.messenger,
|
|
390
|
+
onActiveChainsUpdated: __classPrivateFieldGet(this, _AssetsController_onActiveChainsUpdated, "f"),
|
|
391
|
+
onAssetsUpdate: (response) => this.handleAssetsUpdate(response, 'SnapDataSource'),
|
|
392
|
+
}), "f");
|
|
393
|
+
__classPrivateFieldSet(this, _AssetsController_rpcDataSource, new RpcDataSource_js_1.RpcDataSource({
|
|
394
|
+
messenger: this.messenger,
|
|
395
|
+
onActiveChainsUpdated: __classPrivateFieldGet(this, _AssetsController_onActiveChainsUpdated, "f"),
|
|
396
|
+
getNativeAssetForChain: (chainId) => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetMap).call(this)[chainId] ??
|
|
397
|
+
`${chainId}/erc20:${constants_js_1.ZERO_ADDRESS}`,
|
|
398
|
+
// Share the API platform's TanStack Query client so the RPC token
|
|
399
|
+
// detector caches/dedupes its top-token-list fetches alongside the rest
|
|
400
|
+
// of the package's API calls. Caller-provided rpcConfig.queryClient
|
|
401
|
+
// wins via the spread below.
|
|
402
|
+
queryClient: queryApiClient.queryClient,
|
|
403
|
+
...rpcConfig,
|
|
404
|
+
isOnboarded: rpcConfig.isOnboarded ?? isOnboarded,
|
|
405
|
+
getAssetType: (assetId) => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetType).call(this, assetId),
|
|
406
|
+
}), "f");
|
|
407
|
+
__classPrivateFieldSet(this, _AssetsController_stakedBalanceDataSource, new StakedBalanceDataSource_js_1.StakedBalanceDataSource({
|
|
408
|
+
messenger: this.messenger,
|
|
409
|
+
onActiveChainsUpdated: __classPrivateFieldGet(this, _AssetsController_onActiveChainsUpdated, "f"),
|
|
410
|
+
...stakedBalanceDataSourceConfig,
|
|
411
|
+
}), "f");
|
|
412
|
+
__classPrivateFieldSet(this, _AssetsController_tokenDataSource, new TokenDataSource_js_1.TokenDataSource(this.messenger, {
|
|
413
|
+
queryApiClient,
|
|
414
|
+
getNativeAssetIds: () => {
|
|
415
|
+
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetIdsForEnabledChains).call(this);
|
|
416
|
+
},
|
|
417
|
+
getAssetType: (assetId) => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetType).call(this, assetId),
|
|
418
|
+
}), "f");
|
|
419
|
+
__classPrivateFieldSet(this, _AssetsController_priceDataSource, new PriceDataSource_js_1.PriceDataSource({
|
|
420
|
+
queryApiClient,
|
|
421
|
+
getSelectedCurrency: () => this.state.selectedCurrency,
|
|
422
|
+
...priceDataSourceConfig,
|
|
423
|
+
}), "f");
|
|
424
|
+
__classPrivateFieldSet(this, _AssetsController_detectionMiddleware, new DetectionMiddleware_js_1.DetectionMiddleware(), "f");
|
|
425
|
+
__classPrivateFieldSet(this, _AssetsController_customAssetGraduationMiddleware, new CustomAssetGraduationMiddleware_js_1.CustomAssetGraduationMiddleware({
|
|
426
|
+
getSelectedAccountId: () => {
|
|
427
|
+
try {
|
|
428
|
+
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this)[0]?.id;
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
return undefined;
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
removeCustomAsset: (accountId, assetId) => this.removeCustomAsset(accountId, assetId),
|
|
435
|
+
}), "f");
|
|
436
|
+
__classPrivateFieldSet(this, _AssetsController_rpcFallbackMiddleware, new RpcFallbackMiddleware_js_1.RpcFallbackMiddleware({
|
|
437
|
+
rpcDataSource: __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f"),
|
|
438
|
+
}), "f");
|
|
439
|
+
log('Initializing AssetsController', {
|
|
440
|
+
defaultUpdateInterval: __classPrivateFieldGet(this, _AssetsController_defaultUpdateInterval, "f"),
|
|
441
|
+
});
|
|
442
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_initializeState).call(this);
|
|
443
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeToEvents).call(this);
|
|
444
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_registerActionHandlers).call(this);
|
|
445
|
+
// Subscriptions start only when both UI is open and keyring unlocked -> #updateActive().
|
|
446
|
+
// Subscribe to basic-functionality changes after construction so a synchronous
|
|
447
|
+
// onChange during subscribe cannot run before data sources are initialized.
|
|
448
|
+
if (subscribeToBasicFunctionalityChange) {
|
|
449
|
+
const unsubscribe = subscribeToBasicFunctionalityChange((isBasic) => this.handleBasicFunctionalityChange(isBasic));
|
|
450
|
+
if (typeof unsubscribe === 'function') {
|
|
451
|
+
__classPrivateFieldSet(this, _AssetsController_unsubscribeBasicFunctionality, unsubscribe, "f");
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Returns the callback passed to data sources for reporting active chain updates.
|
|
457
|
+
* Used by tests to simulate a data source reporting chain changes.
|
|
458
|
+
*
|
|
459
|
+
* @returns The onActiveChainsUpdated callback.
|
|
460
|
+
*/
|
|
461
|
+
getOnActiveChainsUpdated() {
|
|
462
|
+
return __classPrivateFieldGet(this, _AssetsController_onActiveChainsUpdated, "f");
|
|
463
|
+
}
|
|
464
|
+
// ============================================================================
|
|
465
|
+
// PUBLIC API: QUERY METHODS
|
|
466
|
+
// ============================================================================
|
|
467
|
+
async getAssets(accounts, options) {
|
|
468
|
+
const chainIds = options?.chainIds ?? [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")];
|
|
469
|
+
const assetTypes = options?.assetTypes ?? ['fungible'];
|
|
470
|
+
const dataTypes = options?.dataTypes ?? ['balance', 'metadata', 'price'];
|
|
471
|
+
if (accounts.length === 0 || chainIds.length === 0) {
|
|
472
|
+
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetsFromState).call(this, accounts, chainIds, assetTypes);
|
|
473
|
+
}
|
|
474
|
+
// Collect custom assets for all requested accounts
|
|
475
|
+
const customAssets = [];
|
|
476
|
+
for (const account of accounts) {
|
|
477
|
+
const accountCustomAssets = this.getCustomAssets(account.id);
|
|
478
|
+
customAssets.push(...accountCustomAssets);
|
|
479
|
+
}
|
|
480
|
+
if (options?.forceUpdate) {
|
|
481
|
+
// Pipeline spans only on unlock/first-init fetch; later forceUpdates pass
|
|
482
|
+
// `undefined` so `emitTrace` / `withTrace` no-op without call-site if/else.
|
|
483
|
+
const pipelineTrace = __classPrivateFieldGet(this, _AssetsController_firstInitFetchReported, "f")
|
|
484
|
+
? undefined
|
|
485
|
+
: __classPrivateFieldGet(this, _AssetsController_trace, "f");
|
|
486
|
+
const request = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
|
|
487
|
+
assetTypes,
|
|
488
|
+
dataTypes,
|
|
489
|
+
customAssets: customAssets.length > 0 ? customAssets : undefined,
|
|
490
|
+
forceUpdate: true,
|
|
491
|
+
assetsForPriceUpdate: options?.assetsForPriceUpdate,
|
|
492
|
+
});
|
|
493
|
+
// Fast pipeline: accountsApi + stakedBalance → detection → token + price.
|
|
494
|
+
// Snap and RPC are excluded here due to their latency (snap triggers account
|
|
495
|
+
// creation, RPC is slow on many chains). Results are committed to state
|
|
496
|
+
// immediately so the UI can display balances without waiting for them.
|
|
497
|
+
//
|
|
498
|
+
// Fast/slow pipelines use merge so partial API snapshots cannot wipe
|
|
499
|
+
// tokens missing from the response (e.g. USDC when only native balance
|
|
500
|
+
// is returned). Balances present in the response are still refreshed.
|
|
501
|
+
const fastSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
502
|
+
? [
|
|
503
|
+
(0, ParallelMiddleware_js_1.createParallelBalanceMiddleware)([
|
|
504
|
+
__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f"),
|
|
505
|
+
__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"),
|
|
506
|
+
]),
|
|
507
|
+
// Graduation must run BEFORE the RPC fallback so it only sees
|
|
508
|
+
// AccountsApi/Websocket balances. RPC intentionally carries
|
|
509
|
+
// custom assets and must never trigger graduation.
|
|
510
|
+
__classPrivateFieldGet(this, _AssetsController_customAssetGraduationMiddleware, "f"),
|
|
511
|
+
__classPrivateFieldGet(this, _AssetsController_rpcFallbackMiddleware, "f"),
|
|
512
|
+
__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
|
|
513
|
+
(0, ParallelMiddleware_js_1.createParallelMiddleware)([
|
|
514
|
+
__classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
|
|
515
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
|
|
516
|
+
]),
|
|
517
|
+
]
|
|
518
|
+
: [__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f")];
|
|
519
|
+
const { response } = await (0, trace_js_1.withTrace)({
|
|
520
|
+
name: TRACE_FETCH_PIPELINE,
|
|
521
|
+
trace: pipelineTrace,
|
|
522
|
+
data: {
|
|
523
|
+
chain_count: chainIds.length,
|
|
524
|
+
account_count: accounts.length,
|
|
525
|
+
basic_functionality: __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this),
|
|
526
|
+
},
|
|
527
|
+
fn: async (parentContext) => {
|
|
528
|
+
const startTime = performance.now();
|
|
529
|
+
const result = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
|
|
530
|
+
sources: fastSources,
|
|
531
|
+
request,
|
|
532
|
+
parentContext,
|
|
533
|
+
trace: pipelineTrace,
|
|
534
|
+
});
|
|
535
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
536
|
+
...result.response,
|
|
537
|
+
updateMode: 'merge',
|
|
538
|
+
replaceCoveredChainBalances: true,
|
|
539
|
+
});
|
|
540
|
+
const durationMs = performance.now() - startTime;
|
|
541
|
+
// Summary fields for Assets Health (nested under the parent span).
|
|
542
|
+
(0, trace_js_1.emitTrace)({
|
|
543
|
+
name: TRACE_FULL_FETCH,
|
|
544
|
+
trace: pipelineTrace,
|
|
545
|
+
data: {
|
|
546
|
+
duration_ms: durationMs,
|
|
547
|
+
chain_count: chainIds.length,
|
|
548
|
+
account_count: accounts.length,
|
|
549
|
+
basic_functionality: __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this),
|
|
550
|
+
asset_count: result.response.assetsBalance
|
|
551
|
+
? Object.values(result.response.assetsBalance).reduce((sum, acct) => sum + Object.keys(acct).length, 0)
|
|
552
|
+
: 0,
|
|
553
|
+
price_count: result.response.assetsPrice
|
|
554
|
+
? Object.keys(result.response.assetsPrice).length
|
|
555
|
+
: 0,
|
|
556
|
+
...result.durationByDataSource,
|
|
557
|
+
},
|
|
558
|
+
parentContext,
|
|
559
|
+
});
|
|
560
|
+
(0, trace_js_1.emitTrace)({
|
|
561
|
+
name: TRACE_FIRST_INIT_FETCH,
|
|
562
|
+
trace: pipelineTrace,
|
|
563
|
+
data: {
|
|
564
|
+
duration_ms: durationMs,
|
|
565
|
+
chain_ids: JSON.stringify(chainIds),
|
|
566
|
+
...result.durationByDataSource,
|
|
567
|
+
},
|
|
568
|
+
parentContext,
|
|
569
|
+
});
|
|
570
|
+
return result;
|
|
571
|
+
},
|
|
572
|
+
});
|
|
573
|
+
// Mark after the unlock/first forceUpdate so later polls skip pipeline spans.
|
|
574
|
+
__classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, true, "f");
|
|
575
|
+
// Background (slow) lane — flattened sibling of the fast lane (not nested
|
|
576
|
+
// inside its withTrace callback). Still fire-and-forget so UI is not blocked.
|
|
577
|
+
const slowPipelineChainIds = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSlowPipelineChainIds).call(this, chainIds, response);
|
|
578
|
+
if (slowPipelineChainIds.length > 0) {
|
|
579
|
+
const slowSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
580
|
+
? [__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")]
|
|
581
|
+
: [__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")];
|
|
582
|
+
const slowRequest = { ...request, chainIds: slowPipelineChainIds };
|
|
583
|
+
(0, trace_js_1.withTrace)({
|
|
584
|
+
name: TRACE_BACKGROUND_FETCH,
|
|
585
|
+
trace: pipelineTrace,
|
|
586
|
+
data: {
|
|
587
|
+
chain_count: slowPipelineChainIds.length,
|
|
588
|
+
account_count: accounts.length,
|
|
589
|
+
},
|
|
590
|
+
fn: async (slowParentContext) => {
|
|
591
|
+
const { response: slowResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
|
|
592
|
+
sources: [
|
|
593
|
+
(0, ParallelMiddleware_js_1.createParallelBalanceMiddleware)(slowSources),
|
|
594
|
+
__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
|
|
595
|
+
...(__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
596
|
+
? [
|
|
597
|
+
(0, ParallelMiddleware_js_1.createParallelMiddleware)([
|
|
598
|
+
__classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
|
|
599
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
|
|
600
|
+
]),
|
|
601
|
+
]
|
|
602
|
+
: []),
|
|
603
|
+
],
|
|
604
|
+
request: slowRequest,
|
|
605
|
+
parentContext: slowParentContext,
|
|
606
|
+
trace: pipelineTrace,
|
|
607
|
+
});
|
|
608
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
609
|
+
...slowResponse,
|
|
610
|
+
updateMode: 'merge',
|
|
611
|
+
});
|
|
612
|
+
},
|
|
613
|
+
}).catch((error) => log('Background pipeline failed', { error }));
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
const result = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetsFromState).call(this, accounts, chainIds, assetTypes);
|
|
617
|
+
return result;
|
|
618
|
+
}
|
|
619
|
+
async getAssetsBalance(accounts, options) {
|
|
620
|
+
// Reuse getAssets with dataTypes: ['balance'] only
|
|
621
|
+
const assets = await this.getAssets(accounts, {
|
|
622
|
+
chainIds: options?.chainIds,
|
|
623
|
+
assetTypes: options?.assetTypes,
|
|
624
|
+
forceUpdate: options?.forceUpdate,
|
|
625
|
+
dataTypes: ['balance', 'metadata'],
|
|
626
|
+
});
|
|
627
|
+
// Extract just the balance from each asset
|
|
628
|
+
const result = {};
|
|
629
|
+
for (const [accountId, accountAssets] of Object.entries(assets)) {
|
|
630
|
+
result[accountId] = {};
|
|
631
|
+
for (const [assetId, asset] of Object.entries(accountAssets)) {
|
|
632
|
+
if (asset.balance) {
|
|
633
|
+
result[accountId][assetId] = asset.balance;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return result;
|
|
638
|
+
}
|
|
639
|
+
getAssetMetadata(assetId) {
|
|
640
|
+
return this.state.assetsInfo[assetId];
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Get a single combined asset (balance + metadata + price + computed
|
|
644
|
+
* `fiatValue`) for an account directly from controller state.
|
|
645
|
+
*
|
|
646
|
+
* Reuses the same state-composition and filtering logic as `getAssets`
|
|
647
|
+
* (balance and metadata are required, a missing price falls back to
|
|
648
|
+
* `{ price: 0, lastUpdated: 0 }` with `fiatValue: 0`, and hidden or
|
|
649
|
+
* otherwise filtered assets are excluded) so the returned shape never
|
|
650
|
+
* drifts from `getAssets`. Reads from current state only and does not
|
|
651
|
+
* trigger a data-source refresh.
|
|
652
|
+
*
|
|
653
|
+
* @param accountId - The account ID (`InternalAccount.id`, not an address).
|
|
654
|
+
* @param assetId - The CAIP-19 asset ID including chain scope
|
|
655
|
+
* (e.g. `eip155:1/erc20:0x...`).
|
|
656
|
+
* @returns The combined `Asset`, or `undefined` when no complete
|
|
657
|
+
* renderable asset (balance + metadata) exists for the account/asset pair.
|
|
658
|
+
* @throws If `accountId` is empty or `assetId` is not a valid CAIP-19 asset ID.
|
|
659
|
+
*/
|
|
660
|
+
getAccountAssetByID(accountId, assetId) {
|
|
661
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_assertNonEmptyAccountId).call(this, accountId, 'getAccountAssetByID');
|
|
662
|
+
const normalizedAssetId = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_normalizeAssetIdOrThrow).call(this, assetId, 'getAccountAssetByID');
|
|
663
|
+
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetFromState).call(this, accountId, normalizedAssetId, {
|
|
664
|
+
assetTypeSet: new Set(['fungible']),
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Get multiple combined assets (balance + metadata + price + computed
|
|
669
|
+
* `fiatValue`) for an account directly from controller state.
|
|
670
|
+
*
|
|
671
|
+
* Applies the same state-composition and filtering rules as
|
|
672
|
+
* `getAccountAssetByID` to each requested asset ID. Asset IDs that do not
|
|
673
|
+
* resolve to a complete renderable asset (missing balance/metadata, hidden,
|
|
674
|
+
* or otherwise filtered out) are omitted from the result. Reads from
|
|
675
|
+
* current state only and does not trigger a data-source refresh.
|
|
676
|
+
*
|
|
677
|
+
* @param accountId - The account ID (`InternalAccount.id`, not an address).
|
|
678
|
+
* @param assetIds - The CAIP-19 asset IDs including chain scope
|
|
679
|
+
* (e.g. `eip155:1/erc20:0x...`).
|
|
680
|
+
* @returns A record of combined `Asset`s keyed by normalized CAIP-19 asset
|
|
681
|
+
* ID, containing only the requested assets that resolved.
|
|
682
|
+
* @throws If `accountId` is empty or any `assetIds` entry is not a valid
|
|
683
|
+
* CAIP-19 asset ID.
|
|
684
|
+
*/
|
|
685
|
+
getAccountAssetsByIDs(accountId, assetIds) {
|
|
686
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_assertNonEmptyAccountId).call(this, accountId, 'getAccountAssetsByIDs');
|
|
687
|
+
const result = Object.create(null);
|
|
688
|
+
for (const assetId of assetIds) {
|
|
689
|
+
const normalizedAssetId = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_normalizeAssetIdOrThrow).call(this, assetId, 'getAccountAssetsByIDs');
|
|
690
|
+
const asset = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetFromState).call(this, accountId, normalizedAssetId, {
|
|
691
|
+
assetTypeSet: new Set(['fungible']),
|
|
692
|
+
});
|
|
693
|
+
if (asset) {
|
|
694
|
+
result[normalizedAssetId] = asset;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
return result;
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Get all combined assets (balance + metadata + price + computed
|
|
701
|
+
* `fiatValue`) an account holds on a given chain scope, directly from
|
|
702
|
+
* controller state.
|
|
703
|
+
*
|
|
704
|
+
* Applies the same state-composition and filtering rules as
|
|
705
|
+
* `getAccountAssetByID` (hidden or otherwise filtered assets are excluded).
|
|
706
|
+
* Reads from current state only and does not trigger a data-source refresh.
|
|
707
|
+
*
|
|
708
|
+
* @param accountId - The account ID (`InternalAccount.id`, not an address).
|
|
709
|
+
* @param scope - The CAIP-2 chain ID to filter by (e.g. `eip155:1`).
|
|
710
|
+
* @returns A record of combined `Asset`s keyed by CAIP-19 asset ID,
|
|
711
|
+
* containing only the account's assets on the given scope.
|
|
712
|
+
* @throws If `accountId` is empty or `scope` is not a valid CAIP-2 chain ID.
|
|
713
|
+
*/
|
|
714
|
+
getAccountAssetsByScope(accountId, scope) {
|
|
715
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_assertNonEmptyAccountId).call(this, accountId, 'getAccountAssetsByScope');
|
|
716
|
+
if (!(0, utils_1.isCaipChainId)(scope)) {
|
|
717
|
+
throw new Error(`AssetsController.getAccountAssetsByScope: invalid CAIP-2 scope "${String(scope)}"`);
|
|
718
|
+
}
|
|
719
|
+
const result = Object.create(null);
|
|
720
|
+
const chainIdSet = new Set([scope]);
|
|
721
|
+
const assetTypeSet = new Set(['fungible']);
|
|
722
|
+
const accountBalances = this.state.assetsBalance[accountId] ?? {};
|
|
723
|
+
for (const assetId of Object.keys(accountBalances)) {
|
|
724
|
+
const typedAssetId = assetId;
|
|
725
|
+
const asset = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetFromState).call(this, accountId, typedAssetId, {
|
|
726
|
+
chainIdSet,
|
|
727
|
+
assetTypeSet,
|
|
728
|
+
});
|
|
729
|
+
if (asset) {
|
|
730
|
+
result[typedAssetId] = asset;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
return result;
|
|
734
|
+
}
|
|
735
|
+
async getAssetsPrice(accounts, options) {
|
|
736
|
+
const assets = await this.getAssets(accounts, {
|
|
737
|
+
chainIds: options?.chainIds,
|
|
738
|
+
assetTypes: options?.assetTypes,
|
|
739
|
+
forceUpdate: options?.forceUpdate,
|
|
740
|
+
dataTypes: ['price'],
|
|
741
|
+
});
|
|
742
|
+
// Extract just the price from each asset (flattened across accounts)
|
|
743
|
+
const result = {};
|
|
744
|
+
for (const accountAssets of Object.values(assets)) {
|
|
745
|
+
for (const [assetId, asset] of Object.entries(accountAssets)) {
|
|
746
|
+
if (asset.price) {
|
|
747
|
+
result[assetId] = asset.price;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
return result;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Returns exchange rates in the format expected by the bridge controller
|
|
755
|
+
* (conversionRates, currencyRates, marketData, currentCurrency) so that
|
|
756
|
+
* when useAssetsControllerForRates is true the bridge can use a single
|
|
757
|
+
* action instead of MultichainAssetsRatesController, TokenRatesController,
|
|
758
|
+
* and CurrencyRateController.
|
|
759
|
+
*
|
|
760
|
+
* @returns Bridge-compatible exchange rate state derived from assetsPrice and selectedCurrency.
|
|
761
|
+
*/
|
|
762
|
+
getExchangeRatesForBridge() {
|
|
763
|
+
const { networkConfigurationsByChainId } = this.messenger.call('NetworkController:getState');
|
|
764
|
+
return (0, index_js_2.formatExchangeRatesForBridge)({
|
|
765
|
+
assetsInfo: this.state.assetsInfo,
|
|
766
|
+
assetsPrice: this.state.assetsPrice,
|
|
767
|
+
selectedCurrency: this.state.selectedCurrency,
|
|
768
|
+
nativeAssetIdentifiers: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetMap).call(this),
|
|
769
|
+
networkConfigurationsByChainId,
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Returns state in the legacy format expected by transaction-pay-controller
|
|
774
|
+
* (TokenBalancesController, AccountTrackerController, TokensController,
|
|
775
|
+
* TokenRatesController, CurrencyRateController shapes) so that when
|
|
776
|
+
* useAssetsController is true the transaction-pay-controller can use a
|
|
777
|
+
* single action instead of five separate getState calls.
|
|
778
|
+
*
|
|
779
|
+
* @returns Legacy-compatible state for transaction-pay-controller.
|
|
780
|
+
*/
|
|
781
|
+
getStateForTransactionPay() {
|
|
782
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
783
|
+
const { networkConfigurationsByChainId } = this.messenger.call('NetworkController:getState');
|
|
784
|
+
return (0, index_js_2.formatStateForTransactionPay)({
|
|
785
|
+
assetsBalance: this.state.assetsBalance,
|
|
786
|
+
assetsInfo: this.state.assetsInfo,
|
|
787
|
+
assetsPrice: this.state.assetsPrice,
|
|
788
|
+
selectedCurrency: this.state.selectedCurrency,
|
|
789
|
+
accounts: accounts.map((a) => ({ id: a.id, address: a.address })),
|
|
790
|
+
nativeAssetIdentifiers: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetMap).call(this),
|
|
791
|
+
networkConfigurationsByChainId,
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
// ============================================================================
|
|
795
|
+
// CUSTOM ASSETS MANAGEMENT
|
|
796
|
+
// ============================================================================
|
|
797
|
+
/**
|
|
798
|
+
* Add a custom asset for an account.
|
|
799
|
+
* Custom assets are included in subscription and fetch operations.
|
|
800
|
+
* Adding a custom asset also unhides it if it was previously hidden.
|
|
801
|
+
*
|
|
802
|
+
* When `pendingMetadata` is provided (e.g. from the extension's pending-tokens
|
|
803
|
+
* flow), the token metadata is persisted immediately into `assetsInfo` so the
|
|
804
|
+
* UI can render it without waiting for the next pipeline fetch.
|
|
805
|
+
*
|
|
806
|
+
* @param accountId - The account ID to add the custom asset for.
|
|
807
|
+
* @param assetId - The CAIP-19 asset ID to add.
|
|
808
|
+
* @param pendingMetadata - Optional token metadata from the UI (pendingTokens format).
|
|
809
|
+
*/
|
|
810
|
+
async addCustomAsset(accountId, assetId, pendingMetadata) {
|
|
811
|
+
const normalizedAssetId = (0, index_js_2.normalizeAssetId)(assetId);
|
|
812
|
+
log('Adding custom asset', { accountId, assetId: normalizedAssetId });
|
|
813
|
+
this.update((state) => {
|
|
814
|
+
var _a;
|
|
815
|
+
const customAssets = state.customAssets;
|
|
816
|
+
if (!customAssets[accountId]) {
|
|
817
|
+
customAssets[accountId] = [];
|
|
818
|
+
}
|
|
819
|
+
// Only add if not already present
|
|
820
|
+
if (!customAssets[accountId].includes(normalizedAssetId)) {
|
|
821
|
+
customAssets[accountId].push(normalizedAssetId);
|
|
822
|
+
}
|
|
823
|
+
// Unhide the asset if it was hidden (via assetPreferences)
|
|
824
|
+
const prefs = state.assetPreferences[normalizedAssetId];
|
|
825
|
+
if (prefs?.hidden) {
|
|
826
|
+
delete prefs.hidden;
|
|
827
|
+
if (Object.keys(prefs).length === 0) {
|
|
828
|
+
delete state.assetPreferences[normalizedAssetId];
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
// Persist metadata from the UI so the token is immediately renderable
|
|
832
|
+
if (pendingMetadata) {
|
|
833
|
+
const parsed = (0, utils_1.parseCaipAssetType)(normalizedAssetId);
|
|
834
|
+
let tokenType = 'erc20';
|
|
835
|
+
if (__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_isNativeAsset).call(this, normalizedAssetId)) {
|
|
836
|
+
tokenType = 'native';
|
|
837
|
+
}
|
|
838
|
+
else if (parsed.chain.namespace === utils_1.KnownCaipNamespace.Solana &&
|
|
839
|
+
parsed.assetNamespace === TokenDataSource_js_1.CaipAssetNamespace.Token) {
|
|
840
|
+
tokenType = 'spl';
|
|
841
|
+
}
|
|
842
|
+
const assetMetadata = {
|
|
843
|
+
type: tokenType,
|
|
844
|
+
symbol: pendingMetadata.symbol,
|
|
845
|
+
name: pendingMetadata.name,
|
|
846
|
+
decimals: pendingMetadata.decimals,
|
|
847
|
+
image: pendingMetadata.iconUrl,
|
|
848
|
+
aggregators: pendingMetadata.aggregators,
|
|
849
|
+
occurrences: pendingMetadata.occurrences,
|
|
850
|
+
};
|
|
851
|
+
state.assetsInfo[normalizedAssetId] =
|
|
852
|
+
assetMetadata;
|
|
853
|
+
}
|
|
854
|
+
// Seed a zero balance so the UI can render the asset immediately,
|
|
855
|
+
// before the next pipeline fetch returns the real amount.
|
|
856
|
+
const balances = state.assetsBalance;
|
|
857
|
+
balances[accountId] ?? (balances[accountId] = {});
|
|
858
|
+
(_a = balances[accountId])[normalizedAssetId] ?? (_a[normalizedAssetId] = { amount: '0' });
|
|
859
|
+
});
|
|
860
|
+
// Fetch data for the newly added custom asset (merge to preserve other chains)
|
|
861
|
+
const account = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((a) => a.id === accountId);
|
|
862
|
+
if (account) {
|
|
863
|
+
const chainId = extractChainId(normalizedAssetId);
|
|
864
|
+
await this.getAssets([account], {
|
|
865
|
+
chainIds: [chainId],
|
|
866
|
+
dataTypes: ['balance', 'metadata', 'price'],
|
|
867
|
+
assetTypes: ['fungible'],
|
|
868
|
+
forceUpdate: true,
|
|
869
|
+
updateMode: 'merge',
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
// Re-evaluate subscriptions so the supplemental RPC poll picks up the
|
|
873
|
+
// new customAsset on chains another data source already owns.
|
|
874
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* Remove a custom asset from an account.
|
|
878
|
+
*
|
|
879
|
+
* @param accountId - The account ID to remove the custom asset from.
|
|
880
|
+
* @param assetId - The CAIP-19 asset ID to remove.
|
|
881
|
+
*/
|
|
882
|
+
removeCustomAsset(accountId, assetId) {
|
|
883
|
+
const normalizedAssetId = (0, index_js_2.normalizeAssetId)(assetId);
|
|
884
|
+
log('Removing custom asset', { accountId, assetId: normalizedAssetId });
|
|
885
|
+
this.update((state) => {
|
|
886
|
+
if (state.customAssets[accountId]) {
|
|
887
|
+
state.customAssets[accountId] = state.customAssets[accountId].filter((id) => id !== normalizedAssetId);
|
|
888
|
+
// Clean up empty arrays
|
|
889
|
+
if (state.customAssets[accountId].length === 0) {
|
|
890
|
+
delete state.customAssets[accountId];
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
// Re-evaluate subscriptions so the supplemental RPC poll for that chain
|
|
895
|
+
// is torn down when no more customAssets remain there.
|
|
896
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* Get all custom assets for an account.
|
|
900
|
+
*
|
|
901
|
+
* @param accountId - The account ID to get custom assets for.
|
|
902
|
+
* @returns Array of CAIP-19 asset IDs for the account's custom assets.
|
|
903
|
+
*/
|
|
904
|
+
getCustomAssets(accountId) {
|
|
905
|
+
return this.state.customAssets[accountId] ?? [];
|
|
906
|
+
}
|
|
907
|
+
// ============================================================================
|
|
908
|
+
// HIDDEN ASSETS MANAGEMENT
|
|
909
|
+
// ============================================================================
|
|
910
|
+
/**
|
|
911
|
+
* Hide an asset globally.
|
|
912
|
+
* Hidden assets are excluded from the asset list returned by getAssets.
|
|
913
|
+
* The hidden state is stored in assetPreferences.
|
|
914
|
+
*
|
|
915
|
+
* @param assetId - The CAIP-19 asset ID to hide.
|
|
916
|
+
*/
|
|
917
|
+
hideAsset(assetId) {
|
|
918
|
+
const normalizedAssetId = (0, index_js_2.normalizeAssetId)(assetId);
|
|
919
|
+
log('Hiding asset', { assetId: normalizedAssetId });
|
|
920
|
+
this.update((state) => {
|
|
921
|
+
if (!state.assetPreferences[normalizedAssetId]) {
|
|
922
|
+
state.assetPreferences[normalizedAssetId] = {};
|
|
923
|
+
}
|
|
924
|
+
state.assetPreferences[normalizedAssetId].hidden = true;
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Unhide an asset globally.
|
|
929
|
+
*
|
|
930
|
+
* @param assetId - The CAIP-19 asset ID to unhide.
|
|
931
|
+
*/
|
|
932
|
+
unhideAsset(assetId) {
|
|
933
|
+
const normalizedAssetId = (0, index_js_2.normalizeAssetId)(assetId);
|
|
934
|
+
log('Unhiding asset', { assetId: normalizedAssetId });
|
|
935
|
+
this.update((state) => {
|
|
936
|
+
const prefs = state.assetPreferences[normalizedAssetId];
|
|
937
|
+
if (prefs) {
|
|
938
|
+
delete prefs.hidden;
|
|
939
|
+
if (Object.keys(prefs).length === 0) {
|
|
940
|
+
delete state.assetPreferences[normalizedAssetId];
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
// ============================================================================
|
|
946
|
+
// CURRENT CURRENCY MANAGEMENT
|
|
947
|
+
// ============================================================================
|
|
948
|
+
/**
|
|
949
|
+
* Set the current currency.
|
|
950
|
+
*
|
|
951
|
+
* @param selectedCurrency - The ISO 4217 currency code to set.
|
|
952
|
+
*/
|
|
953
|
+
setSelectedCurrency(selectedCurrency) {
|
|
954
|
+
const previousCurrency = this.state.selectedCurrency;
|
|
955
|
+
if (previousCurrency === selectedCurrency) {
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
this.update((state) => {
|
|
959
|
+
state.selectedCurrency = selectedCurrency;
|
|
960
|
+
});
|
|
961
|
+
log('Current currency changed', {
|
|
962
|
+
previousCurrency,
|
|
963
|
+
selectedCurrency,
|
|
964
|
+
});
|
|
965
|
+
if (!__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
// Currency changed — old cached prices are in the wrong currency.
|
|
969
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").invalidatePriceCache();
|
|
970
|
+
this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this), {
|
|
971
|
+
forceUpdate: true,
|
|
972
|
+
dataTypes: ['price'],
|
|
973
|
+
assetsForPriceUpdate: Object.values(this.state.assetsBalance).flatMap((balances) => Object.keys(balances)),
|
|
974
|
+
}).catch((error) => {
|
|
975
|
+
log('Failed to fetch asset prices after current currency change', error);
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
// ============================================================================
|
|
979
|
+
// SUBSCRIPTIONS
|
|
980
|
+
// ============================================================================
|
|
981
|
+
/**
|
|
982
|
+
* Subscribe to price updates for all assets held by the given accounts.
|
|
983
|
+
* Polls PriceDataSource which fetches prices from balance state.
|
|
984
|
+
*
|
|
985
|
+
* @param accounts - Accounts to subscribe price updates for.
|
|
986
|
+
* @param chainIds - Chain IDs to filter prices for.
|
|
987
|
+
*/
|
|
988
|
+
subscribeAssetsPrice(accounts, chainIds) {
|
|
989
|
+
if (!__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
const subscriptionKey = 'ds:PriceDataSource';
|
|
993
|
+
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
994
|
+
const isUpdate = existingSubscription !== undefined;
|
|
995
|
+
const request = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
|
|
996
|
+
dataTypes: ['price'],
|
|
997
|
+
});
|
|
998
|
+
const subscribeReq = {
|
|
999
|
+
request,
|
|
1000
|
+
subscriptionId: subscriptionKey,
|
|
1001
|
+
isUpdate,
|
|
1002
|
+
onAssetsUpdate: (response) => this.handleAssetsUpdate(response, 'PriceDataSource'),
|
|
1003
|
+
getAssetsState: () => this.state,
|
|
1004
|
+
};
|
|
1005
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").subscribe(subscribeReq).catch(console.error);
|
|
1006
|
+
// Track subscription
|
|
1007
|
+
const subscription = {
|
|
1008
|
+
chains: chainIds,
|
|
1009
|
+
accountId: subscriptionKey,
|
|
1010
|
+
assetTypes: ['fungible'],
|
|
1011
|
+
dataTypes: ['price'],
|
|
1012
|
+
unsubscribe: () => {
|
|
1013
|
+
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").delete(subscriptionKey);
|
|
1014
|
+
},
|
|
1015
|
+
};
|
|
1016
|
+
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").set(subscriptionKey, subscription);
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Unsubscribe from price updates.
|
|
1020
|
+
*/
|
|
1021
|
+
unsubscribeAssetsPrice() {
|
|
1022
|
+
const subscriptionKey = 'ds:PriceDataSource';
|
|
1023
|
+
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
1024
|
+
if (!existingSubscription) {
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").unsubscribe(subscriptionKey).catch(console.error);
|
|
1028
|
+
existingSubscription.unsubscribe();
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* Handle basic functionality toggle change. Call this from the consumer (extension or mobile)
|
|
1032
|
+
* when the user changes the "Basic functionality" setting. Refreshes subscriptions so the
|
|
1033
|
+
* current {@link AssetsControllerOptions.isBasicFunctionality} getter is used (true = APIs on,
|
|
1034
|
+
* false = RPC only).
|
|
1035
|
+
*
|
|
1036
|
+
* @param _isBasic - The new value (for call-site clarity; the getter is the source of truth).
|
|
1037
|
+
*/
|
|
1038
|
+
handleBasicFunctionalityChange(_isBasic) {
|
|
1039
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this);
|
|
1040
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Handle assets updated from a data source.
|
|
1044
|
+
* Called via the onAssetsUpdate callback passed in SubscriptionRequest when the controller subscribes to a data source.
|
|
1045
|
+
* Runs detection, then (when basic functionality is enabled) token metadata and price enrichment before updating state.
|
|
1046
|
+
* When basic functionality is disabled (RPC-only mode), only detection runs; token and price APIs are not used.
|
|
1047
|
+
*
|
|
1048
|
+
* @param response - The data response with updated assets
|
|
1049
|
+
* @param sourceId - The data source ID reporting the update
|
|
1050
|
+
* @param request - Optional original request for context when enriching
|
|
1051
|
+
*/
|
|
1052
|
+
async handleAssetsUpdate(response, sourceId, request) {
|
|
1053
|
+
log('Assets updated from data source', {
|
|
1054
|
+
sourceId,
|
|
1055
|
+
hasBalance: Boolean(response.assetsBalance),
|
|
1056
|
+
hasPrice: Boolean(response.assetsPrice),
|
|
1057
|
+
});
|
|
1058
|
+
// Enrichment spans only before unlock/first-init fetch completes.
|
|
1059
|
+
const pipelineTrace = __classPrivateFieldGet(this, _AssetsController_firstInitFetchReported, "f")
|
|
1060
|
+
? undefined
|
|
1061
|
+
: __classPrivateFieldGet(this, _AssetsController_trace, "f");
|
|
1062
|
+
await (0, trace_js_1.withTrace)({
|
|
1063
|
+
name: TRACE_UPDATE_PARENT,
|
|
1064
|
+
trace: pipelineTrace,
|
|
1065
|
+
data: {
|
|
1066
|
+
source: sourceId,
|
|
1067
|
+
has_balance: Boolean(response.assetsBalance),
|
|
1068
|
+
has_price: Boolean(response.assetsPrice),
|
|
1069
|
+
balance_account_count: response.assetsBalance
|
|
1070
|
+
? Object.keys(response.assetsBalance).length
|
|
1071
|
+
: 0,
|
|
1072
|
+
},
|
|
1073
|
+
fn: async (parentContext) => {
|
|
1074
|
+
const updateStart = performance.now();
|
|
1075
|
+
const resolvedRequest = request ?? {
|
|
1076
|
+
accountsWithSupportedChains: [],
|
|
1077
|
+
chainIds: [],
|
|
1078
|
+
dataTypes: ['balance', 'metadata', 'price'],
|
|
1079
|
+
};
|
|
1080
|
+
// RPC-only mode (basic functionality off): never run token/price APIs. Strip
|
|
1081
|
+
// those data types so downstream middleware cannot treat them as requested.
|
|
1082
|
+
const pipelineRequest = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
1083
|
+
? resolvedRequest
|
|
1084
|
+
: {
|
|
1085
|
+
...resolvedRequest,
|
|
1086
|
+
dataTypes: resolvedRequest.dataTypes.filter((dt) => dt !== 'metadata' && dt !== 'price'),
|
|
1087
|
+
};
|
|
1088
|
+
// Graduate custom assets only when AccountsAPI / AccountActivity reports
|
|
1089
|
+
// them. RPC already fetches custom assets on purpose, and Snap handles
|
|
1090
|
+
// non-EVM chains the rule does not apply to, so skip the middleware for
|
|
1091
|
+
// those.
|
|
1092
|
+
const shouldGraduateCustomAssets = sourceId === 'AccountsApiDataSource' ||
|
|
1093
|
+
sourceId === 'AccountActivityDataSource';
|
|
1094
|
+
// Websocket updates can carry brand-new spam airdrops: enrich them
|
|
1095
|
+
// with Token API occurrences and drop below-floor tokens BEFORE
|
|
1096
|
+
// detection, so spam is never detected, enriched, priced or persisted.
|
|
1097
|
+
const shouldFilterOccurrences = sourceId === 'AccountActivityDataSource' &&
|
|
1098
|
+
__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this);
|
|
1099
|
+
const enrichmentSources = [
|
|
1100
|
+
...(shouldGraduateCustomAssets
|
|
1101
|
+
? [__classPrivateFieldGet(this, _AssetsController_customAssetGraduationMiddleware, "f")]
|
|
1102
|
+
: []),
|
|
1103
|
+
...(shouldFilterOccurrences
|
|
1104
|
+
? [
|
|
1105
|
+
{
|
|
1106
|
+
getName: () => 'OccurrenceFloorFilter',
|
|
1107
|
+
assetsMiddleware: __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f").occurrenceFilterMiddleware,
|
|
1108
|
+
},
|
|
1109
|
+
]
|
|
1110
|
+
: []),
|
|
1111
|
+
__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
|
|
1112
|
+
];
|
|
1113
|
+
if (__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
|
|
1114
|
+
enrichmentSources.push((0, ParallelMiddleware_js_1.createParallelMiddleware)([
|
|
1115
|
+
__classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
|
|
1116
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
|
|
1117
|
+
]));
|
|
1118
|
+
}
|
|
1119
|
+
const { response: enrichedResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
|
|
1120
|
+
sources: enrichmentSources,
|
|
1121
|
+
request: pipelineRequest,
|
|
1122
|
+
initialResponse: response,
|
|
1123
|
+
parentContext,
|
|
1124
|
+
trace: pipelineTrace,
|
|
1125
|
+
});
|
|
1126
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
1127
|
+
...enrichedResponse,
|
|
1128
|
+
replaceCoveredChainBalances: response.replaceCoveredChainBalances,
|
|
1129
|
+
});
|
|
1130
|
+
// Summary fields for Assets Health (nested under the parent span).
|
|
1131
|
+
(0, trace_js_1.emitTrace)({
|
|
1132
|
+
name: TRACE_UPDATE_PIPELINE,
|
|
1133
|
+
trace: pipelineTrace,
|
|
1134
|
+
data: {
|
|
1135
|
+
source: sourceId,
|
|
1136
|
+
duration_ms: performance.now() - updateStart,
|
|
1137
|
+
has_balance: Boolean(response.assetsBalance),
|
|
1138
|
+
has_price: Boolean(response.assetsPrice),
|
|
1139
|
+
has_metadata: Boolean(enrichedResponse.assetsInfo),
|
|
1140
|
+
balance_account_count: response.assetsBalance
|
|
1141
|
+
? Object.keys(response.assetsBalance).length
|
|
1142
|
+
: 0,
|
|
1143
|
+
},
|
|
1144
|
+
parentContext,
|
|
1145
|
+
});
|
|
1146
|
+
},
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
// ============================================================================
|
|
1150
|
+
// CLEANUP
|
|
1151
|
+
// ============================================================================
|
|
1152
|
+
destroy() {
|
|
1153
|
+
log('Destroying AssetsController', {
|
|
1154
|
+
dataSourceCount: __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_allBalanceDataSources_get).length,
|
|
1155
|
+
subscriptionCount: __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").size,
|
|
1156
|
+
});
|
|
1157
|
+
// Destroy instantiated data sources
|
|
1158
|
+
__classPrivateFieldGet(this, _AssetsController_accountActivityDataSource, "f")?.destroy?.();
|
|
1159
|
+
__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f")?.destroy?.();
|
|
1160
|
+
__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f")?.destroy?.();
|
|
1161
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")?.destroy?.();
|
|
1162
|
+
__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f")?.destroy?.();
|
|
1163
|
+
// Stop all active subscriptions
|
|
1164
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this);
|
|
1165
|
+
if (__classPrivateFieldGet(this, _AssetsController_unsubscribeBasicFunctionality, "f")) {
|
|
1166
|
+
__classPrivateFieldGet(this, _AssetsController_unsubscribeBasicFunctionality, "f").call(this);
|
|
1167
|
+
__classPrivateFieldSet(this, _AssetsController_unsubscribeBasicFunctionality, null, "f");
|
|
1168
|
+
}
|
|
1169
|
+
// Unregister action handlers
|
|
1170
|
+
this.messenger.unregisterActionHandler('AssetsController:getAssets');
|
|
1171
|
+
this.messenger.unregisterActionHandler('AssetsController:getAssetsBalance');
|
|
1172
|
+
this.messenger.unregisterActionHandler('AssetsController:getAssetMetadata');
|
|
1173
|
+
this.messenger.unregisterActionHandler('AssetsController:getAccountAssetByID');
|
|
1174
|
+
this.messenger.unregisterActionHandler('AssetsController:getAccountAssetsByIDs');
|
|
1175
|
+
this.messenger.unregisterActionHandler('AssetsController:getAccountAssetsByScope');
|
|
1176
|
+
this.messenger.unregisterActionHandler('AssetsController:getAssetsPrice');
|
|
1177
|
+
this.messenger.unregisterActionHandler('AssetsController:getExchangeRatesForBridge');
|
|
1178
|
+
this.messenger.unregisterActionHandler('AssetsController:getStateForTransactionPay');
|
|
1179
|
+
this.messenger.unregisterActionHandler('AssetsController:addCustomAsset');
|
|
1180
|
+
this.messenger.unregisterActionHandler('AssetsController:removeCustomAsset');
|
|
1181
|
+
this.messenger.unregisterActionHandler('AssetsController:getCustomAssets');
|
|
1182
|
+
this.messenger.unregisterActionHandler('AssetsController:hideAsset');
|
|
1183
|
+
this.messenger.unregisterActionHandler('AssetsController:unhideAsset');
|
|
1184
|
+
this.messenger.unregisterActionHandler('AssetsController:setSelectedCurrency');
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
exports.AssetsController = AssetsController;
|
|
1188
|
+
_AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctionality = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_trace = new WeakMap(), _AssetsController_captureException = new WeakMap(), _AssetsController_firstInitFetchReported = new WeakMap(), _AssetsController_stateSizeReported = new WeakMap(), _AssetsController_uiOpen = new WeakMap(), _AssetsController_keyringUnlocked = new WeakMap(), _AssetsController_accountTreeInitialized = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_accountRefreshMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(), _AssetsController_lastKnownAccountIds = new WeakMap(), _AssetsController_accountActivityDataSource = new WeakMap(), _AssetsController_accountsApiDataSource = new WeakMap(), _AssetsController_snapDataSource = new WeakMap(), _AssetsController_rpcDataSource = new WeakMap(), _AssetsController_stakedBalanceDataSource = new WeakMap(), _AssetsController_priceDataSource = new WeakMap(), _AssetsController_detectionMiddleware = new WeakMap(), _AssetsController_customAssetGraduationMiddleware = new WeakMap(), _AssetsController_rpcFallbackMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_unsubscribeBasicFunctionality = new WeakMap(), _AssetsController_queryApiClient = new WeakMap(), _AssetsController_onActiveChainsUpdated = new WeakMap(), _AssetsController_instances = new WeakSet(), _AssetsController_emitStateSizeTrace = function _AssetsController_emitStateSizeTrace() {
|
|
1189
|
+
if (!__classPrivateFieldGet(this, _AssetsController_trace, "f") || __classPrivateFieldGet(this, _AssetsController_stateSizeReported, "f")) {
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
__classPrivateFieldSet(this, _AssetsController_stateSizeReported, true, "f");
|
|
1193
|
+
const { assetsBalance: balances, customAssets, assetsInfo, assetsPrice, } = this.state;
|
|
1194
|
+
// Count balance entries and collect unique asset IDs / chain IDs in one pass.
|
|
1195
|
+
let balanceEntries = 0;
|
|
1196
|
+
const uniqueAssets = new Set();
|
|
1197
|
+
const uniqueNetworks = new Set();
|
|
1198
|
+
for (const acct of Object.values(balances)) {
|
|
1199
|
+
const assetIds = Object.keys(acct);
|
|
1200
|
+
balanceEntries += assetIds.length;
|
|
1201
|
+
for (const assetId of assetIds) {
|
|
1202
|
+
uniqueAssets.add(assetId);
|
|
1203
|
+
// CAIP-19 format: "eip155:1/slip44:60" — chainId is everything before "/"
|
|
1204
|
+
const slash = assetId.indexOf('/');
|
|
1205
|
+
if (slash > 0) {
|
|
1206
|
+
uniqueNetworks.add(assetId.slice(0, slash));
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
let customAssetEntries = 0;
|
|
1211
|
+
for (const ids of Object.values(customAssets)) {
|
|
1212
|
+
if (Array.isArray(ids)) {
|
|
1213
|
+
customAssetEntries += ids.length;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
(0, trace_js_1.emitTrace)({
|
|
1217
|
+
name: TRACE_STATE_SIZE,
|
|
1218
|
+
trace: __classPrivateFieldGet(this, _AssetsController_trace, "f"),
|
|
1219
|
+
data: {
|
|
1220
|
+
balance_entries: balanceEntries,
|
|
1221
|
+
balance_accounts: Object.keys(balances).length,
|
|
1222
|
+
// `asset_count` matches the Assets Health dashboard widget field name.
|
|
1223
|
+
asset_count: uniqueAssets.size,
|
|
1224
|
+
unique_asset_count: uniqueAssets.size,
|
|
1225
|
+
network_count: uniqueNetworks.size,
|
|
1226
|
+
metadata_entries: Object.keys(assetsInfo).length,
|
|
1227
|
+
price_entries: Object.keys(assetsPrice).length,
|
|
1228
|
+
custom_asset_entries: customAssetEntries,
|
|
1229
|
+
},
|
|
1230
|
+
});
|
|
1231
|
+
}, _AssetsController_getSelectedAccounts = function _AssetsController_getSelectedAccounts() {
|
|
1232
|
+
const accounts = this.messenger.call('AccountTreeController:getAccountsFromSelectedAccountGroup');
|
|
1233
|
+
if (accounts.length > 0) {
|
|
1234
|
+
return accounts;
|
|
1235
|
+
}
|
|
1236
|
+
const selectedAccount = this.messenger.call('AccountsController:getSelectedAccount');
|
|
1237
|
+
if (selectedAccount) {
|
|
1238
|
+
return [selectedAccount];
|
|
1239
|
+
}
|
|
1240
|
+
return [];
|
|
1241
|
+
}, _AssetsController_allBalanceDataSources_get = function _AssetsController_allBalanceDataSources_get() {
|
|
1242
|
+
return [
|
|
1243
|
+
__classPrivateFieldGet(this, _AssetsController_accountActivityDataSource, "f"),
|
|
1244
|
+
__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f"),
|
|
1245
|
+
__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f"),
|
|
1246
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f"),
|
|
1247
|
+
];
|
|
1248
|
+
}, _AssetsController_initializeNativeAssetsMap = function _AssetsController_initializeNativeAssetsMap(queryApiClient) {
|
|
1249
|
+
queryApiClient.queryClient
|
|
1250
|
+
.fetchQuery({
|
|
1251
|
+
queryKey: NATIVE_ASSETS_QUERY_KEY,
|
|
1252
|
+
queryFn: index_js_2.buildNativeAssetsFromApi,
|
|
1253
|
+
staleTime: Infinity,
|
|
1254
|
+
gcTime: Infinity,
|
|
1255
|
+
})
|
|
1256
|
+
.catch((error) => {
|
|
1257
|
+
// Failure to populate native asset cache is non-fatal;
|
|
1258
|
+
// #isNativeAsset falls back to the seed data from buildNativeAssetsFromConstant.
|
|
1259
|
+
log('Failed to populate native asset cache, falling back to seed data', error);
|
|
1260
|
+
});
|
|
1261
|
+
// Seed the cache synchronously so that synchronous consumers (e.g.
|
|
1262
|
+
// #isNativeAsset, #resolveNativeAssetIds) have data available immediately.
|
|
1263
|
+
// When fetchQuery resolves (currently instant, future: API), it overwrites
|
|
1264
|
+
// this with potentially fresher data.
|
|
1265
|
+
const initialNativeAssetMap = (0, index_js_2.buildNativeAssetsFromConstant)();
|
|
1266
|
+
queryApiClient.setCachedData(NATIVE_ASSETS_QUERY_KEY, initialNativeAssetMap);
|
|
1267
|
+
}, _AssetsController_initializeState = function _AssetsController_initializeState() {
|
|
1268
|
+
const { enabledNetworkMap } = this.messenger.call('NetworkEnablementController:getState');
|
|
1269
|
+
__classPrivateFieldSet(this, _AssetsController_enabledChains, __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_extractEnabledChains).call(this, enabledNetworkMap), "f");
|
|
1270
|
+
log('Initialized state', {
|
|
1271
|
+
enabledNetworkMap,
|
|
1272
|
+
enabledChains: __classPrivateFieldGet(this, _AssetsController_enabledChains, "f"),
|
|
1273
|
+
});
|
|
1274
|
+
}, _AssetsController_extractEnabledChains = function _AssetsController_extractEnabledChains(enabledNetworkMap) {
|
|
1275
|
+
const chains = new Set();
|
|
1276
|
+
for (const [namespace, networks] of Object.entries(enabledNetworkMap)) {
|
|
1277
|
+
for (const [reference, isEnabled] of Object.entries(networks)) {
|
|
1278
|
+
if (isEnabled) {
|
|
1279
|
+
// Check if reference is already a full CAIP-2 chain ID (contains colon)
|
|
1280
|
+
if (reference.includes(':')) {
|
|
1281
|
+
// Already a full chain ID, use as-is
|
|
1282
|
+
chains.add(reference);
|
|
1283
|
+
}
|
|
1284
|
+
else {
|
|
1285
|
+
// Normalize EIP155 chain references from hex to decimal (CAIP-2 standard)
|
|
1286
|
+
const normalizedReference = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_normalizeChainReference).call(this, namespace, reference);
|
|
1287
|
+
chains.add(`${namespace}:${normalizedReference}`);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
return chains;
|
|
1293
|
+
}, _AssetsController_normalizeChainReference = function _AssetsController_normalizeChainReference(namespace, reference) {
|
|
1294
|
+
if (namespace === 'eip155' && (0, utils_1.isStrictHexString)(reference)) {
|
|
1295
|
+
// Convert hex to decimal for EIP155 chains
|
|
1296
|
+
return parseInt(reference, 16).toString();
|
|
1297
|
+
}
|
|
1298
|
+
return reference;
|
|
1299
|
+
}, _AssetsController_subscribeToEvents = function _AssetsController_subscribeToEvents() {
|
|
1300
|
+
// Subscribe to account group changes (when user switches between account groups like Account 1 -> Account 2)
|
|
1301
|
+
this.messenger.subscribe('AccountTreeController:selectedAccountGroupChange', (groupId, previousGroupId) => {
|
|
1302
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleAccountGroupChanged).call(this, groupId, previousGroupId).catch(console.error);
|
|
1303
|
+
});
|
|
1304
|
+
// Catch post-init tree mutations that change the selected account set
|
|
1305
|
+
// (e.g. a snap account added to the current group) without changing
|
|
1306
|
+
// the selected group id. Intermediate `:stateChange` events during
|
|
1307
|
+
// `AccountTreeController.init()` are ignored until `:initialized`.
|
|
1308
|
+
this.messenger.subscribe('AccountTreeController:stateChange', () => {
|
|
1309
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleAccountTreeStateChange).call(this);
|
|
1310
|
+
});
|
|
1311
|
+
// Subscribe to network enablement changes (only enabledNetworkMap)
|
|
1312
|
+
this.messenger.subscribe('NetworkEnablementController:stateChange', ({ enabledNetworkMap }) => {
|
|
1313
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleEnabledNetworksChanged).call(this, enabledNetworkMap).catch(console.error);
|
|
1314
|
+
});
|
|
1315
|
+
// When a network is added or removed from NetworkController, refresh
|
|
1316
|
+
// assets across every data source so balances, prices, and metadata
|
|
1317
|
+
// stay consistent. On add we also seed default tracked assets (e.g.
|
|
1318
|
+
// mUSD on Monad) when the chain is in our defaults registry, so the
|
|
1319
|
+
// entries appear immediately without waiting for it to also be
|
|
1320
|
+
// enabled in NetworkEnablementController.
|
|
1321
|
+
this.messenger.subscribe('NetworkController:networkAdded', (networkConfiguration) => {
|
|
1322
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleNetworkAdded).call(this, networkConfiguration.chainId);
|
|
1323
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_refreshAssetsAfterNetworkAdded).call(this, networkConfiguration.chainId).catch((error) => {
|
|
1324
|
+
log('Failed to refresh assets after network added', { error });
|
|
1325
|
+
});
|
|
1326
|
+
});
|
|
1327
|
+
this.messenger.subscribe('NetworkController:networkRemoved', () => {
|
|
1328
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_refreshAssetsAfterNetworkChange).call(this);
|
|
1329
|
+
});
|
|
1330
|
+
// Selected EVM network switch (network picker). Enablement changes are
|
|
1331
|
+
// handled separately via NetworkEnablementController:stateChange.
|
|
1332
|
+
this.messenger.subscribe('NetworkController:networkDidChange', (networkState) => {
|
|
1333
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleNetworkDidChange).call(this, networkState).catch(console.error);
|
|
1334
|
+
});
|
|
1335
|
+
// Client + Keyring lifecycle: only run when UI is open AND keyring is unlocked
|
|
1336
|
+
this.messenger.subscribe('ClientController:stateChange', (isUiOpen) => {
|
|
1337
|
+
__classPrivateFieldSet(this, _AssetsController_uiOpen, isUiOpen, "f");
|
|
1338
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateActive).call(this);
|
|
1339
|
+
}, client_controller_1.clientControllerSelectors.selectIsUiOpen);
|
|
1340
|
+
this.messenger.subscribe('KeyringController:unlock', () => {
|
|
1341
|
+
__classPrivateFieldSet(this, _AssetsController_keyringUnlocked, true, "f");
|
|
1342
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateActive).call(this);
|
|
1343
|
+
});
|
|
1344
|
+
this.messenger.subscribe('KeyringController:lock', () => {
|
|
1345
|
+
__classPrivateFieldSet(this, _AssetsController_keyringUnlocked, false, "f");
|
|
1346
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateActive).call(this);
|
|
1347
|
+
});
|
|
1348
|
+
// Subscribe to unapproved transactions - TXs that need confirmation
|
|
1349
|
+
// Ensures that balances for the account making transaction are updated (e.g. for gas estimations)
|
|
1350
|
+
this.messenger.subscribe('TransactionController:unapprovedTransactionAdded', (transactionMeta) => {
|
|
1351
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_onUnapprovedTransactionAdded).call(this, transactionMeta);
|
|
1352
|
+
});
|
|
1353
|
+
// Post-tx refresh via the full fetch pipeline (Accounts API + RPC fallback).
|
|
1354
|
+
// RpcDataSource also listens for transactionConfirmed, but only refreshes
|
|
1355
|
+
// chains it owns via an active subscription.
|
|
1356
|
+
this.messenger.subscribe('TransactionController:transactionConfirmed', (transactionMeta) => {
|
|
1357
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_onTransactionConfirmed).call(this, transactionMeta);
|
|
1358
|
+
});
|
|
1359
|
+
// Start tracking only after the account tree is fully built. Unlock can
|
|
1360
|
+
// happen before `AccountTreeController.init()`, and `:stateChange` fires
|
|
1361
|
+
// for intermediate mutations during that build.
|
|
1362
|
+
this.messenger.subscribe('AccountTreeController:initialized', () => {
|
|
1363
|
+
__classPrivateFieldSet(this, _AssetsController_accountTreeInitialized, true, "f");
|
|
1364
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateActive).call(this);
|
|
1365
|
+
});
|
|
1366
|
+
this.messenger.subscribe('AccountTreeController:uninitialized', () => {
|
|
1367
|
+
__classPrivateFieldSet(this, _AssetsController_accountTreeInitialized, false, "f");
|
|
1368
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateActive).call(this);
|
|
1369
|
+
});
|
|
1370
|
+
}, _AssetsController_onUnapprovedTransactionAdded = function _AssetsController_onUnapprovedTransactionAdded(transactionMeta) {
|
|
1371
|
+
const hexChainId = transactionMeta.chainId;
|
|
1372
|
+
if (!hexChainId) {
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
const caipChainId = `eip155:${parseInt(hexChainId, 16)}`;
|
|
1376
|
+
const fromAddress = transactionMeta.txParams.from?.toLowerCase();
|
|
1377
|
+
if (!fromAddress) {
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
const matchedAccount = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((account) => account.address.toLowerCase() === fromAddress);
|
|
1381
|
+
if (!matchedAccount) {
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
this.getAssets([matchedAccount], {
|
|
1385
|
+
chainIds: [caipChainId],
|
|
1386
|
+
forceUpdate: true,
|
|
1387
|
+
}).catch((error) => {
|
|
1388
|
+
log('Failed to refresh assets after unapproved transaction added', {
|
|
1389
|
+
error,
|
|
1390
|
+
});
|
|
1391
|
+
});
|
|
1392
|
+
}, _AssetsController_onTransactionConfirmed = function _AssetsController_onTransactionConfirmed(transactionMeta) {
|
|
1393
|
+
const hexChainId = transactionMeta.chainId;
|
|
1394
|
+
if (!hexChainId) {
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
const caipChainId = `eip155:${parseInt(hexChainId, 16)}`;
|
|
1398
|
+
const fromAddress = transactionMeta.txParams.from?.toLowerCase();
|
|
1399
|
+
if (!fromAddress) {
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
const matchedAccount = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((account) => account.address.toLowerCase() === fromAddress);
|
|
1403
|
+
if (!matchedAccount) {
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
this.getAssets([matchedAccount], {
|
|
1407
|
+
chainIds: [caipChainId],
|
|
1408
|
+
forceUpdate: true,
|
|
1409
|
+
}).catch((error) => {
|
|
1410
|
+
log('Failed to refresh assets after transaction confirmed', { error });
|
|
1411
|
+
});
|
|
1412
|
+
}, _AssetsController_updateActive = function _AssetsController_updateActive() {
|
|
1413
|
+
const shouldRun = __classPrivateFieldGet(this, _AssetsController_uiOpen, "f") && __classPrivateFieldGet(this, _AssetsController_keyringUnlocked, "f") && __classPrivateFieldGet(this, _AssetsController_accountTreeInitialized, "f");
|
|
1414
|
+
if (shouldRun) {
|
|
1415
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_start).call(this);
|
|
1416
|
+
}
|
|
1417
|
+
else {
|
|
1418
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this);
|
|
1419
|
+
}
|
|
1420
|
+
}, _AssetsController_handleAccountTreeStateChange = function _AssetsController_handleAccountTreeStateChange() {
|
|
1421
|
+
const shouldRun = __classPrivateFieldGet(this, _AssetsController_uiOpen, "f") &&
|
|
1422
|
+
__classPrivateFieldGet(this, _AssetsController_keyringUnlocked, "f") &&
|
|
1423
|
+
__classPrivateFieldGet(this, _AssetsController_accountTreeInitialized, "f") &&
|
|
1424
|
+
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").size > 0;
|
|
1425
|
+
if (!shouldRun) {
|
|
1426
|
+
return;
|
|
1427
|
+
}
|
|
1428
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
1429
|
+
const currentIds = new Set(accounts.map((a) => a.id));
|
|
1430
|
+
const accountsChanged = currentIds.size !== __classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").size ||
|
|
1431
|
+
[...currentIds].some((id) => !__classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").has(id));
|
|
1432
|
+
if (!accountsChanged) {
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
const hasOverlap = [...currentIds].some((id) => __classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").has(id));
|
|
1436
|
+
if (!hasOverlap && __classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").size > 0) {
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
log('Account tree changed with new accounts, re-subscribing', {
|
|
1440
|
+
previousCount: __classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").size,
|
|
1441
|
+
currentCount: currentIds.size,
|
|
1442
|
+
});
|
|
1443
|
+
const newAccounts = accounts.filter((account) => !__classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").has(account.id));
|
|
1444
|
+
__classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, currentIds, "f");
|
|
1445
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
1446
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
1447
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_runAccountTreeRefresh).call(this, accounts, newAccounts).catch((error) => {
|
|
1448
|
+
log('Failed to refresh assets after tree change', error);
|
|
1449
|
+
});
|
|
1450
|
+
}, _AssetsController_runAccountTreeRefresh = async function _AssetsController_runAccountTreeRefresh(accounts, newAccounts = []) {
|
|
1451
|
+
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_accountRefreshMutex, "f").acquire();
|
|
1452
|
+
try {
|
|
1453
|
+
await this.getAssets(accounts, {
|
|
1454
|
+
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
1455
|
+
forceUpdate: true,
|
|
1456
|
+
});
|
|
1457
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this, { skipInitialFetch: true });
|
|
1458
|
+
if (newAccounts.length > 0) {
|
|
1459
|
+
await this.getAssets(newAccounts, {
|
|
1460
|
+
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
1461
|
+
forceUpdate: true,
|
|
1462
|
+
});
|
|
1463
|
+
}
|
|
1464
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")]);
|
|
1465
|
+
}
|
|
1466
|
+
catch (error) {
|
|
1467
|
+
log('Failed to fetch assets after tree change', error);
|
|
1468
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this, { skipInitialFetch: true });
|
|
1469
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")]);
|
|
1470
|
+
}
|
|
1471
|
+
finally {
|
|
1472
|
+
releaseLock();
|
|
1473
|
+
}
|
|
1474
|
+
}, _AssetsController_runStartupRefresh =
|
|
1475
|
+
/**
|
|
1476
|
+
* Force-fetch balances then subscribe. Used on unlock / first startup.
|
|
1477
|
+
*
|
|
1478
|
+
* @param accounts - Selected accounts to refresh.
|
|
1479
|
+
*/
|
|
1480
|
+
async function _AssetsController_runStartupRefresh(accounts) {
|
|
1481
|
+
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_accountRefreshMutex, "f").acquire();
|
|
1482
|
+
try {
|
|
1483
|
+
await this.getAssets(accounts, {
|
|
1484
|
+
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
1485
|
+
forceUpdate: true,
|
|
1486
|
+
});
|
|
1487
|
+
// Seed before subscribe so the price poll / update fetch sees natives
|
|
1488
|
+
// and default tracked assets that were never returned by balance APIs.
|
|
1489
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
1490
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
1491
|
+
// Balances were just force-fetched — skip AccountsApi's subscribe-time poll.
|
|
1492
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this, { skipInitialFetch: true });
|
|
1493
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")]);
|
|
1494
|
+
}
|
|
1495
|
+
catch (error) {
|
|
1496
|
+
log('Failed to fetch assets on startup', error);
|
|
1497
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
1498
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
1499
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this, { skipInitialFetch: true });
|
|
1500
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")]);
|
|
1501
|
+
}
|
|
1502
|
+
finally {
|
|
1503
|
+
releaseLock();
|
|
1504
|
+
}
|
|
1505
|
+
}, _AssetsController_registerActionHandlers = function _AssetsController_registerActionHandlers() {
|
|
1506
|
+
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
1507
|
+
}, _AssetsController_handleActiveChainsUpdate = function _AssetsController_handleActiveChainsUpdate(dataSourceId, activeChains, previousChains) {
|
|
1508
|
+
if (!__classPrivateFieldGet(this, _AssetsController_uiOpen, "f") || !__classPrivateFieldGet(this, _AssetsController_keyringUnlocked, "f") || !__classPrivateFieldGet(this, _AssetsController_isEnabled, "f").call(this)) {
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
log('Data source active chains changed', {
|
|
1512
|
+
dataSourceId,
|
|
1513
|
+
chainCount: activeChains.length,
|
|
1514
|
+
chains: activeChains,
|
|
1515
|
+
});
|
|
1516
|
+
const previous = previousChains;
|
|
1517
|
+
const previousSet = new Set(previous);
|
|
1518
|
+
const addedChains = activeChains.filter((ch) => !previousSet.has(ch));
|
|
1519
|
+
const removedChains = previous.filter((ch) => !activeChains.includes(ch));
|
|
1520
|
+
// Refresh subscriptions to use updated data source availability.
|
|
1521
|
+
if (addedChains.length > 0 || removedChains.length > 0) {
|
|
1522
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
1523
|
+
}
|
|
1524
|
+
}, _AssetsController_executeMiddlewares =
|
|
1525
|
+
// ============================================================================
|
|
1526
|
+
// MIDDLEWARE EXECUTION
|
|
1527
|
+
// ============================================================================
|
|
1528
|
+
/**
|
|
1529
|
+
* Execute middlewares with request/response context.
|
|
1530
|
+
* Returns response and exclusive duration per source (sum ≈ wall time).
|
|
1531
|
+
*
|
|
1532
|
+
* @param params - Middleware execution options.
|
|
1533
|
+
* @param params.sources - Data sources or middlewares with getName() and assetsMiddleware.
|
|
1534
|
+
* @param params.request - The data request.
|
|
1535
|
+
* @param params.initialResponse - Optional initial response (for enriching existing data).
|
|
1536
|
+
* @param params.parentContext - Optional parent Sentry span; per-source timings nest under it.
|
|
1537
|
+
* @param params.trace - Optional trace callback; omit after unlock/first-init to skip spans.
|
|
1538
|
+
* @returns Response and durationByDataSource (exclusive ms per source name).
|
|
1539
|
+
*/
|
|
1540
|
+
async function _AssetsController_executeMiddlewares(params) {
|
|
1541
|
+
const { sources, request, initialResponse = {}, parentContext, trace, } = params;
|
|
1542
|
+
const names = sources.map((source) => source.getName());
|
|
1543
|
+
const middlewares = sources.map((source) => source.assetsMiddleware);
|
|
1544
|
+
const inclusive = [];
|
|
1545
|
+
const wrapped = middlewares.map((middleware, i) => (async (ctx, next) => {
|
|
1546
|
+
const start = performance.now();
|
|
1547
|
+
try {
|
|
1548
|
+
return await middleware(ctx, next);
|
|
1549
|
+
}
|
|
1550
|
+
finally {
|
|
1551
|
+
inclusive[i] = performance.now() - start;
|
|
1552
|
+
}
|
|
1553
|
+
}));
|
|
1554
|
+
const middlewareErrors = [];
|
|
1555
|
+
const chain = wrapped.reduceRight((next, middleware, index) => async (ctx) => {
|
|
1556
|
+
try {
|
|
1557
|
+
return await middleware(ctx, next);
|
|
1558
|
+
}
|
|
1559
|
+
catch (error) {
|
|
1560
|
+
const sourceName = names[index] ?? `middleware_${index}`;
|
|
1561
|
+
middlewareErrors.push(sourceName);
|
|
1562
|
+
console.error('[AssetsController] Middleware failed:', error);
|
|
1563
|
+
return next(ctx);
|
|
1564
|
+
}
|
|
1565
|
+
}, async (ctx) => ctx);
|
|
1566
|
+
const result = await chain({
|
|
1567
|
+
request,
|
|
1568
|
+
response: initialResponse,
|
|
1569
|
+
getAssetsState: () => this.state,
|
|
1570
|
+
});
|
|
1571
|
+
const durationByDataSource = {};
|
|
1572
|
+
for (let i = 0; i < inclusive.length; i++) {
|
|
1573
|
+
const nextInc = i + 1 < inclusive.length ? (inclusive[i + 1] ?? 0) : 0;
|
|
1574
|
+
const exclusive = Math.max(0, (inclusive[i] ?? 0) - nextInc);
|
|
1575
|
+
const name = names[i];
|
|
1576
|
+
if (name !== undefined) {
|
|
1577
|
+
durationByDataSource[name] = exclusive;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
if (result.durationByDataSource) {
|
|
1581
|
+
for (const [key, ms] of Object.entries(result.durationByDataSource)) {
|
|
1582
|
+
durationByDataSource[key] = ms;
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
// Emit per-source timing as subspans under the parent fetch/update span
|
|
1586
|
+
// (no-op when `trace` is omitted — unlock/first-init only).
|
|
1587
|
+
for (const [sourceName, durationMs] of Object.entries(durationByDataSource)) {
|
|
1588
|
+
(0, trace_js_1.emitTrace)({
|
|
1589
|
+
name: TRACE_DATA_SOURCE_TIMING,
|
|
1590
|
+
trace,
|
|
1591
|
+
data: {
|
|
1592
|
+
source: sourceName,
|
|
1593
|
+
duration_ms: durationMs,
|
|
1594
|
+
chain_count: request.chainIds.length,
|
|
1595
|
+
account_count: request.accountsWithSupportedChains.length,
|
|
1596
|
+
},
|
|
1597
|
+
tags: {
|
|
1598
|
+
controller: 'AssetsController',
|
|
1599
|
+
// String tag so Spans widgets can group by `source`.
|
|
1600
|
+
source: sourceName,
|
|
1601
|
+
},
|
|
1602
|
+
parentContext,
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
// Failed middlewares: Issues (optional) + perf/Dashboard spans
|
|
1606
|
+
if (middlewareErrors.length > 0) {
|
|
1607
|
+
const failedSources = middlewareErrors.join(',');
|
|
1608
|
+
const assetsError = new errors_js_1.AssetsDataSourceError({
|
|
1609
|
+
failedSources,
|
|
1610
|
+
errorCount: middlewareErrors.length,
|
|
1611
|
+
chainCount: request.chainIds.length,
|
|
1612
|
+
});
|
|
1613
|
+
try {
|
|
1614
|
+
__classPrivateFieldGet(this, _AssetsController_captureException, "f")?.call(this, assetsError);
|
|
1615
|
+
}
|
|
1616
|
+
catch {
|
|
1617
|
+
// Never let telemetry throw.
|
|
1618
|
+
}
|
|
1619
|
+
(0, trace_js_1.emitTrace)({
|
|
1620
|
+
name: TRACE_DATA_SOURCE_ERROR,
|
|
1621
|
+
trace,
|
|
1622
|
+
data: {
|
|
1623
|
+
failed_sources: failedSources,
|
|
1624
|
+
error_count: middlewareErrors.length,
|
|
1625
|
+
chain_count: request.chainIds.length,
|
|
1626
|
+
},
|
|
1627
|
+
tags: {
|
|
1628
|
+
controller: 'AssetsController',
|
|
1629
|
+
severity: 'error',
|
|
1630
|
+
error_type: assetsError.name,
|
|
1631
|
+
},
|
|
1632
|
+
parentContext,
|
|
1633
|
+
});
|
|
1634
|
+
}
|
|
1635
|
+
return { response: result.response, durationByDataSource };
|
|
1636
|
+
}, _AssetsController_assertNonEmptyAccountId = function _AssetsController_assertNonEmptyAccountId(accountId, methodName) {
|
|
1637
|
+
if (typeof accountId !== 'string' || accountId.length === 0) {
|
|
1638
|
+
throw new Error(`AssetsController.${methodName}: accountId must be a non-empty string`);
|
|
1639
|
+
}
|
|
1640
|
+
}, _AssetsController_normalizeAssetIdOrThrow = function _AssetsController_normalizeAssetIdOrThrow(assetId, methodName) {
|
|
1641
|
+
try {
|
|
1642
|
+
return (0, index_js_2.normalizeAssetId)(assetId);
|
|
1643
|
+
}
|
|
1644
|
+
catch {
|
|
1645
|
+
throw new Error(`AssetsController.${methodName}: invalid CAIP-19 assetId "${assetId}"`);
|
|
1646
|
+
}
|
|
1647
|
+
}, _AssetsController_fetchMissingPricesWithoutCache = function _AssetsController_fetchMissingPricesWithoutCache(accounts, chainIds) {
|
|
1648
|
+
if (!__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this) || accounts.length === 0) {
|
|
1649
|
+
return;
|
|
1650
|
+
}
|
|
1651
|
+
const accountIds = new Set(accounts.map((account) => account.id));
|
|
1652
|
+
const chainFilter = new Set(chainIds);
|
|
1653
|
+
const assetsForPriceUpdate = [];
|
|
1654
|
+
const prices = this.state.assetsPrice;
|
|
1655
|
+
for (const [accountId, accountBalances] of Object.entries(this.state.assetsBalance)) {
|
|
1656
|
+
if (!accountIds.has(accountId)) {
|
|
1657
|
+
continue;
|
|
1658
|
+
}
|
|
1659
|
+
for (const assetId of Object.keys(accountBalances)) {
|
|
1660
|
+
if (!chainFilter.has(assetId.split('/')[0])) {
|
|
1661
|
+
continue;
|
|
1662
|
+
}
|
|
1663
|
+
const normalizedAssetId = (0, index_js_2.normalizeAssetId)(assetId);
|
|
1664
|
+
if (prices[normalizedAssetId] ?? prices[assetId]) {
|
|
1665
|
+
continue;
|
|
1666
|
+
}
|
|
1667
|
+
if (!(0, PriceDataSource_js_1.isPriceableAsset)(normalizedAssetId)) {
|
|
1668
|
+
continue;
|
|
1669
|
+
}
|
|
1670
|
+
assetsForPriceUpdate.push(normalizedAssetId);
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
if (assetsForPriceUpdate.length === 0) {
|
|
1674
|
+
return;
|
|
1675
|
+
}
|
|
1676
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f").invalidatePriceCache();
|
|
1677
|
+
this.getAssets(accounts, {
|
|
1678
|
+
forceUpdate: true,
|
|
1679
|
+
dataTypes: ['price'],
|
|
1680
|
+
chainIds,
|
|
1681
|
+
assetsForPriceUpdate,
|
|
1682
|
+
}).catch((error) => {
|
|
1683
|
+
log('Failed to fetch missing prices', { error });
|
|
1684
|
+
});
|
|
1685
|
+
}, _AssetsController_getNativeAssetMap = function _AssetsController_getNativeAssetMap() {
|
|
1686
|
+
return (__classPrivateFieldGet(this, _AssetsController_queryApiClient, "f").getCachedData(NATIVE_ASSETS_QUERY_KEY) ?? EMPTY_NATIVE_ASSET_MAP);
|
|
1687
|
+
}, _AssetsController_isNativeAsset = function _AssetsController_isNativeAsset(assetId) {
|
|
1688
|
+
const parsed = (0, utils_1.parseCaipAssetType)(assetId);
|
|
1689
|
+
if (parsed.assetNamespace === 'slip44') {
|
|
1690
|
+
return true;
|
|
1691
|
+
}
|
|
1692
|
+
const lower = assetId.toLowerCase();
|
|
1693
|
+
const isInNativeAssetMap = Object.values(__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetMap).call(this)).some((id) => id.toLowerCase() === lower);
|
|
1694
|
+
if (isInNativeAssetMap) {
|
|
1695
|
+
return true;
|
|
1696
|
+
}
|
|
1697
|
+
if (parsed.assetNamespace === 'erc20' &&
|
|
1698
|
+
parsed.assetReference === constants_js_1.ZERO_ADDRESS) {
|
|
1699
|
+
return true;
|
|
1700
|
+
}
|
|
1701
|
+
return false;
|
|
1702
|
+
}, _AssetsController_getAssetType = function _AssetsController_getAssetType(assetId) {
|
|
1703
|
+
const parsed = (0, utils_1.parseCaipAssetType)(assetId);
|
|
1704
|
+
if (__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_isNativeAsset).call(this, assetId)) {
|
|
1705
|
+
return 'native';
|
|
1706
|
+
}
|
|
1707
|
+
if (parsed.chain.namespace === utils_1.KnownCaipNamespace.Solana &&
|
|
1708
|
+
parsed.assetNamespace === TokenDataSource_js_1.CaipAssetNamespace.Token) {
|
|
1709
|
+
return 'spl';
|
|
1710
|
+
}
|
|
1711
|
+
return 'erc20';
|
|
1712
|
+
}, _AssetsController_resolveNativeAssetIds = function _AssetsController_resolveNativeAssetIds(chains) {
|
|
1713
|
+
const nativeAssetMap = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetMap).call(this);
|
|
1714
|
+
const ids = [];
|
|
1715
|
+
for (const chainId of chains) {
|
|
1716
|
+
const nativeId = nativeAssetMap[chainId];
|
|
1717
|
+
if (nativeId) {
|
|
1718
|
+
ids.push(nativeId);
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
return ids;
|
|
1722
|
+
}, _AssetsController_getNativeAssetIdsForEnabledChains = function _AssetsController_getNativeAssetIdsForEnabledChains() {
|
|
1723
|
+
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_resolveNativeAssetIds).call(this, __classPrivateFieldGet(this, _AssetsController_enabledChains, "f"));
|
|
1724
|
+
}, _AssetsController_getNativeAssetIdsForAccount = function _AssetsController_getNativeAssetIdsForAccount(account) {
|
|
1725
|
+
return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_resolveNativeAssetIds).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account));
|
|
1726
|
+
}, _AssetsController_getSlowPipelineChainIds = function _AssetsController_getSlowPipelineChainIds(chainIds, fastResponse) {
|
|
1727
|
+
const accountsApiChains = new Set(__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f").getActiveChainsSync());
|
|
1728
|
+
return chainIds.filter((chainId) => {
|
|
1729
|
+
if (fastResponse.errors?.[chainId]) {
|
|
1730
|
+
return true;
|
|
1731
|
+
}
|
|
1732
|
+
if (!accountsApiChains.has(chainId)) {
|
|
1733
|
+
return true;
|
|
1734
|
+
}
|
|
1735
|
+
return false;
|
|
1736
|
+
});
|
|
1737
|
+
}, _AssetsController_ensureNativeBalancesDefaultZero = function _AssetsController_ensureNativeBalancesDefaultZero() {
|
|
1738
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
1739
|
+
if (accounts.length === 0) {
|
|
1740
|
+
return;
|
|
1741
|
+
}
|
|
1742
|
+
this.update((state) => {
|
|
1743
|
+
const balances = state.assetsBalance;
|
|
1744
|
+
for (const account of accounts) {
|
|
1745
|
+
const accountId = account.id;
|
|
1746
|
+
const nativeAssetIds = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetIdsForAccount).call(this, account);
|
|
1747
|
+
if (nativeAssetIds.length === 0) {
|
|
1748
|
+
continue;
|
|
1749
|
+
}
|
|
1750
|
+
if (!balances[accountId]) {
|
|
1751
|
+
balances[accountId] = {};
|
|
1752
|
+
}
|
|
1753
|
+
for (const nativeAssetId of nativeAssetIds) {
|
|
1754
|
+
if (!Object.prototype.hasOwnProperty.call(balances[accountId], nativeAssetId)) {
|
|
1755
|
+
balances[accountId][nativeAssetId] = { amount: '0' };
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
});
|
|
1760
|
+
}, _AssetsController_ensureDefaultTrackedAssetsSeeded = function _AssetsController_ensureDefaultTrackedAssetsSeeded(chainsToSeed) {
|
|
1761
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
1762
|
+
if (accounts.length === 0) {
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1765
|
+
// Default tracked assets are ERC-20s on EVM chains today. Restrict
|
|
1766
|
+
// seeding to accounts that have at least one EVM scope so we don't
|
|
1767
|
+
// pollute non-EVM accounts. The wildcard `eip155:0` scope counts.
|
|
1768
|
+
const evmAccounts = accounts.filter((account) => (account.scopes ?? []).some((scope) => scope.startsWith('eip155:')));
|
|
1769
|
+
if (evmAccounts.length === 0) {
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
// Gate seeding on whether the chain is currently enabled. This is
|
|
1773
|
+
// why mUSD appears on mainnet/Linea immediately (those are normally
|
|
1774
|
+
// enabled at startup) but only appears on Monad once the user
|
|
1775
|
+
// turns the Monad network on.
|
|
1776
|
+
const candidateChains = chainsToSeed ?? [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")];
|
|
1777
|
+
const targetChains = candidateChains.filter((chainId) => defaults_js_1.CHAINS_WITH_DEFAULT_TRACKED_ASSETS.has(chainId));
|
|
1778
|
+
if (targetChains.length === 0) {
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
this.update((state) => {
|
|
1782
|
+
var _a;
|
|
1783
|
+
const balances = state.assetsBalance;
|
|
1784
|
+
const metadata = state.assetsInfo;
|
|
1785
|
+
for (const chainId of targetChains) {
|
|
1786
|
+
const defaultAssetIds = defaults_js_1.DEFAULT_TRACKED_ASSETS_BY_CHAIN.get(chainId) ?? [];
|
|
1787
|
+
for (const assetId of defaultAssetIds) {
|
|
1788
|
+
// Re-seed metadata if state was hydrated from a prior version
|
|
1789
|
+
// that didn't include defaults.
|
|
1790
|
+
if (!metadata[assetId]) {
|
|
1791
|
+
const seed = (0, defaults_js_1.getDefaultAssetMetadata)(assetId);
|
|
1792
|
+
if (seed) {
|
|
1793
|
+
metadata[assetId] = seed;
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
for (const account of evmAccounts) {
|
|
1797
|
+
balances[_a = account.id] ?? (balances[_a] = {});
|
|
1798
|
+
const accountBalances = balances[account.id];
|
|
1799
|
+
accountBalances[assetId] ?? (accountBalances[assetId] = { amount: '0' });
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
});
|
|
1804
|
+
}, _AssetsController_updateState = async function _AssetsController_updateState(response) {
|
|
1805
|
+
const normalizedResponse = normalizeResponse(response);
|
|
1806
|
+
const mode = normalizedResponse.updateMode ?? 'merge';
|
|
1807
|
+
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_controllerMutex, "f").acquire();
|
|
1808
|
+
try {
|
|
1809
|
+
const previousState = this.state;
|
|
1810
|
+
const previousPrices = { ...this.state.assetsPrice };
|
|
1811
|
+
// Use detectedAssets from response (assets without metadata)
|
|
1812
|
+
const detectedAssets = normalizedResponse.detectedAssets ?? {};
|
|
1813
|
+
// Track actual changes for logging
|
|
1814
|
+
const changedBalances = [];
|
|
1815
|
+
const changedMetadata = [];
|
|
1816
|
+
this.update((state) => {
|
|
1817
|
+
// Use type assertions to avoid deep type instantiation issues with Immer Draft types
|
|
1818
|
+
const metadata = state.assetsInfo;
|
|
1819
|
+
const balances = state.assetsBalance;
|
|
1820
|
+
const prices = state.assetsPrice;
|
|
1821
|
+
if (normalizedResponse.assetsInfo) {
|
|
1822
|
+
for (const [key, value] of Object.entries(normalizedResponse.assetsInfo)) {
|
|
1823
|
+
if (!(0, lodash_1.isEqual)(previousState.assetsInfo[key], value)) {
|
|
1824
|
+
changedMetadata.push(key);
|
|
1825
|
+
}
|
|
1826
|
+
const existing = metadata[key];
|
|
1827
|
+
const incoming = value;
|
|
1828
|
+
// When the API returns no symbol or name for this token, it has no
|
|
1829
|
+
// real knowledge of it (e.g. a user-deployed token not indexed by
|
|
1830
|
+
// the API). Preserve richer metadata already in state (e.g. from
|
|
1831
|
+
// pendingMetadata set by addCustomAsset) so that the correct
|
|
1832
|
+
// decimals/symbol/name/image are not overwritten with empty values.
|
|
1833
|
+
if (existing && !incoming.symbol && !incoming.name) {
|
|
1834
|
+
metadata[key] = {
|
|
1835
|
+
...existing,
|
|
1836
|
+
...incoming,
|
|
1837
|
+
symbol: existing.symbol,
|
|
1838
|
+
name: existing.name,
|
|
1839
|
+
decimals: existing.decimals ?? incoming.decimals,
|
|
1840
|
+
image: existing.image ?? incoming.image,
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
else {
|
|
1844
|
+
metadata[key] = value;
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
// Reconcile & self-heal stale asset "types" (e.g. erc20 -> native)
|
|
1849
|
+
// using IDs from new response assetInfo and assetBalance
|
|
1850
|
+
const assetsInfoAssetIdsSet = new Set([
|
|
1851
|
+
...Object.keys(normalizedResponse.assetsInfo ?? {}),
|
|
1852
|
+
...Object.values(normalizedResponse.assetsBalance ?? {}).flatMap((accountBalances) => Object.keys(accountBalances)),
|
|
1853
|
+
]);
|
|
1854
|
+
for (const assetId of assetsInfoAssetIdsSet) {
|
|
1855
|
+
const entry = metadata[assetId];
|
|
1856
|
+
if (!entry) {
|
|
1857
|
+
continue;
|
|
1858
|
+
}
|
|
1859
|
+
const correctType = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetType).call(this, assetId);
|
|
1860
|
+
if (entry.type !== correctType) {
|
|
1861
|
+
metadata[assetId] = { ...entry, type: correctType };
|
|
1862
|
+
if (!changedMetadata.includes(assetId)) {
|
|
1863
|
+
changedMetadata.push(assetId);
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
if (normalizedResponse.assetsBalance) {
|
|
1868
|
+
for (const [accountId, accountBalances] of Object.entries(normalizedResponse.assetsBalance)) {
|
|
1869
|
+
const previousBalances = previousState.assetsBalance[accountId] ?? {};
|
|
1870
|
+
const customAssetIds = state.customAssets[accountId] ?? [];
|
|
1871
|
+
const replaceCoveredChains = mode === 'full' ||
|
|
1872
|
+
normalizedResponse.replaceCoveredChainBalances === true;
|
|
1873
|
+
const effective = mergeAccountBalances(previousBalances, accountBalances, customAssetIds, replaceCoveredChains);
|
|
1874
|
+
// Ensure native tokens have an entry (0 if missing) for chains this account supports
|
|
1875
|
+
const account = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((a) => a.id === accountId);
|
|
1876
|
+
const nativeAssetIdsForAccount = account
|
|
1877
|
+
? __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetIdsForAccount).call(this, account)
|
|
1878
|
+
: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetIdsForEnabledChains).call(this);
|
|
1879
|
+
for (const nativeAssetId of nativeAssetIdsForAccount) {
|
|
1880
|
+
if (!Object.prototype.hasOwnProperty.call(effective, nativeAssetId)) {
|
|
1881
|
+
effective[nativeAssetId] = { amount: '0' };
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
for (const [assetId, balance] of Object.entries(effective)) {
|
|
1885
|
+
const previousBalance = previousBalances[assetId];
|
|
1886
|
+
// Coerce amounts (e.g. "1e-18" from a data source stringifying
|
|
1887
|
+
// a JS Number) into a plain decimal so downstream BigInt()
|
|
1888
|
+
// consumers don't crash. Decimals are read from the freshest
|
|
1889
|
+
// merged metadata when available; when metadata is not yet
|
|
1890
|
+
// known, the amount is left at its natural precision (only
|
|
1891
|
+
// exponent form is rewritten) so balances arriving before
|
|
1892
|
+
// their metadata aren't lossily truncated.
|
|
1893
|
+
const assetDecimals = metadata[assetId]?.decimals;
|
|
1894
|
+
const newAmount = (0, index_js_2.normalizeAmountString)(balance.amount, assetDecimals);
|
|
1895
|
+
effective[assetId] = { ...balance, amount: newAmount };
|
|
1896
|
+
const oldAmount = previousBalance?.amount;
|
|
1897
|
+
const isNewDefaultNativeZero = oldAmount === undefined &&
|
|
1898
|
+
newAmount === '0' &&
|
|
1899
|
+
nativeAssetIdsForAccount.includes(assetId);
|
|
1900
|
+
if (oldAmount !== newAmount && !isNewDefaultNativeZero) {
|
|
1901
|
+
changedBalances.push({
|
|
1902
|
+
accountId,
|
|
1903
|
+
assetId,
|
|
1904
|
+
oldAmount,
|
|
1905
|
+
newAmount,
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
balances[accountId] = effective;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
if (normalizedResponse.assetsPrice) {
|
|
1913
|
+
for (const [key, value] of Object.entries(normalizedResponse.assetsPrice)) {
|
|
1914
|
+
prices[key] = value;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
});
|
|
1918
|
+
// Emit state size trace (throttled to avoid JSON.stringify on every update)
|
|
1919
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitStateSizeTrace).call(this);
|
|
1920
|
+
// Calculate changed prices
|
|
1921
|
+
const changedPriceAssets = normalizedResponse.assetsPrice
|
|
1922
|
+
? Object.keys(normalizedResponse.assetsPrice).filter((assetId) => !(0, lodash_1.isEqual)(previousPrices[assetId], normalizedResponse.assetsPrice?.[assetId]))
|
|
1923
|
+
: [];
|
|
1924
|
+
// Log only actual changes
|
|
1925
|
+
if (changedBalances.length > 0 ||
|
|
1926
|
+
changedMetadata.length > 0 ||
|
|
1927
|
+
changedPriceAssets.length > 0) {
|
|
1928
|
+
log('State updated', {
|
|
1929
|
+
changedBalances: changedBalances.length > 0 ? changedBalances : undefined,
|
|
1930
|
+
changedMetadataCount: changedMetadata.length > 0 ? changedMetadata.length : undefined,
|
|
1931
|
+
changedPricesCount: changedPriceAssets.length > 0
|
|
1932
|
+
? changedPriceAssets.length
|
|
1933
|
+
: undefined,
|
|
1934
|
+
newAssets: Object.keys(detectedAssets).length > 0
|
|
1935
|
+
? Object.entries(detectedAssets).map(([accountId, assets]) => ({
|
|
1936
|
+
accountId,
|
|
1937
|
+
assets,
|
|
1938
|
+
}))
|
|
1939
|
+
: undefined,
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1942
|
+
// Publish balance changed events
|
|
1943
|
+
for (const change of changedBalances) {
|
|
1944
|
+
this.messenger.publish('AssetsController:balanceChanged', {
|
|
1945
|
+
accountId: change.accountId,
|
|
1946
|
+
assetId: change.assetId,
|
|
1947
|
+
previousAmount: change.oldAmount ?? '0',
|
|
1948
|
+
newAmount: change.newAmount,
|
|
1949
|
+
});
|
|
1950
|
+
}
|
|
1951
|
+
// Publish price changed event with full price data
|
|
1952
|
+
if (changedPriceAssets.length > 0 && normalizedResponse.assetsPrice) {
|
|
1953
|
+
// Build prices object with only changed prices
|
|
1954
|
+
const changedPrices = {};
|
|
1955
|
+
for (const assetId of changedPriceAssets) {
|
|
1956
|
+
const price = normalizedResponse.assetsPrice[assetId];
|
|
1957
|
+
if (price) {
|
|
1958
|
+
changedPrices[assetId] = price;
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
this.messenger.publish('AssetsController:priceChanged', {
|
|
1962
|
+
prices: changedPrices,
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1965
|
+
// Publish assets detected events
|
|
1966
|
+
for (const [accountId, assetIds] of Object.entries(detectedAssets)) {
|
|
1967
|
+
if (assetIds.length > 0) {
|
|
1968
|
+
this.messenger.publish('AssetsController:assetsDetected', {
|
|
1969
|
+
accountId,
|
|
1970
|
+
assetIds,
|
|
1971
|
+
});
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
finally {
|
|
1976
|
+
releaseLock();
|
|
1977
|
+
}
|
|
1978
|
+
}, _AssetsController_getAssetsFromState = function _AssetsController_getAssetsFromState(accounts, chainIds, assetTypes) {
|
|
1979
|
+
const result = Object.create(null);
|
|
1980
|
+
// Convert to Sets for O(1) lookups
|
|
1981
|
+
const chainIdSet = new Set(chainIds);
|
|
1982
|
+
const assetTypeSet = new Set(assetTypes);
|
|
1983
|
+
for (const account of accounts) {
|
|
1984
|
+
result[account.id] = Object.create(null);
|
|
1985
|
+
const accountBalances = this.state.assetsBalance[account.id] ?? {};
|
|
1986
|
+
for (const assetId of Object.keys(accountBalances)) {
|
|
1987
|
+
const typedAssetId = assetId;
|
|
1988
|
+
const asset = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetFromState).call(this, account.id, typedAssetId, {
|
|
1989
|
+
chainIdSet,
|
|
1990
|
+
assetTypeSet,
|
|
1991
|
+
});
|
|
1992
|
+
if (asset) {
|
|
1993
|
+
result[account.id][typedAssetId] = asset;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
return result;
|
|
1998
|
+
}, _AssetsController_getAssetFromState = function _AssetsController_getAssetFromState(accountId, assetId, filters) {
|
|
1999
|
+
const balance = this.state.assetsBalance[accountId]?.[assetId];
|
|
2000
|
+
// Skip assets without a balance entry
|
|
2001
|
+
if (!balance) {
|
|
2002
|
+
return undefined;
|
|
2003
|
+
}
|
|
2004
|
+
const metadata = this.state.assetsInfo[assetId];
|
|
2005
|
+
// Skip assets without metadata
|
|
2006
|
+
if (!metadata) {
|
|
2007
|
+
return undefined;
|
|
2008
|
+
}
|
|
2009
|
+
// Skip hidden assets (assetPreferences)
|
|
2010
|
+
const prefs = this.state.assetPreferences[assetId];
|
|
2011
|
+
if (prefs?.hidden) {
|
|
2012
|
+
return undefined;
|
|
2013
|
+
}
|
|
2014
|
+
const assetChainId = extractChainId(assetId);
|
|
2015
|
+
// Skip native tokens on Tempo networks
|
|
2016
|
+
if (__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_shouldHideNativeToken).call(this, assetChainId, metadata)) {
|
|
2017
|
+
return undefined;
|
|
2018
|
+
}
|
|
2019
|
+
if (filters?.chainIdSet && !filters.chainIdSet.has(assetChainId)) {
|
|
2020
|
+
return undefined;
|
|
2021
|
+
}
|
|
2022
|
+
// Filter by asset type
|
|
2023
|
+
if (filters?.assetTypeSet) {
|
|
2024
|
+
const tokenAssetType = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_tokenStandardToAssetType).call(this, metadata.type);
|
|
2025
|
+
if (!filters.assetTypeSet.has(tokenAssetType)) {
|
|
2026
|
+
return undefined;
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
const priceRaw = this.state.assetsPrice[assetId];
|
|
2030
|
+
const price = priceRaw ?? {
|
|
2031
|
+
price: 0,
|
|
2032
|
+
lastUpdated: 0,
|
|
2033
|
+
};
|
|
2034
|
+
// Compute fiat value using BigNumber for precision
|
|
2035
|
+
// Note: balance.amount is already in human-readable format (e.g., "1" for 1 ETH)
|
|
2036
|
+
// so we do NOT divide by 10^decimals here
|
|
2037
|
+
const balanceAmount = new bignumber_js_1.default(balance.amount || '0');
|
|
2038
|
+
const fiatValue = balanceAmount.multipliedBy(price.price || 0).toNumber();
|
|
2039
|
+
return {
|
|
2040
|
+
id: assetId,
|
|
2041
|
+
chainId: assetChainId,
|
|
2042
|
+
balance,
|
|
2043
|
+
metadata,
|
|
2044
|
+
price,
|
|
2045
|
+
fiatValue,
|
|
2046
|
+
};
|
|
2047
|
+
}, _AssetsController_shouldHideNativeToken = function _AssetsController_shouldHideNativeToken(chainId, metadata) {
|
|
2048
|
+
// Check if it's a chain that should skip native tokens
|
|
2049
|
+
if (!(0, assets_js_1.shouldSkipNativeForCaipChainId)(chainId)) {
|
|
2050
|
+
return false;
|
|
2051
|
+
}
|
|
2052
|
+
return metadata.type === 'native';
|
|
2053
|
+
}, _AssetsController_tokenStandardToAssetType = function _AssetsController_tokenStandardToAssetType(tokenStandard) {
|
|
2054
|
+
switch (tokenStandard) {
|
|
2055
|
+
case 'native':
|
|
2056
|
+
case 'erc20':
|
|
2057
|
+
case 'spl':
|
|
2058
|
+
return 'fungible';
|
|
2059
|
+
case 'erc721':
|
|
2060
|
+
return 'nft';
|
|
2061
|
+
case 'erc1155':
|
|
2062
|
+
// ERC1155 can be either fungible or non-fungible, treat as collectible
|
|
2063
|
+
return 'collectible';
|
|
2064
|
+
default:
|
|
2065
|
+
// Unknown standards default to fungible
|
|
2066
|
+
return 'fungible';
|
|
2067
|
+
}
|
|
2068
|
+
}, _AssetsController_start = function _AssetsController_start() {
|
|
2069
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2070
|
+
const chainIds = [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")];
|
|
2071
|
+
if (accounts.length === 0 || chainIds.length === 0) {
|
|
2072
|
+
return;
|
|
2073
|
+
}
|
|
2074
|
+
if (__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").size > 0) {
|
|
2075
|
+
return;
|
|
2076
|
+
}
|
|
2077
|
+
log('Starting asset tracking', {
|
|
2078
|
+
selectedAccountCount: accounts.length,
|
|
2079
|
+
enabledChainCount: chainIds.length,
|
|
2080
|
+
});
|
|
2081
|
+
__classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, new Set(accounts.map((a) => a.id)), "f");
|
|
2082
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_runStartupRefresh).call(this, accounts).catch((error) => {
|
|
2083
|
+
log('Failed to start asset tracking', error);
|
|
2084
|
+
});
|
|
2085
|
+
}, _AssetsController_stop = function _AssetsController_stop() {
|
|
2086
|
+
log('Stopping asset tracking', {
|
|
2087
|
+
activeSubscriptionCount: __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").size,
|
|
2088
|
+
hasPriceSubscription: __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").has('ds:PriceDataSource'),
|
|
2089
|
+
});
|
|
2090
|
+
__classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, false, "f");
|
|
2091
|
+
__classPrivateFieldSet(this, _AssetsController_stateSizeReported, false, "f");
|
|
2092
|
+
__classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, new Set(), "f");
|
|
2093
|
+
// Stop price subscription first (uses direct messenger call)
|
|
2094
|
+
this.unsubscribeAssetsPrice();
|
|
2095
|
+
// Stop balance subscriptions by properly notifying data sources via messenger
|
|
2096
|
+
// This ensures data sources stop their polling timers.
|
|
2097
|
+
// Use #allBalanceDataSources + staked balance source so we unsubscribe from
|
|
2098
|
+
// every source that may have been subscribed.
|
|
2099
|
+
const allSources = [
|
|
2100
|
+
...__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_allBalanceDataSources_get),
|
|
2101
|
+
__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"),
|
|
2102
|
+
];
|
|
2103
|
+
const subscriptionKeys = [...__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").keys()];
|
|
2104
|
+
for (const subscriptionKey of subscriptionKeys) {
|
|
2105
|
+
if (!subscriptionKey.startsWith('ds:')) {
|
|
2106
|
+
continue;
|
|
2107
|
+
}
|
|
2108
|
+
// Subscription keys take the form `ds:<SourceName>` for the regular
|
|
2109
|
+
// subscription or `ds:<SourceName>:<suffix>` for supplemental
|
|
2110
|
+
// subscriptions (e.g. `ds:RpcDataSource:custom`). Split on `:` and
|
|
2111
|
+
// pick the source-name segment so both shapes resolve correctly.
|
|
2112
|
+
const [, sourceId] = subscriptionKey.split(':');
|
|
2113
|
+
const source = allSources.find((ds) => ds.getName() === sourceId);
|
|
2114
|
+
if (source) {
|
|
2115
|
+
// Unsubscribe by the actual key — `#unsubscribeDataSource` only
|
|
2116
|
+
// knows the regular `ds:<SourceName>` shape and would miss
|
|
2117
|
+
// supplemental subscriptions, leaking their polling timers.
|
|
2118
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeBySubscriptionKey).call(this, source, subscriptionKey);
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").clear();
|
|
2122
|
+
}, _AssetsController_subscribeAssets = function _AssetsController_subscribeAssets(options) {
|
|
2123
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2124
|
+
const enabledChains = [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")];
|
|
2125
|
+
if (accounts.length === 0 || enabledChains.length === 0) {
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
2128
|
+
// Subscribe to balance updates (batched by data source)
|
|
2129
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalance).call(this, accounts, enabledChains, options);
|
|
2130
|
+
// Subscribe to staked balance updates (separate from regular balance chain-claiming)
|
|
2131
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeStakedBalance).call(this, accounts, enabledChains);
|
|
2132
|
+
// Subscribe to price updates for all assets held by selected accounts
|
|
2133
|
+
this.subscribeAssetsPrice(accounts, enabledChains);
|
|
2134
|
+
}, _AssetsController_subscribeAssetsBalance = function _AssetsController_subscribeAssetsBalance(accounts, chainIds, options) {
|
|
2135
|
+
const chainToAccounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildChainToAccountsMap).call(this, accounts, new Set(chainIds));
|
|
2136
|
+
const remainingChains = new Set(chainToAccounts.keys());
|
|
2137
|
+
// When basic functionality is on, use all balance data sources; when off,
|
|
2138
|
+
// RPC only.
|
|
2139
|
+
const isBasicFunctionality = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this);
|
|
2140
|
+
const balanceDataSources = isBasicFunctionality
|
|
2141
|
+
? __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_allBalanceDataSources_get)
|
|
2142
|
+
: [__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")];
|
|
2143
|
+
let rpcAssignedChains = new Set();
|
|
2144
|
+
for (const source of balanceDataSources) {
|
|
2145
|
+
const availableChains = new Set(source.getActiveChainsSync());
|
|
2146
|
+
const assignedChains = [];
|
|
2147
|
+
for (const chainId of remainingChains) {
|
|
2148
|
+
if (availableChains.has(chainId)) {
|
|
2149
|
+
assignedChains.push(chainId);
|
|
2150
|
+
remainingChains.delete(chainId);
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
if (assignedChains.length === 0) {
|
|
2154
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
|
|
2155
|
+
continue;
|
|
2156
|
+
}
|
|
2157
|
+
if (source === __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")) {
|
|
2158
|
+
rpcAssignedChains = new Set(assignedChains);
|
|
2159
|
+
}
|
|
2160
|
+
const seenIds = new Set();
|
|
2161
|
+
const accountsForSource = assignedChains
|
|
2162
|
+
.flatMap((chainId) => chainToAccounts.get(chainId) ?? [])
|
|
2163
|
+
.filter((account) => {
|
|
2164
|
+
if (seenIds.has(account.id)) {
|
|
2165
|
+
return false;
|
|
2166
|
+
}
|
|
2167
|
+
seenIds.add(account.id);
|
|
2168
|
+
return true;
|
|
2169
|
+
});
|
|
2170
|
+
if (accountsForSource.length > 0) {
|
|
2171
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeDataSource).call(this, source, accountsForSource, assignedChains, {
|
|
2172
|
+
...(options?.skipInitialFetch &&
|
|
2173
|
+
source === __classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f")
|
|
2174
|
+
? { skipInitialFetch: true }
|
|
2175
|
+
: {}),
|
|
2176
|
+
});
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
// Supplemental RPC subscription for customAssets on chains another data
|
|
2180
|
+
// source claimed during regular handoff. RPC is the sole balance fetcher
|
|
2181
|
+
// for customAssets, so we must always poll them — even when (e.g.)
|
|
2182
|
+
// AccountsApi is already covering the chain for normal balances. The
|
|
2183
|
+
// supplemental subscription runs in `customAssetsOnly` mode so it does
|
|
2184
|
+
// NOT double-poll the regular tracked balances.
|
|
2185
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeRpcCustomAssetsSupplement).call(this, accounts, chainToAccounts, rpcAssignedChains);
|
|
2186
|
+
}, _AssetsController_subscribeRpcCustomAssetsSupplement = function _AssetsController_subscribeRpcCustomAssetsSupplement(accounts, chainToAccounts, rpcAssignedChains) {
|
|
2187
|
+
const rpc = __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f");
|
|
2188
|
+
const supplementalKey = `ds:${rpc.getName()}:custom`;
|
|
2189
|
+
const decision = (0, customAssetsRpcSupplement_js_1.pickRpcCustomAssetsSupplement)({
|
|
2190
|
+
accountIds: accounts.map((account) => account.id),
|
|
2191
|
+
customAssetsByAccount: this.state.customAssets,
|
|
2192
|
+
rpcAssignedChains,
|
|
2193
|
+
rpcAvailableChains: new Set(rpc.getActiveChainsSync()),
|
|
2194
|
+
enabledChains: new Set(chainToAccounts.keys()),
|
|
2195
|
+
});
|
|
2196
|
+
if (decision.chains.length === 0) {
|
|
2197
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeBySubscriptionKey).call(this, rpc, supplementalKey);
|
|
2198
|
+
return;
|
|
2199
|
+
}
|
|
2200
|
+
const supplementalAccounts = accounts.filter((account) => decision.accountIds.has(account.id));
|
|
2201
|
+
if (supplementalAccounts.length === 0) {
|
|
2202
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeBySubscriptionKey).call(this, rpc, supplementalKey);
|
|
2203
|
+
return;
|
|
2204
|
+
}
|
|
2205
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeDataSource).call(this, rpc, supplementalAccounts, decision.chains, {
|
|
2206
|
+
subscriptionKey: supplementalKey,
|
|
2207
|
+
customAssetsOnly: true,
|
|
2208
|
+
});
|
|
2209
|
+
}, _AssetsController_unsubscribeBySubscriptionKey = function _AssetsController_unsubscribeBySubscriptionKey(source, subscriptionKey) {
|
|
2210
|
+
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
2211
|
+
if (existingSubscription) {
|
|
2212
|
+
source.unsubscribe(subscriptionKey).catch(() => undefined);
|
|
2213
|
+
existingSubscription.unsubscribe();
|
|
2214
|
+
}
|
|
2215
|
+
}, _AssetsController_subscribeStakedBalance = function _AssetsController_subscribeStakedBalance(accounts, chainIds) {
|
|
2216
|
+
const source = __classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f");
|
|
2217
|
+
if (!source) {
|
|
2218
|
+
return;
|
|
2219
|
+
}
|
|
2220
|
+
const availableChains = new Set(source.getActiveChainsSync());
|
|
2221
|
+
const assignedChains = chainIds.filter((chainId) => availableChains.has(chainId));
|
|
2222
|
+
if (assignedChains.length === 0) {
|
|
2223
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
|
|
2224
|
+
return;
|
|
2225
|
+
}
|
|
2226
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeDataSource).call(this, source, accounts, assignedChains);
|
|
2227
|
+
}, _AssetsController_buildChainToAccountsMap = function _AssetsController_buildChainToAccountsMap(accounts, chainsToSubscribe) {
|
|
2228
|
+
const chainToAccounts = new Map();
|
|
2229
|
+
for (const account of accounts) {
|
|
2230
|
+
for (const chainId of __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account)) {
|
|
2231
|
+
if (!chainsToSubscribe.has(chainId)) {
|
|
2232
|
+
continue;
|
|
2233
|
+
}
|
|
2234
|
+
let list = chainToAccounts.get(chainId);
|
|
2235
|
+
if (!list) {
|
|
2236
|
+
list = [];
|
|
2237
|
+
chainToAccounts.set(chainId, list);
|
|
2238
|
+
}
|
|
2239
|
+
list.push(account);
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
return chainToAccounts;
|
|
2243
|
+
}, _AssetsController_subscribeDataSource = function _AssetsController_subscribeDataSource(source, accounts, chains, options = {}) {
|
|
2244
|
+
const sourceId = source.getName();
|
|
2245
|
+
const subscriptionKey = options.subscriptionKey ?? `ds:${sourceId}`;
|
|
2246
|
+
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
2247
|
+
const isUpdate = existingSubscription !== undefined;
|
|
2248
|
+
log('Subscribe to data source', {
|
|
2249
|
+
sourceId,
|
|
2250
|
+
subscriptionKey,
|
|
2251
|
+
isUpdate,
|
|
2252
|
+
accountCount: accounts.length,
|
|
2253
|
+
chainCount: chains.length,
|
|
2254
|
+
customAssetsOnly: options.customAssetsOnly === true,
|
|
2255
|
+
skipInitialFetch: options.skipInitialFetch === true,
|
|
2256
|
+
});
|
|
2257
|
+
const subscribeReq = {
|
|
2258
|
+
request: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chains, {
|
|
2259
|
+
assetTypes: ['fungible'],
|
|
2260
|
+
dataTypes: ['balance'],
|
|
2261
|
+
updateInterval: __classPrivateFieldGet(this, _AssetsController_defaultUpdateInterval, "f"),
|
|
2262
|
+
...(options.customAssetsOnly === true
|
|
2263
|
+
? { customAssetsOnly: true }
|
|
2264
|
+
: {}),
|
|
2265
|
+
}),
|
|
2266
|
+
subscriptionId: subscriptionKey,
|
|
2267
|
+
isUpdate,
|
|
2268
|
+
onAssetsUpdate: (response, request) => this.handleAssetsUpdate(response, sourceId, request),
|
|
2269
|
+
getAssetsState: () => this.state,
|
|
2270
|
+
...(options.skipInitialFetch === true ? { skipInitialFetch: true } : {}),
|
|
2271
|
+
};
|
|
2272
|
+
source.subscribe(subscribeReq).catch((error) => {
|
|
2273
|
+
console.error(`[AssetsController] Failed to subscribe to '${sourceId}':`, error);
|
|
2274
|
+
(0, trace_js_1.emitTrace)({
|
|
2275
|
+
name: TRACE_SUBSCRIPTION_ERROR,
|
|
2276
|
+
trace: __classPrivateFieldGet(this, _AssetsController_trace, "f"),
|
|
2277
|
+
data: {
|
|
2278
|
+
source: sourceId,
|
|
2279
|
+
error_message: String(error),
|
|
2280
|
+
},
|
|
2281
|
+
});
|
|
2282
|
+
});
|
|
2283
|
+
// Track subscription
|
|
2284
|
+
const subscription = {
|
|
2285
|
+
chains,
|
|
2286
|
+
accountId: subscriptionKey,
|
|
2287
|
+
assetTypes: ['fungible'],
|
|
2288
|
+
dataTypes: ['balance'],
|
|
2289
|
+
unsubscribe: () => {
|
|
2290
|
+
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").delete(subscriptionKey);
|
|
2291
|
+
},
|
|
2292
|
+
};
|
|
2293
|
+
__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").set(subscriptionKey, subscription);
|
|
2294
|
+
}, _AssetsController_unsubscribeDataSource = function _AssetsController_unsubscribeDataSource(source) {
|
|
2295
|
+
const subscriptionKey = `ds:${source.getName()}`;
|
|
2296
|
+
const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
|
|
2297
|
+
if (existingSubscription) {
|
|
2298
|
+
source.unsubscribe(subscriptionKey).catch(() => undefined);
|
|
2299
|
+
existingSubscription.unsubscribe();
|
|
2300
|
+
}
|
|
2301
|
+
}, _AssetsController_buildDataRequest = function _AssetsController_buildDataRequest(accounts, chainIds, partial = {}) {
|
|
2302
|
+
const chainIdSet = new Set(chainIds);
|
|
2303
|
+
// Force update will pass in additional chains for wildcard account scope
|
|
2304
|
+
// Enables updates for chains that are not selected (e.g. for unapproved transactions)
|
|
2305
|
+
const forceUpdateChains = partial.forceUpdate ? chainIds : undefined;
|
|
2306
|
+
const accountsWithSupportedChains = accounts.map((account) => ({
|
|
2307
|
+
account,
|
|
2308
|
+
supportedChains: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account, forceUpdateChains).filter((chain) => chainIdSet.has(chain)),
|
|
2309
|
+
}));
|
|
2310
|
+
return {
|
|
2311
|
+
accountsWithSupportedChains,
|
|
2312
|
+
chainIds,
|
|
2313
|
+
...partial,
|
|
2314
|
+
};
|
|
2315
|
+
}, _AssetsController_getEnabledChainsForAccount = function _AssetsController_getEnabledChainsForAccount(account, additionalChains) {
|
|
2316
|
+
// Account scopes are CAIP-2 chain IDs like "eip155:1", "solana:mainnet", "bip122:..."
|
|
2317
|
+
const scopes = account.scopes ?? [];
|
|
2318
|
+
const result = [];
|
|
2319
|
+
for (const scope of scopes) {
|
|
2320
|
+
const scopeStr = scope;
|
|
2321
|
+
if (!(0, utils_1.isCaipChainId)(scopeStr)) {
|
|
2322
|
+
result.push(scope);
|
|
2323
|
+
continue;
|
|
2324
|
+
}
|
|
2325
|
+
const { namespace, reference } = (0, utils_1.parseCaipChainId)(scopeStr);
|
|
2326
|
+
// Wildcard scope (e.g., "eip155:0" means all enabled chains in that namespace)
|
|
2327
|
+
if (reference === '0') {
|
|
2328
|
+
// Add enabled chains
|
|
2329
|
+
for (const chain of __classPrivateFieldGet(this, _AssetsController_enabledChains, "f")) {
|
|
2330
|
+
if ((0, utils_1.isCaipChainId)(chain)) {
|
|
2331
|
+
const chainParsed = (0, utils_1.parseCaipChainId)(chain);
|
|
2332
|
+
if (chainParsed.namespace === namespace) {
|
|
2333
|
+
result.push(chain);
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
// Add additional chains
|
|
2338
|
+
for (const chain of additionalChains ?? []) {
|
|
2339
|
+
if ((0, utils_1.isCaipChainId)(chain)) {
|
|
2340
|
+
const chainParsed = (0, utils_1.parseCaipChainId)(chain);
|
|
2341
|
+
if (chainParsed.namespace === namespace) {
|
|
2342
|
+
result.push(chain);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
else if (namespace === 'eip155' && (0, utils_1.isStrictHexString)(reference)) {
|
|
2348
|
+
// Normalize hex to decimal for EIP155
|
|
2349
|
+
result.push(`eip155:${parseInt(reference, 16)}`);
|
|
2350
|
+
}
|
|
2351
|
+
else {
|
|
2352
|
+
result.push(scope);
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
return result;
|
|
2356
|
+
}, _AssetsController_handleAccountGroupChanged =
|
|
2357
|
+
// ============================================================================
|
|
2358
|
+
// EVENT HANDLERS
|
|
2359
|
+
// ============================================================================
|
|
2360
|
+
async function _AssetsController_handleAccountGroupChanged(groupId, previousGroupId = '') {
|
|
2361
|
+
// The selected account group can be empty during onboarding or wallet reset.
|
|
2362
|
+
if (!groupId) {
|
|
2363
|
+
return;
|
|
2364
|
+
}
|
|
2365
|
+
// First start is owned by `AccountTreeController:initialized` / `#start`.
|
|
2366
|
+
// ATC also re-publishes `selectedAccountGroupChange` on every `init()`
|
|
2367
|
+
// (including when the group did not change) so late subscribers can catch
|
|
2368
|
+
// up — ignore those until we are already tracking.
|
|
2369
|
+
if (__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").size === 0) {
|
|
2370
|
+
return;
|
|
2371
|
+
}
|
|
2372
|
+
if (groupId === previousGroupId) {
|
|
2373
|
+
return;
|
|
2374
|
+
}
|
|
2375
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2376
|
+
log('Account group changed', {
|
|
2377
|
+
accountCount: accounts.length,
|
|
2378
|
+
accountIds: accounts.map((a) => a.id),
|
|
2379
|
+
groupId,
|
|
2380
|
+
previousGroupId,
|
|
2381
|
+
});
|
|
2382
|
+
__classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, new Set(accounts.map((a) => a.id)), "f");
|
|
2383
|
+
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_accountRefreshMutex, "f").acquire();
|
|
2384
|
+
try {
|
|
2385
|
+
if (accounts.length > 0) {
|
|
2386
|
+
await this.getAssets(accounts, {
|
|
2387
|
+
chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
|
|
2388
|
+
forceUpdate: true,
|
|
2389
|
+
});
|
|
2390
|
+
}
|
|
2391
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
2392
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this);
|
|
2393
|
+
// Subscribe after seed so the price poll sees natives / defaults.
|
|
2394
|
+
// Balances were just force-fetched — skip AccountsApi's subscribe-time poll.
|
|
2395
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this, { skipInitialFetch: true });
|
|
2396
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")]);
|
|
2397
|
+
}
|
|
2398
|
+
finally {
|
|
2399
|
+
releaseLock();
|
|
2400
|
+
}
|
|
2401
|
+
}, _AssetsController_handleEnabledNetworksChanged = async function _AssetsController_handleEnabledNetworksChanged(enabledNetworkMap) {
|
|
2402
|
+
const previousChains = __classPrivateFieldGet(this, _AssetsController_enabledChains, "f");
|
|
2403
|
+
__classPrivateFieldSet(this, _AssetsController_enabledChains, __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_extractEnabledChains).call(this, enabledNetworkMap), "f");
|
|
2404
|
+
// Find newly enabled chains (in new set but not in previous)
|
|
2405
|
+
const addedChains = [];
|
|
2406
|
+
for (const chain of __classPrivateFieldGet(this, _AssetsController_enabledChains, "f")) {
|
|
2407
|
+
if (!previousChains.has(chain)) {
|
|
2408
|
+
addedChains.push(chain);
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
// Find disabled chains to clean up (in previous but not in new)
|
|
2412
|
+
const removedChains = [];
|
|
2413
|
+
for (const chain of previousChains) {
|
|
2414
|
+
if (!__classPrivateFieldGet(this, _AssetsController_enabledChains, "f").has(chain)) {
|
|
2415
|
+
removedChains.push(chain);
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
log('Enabled networks changed', {
|
|
2419
|
+
previousCount: previousChains.size,
|
|
2420
|
+
newCount: __classPrivateFieldGet(this, _AssetsController_enabledChains, "f").size,
|
|
2421
|
+
addedChains,
|
|
2422
|
+
removedChains,
|
|
2423
|
+
});
|
|
2424
|
+
// Note: We intentionally do NOT delete balance data for disabled chains.
|
|
2425
|
+
// Users may want to see historical balances even if the network is currently disabled.
|
|
2426
|
+
// The data will simply not be updated until the network is re-enabled.
|
|
2427
|
+
// Refresh subscriptions for new chain set
|
|
2428
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
2429
|
+
// Do one-time fetch for newly enabled chains; merge so we keep existing chain balances
|
|
2430
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2431
|
+
if (addedChains.length > 0 && accounts.length > 0) {
|
|
2432
|
+
await this.getAssets(accounts, {
|
|
2433
|
+
chainIds: addedChains,
|
|
2434
|
+
forceUpdate: true,
|
|
2435
|
+
updateMode: 'merge',
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
2438
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
2439
|
+
// Seed default tracked assets (mUSD) for any chain the user has
|
|
2440
|
+
// *just* enabled. This is what makes mUSD appear on Monad after
|
|
2441
|
+
// the user finally adds it to NetworkEnablementController.
|
|
2442
|
+
if (addedChains.length > 0) {
|
|
2443
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this, addedChains);
|
|
2444
|
+
}
|
|
2445
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")]);
|
|
2446
|
+
}, _AssetsController_handleNetworkAdded = function _AssetsController_handleNetworkAdded(hexChainId) {
|
|
2447
|
+
let caipChainId;
|
|
2448
|
+
try {
|
|
2449
|
+
caipChainId = `eip155:${parseInt(hexChainId, 16)}`;
|
|
2450
|
+
}
|
|
2451
|
+
catch {
|
|
2452
|
+
return;
|
|
2453
|
+
}
|
|
2454
|
+
if (!defaults_js_1.CHAINS_WITH_DEFAULT_TRACKED_ASSETS.has(caipChainId)) {
|
|
2455
|
+
return;
|
|
2456
|
+
}
|
|
2457
|
+
log('Network added — seeding default tracked assets', {
|
|
2458
|
+
hexChainId,
|
|
2459
|
+
caipChainId,
|
|
2460
|
+
});
|
|
2461
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureDefaultTrackedAssetsSeeded).call(this, [caipChainId]);
|
|
2462
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2463
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [caipChainId]);
|
|
2464
|
+
}, _AssetsController_refreshActiveChainsOnNetworkSwitch =
|
|
2465
|
+
/**
|
|
2466
|
+
* Refresh data-source `activeChains` after an EVM network switch so API/Rpc
|
|
2467
|
+
* chain claiming is not stuck on an empty or stale init-time list.
|
|
2468
|
+
*/
|
|
2469
|
+
async function _AssetsController_refreshActiveChainsOnNetworkSwitch() {
|
|
2470
|
+
await __classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f").refreshActiveChains();
|
|
2471
|
+
__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f").refreshActiveChainsFromNetworkState();
|
|
2472
|
+
}, _AssetsController_getSelectedEvmChainIdFromNetworkState = function _AssetsController_getSelectedEvmChainIdFromNetworkState(networkState) {
|
|
2473
|
+
try {
|
|
2474
|
+
const networkClient = this.messenger.call('NetworkController:getNetworkClientById', networkState.selectedNetworkClientId);
|
|
2475
|
+
const hexChainId = networkClient.configuration?.chainId;
|
|
2476
|
+
if (!hexChainId) {
|
|
2477
|
+
return undefined;
|
|
2478
|
+
}
|
|
2479
|
+
return `eip155:${parseInt(hexChainId, 16)}`;
|
|
2480
|
+
}
|
|
2481
|
+
catch {
|
|
2482
|
+
return undefined;
|
|
2483
|
+
}
|
|
2484
|
+
}, _AssetsController_handleNetworkDidChange =
|
|
2485
|
+
/**
|
|
2486
|
+
* Refresh subscriptions and fetch balances when the user switches the
|
|
2487
|
+
* selected EVM network in the UI (`NetworkController:networkDidChange`).
|
|
2488
|
+
*
|
|
2489
|
+
* @param networkState - NetworkController state after the switch.
|
|
2490
|
+
*/
|
|
2491
|
+
async function _AssetsController_handleNetworkDidChange(networkState) {
|
|
2492
|
+
if (!__classPrivateFieldGet(this, _AssetsController_uiOpen, "f") || !__classPrivateFieldGet(this, _AssetsController_keyringUnlocked, "f") || !__classPrivateFieldGet(this, _AssetsController_isEnabled, "f").call(this)) {
|
|
2493
|
+
return;
|
|
2494
|
+
}
|
|
2495
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2496
|
+
if (accounts.length === 0) {
|
|
2497
|
+
return;
|
|
2498
|
+
}
|
|
2499
|
+
const selectedChainId = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedEvmChainIdFromNetworkState).call(this, networkState);
|
|
2500
|
+
if (!selectedChainId) {
|
|
2501
|
+
return;
|
|
2502
|
+
}
|
|
2503
|
+
log('Selected EVM network switched', {
|
|
2504
|
+
selectedNetworkClientId: networkState.selectedNetworkClientId,
|
|
2505
|
+
selectedChainId,
|
|
2506
|
+
});
|
|
2507
|
+
const releaseLock = await __classPrivateFieldGet(this, _AssetsController_accountRefreshMutex, "f").acquire();
|
|
2508
|
+
try {
|
|
2509
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_refreshActiveChainsOnNetworkSwitch).call(this);
|
|
2510
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
|
|
2511
|
+
await this.getAssets(accounts, {
|
|
2512
|
+
chainIds: [selectedChainId],
|
|
2513
|
+
forceUpdate: true,
|
|
2514
|
+
dataTypes: ['balance', 'metadata', 'price'],
|
|
2515
|
+
});
|
|
2516
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
2517
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [selectedChainId]);
|
|
2518
|
+
}
|
|
2519
|
+
finally {
|
|
2520
|
+
releaseLock();
|
|
2521
|
+
}
|
|
2522
|
+
}, _AssetsController_refreshAssetsAfterNetworkChange = function _AssetsController_refreshAssetsAfterNetworkChange() {
|
|
2523
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2524
|
+
if (accounts.length === 0) {
|
|
2525
|
+
return;
|
|
2526
|
+
}
|
|
2527
|
+
this.getAssets(accounts, {
|
|
2528
|
+
forceUpdate: true,
|
|
2529
|
+
dataTypes: ['balance', 'metadata'],
|
|
2530
|
+
}).catch((error) => {
|
|
2531
|
+
log('Failed to refresh assets after network change', { error });
|
|
2532
|
+
});
|
|
2533
|
+
}, _AssetsController_refreshAssetsAfterNetworkAdded =
|
|
2534
|
+
/**
|
|
2535
|
+
* Refresh balances and fetch missing prices after a network is added.
|
|
2536
|
+
*
|
|
2537
|
+
* @param hexChainId - Hex chain id of the newly-added network.
|
|
2538
|
+
*/
|
|
2539
|
+
async function _AssetsController_refreshAssetsAfterNetworkAdded(hexChainId) {
|
|
2540
|
+
const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
|
|
2541
|
+
if (accounts.length === 0) {
|
|
2542
|
+
return;
|
|
2543
|
+
}
|
|
2544
|
+
let caipChainId;
|
|
2545
|
+
try {
|
|
2546
|
+
caipChainId = `eip155:${parseInt(hexChainId, 16)}`;
|
|
2547
|
+
}
|
|
2548
|
+
catch {
|
|
2549
|
+
return;
|
|
2550
|
+
}
|
|
2551
|
+
await this.getAssets(accounts, {
|
|
2552
|
+
chainIds: [caipChainId],
|
|
2553
|
+
forceUpdate: true,
|
|
2554
|
+
dataTypes: ['balance', 'metadata', 'price'],
|
|
2555
|
+
});
|
|
2556
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
|
|
2557
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [caipChainId]);
|
|
2558
|
+
};
|
|
2559
|
+
//# sourceMappingURL=AssetsController.cjs.map
|