@metamask/assets-controller 1.0.0 → 2.0.1

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.
Files changed (166) hide show
  1. package/CHANGELOG.md +36 -1
  2. package/dist/AssetsController.cjs +175 -64
  3. package/dist/AssetsController.cjs.map +1 -1
  4. package/dist/AssetsController.d.cts +68 -9
  5. package/dist/AssetsController.d.cts.map +1 -1
  6. package/dist/AssetsController.d.mts +68 -9
  7. package/dist/AssetsController.d.mts.map +1 -1
  8. package/dist/AssetsController.mjs +176 -65
  9. package/dist/AssetsController.mjs.map +1 -1
  10. package/dist/data-sources/AccountsApiDataSource.cjs +70 -15
  11. package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
  12. package/dist/data-sources/AccountsApiDataSource.d.cts +22 -3
  13. package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -1
  14. package/dist/data-sources/AccountsApiDataSource.d.mts +22 -3
  15. package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -1
  16. package/dist/data-sources/AccountsApiDataSource.mjs +66 -12
  17. package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
  18. package/dist/data-sources/BackendWebsocketDataSource.cjs +7 -5
  19. package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -1
  20. package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -1
  21. package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -1
  22. package/dist/data-sources/BackendWebsocketDataSource.mjs +7 -5
  23. package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
  24. package/dist/data-sources/PriceDataSource.cjs +17 -4
  25. package/dist/data-sources/PriceDataSource.cjs.map +1 -1
  26. package/dist/data-sources/PriceDataSource.d.cts +8 -4
  27. package/dist/data-sources/PriceDataSource.d.cts.map +1 -1
  28. package/dist/data-sources/PriceDataSource.d.mts +8 -4
  29. package/dist/data-sources/PriceDataSource.d.mts.map +1 -1
  30. package/dist/data-sources/PriceDataSource.mjs +17 -4
  31. package/dist/data-sources/PriceDataSource.mjs.map +1 -1
  32. package/dist/data-sources/RpcDataSource.cjs +123 -44
  33. package/dist/data-sources/RpcDataSource.cjs.map +1 -1
  34. package/dist/data-sources/RpcDataSource.d.cts +16 -62
  35. package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
  36. package/dist/data-sources/RpcDataSource.d.mts +16 -62
  37. package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
  38. package/dist/data-sources/RpcDataSource.mjs +124 -45
  39. package/dist/data-sources/RpcDataSource.mjs.map +1 -1
  40. package/dist/data-sources/SnapDataSource.cjs +22 -10
  41. package/dist/data-sources/SnapDataSource.cjs.map +1 -1
  42. package/dist/data-sources/SnapDataSource.d.cts +2 -1
  43. package/dist/data-sources/SnapDataSource.d.cts.map +1 -1
  44. package/dist/data-sources/SnapDataSource.d.mts +2 -1
  45. package/dist/data-sources/SnapDataSource.d.mts.map +1 -1
  46. package/dist/data-sources/SnapDataSource.mjs +22 -10
  47. package/dist/data-sources/SnapDataSource.mjs.map +1 -1
  48. package/dist/data-sources/StakedBalanceDataSource.cjs +597 -0
  49. package/dist/data-sources/StakedBalanceDataSource.cjs.map +1 -0
  50. package/dist/data-sources/StakedBalanceDataSource.d.cts +72 -0
  51. package/dist/data-sources/StakedBalanceDataSource.d.cts.map +1 -0
  52. package/dist/data-sources/StakedBalanceDataSource.d.mts +72 -0
  53. package/dist/data-sources/StakedBalanceDataSource.d.mts.map +1 -0
  54. package/dist/data-sources/StakedBalanceDataSource.mjs +593 -0
  55. package/dist/data-sources/StakedBalanceDataSource.mjs.map +1 -0
  56. package/dist/data-sources/TokenDataSource.cjs +12 -5
  57. package/dist/data-sources/TokenDataSource.cjs.map +1 -1
  58. package/dist/data-sources/TokenDataSource.d.cts +1 -0
  59. package/dist/data-sources/TokenDataSource.d.cts.map +1 -1
  60. package/dist/data-sources/TokenDataSource.d.mts +1 -0
  61. package/dist/data-sources/TokenDataSource.d.mts.map +1 -1
  62. package/dist/data-sources/TokenDataSource.mjs +12 -5
  63. package/dist/data-sources/TokenDataSource.mjs.map +1 -1
  64. package/dist/data-sources/evm-rpc-services/index.cjs +5 -1
  65. package/dist/data-sources/evm-rpc-services/index.cjs.map +1 -1
  66. package/dist/data-sources/evm-rpc-services/index.d.cts +1 -1
  67. package/dist/data-sources/evm-rpc-services/index.d.cts.map +1 -1
  68. package/dist/data-sources/evm-rpc-services/index.d.mts +1 -1
  69. package/dist/data-sources/evm-rpc-services/index.d.mts.map +1 -1
  70. package/dist/data-sources/evm-rpc-services/index.mjs +1 -1
  71. package/dist/data-sources/evm-rpc-services/index.mjs.map +1 -1
  72. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.cjs +132 -0
  73. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.cjs.map +1 -0
  74. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.cts +80 -0
  75. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.cts.map +1 -0
  76. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.mts +80 -0
  77. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.mts.map +1 -0
  78. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.mjs +126 -0
  79. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.mjs.map +1 -0
  80. package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs +16 -0
  81. package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs.map +1 -1
  82. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts +5 -1
  83. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts.map +1 -1
  84. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts +5 -1
  85. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts.map +1 -1
  86. package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs +16 -0
  87. package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs.map +1 -1
  88. package/dist/data-sources/evm-rpc-services/services/index.cjs +6 -1
  89. package/dist/data-sources/evm-rpc-services/services/index.cjs.map +1 -1
  90. package/dist/data-sources/evm-rpc-services/services/index.d.cts +1 -0
  91. package/dist/data-sources/evm-rpc-services/services/index.d.cts.map +1 -1
  92. package/dist/data-sources/evm-rpc-services/services/index.d.mts +1 -0
  93. package/dist/data-sources/evm-rpc-services/services/index.d.mts.map +1 -1
  94. package/dist/data-sources/evm-rpc-services/services/index.mjs +1 -0
  95. package/dist/data-sources/evm-rpc-services/services/index.mjs.map +1 -1
  96. package/dist/data-sources/evm-rpc-services/types/services.cjs.map +1 -1
  97. package/dist/data-sources/evm-rpc-services/types/services.d.cts +4 -0
  98. package/dist/data-sources/evm-rpc-services/types/services.d.cts.map +1 -1
  99. package/dist/data-sources/evm-rpc-services/types/services.d.mts +4 -0
  100. package/dist/data-sources/evm-rpc-services/types/services.d.mts.map +1 -1
  101. package/dist/data-sources/evm-rpc-services/types/services.mjs.map +1 -1
  102. package/dist/data-sources/evm-rpc-services/types/state.cjs.map +1 -1
  103. package/dist/data-sources/evm-rpc-services/types/state.d.cts +3 -3
  104. package/dist/data-sources/evm-rpc-services/types/state.d.cts.map +1 -1
  105. package/dist/data-sources/evm-rpc-services/types/state.d.mts +3 -3
  106. package/dist/data-sources/evm-rpc-services/types/state.d.mts.map +1 -1
  107. package/dist/data-sources/evm-rpc-services/types/state.mjs.map +1 -1
  108. package/dist/data-sources/evm-rpc-services/utils/index.cjs +9 -1
  109. package/dist/data-sources/evm-rpc-services/utils/index.cjs.map +1 -1
  110. package/dist/data-sources/evm-rpc-services/utils/index.d.cts +2 -0
  111. package/dist/data-sources/evm-rpc-services/utils/index.d.cts.map +1 -1
  112. package/dist/data-sources/evm-rpc-services/utils/index.d.mts +2 -0
  113. package/dist/data-sources/evm-rpc-services/utils/index.d.mts.map +1 -1
  114. package/dist/data-sources/evm-rpc-services/utils/index.mjs +2 -0
  115. package/dist/data-sources/evm-rpc-services/utils/index.mjs.map +1 -1
  116. package/dist/data-sources/evm-rpc-services/utils/parsing.cjs +47 -0
  117. package/dist/data-sources/evm-rpc-services/utils/parsing.cjs.map +1 -0
  118. package/dist/data-sources/evm-rpc-services/utils/parsing.d.cts +25 -0
  119. package/dist/data-sources/evm-rpc-services/utils/parsing.d.cts.map +1 -0
  120. package/dist/data-sources/evm-rpc-services/utils/parsing.d.mts +25 -0
  121. package/dist/data-sources/evm-rpc-services/utils/parsing.d.mts.map +1 -0
  122. package/dist/data-sources/evm-rpc-services/utils/parsing.mjs +39 -0
  123. package/dist/data-sources/evm-rpc-services/utils/parsing.mjs.map +1 -0
  124. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.cjs +68 -0
  125. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.cjs.map +1 -0
  126. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.cts +25 -0
  127. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.cts.map +1 -0
  128. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.mts +25 -0
  129. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.mts.map +1 -0
  130. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.mjs +62 -0
  131. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.mjs.map +1 -0
  132. package/dist/data-sources/index.cjs +3 -1
  133. package/dist/data-sources/index.cjs.map +1 -1
  134. package/dist/data-sources/index.d.cts +3 -2
  135. package/dist/data-sources/index.d.cts.map +1 -1
  136. package/dist/data-sources/index.d.mts +3 -2
  137. package/dist/data-sources/index.d.mts.map +1 -1
  138. package/dist/data-sources/index.mjs +1 -0
  139. package/dist/data-sources/index.mjs.map +1 -1
  140. package/dist/index.cjs.map +1 -1
  141. package/dist/index.d.cts +3 -3
  142. package/dist/index.d.cts.map +1 -1
  143. package/dist/index.d.mts +3 -3
  144. package/dist/index.d.mts.map +1 -1
  145. package/dist/index.mjs.map +1 -1
  146. package/dist/middlewares/DetectionMiddleware.cjs +4 -1
  147. package/dist/middlewares/DetectionMiddleware.cjs.map +1 -1
  148. package/dist/middlewares/DetectionMiddleware.d.cts +1 -0
  149. package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -1
  150. package/dist/middlewares/DetectionMiddleware.d.mts +1 -0
  151. package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -1
  152. package/dist/middlewares/DetectionMiddleware.mjs +4 -1
  153. package/dist/middlewares/DetectionMiddleware.mjs.map +1 -1
  154. package/dist/selectors/balance.cjs +2 -2
  155. package/dist/selectors/balance.cjs.map +1 -1
  156. package/dist/selectors/balance.d.cts.map +1 -1
  157. package/dist/selectors/balance.d.mts.map +1 -1
  158. package/dist/selectors/balance.mjs +2 -2
  159. package/dist/selectors/balance.mjs.map +1 -1
  160. package/dist/types.cjs.map +1 -1
  161. package/dist/types.d.cts +3 -3
  162. package/dist/types.d.cts.map +1 -1
  163. package/dist/types.d.mts +3 -3
  164. package/dist/types.d.mts.map +1 -1
  165. package/dist/types.mjs.map +1 -1
  166. package/package.json +17 -12
