@metamask-previews/assets-controller 0.0.0-preview-903db2da → 0.0.0-preview-3ec2a74

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 (250) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/AssetsController.cjs +1028 -61
  3. package/dist/AssetsController.cjs.map +1 -1
  4. package/dist/AssetsController.d.cts +229 -83
  5. package/dist/AssetsController.d.cts.map +1 -1
  6. package/dist/AssetsController.d.mts +229 -83
  7. package/dist/AssetsController.d.mts.map +1 -1
  8. package/dist/AssetsController.mjs +1024 -59
  9. package/dist/AssetsController.mjs.map +1 -1
  10. package/dist/data-sources/AbstractDataSource.cjs +103 -0
  11. package/dist/data-sources/AbstractDataSource.cjs.map +1 -0
  12. package/dist/data-sources/AbstractDataSource.d.cts +92 -0
  13. package/dist/data-sources/AbstractDataSource.d.cts.map +1 -0
  14. package/dist/data-sources/AbstractDataSource.d.mts +92 -0
  15. package/dist/data-sources/AbstractDataSource.d.mts.map +1 -0
  16. package/dist/data-sources/AbstractDataSource.mjs +99 -0
  17. package/dist/data-sources/AbstractDataSource.mjs.map +1 -0
  18. package/dist/data-sources/AccountsApiDataSource.cjs +421 -0
  19. package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -0
  20. package/dist/data-sources/AccountsApiDataSource.d.cts +103 -0
  21. package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -0
  22. package/dist/data-sources/AccountsApiDataSource.d.mts +103 -0
  23. package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -0
  24. package/dist/data-sources/AccountsApiDataSource.mjs +416 -0
  25. package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -0
  26. package/dist/data-sources/BackendWebsocketDataSource.cjs +388 -0
  27. package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -0
  28. package/dist/data-sources/BackendWebsocketDataSource.d.cts +95 -0
  29. package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -0
  30. package/dist/data-sources/BackendWebsocketDataSource.d.mts +95 -0
  31. package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -0
  32. package/dist/data-sources/BackendWebsocketDataSource.mjs +383 -0
  33. package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -0
  34. package/dist/data-sources/PriceDataSource.cjs +350 -0
  35. package/dist/data-sources/PriceDataSource.cjs.map +1 -0
  36. package/dist/data-sources/PriceDataSource.d.cts +153 -0
  37. package/dist/data-sources/PriceDataSource.d.cts.map +1 -0
  38. package/dist/data-sources/PriceDataSource.d.mts +153 -0
  39. package/dist/data-sources/PriceDataSource.d.mts.map +1 -0
  40. package/dist/data-sources/PriceDataSource.mjs +346 -0
  41. package/dist/data-sources/PriceDataSource.mjs.map +1 -0
  42. package/dist/data-sources/RpcDataSource.cjs +410 -0
  43. package/dist/data-sources/RpcDataSource.cjs.map +1 -0
  44. package/dist/data-sources/RpcDataSource.d.cts +154 -0
  45. package/dist/data-sources/RpcDataSource.d.cts.map +1 -0
  46. package/dist/data-sources/RpcDataSource.d.mts +154 -0
  47. package/dist/data-sources/RpcDataSource.d.mts.map +1 -0
  48. package/dist/data-sources/RpcDataSource.mjs +405 -0
  49. package/dist/data-sources/RpcDataSource.mjs.map +1 -0
  50. package/dist/data-sources/SnapDataSource.cjs +734 -0
  51. package/dist/data-sources/SnapDataSource.cjs.map +1 -0
  52. package/dist/data-sources/SnapDataSource.d.cts +217 -0
  53. package/dist/data-sources/SnapDataSource.d.cts.map +1 -0
  54. package/dist/data-sources/SnapDataSource.d.mts +217 -0
  55. package/dist/data-sources/SnapDataSource.d.mts.map +1 -0
  56. package/dist/data-sources/SnapDataSource.mjs +723 -0
  57. package/dist/data-sources/SnapDataSource.mjs.map +1 -0
  58. package/dist/data-sources/TokenDataSource.cjs +179 -0
  59. package/dist/data-sources/TokenDataSource.cjs.map +1 -0
  60. package/dist/data-sources/TokenDataSource.d.cts +62 -0
  61. package/dist/data-sources/TokenDataSource.d.cts.map +1 -0
  62. package/dist/data-sources/TokenDataSource.d.mts +62 -0
  63. package/dist/data-sources/TokenDataSource.d.mts.map +1 -0
  64. package/dist/data-sources/TokenDataSource.mjs +175 -0
  65. package/dist/data-sources/TokenDataSource.mjs.map +1 -0
  66. package/dist/data-sources/index.cjs +62 -0
  67. package/dist/data-sources/index.cjs.map +1 -0
  68. package/dist/data-sources/index.d.cts +9 -0
  69. package/dist/data-sources/index.d.cts.map +1 -0
  70. package/dist/data-sources/index.d.mts +9 -0
  71. package/dist/data-sources/index.d.mts.map +1 -0
  72. package/dist/data-sources/index.mjs +23 -0
  73. package/dist/data-sources/index.mjs.map +1 -0
  74. package/dist/data-sources/initDataSources.cjs +199 -0
  75. package/dist/data-sources/initDataSources.cjs.map +1 -0
  76. package/dist/data-sources/initDataSources.d.cts +123 -0
  77. package/dist/data-sources/initDataSources.d.cts.map +1 -0
  78. package/dist/data-sources/initDataSources.d.mts +123 -0
  79. package/dist/data-sources/initDataSources.d.mts.map +1 -0
  80. package/dist/data-sources/initDataSources.mjs +194 -0
  81. package/dist/data-sources/initDataSources.mjs.map +1 -0
  82. package/dist/data-sources/rpc-datasource/clients/MulticallClient.cjs +638 -0
  83. package/dist/data-sources/rpc-datasource/clients/MulticallClient.cjs.map +1 -0
  84. package/dist/data-sources/rpc-datasource/clients/MulticallClient.d.cts +47 -0
  85. package/dist/data-sources/rpc-datasource/clients/MulticallClient.d.cts.map +1 -0
  86. package/dist/data-sources/rpc-datasource/clients/MulticallClient.d.mts +47 -0
  87. package/dist/data-sources/rpc-datasource/clients/MulticallClient.d.mts.map +1 -0
  88. package/dist/data-sources/rpc-datasource/clients/MulticallClient.mjs +632 -0
  89. package/dist/data-sources/rpc-datasource/clients/MulticallClient.mjs.map +1 -0
  90. package/dist/data-sources/rpc-datasource/clients/index.cjs +8 -0
  91. package/dist/data-sources/rpc-datasource/clients/index.cjs.map +1 -0
  92. package/dist/data-sources/rpc-datasource/clients/index.d.cts +3 -0
  93. package/dist/data-sources/rpc-datasource/clients/index.d.cts.map +1 -0
  94. package/dist/data-sources/rpc-datasource/clients/index.d.mts +3 -0
  95. package/dist/data-sources/rpc-datasource/clients/index.d.mts.map +1 -0
  96. package/dist/data-sources/rpc-datasource/clients/index.mjs +2 -0
  97. package/dist/data-sources/rpc-datasource/clients/index.mjs.map +1 -0
  98. package/dist/data-sources/rpc-datasource/index.cjs +9 -0
  99. package/dist/data-sources/rpc-datasource/index.cjs.map +1 -0
  100. package/dist/data-sources/rpc-datasource/index.d.cts +4 -0
  101. package/dist/data-sources/rpc-datasource/index.d.cts.map +1 -0
  102. package/dist/data-sources/rpc-datasource/index.d.mts +4 -0
  103. package/dist/data-sources/rpc-datasource/index.d.mts.map +1 -0
  104. package/dist/data-sources/rpc-datasource/index.mjs +3 -0
  105. package/dist/data-sources/rpc-datasource/index.mjs.map +1 -0
  106. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.cjs +167 -0
  107. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.cjs.map +1 -0
  108. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.cts +16 -0
  109. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.cts.map +1 -0
  110. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.mts +16 -0
  111. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.mts.map +1 -0
  112. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.mjs +163 -0
  113. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.mjs.map +1 -0
  114. package/dist/data-sources/rpc-datasource/services/TokenDetector.cjs +173 -0
  115. package/dist/data-sources/rpc-datasource/services/TokenDetector.cjs.map +1 -0
  116. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.cts +14 -0
  117. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.cts.map +1 -0
  118. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.mts +14 -0
  119. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.mts.map +1 -0
  120. package/dist/data-sources/rpc-datasource/services/TokenDetector.mjs +169 -0
  121. package/dist/data-sources/rpc-datasource/services/TokenDetector.mjs.map +1 -0
  122. package/dist/data-sources/rpc-datasource/services/index.cjs +8 -0
  123. package/dist/data-sources/rpc-datasource/services/index.cjs.map +1 -0
  124. package/dist/data-sources/rpc-datasource/services/index.d.cts +3 -0
  125. package/dist/data-sources/rpc-datasource/services/index.d.cts.map +1 -0
  126. package/dist/data-sources/rpc-datasource/services/index.d.mts +3 -0
  127. package/dist/data-sources/rpc-datasource/services/index.d.mts.map +1 -0
  128. package/dist/data-sources/rpc-datasource/services/index.mjs +3 -0
  129. package/dist/data-sources/rpc-datasource/services/index.mjs.map +1 -0
  130. package/dist/data-sources/rpc-datasource/types/assets.cjs +3 -0
  131. package/dist/data-sources/rpc-datasource/types/assets.cjs.map +1 -0
  132. package/dist/data-sources/rpc-datasource/types/assets.d.cts +53 -0
  133. package/dist/data-sources/rpc-datasource/types/assets.d.cts.map +1 -0
  134. package/dist/data-sources/rpc-datasource/types/assets.d.mts +53 -0
  135. package/dist/data-sources/rpc-datasource/types/assets.d.mts.map +1 -0
  136. package/dist/data-sources/rpc-datasource/types/assets.mjs +2 -0
  137. package/dist/data-sources/rpc-datasource/types/assets.mjs.map +1 -0
  138. package/dist/data-sources/rpc-datasource/types/config.cjs +3 -0
  139. package/dist/data-sources/rpc-datasource/types/config.cjs.map +1 -0
  140. package/dist/data-sources/rpc-datasource/types/config.d.cts +18 -0
  141. package/dist/data-sources/rpc-datasource/types/config.d.cts.map +1 -0
  142. package/dist/data-sources/rpc-datasource/types/config.d.mts +18 -0
  143. package/dist/data-sources/rpc-datasource/types/config.d.mts.map +1 -0
  144. package/dist/data-sources/rpc-datasource/types/config.mjs +2 -0
  145. package/dist/data-sources/rpc-datasource/types/config.mjs.map +1 -0
  146. package/dist/data-sources/rpc-datasource/types/core.cjs +3 -0
  147. package/dist/data-sources/rpc-datasource/types/core.cjs.map +1 -0
  148. package/dist/data-sources/rpc-datasource/types/core.d.cts +19 -0
  149. package/dist/data-sources/rpc-datasource/types/core.d.cts.map +1 -0
  150. package/dist/data-sources/rpc-datasource/types/core.d.mts +19 -0
  151. package/dist/data-sources/rpc-datasource/types/core.d.mts.map +1 -0
  152. package/dist/data-sources/rpc-datasource/types/core.mjs +2 -0
  153. package/dist/data-sources/rpc-datasource/types/core.mjs.map +1 -0
  154. package/dist/data-sources/rpc-datasource/types/index.cjs +3 -0
  155. package/dist/data-sources/rpc-datasource/types/index.cjs.map +1 -0
  156. package/dist/data-sources/rpc-datasource/types/index.d.cts +7 -0
  157. package/dist/data-sources/rpc-datasource/types/index.d.cts.map +1 -0
  158. package/dist/data-sources/rpc-datasource/types/index.d.mts +7 -0
  159. package/dist/data-sources/rpc-datasource/types/index.d.mts.map +1 -0
  160. package/dist/data-sources/rpc-datasource/types/index.mjs +2 -0
  161. package/dist/data-sources/rpc-datasource/types/index.mjs.map +1 -0
  162. package/dist/data-sources/rpc-datasource/types/multicall.cjs +3 -0
  163. package/dist/data-sources/rpc-datasource/types/multicall.cjs.map +1 -0
  164. package/dist/data-sources/rpc-datasource/types/multicall.d.cts +24 -0
  165. package/dist/data-sources/rpc-datasource/types/multicall.d.cts.map +1 -0
  166. package/dist/data-sources/rpc-datasource/types/multicall.d.mts +24 -0
  167. package/dist/data-sources/rpc-datasource/types/multicall.d.mts.map +1 -0
  168. package/dist/data-sources/rpc-datasource/types/multicall.mjs +2 -0
  169. package/dist/data-sources/rpc-datasource/types/multicall.mjs.map +1 -0
  170. package/dist/data-sources/rpc-datasource/types/services.cjs +3 -0
  171. package/dist/data-sources/rpc-datasource/types/services.cjs.map +1 -0
  172. package/dist/data-sources/rpc-datasource/types/services.d.cts +74 -0
  173. package/dist/data-sources/rpc-datasource/types/services.d.cts.map +1 -0
  174. package/dist/data-sources/rpc-datasource/types/services.d.mts +74 -0
  175. package/dist/data-sources/rpc-datasource/types/services.d.mts.map +1 -0
  176. package/dist/data-sources/rpc-datasource/types/services.mjs +2 -0
  177. package/dist/data-sources/rpc-datasource/types/services.mjs.map +1 -0
  178. package/dist/data-sources/rpc-datasource/types/state.cjs +3 -0
  179. package/dist/data-sources/rpc-datasource/types/state.cjs.map +1 -0
  180. package/dist/data-sources/rpc-datasource/types/state.d.cts +67 -0
  181. package/dist/data-sources/rpc-datasource/types/state.d.cts.map +1 -0
  182. package/dist/data-sources/rpc-datasource/types/state.d.mts +67 -0
  183. package/dist/data-sources/rpc-datasource/types/state.d.mts.map +1 -0
  184. package/dist/data-sources/rpc-datasource/types/state.mjs +2 -0
  185. package/dist/data-sources/rpc-datasource/types/state.mjs.map +1 -0
  186. package/dist/data-sources/rpc-datasource/utils/batch.cjs +45 -0
  187. package/dist/data-sources/rpc-datasource/utils/batch.cjs.map +1 -0
  188. package/dist/data-sources/rpc-datasource/utils/batch.d.cts +28 -0
  189. package/dist/data-sources/rpc-datasource/utils/batch.d.cts.map +1 -0
  190. package/dist/data-sources/rpc-datasource/utils/batch.d.mts +28 -0
  191. package/dist/data-sources/rpc-datasource/utils/batch.d.mts.map +1 -0
  192. package/dist/data-sources/rpc-datasource/utils/batch.mjs +40 -0
  193. package/dist/data-sources/rpc-datasource/utils/batch.mjs.map +1 -0
  194. package/dist/data-sources/rpc-datasource/utils/index.cjs +7 -0
  195. package/dist/data-sources/rpc-datasource/utils/index.cjs.map +1 -0
  196. package/dist/data-sources/rpc-datasource/utils/index.d.cts +2 -0
  197. package/dist/data-sources/rpc-datasource/utils/index.d.cts.map +1 -0
  198. package/dist/data-sources/rpc-datasource/utils/index.d.mts +2 -0
  199. package/dist/data-sources/rpc-datasource/utils/index.d.mts.map +1 -0
  200. package/dist/data-sources/rpc-datasource/utils/index.mjs +2 -0
  201. package/dist/data-sources/rpc-datasource/utils/index.mjs.map +1 -0
  202. package/dist/index.cjs +70 -1
  203. package/dist/index.cjs.map +1 -1
  204. package/dist/index.d.cts +19 -1
  205. package/dist/index.d.cts.map +1 -1
  206. package/dist/index.d.mts +19 -1
  207. package/dist/index.d.mts.map +1 -1
  208. package/dist/index.mjs +31 -0
  209. package/dist/index.mjs.map +1 -1
  210. package/dist/logger.cjs +7 -0
  211. package/dist/logger.cjs.map +1 -0
  212. package/dist/logger.d.cts +5 -0
  213. package/dist/logger.d.cts.map +1 -0
  214. package/dist/logger.d.mts +5 -0
  215. package/dist/logger.d.mts.map +1 -0
  216. package/dist/logger.mjs +4 -0
  217. package/dist/logger.mjs.map +1 -0
  218. package/dist/middlewares/DetectionMiddleware.cjs +101 -0
  219. package/dist/middlewares/DetectionMiddleware.cjs.map +1 -0
  220. package/dist/middlewares/DetectionMiddleware.d.cts +54 -0
  221. package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -0
  222. package/dist/middlewares/DetectionMiddleware.d.mts +54 -0
  223. package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -0
  224. package/dist/middlewares/DetectionMiddleware.mjs +97 -0
  225. package/dist/middlewares/DetectionMiddleware.mjs.map +1 -0
  226. package/dist/middlewares/index.cjs +6 -0
  227. package/dist/middlewares/index.cjs.map +1 -0
  228. package/dist/middlewares/index.d.cts +2 -0
  229. package/dist/middlewares/index.d.cts.map +1 -0
  230. package/dist/middlewares/index.d.mts +2 -0
  231. package/dist/middlewares/index.d.mts.map +1 -0
  232. package/dist/middlewares/index.mjs +2 -0
  233. package/dist/middlewares/index.mjs.map +1 -0
  234. package/dist/types.cjs +39 -0
  235. package/dist/types.cjs.map +1 -0
  236. package/dist/types.d.cts +360 -0
  237. package/dist/types.d.cts.map +1 -0
  238. package/dist/types.d.mts +360 -0
  239. package/dist/types.d.mts.map +1 -0
  240. package/dist/types.mjs +35 -0
  241. package/dist/types.mjs.map +1 -0
  242. package/dist/utils.cjs +28 -0
  243. package/dist/utils.cjs.map +1 -0
  244. package/dist/utils.d.cts +13 -0
  245. package/dist/utils.d.cts.map +1 -0
  246. package/dist/utils.d.mts +13 -0
  247. package/dist/utils.d.mts.map +1 -0
  248. package/dist/utils.mjs +24 -0
  249. package/dist/utils.mjs.map +1 -0
  250. package/package.json +15 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackendWebsocketDataSource.mjs","sourceRoot":"","sources":["../../src/data-sources/BackendWebsocketDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n BackendWebSocketServiceActions,\n BackendWebSocketServiceEvents,\n ServerNotificationMessage,\n WebSocketSubscription,\n WebSocketState,\n AccountActivityMessage,\n BalanceUpdate,\n} from '@metamask/core-backend';\nimport type { Messenger } from '@metamask/messenger';\n\nimport { AbstractDataSource } from './AbstractDataSource';\nimport type {\n DataSourceState,\n SubscriptionRequest,\n} from './AbstractDataSource';\nimport { projectLogger, createModuleLogger } from '../logger';\nimport type {\n ChainId,\n Caip19AssetId,\n AssetMetadata,\n AssetBalance,\n DataRequest,\n DataResponse,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'BackendWebsocketDataSource';\nconst CHANNEL_TYPE = 'account-activity.v1';\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n// Action types that BackendWebsocketDataSource exposes\nexport type BackendWebsocketDataSourceGetActiveChainsAction = {\n type: 'BackendWebsocketDataSource:getActiveChains';\n handler: () => Promise<ChainId[]>;\n};\n\nexport type BackendWebsocketDataSourceSubscribeAction = {\n type: 'BackendWebsocketDataSource:subscribe';\n handler: (request: SubscriptionRequest) => Promise<void>;\n};\n\nexport type BackendWebsocketDataSourceUnsubscribeAction = {\n type: 'BackendWebsocketDataSource:unsubscribe';\n handler: (subscriptionId: string) => Promise<void>;\n};\n\nexport type BackendWebsocketDataSourceActions =\n | BackendWebsocketDataSourceGetActiveChainsAction\n | BackendWebsocketDataSourceSubscribeAction\n | BackendWebsocketDataSourceUnsubscribeAction;\n\n// Event types that BackendWebsocketDataSource publishes\nexport type BackendWebsocketDataSourceActiveChainsChangedEvent = {\n type: 'BackendWebsocketDataSource:activeChainsUpdated';\n payload: [ChainId[]];\n};\n\nexport type BackendWebsocketDataSourceAssetsUpdatedEvent = {\n type: 'BackendWebsocketDataSource:assetsUpdated';\n payload: [DataResponse, string | undefined];\n};\n\nexport type BackendWebsocketDataSourceEvents =\n | BackendWebsocketDataSourceActiveChainsChangedEvent\n | BackendWebsocketDataSourceAssetsUpdatedEvent;\n\n// Actions to report to AssetsController\ntype AssetsControllerActiveChainsUpdateAction = {\n type: 'AssetsController:activeChainsUpdate';\n handler: (dataSourceId: string, activeChains: ChainId[]) => void;\n};\n\ntype AssetsControllerAssetsUpdateAction = {\n type: 'AssetsController:assetsUpdate';\n handler: (response: DataResponse, sourceId: string) => Promise<void>;\n};\n\n// Allowed actions that BackendWebsocketDataSource can call\nexport type BackendWebsocketDataSourceAllowedActions =\n | BackendWebSocketServiceActions\n | AssetsControllerActiveChainsUpdateAction\n | AssetsControllerAssetsUpdateAction;\n\n// Event type from AccountsApiDataSource that we subscribe to\nexport type AccountsApiDataSourceActiveChainsChangedEvent = {\n type: 'AccountsApiDataSource:activeChainsUpdated';\n payload: [ChainId[]];\n};\n\n// Allowed events that BackendWebsocketDataSource can subscribe to\nexport type BackendWebsocketDataSourceAllowedEvents =\n | BackendWebSocketServiceEvents\n | AccountsApiDataSourceActiveChainsChangedEvent;\n\nexport type BackendWebsocketDataSourceMessenger = Messenger<\n typeof CONTROLLER_NAME,\n BackendWebsocketDataSourceActions | BackendWebsocketDataSourceAllowedActions,\n BackendWebsocketDataSourceEvents | BackendWebsocketDataSourceAllowedEvents\n>;\n\n// ============================================================================\n// STATE\n// ============================================================================\n\nexport type BackendWebsocketDataSourceState = DataSourceState;\n\nconst defaultState: BackendWebsocketDataSourceState = {\n activeChains: [],\n};\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type BackendWebsocketDataSourceOptions = {\n messenger: BackendWebsocketDataSourceMessenger;\n state?: Partial<BackendWebsocketDataSourceState>;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Extract namespace from a CAIP-2 chain ID.\n * E.g., \"eip155:1\" -> \"eip155\", \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\" -> \"solana\"\n *\n * @param chainId - The CAIP-2 chain ID to extract namespace from.\n * @returns The namespace portion of the chain ID.\n */\nfunction extractNamespace(chainId: ChainId): string {\n const [namespace] = chainId.split(':');\n return namespace;\n}\n\n/**\n * Get unique namespaces from chain IDs.\n *\n * @param chainIds - Array of CAIP-2 chain IDs.\n * @returns Array of unique namespaces.\n */\nfunction getUniqueNamespaces(chainIds: ChainId[]): string[] {\n const namespaces = new Set<string>();\n for (const chainId of chainIds) {\n namespaces.add(extractNamespace(chainId));\n }\n return Array.from(namespaces);\n}\n\n/**\n * Build WebSocket channel name for account activity using CAIP-10 wildcard format.\n * Uses 0 as the chain reference to subscribe to all chains in the namespace.\n * Format: account-activity.v1.eip155:0:0x1234... (all EVM chains)\n * Format: account-activity.v1.solana:0:ABC123... (all Solana chains)\n *\n * @param namespace - The chain namespace (e.g., \"eip155\", \"solana\").\n * @param address - The account address.\n * @returns The WebSocket channel name.\n */\nfunction buildAccountActivityChannel(\n namespace: string,\n address: string,\n): string {\n return `${CHANNEL_TYPE}.${namespace}:0:${address.toLowerCase()}`;\n}\n\n// Note: AccountActivityMessage and BalanceUpdate types are imported from @metamask/core-backend\n\n// ============================================================================\n// BACKEND WEBSOCKET DATA SOURCE\n// ============================================================================\n\n/**\n * Data source for receiving real-time balance updates via WebSocket.\n *\n * This data source connects directly to BackendWebSocketService to receive\n * push notifications for account balance changes. Unlike AccountsApiDataSource\n * which polls for data, this provides instant updates.\n *\n * Uses Messenger pattern for all interactions:\n * - Calls BackendWebSocketService methods via messenger actions\n * - Exposes its own actions for AssetsController to call\n * - Publishes events for AssetsController to subscribe to\n *\n * Actions exposed:\n * - BackendWebsocketDataSource:getActiveChains\n * - BackendWebsocketDataSource:subscribe\n * - BackendWebsocketDataSource:unsubscribe\n *\n * Events published:\n * - BackendWebsocketDataSource:activeChainsUpdated\n * - BackendWebsocketDataSource:assetsUpdated\n *\n * Actions called (from BackendWebSocketService):\n * - BackendWebSocketService:subscribe\n * - BackendWebSocketService:getConnectionInfo\n * - BackendWebSocketService:findSubscriptionsByChannelPrefix\n */\nexport class BackendWebsocketDataSource extends AbstractDataSource<\n typeof CONTROLLER_NAME,\n BackendWebsocketDataSourceState\n> {\n readonly #messenger: BackendWebsocketDataSourceMessenger;\n\n /** WebSocket subscriptions by our internal subscription ID */\n readonly #wsSubscriptions: Map<string, WebSocketSubscription> = new Map();\n\n /** Pending subscription requests to process when WebSocket connects */\n readonly #pendingSubscriptions: Map<string, SubscriptionRequest> = new Map();\n\n /** Store original subscription requests for reconnection */\n readonly #subscriptionRequests: Map<string, SubscriptionRequest> = new Map();\n\n constructor(options: BackendWebsocketDataSourceOptions) {\n super(CONTROLLER_NAME, {\n ...defaultState,\n ...options.state,\n });\n\n this.#messenger = options.messenger;\n\n this.#registerActionHandlers();\n this.#subscribeToEvents();\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n #registerActionHandlers(): void {\n const getActiveChainsHandler: BackendWebsocketDataSourceGetActiveChainsAction['handler'] =\n async () => this.getActiveChains();\n\n const subscribeHandler: BackendWebsocketDataSourceSubscribeAction['handler'] =\n async (request) => this.subscribe(request);\n\n const unsubscribeHandler: BackendWebsocketDataSourceUnsubscribeAction['handler'] =\n async (subscriptionId) => this.unsubscribe(subscriptionId);\n\n this.#messenger.registerActionHandler(\n 'BackendWebsocketDataSource:getActiveChains',\n getActiveChainsHandler,\n );\n\n this.#messenger.registerActionHandler(\n 'BackendWebsocketDataSource:subscribe',\n subscribeHandler,\n );\n\n this.#messenger.registerActionHandler(\n 'BackendWebsocketDataSource:unsubscribe',\n unsubscribeHandler,\n );\n }\n\n #subscribeToEvents(): void {\n // Listen for WebSocket connection state changes\n this.#messenger.subscribe(\n 'BackendWebSocketService:connectionStateChanged',\n (connectionInfo) => {\n if (connectionInfo.state === ('connected' as WebSocketState)) {\n // WebSocket connected - process any pending subscriptions\n this.#processPendingSubscriptions().catch(console.error);\n } else if (\n connectionInfo.state === ('disconnected' as WebSocketState)\n ) {\n // When disconnected, all subscriptions are cleared server-side\n // Move active subscriptions to pending for re-subscription on reconnect\n this.#handleDisconnect();\n }\n },\n );\n\n // Listen for AccountsApiDataSource active chains changes\n // This keeps BackendWebsocketDataSource in sync with the supported chains\n // since both use the same backend infrastructure\n this.#messenger.subscribe(\n 'AccountsApiDataSource:activeChainsUpdated',\n (chains: ChainId[]) => {\n this.updateActiveChains(chains, (updatedChains) =>\n this.#messenger.call(\n 'AssetsController:activeChainsUpdate',\n CONTROLLER_NAME,\n updatedChains,\n ),\n );\n },\n );\n }\n\n /**\n * Handle WebSocket disconnection.\n * Moves all active subscriptions to pending for re-subscription on reconnect.\n */\n #handleDisconnect(): void {\n log('WebSocket disconnected, preserving subscriptions for reconnect', {\n activeSubscriptionCount: this.activeSubscriptions.size,\n wsSubscriptionCount: this.#wsSubscriptions.size,\n });\n\n // Move active subscriptions to pending for re-subscription\n for (const [subscriptionId] of this.activeSubscriptions) {\n const originalRequest = this.#subscriptionRequests.get(subscriptionId);\n if (originalRequest) {\n // Mark as update since it was previously active\n this.#pendingSubscriptions.set(subscriptionId, {\n ...originalRequest,\n isUpdate: false, // Treat as new subscription since server cleared it\n });\n }\n }\n\n // Clear WebSocket subscriptions (server-side already cleared)\n this.#wsSubscriptions.clear();\n\n // Clear active subscriptions (they're no longer valid)\n this.activeSubscriptions.clear();\n }\n\n /**\n * Process any pending subscriptions that were queued while WebSocket was disconnected.\n */\n async #processPendingSubscriptions(): Promise<void> {\n if (this.#pendingSubscriptions.size === 0) {\n return;\n }\n\n // Process all pending subscriptions\n const pendingEntries = Array.from(this.#pendingSubscriptions.entries());\n\n for (const [subscriptionId, request] of pendingEntries) {\n try {\n // Remove from pending before processing to avoid infinite loop\n this.#pendingSubscriptions.delete(subscriptionId);\n await this.subscribe(request);\n } catch (error) {\n log('Failed to process pending subscription', {\n subscriptionId,\n error,\n });\n }\n }\n }\n\n // ============================================================================\n // ACTIVE CHAINS\n // ============================================================================\n\n /**\n * Update active chains when AccountsApiDataSource reports new supported chains.\n *\n * @param chains - Array of supported chain IDs.\n */\n updateSupportedChains(chains: ChainId[]): void {\n this.updateActiveChains(chains, (updatedChains) =>\n this.#messenger.call(\n 'AssetsController:activeChainsUpdate',\n CONTROLLER_NAME,\n updatedChains,\n ),\n );\n }\n\n // ============================================================================\n // SUBSCRIBE\n // ============================================================================\n\n async subscribe(subscriptionRequest: SubscriptionRequest): Promise<void> {\n const { request, subscriptionId, isUpdate } = subscriptionRequest;\n\n // Filter to active chains only\n const chainsToSubscribe = request.chainIds.filter((chainId) =>\n this.state.activeChains.includes(chainId),\n );\n\n const addresses = request.accounts.map((a) => a.address);\n\n if (chainsToSubscribe.length === 0) {\n return;\n }\n\n // Check WebSocket connection status\n try {\n const connectionInfo = this.#messenger.call(\n 'BackendWebSocketService:getConnectionInfo',\n );\n if (connectionInfo.state !== ('connected' as WebSocketState)) {\n // Store the subscription request to process when WebSocket connects\n this.#pendingSubscriptions.set(subscriptionId, subscriptionRequest);\n return;\n }\n } catch {\n // Store anyway - will be processed when we can connect\n this.#pendingSubscriptions.set(subscriptionId, subscriptionRequest);\n return;\n }\n\n // Remove from pending if it was there (we're processing it now)\n this.#pendingSubscriptions.delete(subscriptionId);\n\n // Handle subscription update\n if (isUpdate) {\n const existing = this.activeSubscriptions.get(subscriptionId);\n if (existing) {\n // Check if accounts changed - if so, we need to re-subscribe to different channels\n const existingAddresses = existing.addresses ?? [];\n const addressesChanged =\n addresses.length !== existingAddresses.length ||\n addresses.some((addr) => !existingAddresses.includes(addr));\n\n if (!addressesChanged) {\n // Only chains changed - just update chains and return\n existing.chains = chainsToSubscribe;\n return;\n }\n // Accounts changed - fall through to re-subscribe with new channels\n }\n }\n\n // Clean up existing subscription if any\n await this.unsubscribe(subscriptionId);\n\n // Extract unique namespaces from chains (e.g., eip155, solana)\n const namespaces = getUniqueNamespaces(chainsToSubscribe);\n\n // Build channel names using CAIP-10 wildcard format\n const channels: string[] = [];\n for (const namespace of namespaces) {\n for (const address of addresses) {\n channels.push(buildAccountActivityChannel(namespace, address));\n }\n }\n\n try {\n // Create WebSocket subscription\n const wsSubscription = await this.#messenger.call(\n 'BackendWebSocketService:subscribe',\n {\n channels,\n channelType: CHANNEL_TYPE,\n callback: (notification: ServerNotificationMessage) => {\n this.#handleNotification(notification, request);\n },\n },\n );\n\n // Store WebSocket subscription\n this.#wsSubscriptions.set(subscriptionId, wsSubscription);\n\n // Store in abstract class tracking\n this.activeSubscriptions.set(subscriptionId, {\n cleanup: () => {\n const wsSub = this.#wsSubscriptions.get(subscriptionId);\n if (wsSub) {\n wsSub.unsubscribe().catch((unsubErr) => {\n log('Error unsubscribing', { subscriptionId, error: unsubErr });\n });\n this.#wsSubscriptions.delete(subscriptionId);\n }\n // Also clean up the stored request\n this.#subscriptionRequests.delete(subscriptionId);\n },\n chains: chainsToSubscribe,\n addresses,\n });\n\n // Store original request for reconnection\n this.#subscriptionRequests.set(subscriptionId, subscriptionRequest);\n } catch (error) {\n log('WebSocket subscription FAILED', {\n subscriptionId,\n error,\n chains: chainsToSubscribe,\n });\n }\n }\n\n // ============================================================================\n // NOTIFICATION HANDLING\n // ============================================================================\n\n #handleNotification(\n notification: ServerNotificationMessage,\n request: DataRequest,\n ): void {\n try {\n const activityMessage =\n notification.data as unknown as AccountActivityMessage;\n const { address, tx, updates } = activityMessage;\n\n if (!address || !tx || !updates) {\n return;\n }\n\n // Extract chain ID from transaction (CAIP-2 format, e.g., \"eip155:8453\")\n const chainId = tx.chain as ChainId;\n\n // Find matching account in request\n const account = request.accounts.find(\n (a) => a.address.toLowerCase() === address.toLowerCase(),\n );\n if (!account) {\n return;\n }\n const accountId = account.id;\n\n // Process all balance updates from the activity message\n const response = this.#processBalanceUpdates(updates, chainId, accountId);\n\n if (Object.keys(response).length > 0) {\n // Report update to AssetsController\n this.#messenger\n .call('AssetsController:assetsUpdate', response, CONTROLLER_NAME)\n .catch(console.error);\n }\n } catch (error) {\n log('Error handling notification', error);\n }\n }\n\n /**\n * Process balance updates from AccountActivityMessage.\n * Each update contains asset info, post-transaction balance, and transfer details.\n *\n * @param updates - Array of balance updates from the activity message.\n * @param _chainId - The chain ID (unused but kept for context).\n * @param accountId - The account ID to process updates for.\n * @returns DataResponse containing processed balance and metadata.\n */\n #processBalanceUpdates(\n updates: BalanceUpdate[],\n _chainId: ChainId,\n accountId: string,\n ): DataResponse {\n const assetsBalance: Record<string, Record<Caip19AssetId, AssetBalance>> = {\n [accountId]: {},\n };\n const assetsMetadata: Record<Caip19AssetId, AssetMetadata> = {};\n\n for (const update of updates) {\n const { asset, postBalance } = update;\n\n if (!asset || !postBalance) {\n continue;\n }\n\n // Asset type is in CAIP format: \"eip155:1/erc20:0x...\" or \"eip155:1/slip44:60\"\n // We can use it directly as the asset ID\n const assetId = asset.type as Caip19AssetId;\n\n // Determine token type from asset type string\n const isNative = asset.type.includes('/slip44:');\n const tokenType = isNative ? 'native' : 'erc20';\n\n // Parse balance amount (already in hex format like \"0xc350\")\n const balanceAmount = postBalance.amount.startsWith('0x')\n ? BigInt(postBalance.amount).toString()\n : postBalance.amount;\n\n assetsBalance[accountId][assetId] = {\n amount: balanceAmount,\n };\n\n assetsMetadata[assetId] = {\n type: tokenType,\n symbol: asset.unit,\n name: asset.unit, // Use unit as name (actual name may not be in the message)\n decimals: asset.decimals,\n };\n }\n\n const response: DataResponse = {};\n if (Object.keys(assetsBalance[accountId]).length > 0) {\n response.assetsBalance = assetsBalance;\n response.assetsMetadata = assetsMetadata;\n }\n\n return response;\n }\n\n // ============================================================================\n // CLEANUP\n // ============================================================================\n\n destroy(): void {\n // Clean up WebSocket subscriptions\n // Convert to array first to avoid modifying map during iteration\n const subscriptions = [...this.#wsSubscriptions.values()];\n for (const wsSub of subscriptions) {\n try {\n // Fire and forget - don't await in destroy\n wsSub.unsubscribe().catch(() => {\n // Ignore errors during cleanup\n });\n } catch {\n // Ignore errors during cleanup\n }\n }\n this.#wsSubscriptions.clear();\n\n // Clean up base class subscriptions\n super.destroy();\n }\n}\n\n// ============================================================================\n// FACTORY FUNCTION\n// ============================================================================\n\n/**\n * Creates a BackendWebsocketDataSource instance.\n *\n * @param options - Configuration options for the data source.\n * @returns A new BackendWebsocketDataSource instance.\n */\nexport function createBackendWebsocketDataSource(\n options: BackendWebsocketDataSourceOptions,\n): BackendWebsocketDataSource {\n return new BackendWebsocketDataSource(options);\n}\n"]}
@@ -0,0 +1,350 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ 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");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ 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");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _PriceDataSource_instances, _PriceDataSource_messenger, _PriceDataSource_currency, _PriceDataSource_pollInterval, _PriceDataSource_apiClient, _PriceDataSource_activeSubscriptions, _PriceDataSource_registerActionHandlers, _PriceDataSource_fetchSpotPrices, _PriceDataSource_getAssetIdsFromBalanceState;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.PriceDataSource = void 0;
16
+ const core_backend_1 = require("@metamask/core-backend");
17
+ const logger_1 = require("../logger.cjs");
18
+ const types_1 = require("../types.cjs");
19
+ // ============================================================================
20
+ // CONSTANTS
21
+ // ============================================================================
22
+ const CONTROLLER_NAME = 'PriceDataSource';
23
+ const DEFAULT_POLL_INTERVAL = 60000; // 1 minute for price updates
24
+ const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, CONTROLLER_NAME);
25
+ // ============================================================================
26
+ // HELPER FUNCTIONS
27
+ // ============================================================================
28
+ /**
29
+ * Asset reference patterns that should NOT be sent to the Price API.
30
+ * These are internal resource tracking values without market prices.
31
+ */
32
+ const NON_PRICEABLE_ASSET_PATTERNS = [
33
+ // Tron resource assets (bandwidth, energy, staking states)
34
+ /\/slip44:\d+-staked-for-/u,
35
+ /\/slip44:bandwidth$/u,
36
+ /\/slip44:energy$/u,
37
+ /\/slip44:maximum-bandwidth$/u,
38
+ /\/slip44:maximum-energy$/u,
39
+ ];
40
+ /**
41
+ * Check if an asset ID represents a priceable asset.
42
+ * Filters out internal resource tracking values that don't have market prices.
43
+ *
44
+ * @param assetId - The CAIP-19 asset ID to check.
45
+ * @returns True if the asset has market price data.
46
+ */
47
+ function isPriceableAsset(assetId) {
48
+ return !NON_PRICEABLE_ASSET_PATTERNS.some((pattern) => pattern.test(assetId));
49
+ }
50
+ /**
51
+ * Type guard to check if market data has a valid price
52
+ *
53
+ * @param data - The data to check.
54
+ * @returns True if data is valid SpotPriceMarketData.
55
+ */
56
+ function isValidMarketData(data) {
57
+ return (typeof data === 'object' &&
58
+ data !== null &&
59
+ 'price' in data &&
60
+ typeof data.price === 'number');
61
+ }
62
+ function transformMarketDataToAssetPrice(marketData) {
63
+ return {
64
+ price: marketData.price,
65
+ priceChange24h: marketData.pricePercentChange1d,
66
+ lastUpdated: Date.now(),
67
+ // Extended market data
68
+ marketCap: marketData.marketCap,
69
+ volume24h: marketData.totalVolume,
70
+ };
71
+ }
72
+ // ============================================================================
73
+ // PRICE DATA SOURCE
74
+ // ============================================================================
75
+ /**
76
+ * PriceDataSource fetches asset prices from the Price API.
77
+ *
78
+ * This data source:
79
+ * - Fetches prices from Price API v3 spot-prices endpoint
80
+ * - Supports one-time fetch and subscription-based polling
81
+ * - In subscribe mode, automatically fetches prices for all assets in assetsBalance state
82
+ * - Publishes price updates via messenger events
83
+ *
84
+ * Usage:
85
+ * ```typescript
86
+ * // Create and initialize (registers messenger actions)
87
+ * const priceDataSource = new PriceDataSource({ messenger });
88
+ *
89
+ * // One-time fetch for specific assets
90
+ * const response = await messenger.call('PriceDataSource:fetch', {
91
+ * customAssets: ['eip155:1/erc20:0x...'],
92
+ * });
93
+ *
94
+ * // Subscribe to price updates (polls all assets in balance state)
95
+ * await messenger.call('PriceDataSource:subscribe', { request, subscriptionId });
96
+ *
97
+ * // Listen for updates
98
+ * messenger.subscribe('PriceDataSource:assetsUpdated', (response) => {
99
+ * // Handle price updates
100
+ * });
101
+ * ```
102
+ */
103
+ class PriceDataSource {
104
+ constructor(options) {
105
+ _PriceDataSource_instances.add(this);
106
+ this.name = CONTROLLER_NAME;
107
+ _PriceDataSource_messenger.set(this, void 0);
108
+ _PriceDataSource_currency.set(this, void 0);
109
+ _PriceDataSource_pollInterval.set(this, void 0);
110
+ /** ApiPlatformClient for cached API calls */
111
+ _PriceDataSource_apiClient.set(this, void 0);
112
+ /** Active subscriptions by ID */
113
+ _PriceDataSource_activeSubscriptions.set(this, new Map());
114
+ __classPrivateFieldSet(this, _PriceDataSource_messenger, options.messenger, "f");
115
+ __classPrivateFieldSet(this, _PriceDataSource_currency, options.currency ?? 'usd', "f");
116
+ __classPrivateFieldSet(this, _PriceDataSource_pollInterval, options.pollInterval ?? DEFAULT_POLL_INTERVAL, "f");
117
+ __classPrivateFieldSet(this, _PriceDataSource_apiClient, options.queryApiClient, "f");
118
+ __classPrivateFieldGet(this, _PriceDataSource_instances, "m", _PriceDataSource_registerActionHandlers).call(this);
119
+ }
120
+ // ============================================================================
121
+ // MIDDLEWARE
122
+ // ============================================================================
123
+ /**
124
+ * Get the middleware for enriching responses with price data.
125
+ *
126
+ * This middleware:
127
+ * 1. Extracts the response from context
128
+ * 2. Fetches prices for detected assets (assets without metadata)
129
+ * 3. Enriches the response with fetched prices
130
+ * 4. Calls next() at the end to continue the middleware chain
131
+ *
132
+ * Note: This middleware ONLY fetches prices for detected assets.
133
+ * For fetching prices for all assets, use the subscription mechanism
134
+ * which polls prices for all assets in the balance state.
135
+ *
136
+ * @returns The middleware function for the assets pipeline.
137
+ */
138
+ get assetsMiddleware() {
139
+ return (0, types_1.forDataTypes)(['price'], async (ctx, next) => {
140
+ // Extract response from context
141
+ const { response } = ctx;
142
+ // Only fetch prices for detected assets (assets without metadata)
143
+ // The subscription handles fetching prices for all existing assets
144
+ if (!response.detectedAssets) {
145
+ return next(ctx);
146
+ }
147
+ const detectedAssetIds = new Set();
148
+ for (const detectedIds of Object.values(response.detectedAssets)) {
149
+ for (const assetId of detectedIds) {
150
+ detectedAssetIds.add(assetId);
151
+ }
152
+ }
153
+ if (detectedAssetIds.size === 0) {
154
+ return next(ctx);
155
+ }
156
+ // Filter to only priceable assets
157
+ const priceableAssetIds = [...detectedAssetIds].filter(isPriceableAsset);
158
+ if (priceableAssetIds.length === 0) {
159
+ return next(ctx);
160
+ }
161
+ try {
162
+ const priceResponse = await __classPrivateFieldGet(this, _PriceDataSource_instances, "m", _PriceDataSource_fetchSpotPrices).call(this, priceableAssetIds, true);
163
+ response.assetsPrice ?? (response.assetsPrice = {});
164
+ for (const [assetId, marketData] of Object.entries(priceResponse)) {
165
+ if (!isValidMarketData(marketData)) {
166
+ continue;
167
+ }
168
+ const caipAssetId = assetId;
169
+ response.assetsPrice[caipAssetId] =
170
+ transformMarketDataToAssetPrice(marketData);
171
+ }
172
+ }
173
+ catch (error) {
174
+ log('Failed to fetch prices via middleware', { error });
175
+ }
176
+ // Call next() at the end to continue the middleware chain
177
+ return next(ctx);
178
+ });
179
+ }
180
+ // ============================================================================
181
+ // FETCH
182
+ // ============================================================================
183
+ /**
184
+ * Fetch prices for assets held by the accounts and chains in the request.
185
+ * Gets asset IDs from balance state, filtered by request.accounts and request.chainIds.
186
+ *
187
+ * @param request - The data request specifying accounts and chains.
188
+ * @returns DataResponse containing asset prices.
189
+ */
190
+ async fetch(request) {
191
+ const response = {};
192
+ // Get asset IDs from balance state, filtered by accounts and chains
193
+ const rawAssetIds = __classPrivateFieldGet(this, _PriceDataSource_instances, "m", _PriceDataSource_getAssetIdsFromBalanceState).call(this, request);
194
+ // Filter out non-priceable assets (e.g., Tron bandwidth/energy resources)
195
+ const assetIds = rawAssetIds.filter(isPriceableAsset);
196
+ if (assetIds.length === 0) {
197
+ return response;
198
+ }
199
+ try {
200
+ const priceResponse = await __classPrivateFieldGet(this, _PriceDataSource_instances, "m", _PriceDataSource_fetchSpotPrices).call(this, [...assetIds], true);
201
+ response.assetsPrice = {};
202
+ for (const [assetId, marketData] of Object.entries(priceResponse)) {
203
+ // Skip assets with invalid market data (API doesn't have price for this asset)
204
+ if (!isValidMarketData(marketData)) {
205
+ continue;
206
+ }
207
+ const caipAssetId = assetId;
208
+ response.assetsPrice[caipAssetId] =
209
+ transformMarketDataToAssetPrice(marketData);
210
+ }
211
+ }
212
+ catch (error) {
213
+ log('Failed to fetch prices', { error });
214
+ }
215
+ return response;
216
+ }
217
+ // ============================================================================
218
+ // SUBSCRIBE
219
+ // ============================================================================
220
+ /**
221
+ * Subscribe to price updates.
222
+ * Sets up polling that fetches prices for all assets in assetsBalance state.
223
+ *
224
+ * @param subscriptionRequest - The subscription request configuration.
225
+ */
226
+ async subscribe(subscriptionRequest) {
227
+ const { request, subscriptionId, isUpdate } = subscriptionRequest;
228
+ // Handle subscription update - just update the request
229
+ if (isUpdate) {
230
+ const existing = __classPrivateFieldGet(this, _PriceDataSource_activeSubscriptions, "f").get(subscriptionId);
231
+ if (existing) {
232
+ existing.request = request;
233
+ return;
234
+ }
235
+ }
236
+ // Clean up existing subscription
237
+ await this.unsubscribe(subscriptionId);
238
+ const pollInterval = request.updateInterval ?? __classPrivateFieldGet(this, _PriceDataSource_pollInterval, "f");
239
+ // Create poll function - fetches prices for all assets in balance state
240
+ const pollFn = async () => {
241
+ try {
242
+ const subscription = __classPrivateFieldGet(this, _PriceDataSource_activeSubscriptions, "f").get(subscriptionId);
243
+ if (!subscription) {
244
+ return;
245
+ }
246
+ // Fetch prices for all assets currently in balance state
247
+ const fetchResponse = await this.fetch(subscription.request);
248
+ // Only report if we got prices
249
+ if (fetchResponse.assetsPrice &&
250
+ Object.keys(fetchResponse.assetsPrice).length > 0) {
251
+ await __classPrivateFieldGet(this, _PriceDataSource_messenger, "f").call('AssetsController:assetsUpdate', fetchResponse, CONTROLLER_NAME);
252
+ }
253
+ }
254
+ catch (error) {
255
+ log('Subscription poll failed', { subscriptionId, error });
256
+ }
257
+ };
258
+ // Set up polling
259
+ const timer = setInterval(() => {
260
+ pollFn().catch(console.error);
261
+ }, pollInterval);
262
+ // Store subscription
263
+ __classPrivateFieldGet(this, _PriceDataSource_activeSubscriptions, "f").set(subscriptionId, {
264
+ cleanup: () => {
265
+ clearInterval(timer);
266
+ },
267
+ request,
268
+ });
269
+ // Initial fetch
270
+ await pollFn();
271
+ }
272
+ /**
273
+ * Unsubscribe from price updates.
274
+ *
275
+ * @param subscriptionId - The ID of the subscription to cancel.
276
+ */
277
+ async unsubscribe(subscriptionId) {
278
+ const subscription = __classPrivateFieldGet(this, _PriceDataSource_activeSubscriptions, "f").get(subscriptionId);
279
+ if (subscription) {
280
+ subscription.cleanup();
281
+ __classPrivateFieldGet(this, _PriceDataSource_activeSubscriptions, "f").delete(subscriptionId);
282
+ }
283
+ }
284
+ /**
285
+ * Destroy the data source and clean up all subscriptions.
286
+ */
287
+ destroy() {
288
+ for (const subscription of __classPrivateFieldGet(this, _PriceDataSource_activeSubscriptions, "f").values()) {
289
+ subscription.cleanup();
290
+ }
291
+ __classPrivateFieldGet(this, _PriceDataSource_activeSubscriptions, "f").clear();
292
+ }
293
+ }
294
+ exports.PriceDataSource = PriceDataSource;
295
+ _PriceDataSource_messenger = new WeakMap(), _PriceDataSource_currency = new WeakMap(), _PriceDataSource_pollInterval = new WeakMap(), _PriceDataSource_apiClient = new WeakMap(), _PriceDataSource_activeSubscriptions = new WeakMap(), _PriceDataSource_instances = new WeakSet(), _PriceDataSource_registerActionHandlers = function _PriceDataSource_registerActionHandlers() {
296
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
297
+ const messenger = __classPrivateFieldGet(this, _PriceDataSource_messenger, "f");
298
+ messenger.registerActionHandler('PriceDataSource:getAssetsMiddleware', () => this.assetsMiddleware);
299
+ messenger.registerActionHandler('PriceDataSource:fetch', (request) => this.fetch(request));
300
+ messenger.registerActionHandler('PriceDataSource:subscribe', (subscriptionRequest) => this.subscribe(subscriptionRequest));
301
+ messenger.registerActionHandler('PriceDataSource:unsubscribe', (subscriptionId) => this.unsubscribe(subscriptionId));
302
+ }, _PriceDataSource_fetchSpotPrices =
303
+ // ============================================================================
304
+ // HELPERS
305
+ // ============================================================================
306
+ /**
307
+ * Fetch spot prices with caching and deduplication via query service.
308
+ *
309
+ * @param assetIds - Array of CAIP-19 asset IDs
310
+ * @param includeMarketData - Whether to include market data
311
+ * @returns Spot prices response
312
+ */
313
+ async function _PriceDataSource_fetchSpotPrices(assetIds, includeMarketData) {
314
+ return __classPrivateFieldGet(this, _PriceDataSource_apiClient, "f").prices.fetchV3SpotPrices(assetIds, {
315
+ currency: __classPrivateFieldGet(this, _PriceDataSource_currency, "f"),
316
+ includeMarketData,
317
+ });
318
+ }, _PriceDataSource_getAssetIdsFromBalanceState = function _PriceDataSource_getAssetIdsFromBalanceState(request) {
319
+ try {
320
+ const state = __classPrivateFieldGet(this, _PriceDataSource_messenger, "f").call('AssetsController:getState');
321
+ const assetIds = new Set();
322
+ const accountIds = request.accounts.map((a) => a.id);
323
+ const accountFilter = accountIds.length > 0 ? new Set(accountIds) : undefined;
324
+ const chainFilter = request.chainIds.length > 0 ? new Set(request.chainIds) : undefined;
325
+ if (state?.assetsBalance) {
326
+ for (const [accountId, accountBalances] of Object.entries(state.assetsBalance)) {
327
+ // Filter by account if specified
328
+ if (accountFilter && !accountFilter.has(accountId)) {
329
+ continue;
330
+ }
331
+ for (const assetId of Object.keys(accountBalances)) {
332
+ // Filter by chain if specified
333
+ if (chainFilter) {
334
+ const chainId = assetId.split('/')[0];
335
+ if (!chainFilter.has(chainId)) {
336
+ continue;
337
+ }
338
+ }
339
+ assetIds.add(assetId);
340
+ }
341
+ }
342
+ }
343
+ return [...assetIds];
344
+ }
345
+ catch (error) {
346
+ log('Failed to get asset IDs from balance state', { error });
347
+ return [];
348
+ }
349
+ };
350
+ //# sourceMappingURL=PriceDataSource.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PriceDataSource.cjs","sourceRoot":"","sources":["../../src/data-sources/PriceDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n SupportedCurrency,\n V3SpotPricesResponse,\n} from '@metamask/core-backend';\nimport { ApiPlatformClient } from '@metamask/core-backend';\nimport type { Messenger } from '@metamask/messenger';\n\nimport type { SubscriptionRequest } from './AbstractDataSource';\nimport { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type {\n Caip19AssetId,\n AssetPrice,\n AssetBalance,\n AccountId,\n ChainId,\n DataRequest,\n DataResponse,\n Middleware,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'PriceDataSource';\nconst DEFAULT_POLL_INTERVAL = 60_000; // 1 minute for price updates\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n/**\n * Action to get balance state (used to determine which assets need prices).\n */\ntype GetAssetsBalanceStateAction = {\n type: 'AssetsController:getState';\n handler: () => {\n assetsBalance: Record<AccountId, Record<Caip19AssetId, AssetBalance>>;\n };\n};\n\n/**\n * Action to get the PriceDataSource middleware.\n */\nexport type PriceDataSourceGetAssetsMiddlewareAction = {\n type: `${typeof CONTROLLER_NAME}:getAssetsMiddleware`;\n handler: () => Middleware;\n};\n\n/**\n * Action to fetch prices for assets.\n */\nexport type PriceDataSourceFetchAction = {\n type: `${typeof CONTROLLER_NAME}:fetch`;\n handler: (request: DataRequest) => Promise<DataResponse>;\n};\n\n/**\n * Action to subscribe to price updates.\n */\nexport type PriceDataSourceSubscribeAction = {\n type: `${typeof CONTROLLER_NAME}:subscribe`;\n handler: (request: SubscriptionRequest) => Promise<void>;\n};\n\n/**\n * Action to unsubscribe from price updates.\n */\nexport type PriceDataSourceUnsubscribeAction = {\n type: `${typeof CONTROLLER_NAME}:unsubscribe`;\n handler: (subscriptionId: string) => Promise<void>;\n};\n\n/**\n * All actions exposed by PriceDataSource.\n */\nexport type PriceDataSourceActions =\n | PriceDataSourceGetAssetsMiddlewareAction\n | PriceDataSourceFetchAction\n | PriceDataSourceSubscribeAction\n | PriceDataSourceUnsubscribeAction;\n\n/**\n * Event emitted when prices are updated.\n */\nexport type PriceDataSourceAssetsUpdatedEvent = {\n type: `${typeof CONTROLLER_NAME}:assetsUpdated`;\n payload: [DataResponse, string];\n};\n\n/**\n * All events exposed by PriceDataSource.\n */\nexport type PriceDataSourceEvents = PriceDataSourceAssetsUpdatedEvent;\n\n// Action to report assets updated to AssetsController\ntype AssetsControllerAssetsUpdateAction = {\n type: 'AssetsController:assetsUpdate';\n handler: (response: DataResponse, sourceId: string) => Promise<void>;\n};\n\n/**\n * External actions that PriceDataSource needs to call.\n * Note: Uses ApiPlatformClient directly, so no BackendApiClient actions needed.\n */\nexport type PriceDataSourceAllowedActions =\n | GetAssetsBalanceStateAction\n | AssetsControllerAssetsUpdateAction;\n\nexport type PriceDataSourceMessenger = Messenger<\n typeof CONTROLLER_NAME,\n PriceDataSourceAllowedActions | PriceDataSourceActions,\n PriceDataSourceEvents\n>;\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type PriceDataSourceOptions = {\n messenger: PriceDataSourceMessenger;\n /** ApiPlatformClient for API calls with caching */\n queryApiClient: ApiPlatformClient;\n /** Currency to fetch prices in (default: 'usd') */\n currency?: SupportedCurrency;\n /** Polling interval in ms (default: 60000) */\n pollInterval?: number;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Asset reference patterns that should NOT be sent to the Price API.\n * These are internal resource tracking values without market prices.\n */\nconst NON_PRICEABLE_ASSET_PATTERNS = [\n // Tron resource assets (bandwidth, energy, staking states)\n /\\/slip44:\\d+-staked-for-/u,\n /\\/slip44:bandwidth$/u,\n /\\/slip44:energy$/u,\n /\\/slip44:maximum-bandwidth$/u,\n /\\/slip44:maximum-energy$/u,\n];\n\n/**\n * Check if an asset ID represents a priceable asset.\n * Filters out internal resource tracking values that don't have market prices.\n *\n * @param assetId - The CAIP-19 asset ID to check.\n * @returns True if the asset has market price data.\n */\nfunction isPriceableAsset(assetId: Caip19AssetId): boolean {\n return !NON_PRICEABLE_ASSET_PATTERNS.some((pattern) => pattern.test(assetId));\n}\n\n/** Market data item from spot prices response */\ntype SpotPriceMarketData = {\n price: number;\n pricePercentChange1d?: number;\n marketCap?: number;\n totalVolume?: number;\n};\n\n/**\n * Type guard to check if market data has a valid price\n *\n * @param data - The data to check.\n * @returns True if data is valid SpotPriceMarketData.\n */\nfunction isValidMarketData(data: unknown): data is SpotPriceMarketData {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'price' in data &&\n typeof (data as SpotPriceMarketData).price === 'number'\n );\n}\n\nfunction transformMarketDataToAssetPrice(\n marketData: SpotPriceMarketData,\n): AssetPrice {\n return {\n price: marketData.price,\n priceChange24h: marketData.pricePercentChange1d,\n lastUpdated: Date.now(),\n // Extended market data\n marketCap: marketData.marketCap,\n volume24h: marketData.totalVolume,\n };\n}\n\n// ============================================================================\n// PRICE DATA SOURCE\n// ============================================================================\n\n/**\n * PriceDataSource fetches asset prices from the Price API.\n *\n * This data source:\n * - Fetches prices from Price API v3 spot-prices endpoint\n * - Supports one-time fetch and subscription-based polling\n * - In subscribe mode, automatically fetches prices for all assets in assetsBalance state\n * - Publishes price updates via messenger events\n *\n * Usage:\n * ```typescript\n * // Create and initialize (registers messenger actions)\n * const priceDataSource = new PriceDataSource({ messenger });\n *\n * // One-time fetch for specific assets\n * const response = await messenger.call('PriceDataSource:fetch', {\n * customAssets: ['eip155:1/erc20:0x...'],\n * });\n *\n * // Subscribe to price updates (polls all assets in balance state)\n * await messenger.call('PriceDataSource:subscribe', { request, subscriptionId });\n *\n * // Listen for updates\n * messenger.subscribe('PriceDataSource:assetsUpdated', (response) => {\n * // Handle price updates\n * });\n * ```\n */\nexport class PriceDataSource {\n readonly name = CONTROLLER_NAME;\n\n readonly #messenger: PriceDataSourceMessenger;\n\n readonly #currency: SupportedCurrency;\n\n readonly #pollInterval: number;\n\n /** ApiPlatformClient for cached API calls */\n readonly #apiClient: ApiPlatformClient;\n\n /** Active subscriptions by ID */\n readonly #activeSubscriptions: Map<\n string,\n { cleanup: () => void; request: DataRequest }\n > = new Map();\n\n constructor(options: PriceDataSourceOptions) {\n this.#messenger = options.messenger;\n this.#currency = options.currency ?? 'usd';\n this.#pollInterval = options.pollInterval ?? DEFAULT_POLL_INTERVAL;\n this.#apiClient = options.queryApiClient;\n\n this.#registerActionHandlers();\n }\n\n #registerActionHandlers(): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const messenger = this.#messenger as any;\n\n messenger.registerActionHandler(\n 'PriceDataSource:getAssetsMiddleware',\n () => this.assetsMiddleware,\n );\n\n messenger.registerActionHandler(\n 'PriceDataSource:fetch',\n (request: DataRequest) => this.fetch(request),\n );\n\n messenger.registerActionHandler(\n 'PriceDataSource:subscribe',\n (subscriptionRequest: SubscriptionRequest) =>\n this.subscribe(subscriptionRequest),\n );\n\n messenger.registerActionHandler(\n 'PriceDataSource:unsubscribe',\n (subscriptionId: string) => this.unsubscribe(subscriptionId),\n );\n }\n\n // ============================================================================\n // MIDDLEWARE\n // ============================================================================\n\n /**\n * Get the middleware for enriching responses with price data.\n *\n * This middleware:\n * 1. Extracts the response from context\n * 2. Fetches prices for detected assets (assets without metadata)\n * 3. Enriches the response with fetched prices\n * 4. Calls next() at the end to continue the middleware chain\n *\n * Note: This middleware ONLY fetches prices for detected assets.\n * For fetching prices for all assets, use the subscription mechanism\n * which polls prices for all assets in the balance state.\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['price'], async (ctx, next) => {\n // Extract response from context\n const { response } = ctx;\n\n // Only fetch prices for detected assets (assets without metadata)\n // The subscription handles fetching prices for all existing assets\n if (!response.detectedAssets) {\n return next(ctx);\n }\n\n const detectedAssetIds = new Set<Caip19AssetId>();\n for (const detectedIds of Object.values(response.detectedAssets)) {\n for (const assetId of detectedIds) {\n detectedAssetIds.add(assetId);\n }\n }\n\n if (detectedAssetIds.size === 0) {\n return next(ctx);\n }\n\n // Filter to only priceable assets\n const priceableAssetIds = [...detectedAssetIds].filter(isPriceableAsset);\n\n if (priceableAssetIds.length === 0) {\n return next(ctx);\n }\n\n try {\n const priceResponse = await this.#fetchSpotPrices(\n priceableAssetIds,\n true, // includeMarketData\n );\n\n response.assetsPrice ??= {};\n\n for (const [assetId, marketData] of Object.entries(priceResponse)) {\n if (!isValidMarketData(marketData)) {\n continue;\n }\n\n const caipAssetId = assetId as Caip19AssetId;\n response.assetsPrice[caipAssetId] =\n transformMarketDataToAssetPrice(marketData);\n }\n } catch (error) {\n log('Failed to fetch prices via middleware', { error });\n }\n\n // Call next() at the end to continue the middleware chain\n return next(ctx);\n });\n }\n\n // ============================================================================\n // HELPERS\n // ============================================================================\n\n /**\n * Fetch spot prices with caching and deduplication via query service.\n *\n * @param assetIds - Array of CAIP-19 asset IDs\n * @param includeMarketData - Whether to include market data\n * @returns Spot prices response\n */\n async #fetchSpotPrices(\n assetIds: string[],\n includeMarketData: boolean,\n ): Promise<V3SpotPricesResponse> {\n return this.#apiClient.prices.fetchV3SpotPrices(assetIds, {\n currency: this.#currency,\n includeMarketData,\n });\n }\n\n /**\n * Get unique asset IDs from the assetsBalance state.\n * Filters by accounts and chains from the request.\n *\n * @param request - Data request with accounts and chainIds filters.\n * @returns Array of CAIP-19 asset IDs from balance state.\n */\n #getAssetIdsFromBalanceState(request: DataRequest): Caip19AssetId[] {\n try {\n const state = this.#messenger.call('AssetsController:getState');\n const assetIds = new Set<Caip19AssetId>();\n\n const accountIds = request.accounts.map((a) => a.id);\n const accountFilter =\n accountIds.length > 0 ? new Set(accountIds) : undefined;\n const chainFilter =\n request.chainIds.length > 0 ? new Set(request.chainIds) : undefined;\n\n if (state?.assetsBalance) {\n for (const [accountId, accountBalances] of Object.entries(\n state.assetsBalance,\n )) {\n // Filter by account if specified\n if (accountFilter && !accountFilter.has(accountId)) {\n continue;\n }\n\n for (const assetId of Object.keys(\n accountBalances as Record<string, unknown>,\n )) {\n // Filter by chain if specified\n if (chainFilter) {\n const chainId = assetId.split('/')[0] as ChainId;\n if (!chainFilter.has(chainId)) {\n continue;\n }\n }\n assetIds.add(assetId as Caip19AssetId);\n }\n }\n }\n\n return [...assetIds];\n } catch (error) {\n log('Failed to get asset IDs from balance state', { error });\n return [];\n }\n }\n\n // ============================================================================\n // FETCH\n // ============================================================================\n\n /**\n * Fetch prices for assets held by the accounts and chains in the request.\n * Gets asset IDs from balance state, filtered by request.accounts and request.chainIds.\n *\n * @param request - The data request specifying accounts and chains.\n * @returns DataResponse containing asset prices.\n */\n async fetch(request: DataRequest): Promise<DataResponse> {\n const response: DataResponse = {};\n\n // Get asset IDs from balance state, filtered by accounts and chains\n const rawAssetIds = this.#getAssetIdsFromBalanceState(request);\n\n // Filter out non-priceable assets (e.g., Tron bandwidth/energy resources)\n const assetIds = rawAssetIds.filter(isPriceableAsset);\n\n if (assetIds.length === 0) {\n return response;\n }\n\n try {\n const priceResponse = await this.#fetchSpotPrices(\n [...assetIds],\n true, // includeMarketData\n );\n\n response.assetsPrice = {};\n\n for (const [assetId, marketData] of Object.entries(priceResponse)) {\n // Skip assets with invalid market data (API doesn't have price for this asset)\n if (!isValidMarketData(marketData)) {\n continue;\n }\n\n const caipAssetId = assetId as Caip19AssetId;\n response.assetsPrice[caipAssetId] =\n transformMarketDataToAssetPrice(marketData);\n }\n } catch (error) {\n log('Failed to fetch prices', { error });\n }\n\n return response;\n }\n\n // ============================================================================\n // SUBSCRIBE\n // ============================================================================\n\n /**\n * Subscribe to price updates.\n * Sets up polling that fetches prices for all assets in assetsBalance state.\n *\n * @param subscriptionRequest - The subscription request configuration.\n */\n async subscribe(subscriptionRequest: SubscriptionRequest): Promise<void> {\n const { request, subscriptionId, isUpdate } = subscriptionRequest;\n\n // Handle subscription update - just update the request\n if (isUpdate) {\n const existing = this.#activeSubscriptions.get(subscriptionId);\n if (existing) {\n existing.request = request;\n return;\n }\n }\n\n // Clean up existing subscription\n await this.unsubscribe(subscriptionId);\n\n const pollInterval = request.updateInterval ?? this.#pollInterval;\n\n // Create poll function - fetches prices for all assets in balance state\n const pollFn = async (): Promise<void> => {\n try {\n const subscription = this.#activeSubscriptions.get(subscriptionId);\n if (!subscription) {\n return;\n }\n\n // Fetch prices for all assets currently in balance state\n const fetchResponse = await this.fetch(subscription.request);\n\n // Only report if we got prices\n if (\n fetchResponse.assetsPrice &&\n Object.keys(fetchResponse.assetsPrice).length > 0\n ) {\n await this.#messenger.call(\n 'AssetsController:assetsUpdate',\n fetchResponse,\n CONTROLLER_NAME,\n );\n }\n } catch (error) {\n log('Subscription poll failed', { subscriptionId, error });\n }\n };\n\n // Set up polling\n const timer = setInterval(() => {\n pollFn().catch(console.error);\n }, pollInterval);\n\n // Store subscription\n this.#activeSubscriptions.set(subscriptionId, {\n cleanup: () => {\n clearInterval(timer);\n },\n request,\n });\n\n // Initial fetch\n await pollFn();\n }\n\n /**\n * Unsubscribe from price updates.\n *\n * @param subscriptionId - The ID of the subscription to cancel.\n */\n async unsubscribe(subscriptionId: string): Promise<void> {\n const subscription = this.#activeSubscriptions.get(subscriptionId);\n if (subscription) {\n subscription.cleanup();\n this.#activeSubscriptions.delete(subscriptionId);\n }\n }\n\n /**\n * Destroy the data source and clean up all subscriptions.\n */\n destroy(): void {\n for (const subscription of this.#activeSubscriptions.values()) {\n subscription.cleanup();\n }\n this.#activeSubscriptions.clear();\n }\n}\n"]}
@@ -0,0 +1,153 @@
1
+ import type { SupportedCurrency } from "@metamask/core-backend";
2
+ import { ApiPlatformClient } from "@metamask/core-backend";
3
+ import type { Messenger } from "@metamask/messenger";
4
+ import type { SubscriptionRequest } from "./AbstractDataSource.cjs";
5
+ import type { Caip19AssetId, AssetBalance, AccountId, DataRequest, DataResponse, Middleware } from "../types.cjs";
6
+ declare const CONTROLLER_NAME = "PriceDataSource";
7
+ /**
8
+ * Action to get balance state (used to determine which assets need prices).
9
+ */
10
+ type GetAssetsBalanceStateAction = {
11
+ type: 'AssetsController:getState';
12
+ handler: () => {
13
+ assetsBalance: Record<AccountId, Record<Caip19AssetId, AssetBalance>>;
14
+ };
15
+ };
16
+ /**
17
+ * Action to get the PriceDataSource middleware.
18
+ */
19
+ export type PriceDataSourceGetAssetsMiddlewareAction = {
20
+ type: `${typeof CONTROLLER_NAME}:getAssetsMiddleware`;
21
+ handler: () => Middleware;
22
+ };
23
+ /**
24
+ * Action to fetch prices for assets.
25
+ */
26
+ export type PriceDataSourceFetchAction = {
27
+ type: `${typeof CONTROLLER_NAME}:fetch`;
28
+ handler: (request: DataRequest) => Promise<DataResponse>;
29
+ };
30
+ /**
31
+ * Action to subscribe to price updates.
32
+ */
33
+ export type PriceDataSourceSubscribeAction = {
34
+ type: `${typeof CONTROLLER_NAME}:subscribe`;
35
+ handler: (request: SubscriptionRequest) => Promise<void>;
36
+ };
37
+ /**
38
+ * Action to unsubscribe from price updates.
39
+ */
40
+ export type PriceDataSourceUnsubscribeAction = {
41
+ type: `${typeof CONTROLLER_NAME}:unsubscribe`;
42
+ handler: (subscriptionId: string) => Promise<void>;
43
+ };
44
+ /**
45
+ * All actions exposed by PriceDataSource.
46
+ */
47
+ export type PriceDataSourceActions = PriceDataSourceGetAssetsMiddlewareAction | PriceDataSourceFetchAction | PriceDataSourceSubscribeAction | PriceDataSourceUnsubscribeAction;
48
+ /**
49
+ * Event emitted when prices are updated.
50
+ */
51
+ export type PriceDataSourceAssetsUpdatedEvent = {
52
+ type: `${typeof CONTROLLER_NAME}:assetsUpdated`;
53
+ payload: [DataResponse, string];
54
+ };
55
+ /**
56
+ * All events exposed by PriceDataSource.
57
+ */
58
+ export type PriceDataSourceEvents = PriceDataSourceAssetsUpdatedEvent;
59
+ type AssetsControllerAssetsUpdateAction = {
60
+ type: 'AssetsController:assetsUpdate';
61
+ handler: (response: DataResponse, sourceId: string) => Promise<void>;
62
+ };
63
+ /**
64
+ * External actions that PriceDataSource needs to call.
65
+ * Note: Uses ApiPlatformClient directly, so no BackendApiClient actions needed.
66
+ */
67
+ export type PriceDataSourceAllowedActions = GetAssetsBalanceStateAction | AssetsControllerAssetsUpdateAction;
68
+ export type PriceDataSourceMessenger = Messenger<typeof CONTROLLER_NAME, PriceDataSourceAllowedActions | PriceDataSourceActions, PriceDataSourceEvents>;
69
+ export type PriceDataSourceOptions = {
70
+ messenger: PriceDataSourceMessenger;
71
+ /** ApiPlatformClient for API calls with caching */
72
+ queryApiClient: ApiPlatformClient;
73
+ /** Currency to fetch prices in (default: 'usd') */
74
+ currency?: SupportedCurrency;
75
+ /** Polling interval in ms (default: 60000) */
76
+ pollInterval?: number;
77
+ };
78
+ /**
79
+ * PriceDataSource fetches asset prices from the Price API.
80
+ *
81
+ * This data source:
82
+ * - Fetches prices from Price API v3 spot-prices endpoint
83
+ * - Supports one-time fetch and subscription-based polling
84
+ * - In subscribe mode, automatically fetches prices for all assets in assetsBalance state
85
+ * - Publishes price updates via messenger events
86
+ *
87
+ * Usage:
88
+ * ```typescript
89
+ * // Create and initialize (registers messenger actions)
90
+ * const priceDataSource = new PriceDataSource({ messenger });
91
+ *
92
+ * // One-time fetch for specific assets
93
+ * const response = await messenger.call('PriceDataSource:fetch', {
94
+ * customAssets: ['eip155:1/erc20:0x...'],
95
+ * });
96
+ *
97
+ * // Subscribe to price updates (polls all assets in balance state)
98
+ * await messenger.call('PriceDataSource:subscribe', { request, subscriptionId });
99
+ *
100
+ * // Listen for updates
101
+ * messenger.subscribe('PriceDataSource:assetsUpdated', (response) => {
102
+ * // Handle price updates
103
+ * });
104
+ * ```
105
+ */
106
+ export declare class PriceDataSource {
107
+ #private;
108
+ readonly name = "PriceDataSource";
109
+ constructor(options: PriceDataSourceOptions);
110
+ /**
111
+ * Get the middleware for enriching responses with price data.
112
+ *
113
+ * This middleware:
114
+ * 1. Extracts the response from context
115
+ * 2. Fetches prices for detected assets (assets without metadata)
116
+ * 3. Enriches the response with fetched prices
117
+ * 4. Calls next() at the end to continue the middleware chain
118
+ *
119
+ * Note: This middleware ONLY fetches prices for detected assets.
120
+ * For fetching prices for all assets, use the subscription mechanism
121
+ * which polls prices for all assets in the balance state.
122
+ *
123
+ * @returns The middleware function for the assets pipeline.
124
+ */
125
+ get assetsMiddleware(): Middleware;
126
+ /**
127
+ * Fetch prices for assets held by the accounts and chains in the request.
128
+ * Gets asset IDs from balance state, filtered by request.accounts and request.chainIds.
129
+ *
130
+ * @param request - The data request specifying accounts and chains.
131
+ * @returns DataResponse containing asset prices.
132
+ */
133
+ fetch(request: DataRequest): Promise<DataResponse>;
134
+ /**
135
+ * Subscribe to price updates.
136
+ * Sets up polling that fetches prices for all assets in assetsBalance state.
137
+ *
138
+ * @param subscriptionRequest - The subscription request configuration.
139
+ */
140
+ subscribe(subscriptionRequest: SubscriptionRequest): Promise<void>;
141
+ /**
142
+ * Unsubscribe from price updates.
143
+ *
144
+ * @param subscriptionId - The ID of the subscription to cancel.
145
+ */
146
+ unsubscribe(subscriptionId: string): Promise<void>;
147
+ /**
148
+ * Destroy the data source and clean up all subscriptions.
149
+ */
150
+ destroy(): void;
151
+ }
152
+ export {};
153
+ //# sourceMappingURL=PriceDataSource.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PriceDataSource.d.cts","sourceRoot":"","sources":["../../src/data-sources/PriceDataSource.ts"],"names":[],"mappings":"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"}