@@ -9,10 +9,10 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  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");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _RpcDataSource_instances, _RpcDataSource_messenger, _RpcDataSource_onActiveChainsUpdated, _RpcDataSource_timeout, _RpcDataSource_tokenDetectionEnabled, _RpcDataSource_activeChains, _RpcDataSource_chainStatuses, _RpcDataSource_providerCache, _RpcDataSource_activeSubscriptions, _RpcDataSource_multicallClient, _RpcDataSource_balanceFetcher, _RpcDataSource_tokenDetector, _RpcDataSource_convertToHumanReadable, _RpcDataSource_collectMetadataForBalances, _RpcDataSource_handleBalanceUpdate, _RpcDataSource_handleDetectionUpdate, _RpcDataSource_subscribeToNetworkController, _RpcDataSource_initializeFromNetworkController, _RpcDataSource_updateFromNetworkState, _RpcDataSource_getProvider, _RpcDataSource_getMulticallProvider, _RpcDataSource_clearProviderCache, _RpcDataSource_buildNativeAssetId, _RpcDataSource_getExistingAssetsMetadata, _RpcDataSource_getTokenMetadataFromTokenList;
12
+ var _RpcDataSource_instances, _RpcDataSource_messenger, _RpcDataSource_onActiveChainsUpdated, _RpcDataSource_timeout, _RpcDataSource_tokenDetectionEnabled, _RpcDataSource_useExternalService, _RpcDataSource_activeChains, _RpcDataSource_chainStatuses, _RpcDataSource_providerCache, _RpcDataSource_activeSubscriptions, _RpcDataSource_unsubscribeTransactionConfirmed, _RpcDataSource_unsubscribeIncomingTransactions, _RpcDataSource_multicallClient, _RpcDataSource_balanceFetcher, _RpcDataSource_tokenDetector, _RpcDataSource_convertToHumanReadable, _RpcDataSource_collectMetadataForBalances, _RpcDataSource_handleBalanceUpdate, _RpcDataSource_handleDetectionUpdate, _RpcDataSource_subscribeToNetworkController, _RpcDataSource_subscribeToTransactionEvents, _RpcDataSource_onTransactionConfirmed, _RpcDataSource_onIncomingTransactions, _RpcDataSource_refreshBalanceForChains, _RpcDataSource_initializeFromNetworkController, _RpcDataSource_updateFromNetworkState, _RpcDataSource_getProvider, _RpcDataSource_getMulticallProvider, _RpcDataSource_clearProviderCache, _RpcDataSource_buildNativeAssetId, _RpcDataSource_getExistingAssetsMetadata, _RpcDataSource_getTokenMetadataFromTokenList;
13
13
  import { Web3Provider } from "@ethersproject/providers";
14
14
  import { toHex } from "@metamask/controller-utils";
15
- import { isStrictHexString, isCaipChainId, parseCaipChainId } from "@metamask/utils";
15
+ import { isStrictHexString, isCaipChainId, numberToHex, parseCaipAssetType, parseCaipChainId } from "@metamask/utils";
16
16
  import BigNumberJS from "bignumber.js";
17
17
  import { AbstractDataSource } from "./AbstractDataSource.mjs";
18
18
  import { BalanceFetcher, MulticallClient, TokenDetector } from "./evm-rpc-services/index.mjs";
@@ -62,6 +62,7 @@ export class RpcDataSource extends AbstractDataSource {
62
62
  _RpcDataSource_onActiveChainsUpdated.set(this, void 0);
63
63
  _RpcDataSource_timeout.set(this, void 0);
64
64
  _RpcDataSource_tokenDetectionEnabled.set(this, void 0);
65
+ _RpcDataSource_useExternalService.set(this, void 0);
65
66
  /** Currently active chains */
66
67
  _RpcDataSource_activeChains.set(this, []);
67
68
  /** Network status for each active chain */
@@ -70,6 +71,8 @@ export class RpcDataSource extends AbstractDataSource {
70
71
  _RpcDataSource_providerCache.set(this, new Map());
71
72
  /** Active subscriptions by ID */
72
73
  _RpcDataSource_activeSubscriptions.set(this, new Map());
74
+ _RpcDataSource_unsubscribeTransactionConfirmed.set(this, undefined);
75
+ _RpcDataSource_unsubscribeIncomingTransactions.set(this, undefined);
73
76
  // Rpc-datasource components
74
77
  _RpcDataSource_multicallClient.set(this, void 0);
75
78
  _RpcDataSource_balanceFetcher.set(this, void 0);
@@ -77,14 +80,16 @@ export class RpcDataSource extends AbstractDataSource {
77
80
  __classPrivateFieldSet(this, _RpcDataSource_messenger, options.messenger, "f");
78
81
  __classPrivateFieldSet(this, _RpcDataSource_onActiveChainsUpdated, options.onActiveChainsUpdated, "f");
79
82
  __classPrivateFieldSet(this, _RpcDataSource_timeout, options.timeout ?? 10000, "f");
80
- __classPrivateFieldSet(this, _RpcDataSource_tokenDetectionEnabled, options.tokenDetectionEnabled ?? false, "f");
83
+ __classPrivateFieldSet(this, _RpcDataSource_tokenDetectionEnabled, options.tokenDetectionEnabled ?? (() => true), "f");
84
+ __classPrivateFieldSet(this, _RpcDataSource_useExternalService, options.useExternalService ?? (() => true), "f");
81
85
  const balanceInterval = options.balanceInterval ?? DEFAULT_BALANCE_INTERVAL;
82
86
  const detectionInterval = options.detectionInterval ?? DEFAULT_DETECTION_INTERVAL;
83
87
  log('Initializing RpcDataSource', {
84
88
  timeout: __classPrivateFieldGet(this, _RpcDataSource_timeout, "f"),
85
89
  balanceInterval,
86
90
  detectionInterval,
87
- tokenDetectionEnabled: __classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f"),
91
+ tokenDetectionEnabled: __classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f").call(this),
92
+ useExternalService: __classPrivateFieldGet(this, _RpcDataSource_useExternalService, "f").call(this),
88
93
  });
89
94
  // Initialize MulticallClient with a provider getter
90
95
  __classPrivateFieldSet(this, _RpcDataSource_multicallClient, new MulticallClient((hexChainId) => {
@@ -108,9 +113,14 @@ export class RpcDataSource extends AbstractDataSource {
108
113
  __classPrivateFieldSet(this, _RpcDataSource_balanceFetcher, new BalanceFetcher(__classPrivateFieldGet(this, _RpcDataSource_multicallClient, "f"), balanceFetcherMessenger, { pollingInterval: balanceInterval }), "f");
109
114
  __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").setOnBalanceUpdate(__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_handleBalanceUpdate).bind(this));
110
115
  // Initialize TokenDetector with polling interval
111
- __classPrivateFieldSet(this, _RpcDataSource_tokenDetector, new TokenDetector(__classPrivateFieldGet(this, _RpcDataSource_multicallClient, "f"), tokenDetectorMessenger, { pollingInterval: detectionInterval }), "f");
116
+ __classPrivateFieldSet(this, _RpcDataSource_tokenDetector, new TokenDetector(__classPrivateFieldGet(this, _RpcDataSource_multicallClient, "f"), tokenDetectorMessenger, {
117
+ pollingInterval: detectionInterval,
118
+ tokenDetectionEnabled: __classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f"),
119
+ useExternalService: __classPrivateFieldGet(this, _RpcDataSource_useExternalService, "f"),
120
+ }), "f");
112
121
  __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").setOnDetectionUpdate(__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_handleDetectionUpdate).bind(this));
113
122
  __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_subscribeToNetworkController).call(this);
123
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_subscribeToTransactionEvents).call(this);
114
124
  __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_initializeFromNetworkController).call(this);
115
125
  }
116
126
  /**
@@ -182,7 +192,7 @@ export class RpcDataSource extends AbstractDataSource {
182
192
  return response;
183
193
  }
184
194
  const assetsBalance = {};
185
- const assetsMetadata = {};
195
+ const assetsInfo = {};
186
196
  const failedChains = [];
187
197
  // Fetch balances for each account and its supported chains (pre-computed in request)
188
198
  for (const { account, supportedChains, } of request.accountsWithSupportedChains) {
@@ -202,10 +212,10 @@ export class RpcDataSource extends AbstractDataSource {
202
212
  }
203
213
  // Collect metadata for all balances
204
214
  const balanceMetadata = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_collectMetadataForBalances).call(this, result.balances, chainId);
205
- Object.assign(assetsMetadata, balanceMetadata);
215
+ Object.assign(assetsInfo, balanceMetadata);
206
216
  // Convert balances to human-readable format
207
217
  for (const balance of result.balances) {
208
- const metadata = assetsMetadata[balance.assetId];
218
+ const metadata = assetsInfo[balance.assetId];
209
219
  // Default to 18 decimals (ERC20 standard) for consistent human-readable format
210
220
  const decimals = metadata?.decimals ?? 18;
211
221
  const humanReadableAmount = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_convertToHumanReadable).call(this, balance.balance, decimals);
@@ -224,7 +234,7 @@ export class RpcDataSource extends AbstractDataSource {
224
234
  // Even on error, include native token metadata
225
235
  const chainStatus = __classPrivateFieldGet(this, _RpcDataSource_chainStatuses, "f")[chainId];
226
236
  if (chainStatus) {
227
- assetsMetadata[nativeAssetId] = {
237
+ assetsInfo[nativeAssetId] = {
228
238
  type: 'native',
229
239
  symbol: chainStatus.nativeCurrency,
230
240
  name: chainStatus.nativeCurrency,
@@ -255,8 +265,8 @@ export class RpcDataSource extends AbstractDataSource {
255
265
  }
256
266
  response.assetsBalance = assetsBalance;
257
267
  // Include metadata for native tokens if we have any
258
- if (Object.keys(assetsMetadata).length > 0) {
259
- response.assetsMetadata = assetsMetadata;
268
+ if (Object.keys(assetsInfo).length > 0) {
269
+ response.assetsInfo = assetsInfo;
260
270
  }
261
271
  return response;
262
272
  }
@@ -268,14 +278,17 @@ export class RpcDataSource extends AbstractDataSource {
268
278
  * @returns Promise resolving to a DataResponse with detected assets.
269
279
  */
270
280
  async detectTokens(chainId, account) {
271
- if (!__classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f")) {
281
+ if (!__classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f").call(this) || !__classPrivateFieldGet(this, _RpcDataSource_useExternalService, "f").call(this)) {
272
282
  return {};
273
283
  }
274
284
  const hexChainId = caipChainIdToHex(chainId);
275
285
  const { address, id: accountId } = account;
276
286
  log('Running token detection', { chainId, accountId });
277
287
  try {
278
- const result = await __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").detectTokens(hexChainId, accountId, address);
288
+ const result = await __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").detectTokens(hexChainId, accountId, address, {
289
+ tokenDetectionEnabled: __classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f").call(this),
290
+ useExternalService: __classPrivateFieldGet(this, _RpcDataSource_useExternalService, "f").call(this),
291
+ });
279
292
  if (result.detectedAssets.length === 0) {
280
293
  log('No new tokens detected');
281
294
  return {};
@@ -287,11 +300,11 @@ export class RpcDataSource extends AbstractDataSource {
287
300
  });
288
301
  // Convert detected assets to DataResponse format
289
302
  const balances = {};
290
- const assetsMetadata = {};
303
+ const assetsInfo = {};
291
304
  // Build metadata from detected assets
292
305
  for (const asset of result.detectedAssets) {
293
306
  if (asset.symbol && asset.decimals !== undefined) {
294
- assetsMetadata[asset.assetId] = {
307
+ assetsInfo[asset.assetId] = {
295
308
  type: 'erc20',
296
309
  symbol: asset.symbol,
297
310
  name: asset.name ?? asset.symbol,
@@ -319,8 +332,8 @@ export class RpcDataSource extends AbstractDataSource {
319
332
  },
320
333
  };
321
334
  // Include metadata if we have any
322
- if (Object.keys(assetsMetadata).length > 0) {
323
- response.assetsMetadata = assetsMetadata;
335
+ if (Object.keys(assetsInfo).length > 0) {
336
+ response.assetsInfo = assetsInfo;
324
337
  }
325
338
  return response;
326
339
  }
@@ -356,11 +369,11 @@ export class RpcDataSource extends AbstractDataSource {
356
369
  };
357
370
  }
358
371
  }
359
- if (response.assetsMetadata) {
360
- (_c = context.response).assetsMetadata ?? (_c.assetsMetadata = {});
361
- context.response.assetsMetadata = {
362
- ...context.response.assetsMetadata,
363
- ...response.assetsMetadata,
372
+ if (response.assetsInfo) {
373
+ (_c = context.response).assetsInfo ?? (_c.assetsInfo = {});
374
+ context.response.assetsInfo = {
375
+ ...context.response.assetsInfo,
376
+ ...response.assetsInfo,
364
377
  };
365
378
  }
366
379
  const failedChains = new Set(Object.keys(response.errors ?? {}));
@@ -430,8 +443,8 @@ export class RpcDataSource extends AbstractDataSource {
430
443
  };
431
444
  const balanceToken = __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").startPolling(balanceInput);
432
445
  balancePollingTokens.push(balanceToken);
433
- // Start detection polling if enabled
434
- if (__classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f")) {
446
+ // Start detection polling if enabled and external services allowed
447
+ if (__classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f").call(this) && __classPrivateFieldGet(this, _RpcDataSource_useExternalService, "f").call(this)) {
435
448
  const detectionInput = {
436
449
  chainId: hexChainId,
437
450
  accountId,
@@ -483,6 +496,8 @@ export class RpcDataSource extends AbstractDataSource {
483
496
  */
484
497
  destroy() {
485
498
  log('Destroying RpcDataSource');
499
+ __classPrivateFieldGet(this, _RpcDataSource_unsubscribeTransactionConfirmed, "f")?.call(this);
500
+ __classPrivateFieldGet(this, _RpcDataSource_unsubscribeIncomingTransactions, "f")?.call(this);
486
501
  // Stop all polling
487
502
  __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").stopAllPolling();
488
503
  __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").stopAllPolling();
@@ -492,19 +507,19 @@ export class RpcDataSource extends AbstractDataSource {
492
507
  __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").clear();
493
508
  }
494
509
  }
495
- _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_onActiveChainsUpdated = new WeakMap(), _RpcDataSource_timeout = new WeakMap(), _RpcDataSource_tokenDetectionEnabled = new WeakMap(), _RpcDataSource_activeChains = new WeakMap(), _RpcDataSource_chainStatuses = new WeakMap(), _RpcDataSource_providerCache = new WeakMap(), _RpcDataSource_activeSubscriptions = new WeakMap(), _RpcDataSource_multicallClient = new WeakMap(), _RpcDataSource_balanceFetcher = new WeakMap(), _RpcDataSource_tokenDetector = new WeakMap(), _RpcDataSource_instances = new WeakSet(), _RpcDataSource_convertToHumanReadable = function _RpcDataSource_convertToHumanReadable(rawBalance, decimals) {
510
+ _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_onActiveChainsUpdated = new WeakMap(), _RpcDataSource_timeout = new WeakMap(), _RpcDataSource_tokenDetectionEnabled = new WeakMap(), _RpcDataSource_useExternalService = new WeakMap(), _RpcDataSource_activeChains = new WeakMap(), _RpcDataSource_chainStatuses = new WeakMap(), _RpcDataSource_providerCache = new WeakMap(), _RpcDataSource_activeSubscriptions = new WeakMap(), _RpcDataSource_unsubscribeTransactionConfirmed = new WeakMap(), _RpcDataSource_unsubscribeIncomingTransactions = new WeakMap(), _RpcDataSource_multicallClient = new WeakMap(), _RpcDataSource_balanceFetcher = new WeakMap(), _RpcDataSource_tokenDetector = new WeakMap(), _RpcDataSource_instances = new WeakSet(), _RpcDataSource_convertToHumanReadable = function _RpcDataSource_convertToHumanReadable(rawBalance, decimals) {
496
511
  const rawAmount = new BigNumberJS(rawBalance);
497
512
  const divisor = new BigNumberJS(10).pow(decimals);
498
513
  return rawAmount.dividedBy(divisor).toString();
499
514
  }, _RpcDataSource_collectMetadataForBalances = function _RpcDataSource_collectMetadataForBalances(balances, chainId) {
500
- const assetsMetadata = {};
515
+ const assetsInfo = {};
501
516
  const existingMetadata = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_getExistingAssetsMetadata).call(this);
502
517
  for (const balance of balances) {
503
518
  const isNative = balance.assetId.includes('/slip44:');
504
519
  if (isNative) {
505
520
  const chainStatus = __classPrivateFieldGet(this, _RpcDataSource_chainStatuses, "f")[chainId];
506
521
  if (chainStatus) {
507
- assetsMetadata[balance.assetId] = {
522
+ assetsInfo[balance.assetId] = {
508
523
  type: 'native',
509
524
  symbol: chainStatus.nativeCurrency,
510
525
  name: chainStatus.nativeCurrency,
@@ -516,19 +531,19 @@ _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_onActiveChainsUpdated =
516
531
  // For ERC20 tokens, try existing metadata from state first
517
532
  const existingMeta = existingMetadata[balance.assetId];
518
533
  if (existingMeta) {
519
- assetsMetadata[balance.assetId] = existingMeta;
534
+ assetsInfo[balance.assetId] = existingMeta;
520
535
  }
521
536
  else {
522
537
  // Fallback to token list if not in state
523
538
  const tokenListMeta = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_getTokenMetadataFromTokenList).call(this, balance.assetId);
524
539
  if (tokenListMeta) {
525
- assetsMetadata[balance.assetId] = tokenListMeta;
540
+ assetsInfo[balance.assetId] = tokenListMeta;
526
541
  }
527
542
  else {
528
543
  // Default metadata for unknown ERC20 tokens.
529
544
  // Use 18 decimals (the standard for most ERC20 tokens)
530
545
  // to ensure consistent human-readable balance format.
531
- assetsMetadata[balance.assetId] = {
546
+ assetsInfo[balance.assetId] = {
532
547
  type: 'erc20',
533
548
  symbol: '',
534
549
  name: '',
@@ -538,17 +553,17 @@ _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_onActiveChainsUpdated =
538
553
  }
539
554
  }
540
555
  }
541
- return assetsMetadata;
556
+ return assetsInfo;
542
557
  }, _RpcDataSource_handleBalanceUpdate = function _RpcDataSource_handleBalanceUpdate(result) {
543
558
  const newBalances = {};
544
559
  // Convert hex chain ID to CAIP-2 format
545
560
  const chainIdDecimal = parseInt(result.chainId, 16);
546
561
  const caipChainId = `eip155:${chainIdDecimal}`;
547
562
  // Collect metadata for all balances
548
- const assetsMetadata = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_collectMetadataForBalances).call(this, result.balances, caipChainId);
563
+ const assetsInfo = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_collectMetadataForBalances).call(this, result.balances, caipChainId);
549
564
  // Convert balances to human-readable format using metadata
550
565
  for (const balance of result.balances) {
551
- const metadata = assetsMetadata[balance.assetId];
566
+ const metadata = assetsInfo[balance.assetId];
552
567
  // Default to 18 decimals (ERC20 standard) for consistent human-readable format
553
568
  const decimals = metadata?.decimals ?? 18;
554
569
  const humanReadableAmount = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_convertToHumanReadable).call(this, balance.balance, decimals);
@@ -562,7 +577,7 @@ _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_onActiveChainsUpdated =
562
577
  assetsBalance: {
563
578
  [result.accountId]: newBalances,
564
579
  },
565
- assetsMetadata,
580
+ assetsInfo,
566
581
  };
567
582
  log('Balance update response', {
568
583
  accountId: result.accountId,
@@ -613,7 +628,7 @@ _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_onActiveChainsUpdated =
613
628
  detectedAssets: {
614
629
  [result.accountId]: result.detectedAssets.map((asset) => asset.assetId),
615
630
  },
616
- assetsMetadata: newMetadata,
631
+ assetsInfo: newMetadata,
617
632
  assetsBalance: {
618
633
  [result.accountId]: newBalances,
619
634
  },
@@ -629,6 +644,73 @@ _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_onActiveChainsUpdated =
629
644
  __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_clearProviderCache).call(this);
630
645
  __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_updateFromNetworkState).call(this, networkState);
631
646
  });
647
+ }, _RpcDataSource_subscribeToTransactionEvents = function _RpcDataSource_subscribeToTransactionEvents() {
648
+ const unsubConfirmed = __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").subscribe('TransactionController:transactionConfirmed', __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_onTransactionConfirmed).bind(this));
649
+ __classPrivateFieldSet(this, _RpcDataSource_unsubscribeTransactionConfirmed, typeof unsubConfirmed === 'function' ? unsubConfirmed : undefined, "f");
650
+ const unsubIncoming = __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").subscribe('TransactionController:incomingTransactionsReceived', __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_onIncomingTransactions).bind(this));
651
+ __classPrivateFieldSet(this, _RpcDataSource_unsubscribeIncomingTransactions, typeof unsubIncoming === 'function' ? unsubIncoming : undefined, "f");
652
+ }, _RpcDataSource_onTransactionConfirmed = function _RpcDataSource_onTransactionConfirmed(payload) {
653
+ const hexChainId = payload?.chainId;
654
+ if (!hexChainId) {
655
+ return;
656
+ }
657
+ const caipChainId = `eip155:${parseInt(hexChainId, 16)}`;
658
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_refreshBalanceForChains).call(this, [caipChainId]).catch((error) => {
659
+ log('Failed to refresh balance after transaction confirmed', { error });
660
+ });
661
+ }, _RpcDataSource_onIncomingTransactions = function _RpcDataSource_onIncomingTransactions(payload) {
662
+ const chainIds = Array.from(new Set((payload ?? [])
663
+ .map((item) => item?.chainId)
664
+ .filter((id) => Boolean(id))));
665
+ const caipChainIds = chainIds.map((hexChainId) => `eip155:${parseInt(hexChainId, 16)}`);
666
+ const toRefresh = caipChainIds.length > 0 ? caipChainIds : [...__classPrivateFieldGet(this, _RpcDataSource_activeChains, "f")];
667
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_refreshBalanceForChains).call(this, toRefresh).catch((error) => {
668
+ log('Failed to refresh balance after incoming transactions', { error });
669
+ });
670
+ }, _RpcDataSource_refreshBalanceForChains =
671
+ /**
672
+ * Fetch balances for the given chains across all active subscriptions and
673
+ * push updates to the controller.
674
+ *
675
+ * @param chainIds - CAIP-2 chain IDs to refresh.
676
+ */
677
+ async function _RpcDataSource_refreshBalanceForChains(chainIds) {
678
+ const chainIdsSet = new Set(chainIds);
679
+ const chainsToFetch = chainIds.filter((chainId) => __classPrivateFieldGet(this, _RpcDataSource_activeChains, "f").includes(chainId));
680
+ if (chainsToFetch.length === 0) {
681
+ return;
682
+ }
683
+ for (const subscription of __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").values()) {
684
+ const subscriptionChains = subscription.chains.filter((chainId) => chainIdsSet.has(chainId));
685
+ if (subscriptionChains.length === 0) {
686
+ continue;
687
+ }
688
+ const request = {
689
+ accountsWithSupportedChains: subscription.accounts.map((account) => ({
690
+ account,
691
+ supportedChains: subscriptionChains,
692
+ })),
693
+ chainIds: subscriptionChains,
694
+ dataTypes: ['balance'],
695
+ };
696
+ try {
697
+ const response = await this.fetch(request);
698
+ if (response.assetsBalance &&
699
+ Object.keys(response.assetsBalance).length > 0) {
700
+ subscription.onAssetsUpdate(response)?.catch((error) => {
701
+ log('Failed to report balance update after transaction', {
702
+ error,
703
+ });
704
+ });
705
+ }
706
+ }
707
+ catch (error) {
708
+ log('Failed to fetch balance after transaction', {
709
+ chains: subscriptionChains,
710
+ error,
711
+ });
712
+ }
713
+ }
632
714
  }, _RpcDataSource_initializeFromNetworkController = function _RpcDataSource_initializeFromNetworkController() {
633
715
  log('Initializing from NetworkController');
634
716
  try {
@@ -726,12 +808,11 @@ _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_onActiveChainsUpdated =
726
808
  __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").clear();
727
809
  }, _RpcDataSource_buildNativeAssetId = function _RpcDataSource_buildNativeAssetId(chainId) {
728
810
  const { nativeAssetIdentifiers } = __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").call('NetworkEnablementController:getState');
729
- return (nativeAssetIdentifiers[chainId] ??
730
- `${chainId}/slip44:60`);
811
+ return nativeAssetIdentifiers[chainId] ?? `${chainId}/slip44:60`;
731
812
  }, _RpcDataSource_getExistingAssetsMetadata = function _RpcDataSource_getExistingAssetsMetadata() {
732
813
  try {
733
814
  const state = __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").call('AssetsController:getState');
734
- return (state.assetsMetadata ?? {});
815
+ return state.assetsInfo ?? {};
735
816
  }
736
817
  catch {
737
818
  // If AssetsController:getState fails, return empty metadata
@@ -739,15 +820,13 @@ _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_onActiveChainsUpdated =
739
820
  }
740
821
  }, _RpcDataSource_getTokenMetadataFromTokenList = function _RpcDataSource_getTokenMetadataFromTokenList(assetId) {
741
822
  try {
742
- // Parse asset ID to get chain and token address
743
- // Format: eip155:{chainId}/erc20:{address}
744
- const [chainPart, assetPart] = assetId.split('/');
745
- if (!assetPart?.startsWith('erc20:')) {
823
+ const parsed = parseCaipAssetType(assetId);
824
+ if (parsed.assetNamespace !== 'erc20') {
746
825
  return undefined;
747
826
  }
748
- const tokenAddress = assetPart.slice(6); // Remove 'erc20:' prefix
749
- const chainIdDecimal = chainPart.split(':')[1];
750
- const hexChainId = `0x${parseInt(chainIdDecimal, 10).toString(16)}`;
827
+ const tokenAddress = parsed.assetReference;
828
+ const { reference } = parseCaipChainId(parsed.chainId);
829
+ const hexChainId = numberToHex(parseInt(reference, 10));
751
830
  const tokenListState = __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").call('TokenListController:getState');
752
831
  const chainCacheEntry = tokenListState?.tokensChainsCache?.[hexChainId];
753
832
  const chainTokenList = chainCacheEntry?.data;