@metamask-previews/assets-controllers 56.0.0-preview-eeefabb3 → 57.0.0-preview-6c44e568

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -13,6 +13,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13
13
  - Added `fetchHistoricalPricesForAsset` method to `MultichainAssetsRatesController` ([#5639](https://github.com/MetaMask/core/pull/5639))
14
14
  - Added `getSelectedMultichainAccount` action to `multichainAssetsRatesController` ([#5639](https://github.com/MetaMask/core/pull/5639))
15
15
  - Added new state field `historicalPrices` to `MultichainAssetsRatesController` ([#5639](https://github.com/MetaMask/core/pull/5639))
16
+
17
+ ### Changed
18
+
19
+ - **BREAKING:** Bump `@metamask/snaps-controllers` peer dependency from ^9.19.0 to ^11.0.0 ([#5639](https://github.com/MetaMask/core/pull/5639))
20
+ - **BREAKING:** Bump `@metamask/providers` peer dependency from ^18.1.0 to ^21.0.0 ([#5639](https://github.com/MetaMask/core/pull/5639))
21
+ - Bump `@metamask/snaps-utils` from ^8.10.0 to ^9.2.0 ([#5639](https://github.com/MetaMask/core/pull/5639))
22
+
23
+ ## [57.0.0]
24
+
25
+ ### Added
26
+
16
27
  - Add a new `DeFiPositionsController` that maintains an updated list of DeFi positions for EVM accounts ([#5400](https://github.com/MetaMask/core/pull/5400))
17
28
  - Export `DeFiPositionsController`
18
29
  - Export the following types
@@ -26,10 +37,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
26
37
 
27
38
  ### Changed
28
39
 
29
- - Bump `@metamask/snaps-sdk` from ^6.17.1 to ^6.22.0 ([#5639](https://github.com/MetaMask/core/pull/5639))
30
- - Bump `@metamask/snaps-utils` from ^8.10.0 to ^9.2.0 ([#5639](https://github.com/MetaMask/core/pull/5639))
31
- - Bump `@metamask/snaps-controllers` peer dependency from ^9.19.0 to ^11.2.1 ([#5639](https://github.com/MetaMask/core/pull/5639))
32
- - Bump `@metamask/providers` from ^18.1.1 to ^21.0.0 ([#5639](https://github.com/MetaMask/core/pull/5639))
33
40
  - **BREAKING** Add `@metamask/transaction-controller` as a peer dependency at `^54.0.0` ([#5400](https://github.com/MetaMask/core/pull/5400))
34
41
 
35
42
  ## [56.0.0]
@@ -1545,7 +1552,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1545
1552
 
1546
1553
  - Use Ethers for AssetsContractController ([#845](https://github.com/MetaMask/core/pull/845))
1547
1554
 
1548
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@56.0.0...HEAD
1555
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@57.0.0...HEAD
1556
+ [57.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@56.0.0...@metamask/assets-controllers@57.0.0
1549
1557
  [56.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@55.0.1...@metamask/assets-controllers@56.0.0
1550
1558
  [55.0.1]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@55.0.0...@metamask/assets-controllers@55.0.1
1551
1559
  [55.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@54.0.0...@metamask/assets-controllers@55.0.0
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-positions.cjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":";;;AAwDA,gDAAgD;AACnC,QAAA,sBAAsB,GACjC,6CAA6C,CAAC;AAEhD;;;;GAIG;AACH,SAAgB,oBAAoB;IAClC,OAAO,KAAK,EAAE,cAAsB,EAAmC,EAAE;QACvE,MAAM,qBAAqB,GAAG,MAAM,KAAK,CACvC,GAAG,8BAAsB,cAAc,cAAc,EAAE,CACxD,CAAC;QAEF,IAAI,qBAAqB,CAAC,MAAM,KAAK,GAAG,EAAE;YACxC,MAAM,IAAI,KAAK,CACb,yCAAyC,qBAAqB,CAAC,MAAM,EAAE,CACxE,CAAC;SACH;QAED,OAAO,CAAC,MAAM,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACnD,CAAC,CAAC;AACJ,CAAC;AAdD,oDAcC","sourcesContent":["export type DefiPositionResponse = AdapterResponse<{\n tokens: ProtocolToken[];\n}>;\n\ntype ProtocolDetails = {\n chainId: number;\n protocolId: string;\n productId: string;\n name: string;\n description: string;\n iconUrl: string;\n siteUrl: string;\n positionType: PositionType;\n metadata?: {\n groupPositions?: boolean;\n };\n};\n\ntype AdapterResponse<ProtocolResponse> =\n | (ProtocolDetails & {\n chainName: string;\n } & (\n | (ProtocolResponse & { success: true })\n | (AdapterErrorResponse & { success: false })\n ))\n | (AdapterErrorResponse & { success: false });\n\ntype AdapterErrorResponse = {\n error: {\n message: string;\n };\n};\n\nexport type PositionType = 'supply' | 'borrow' | 'stake' | 'reward';\n\nexport type ProtocolToken = Balance & {\n type: 'protocol';\n tokenId?: string;\n};\n\nexport type Underlying = Balance & {\n type: 'underlying' | 'underlying-claimable';\n iconUrl: string;\n};\n\nexport type Balance = {\n address: string;\n name: string;\n symbol: string;\n decimals: number;\n balanceRaw: string;\n balance: number;\n price?: number;\n tokens?: Underlying[];\n};\n\n// TODO: Update with prod API URL when available\nexport const DEFI_POSITIONS_API_URL =\n 'https://defiadapters.dev-api.cx.metamask.io';\n\n/**\n * Builds a function that fetches DeFi positions for a given account address\n *\n * @returns A function that fetches DeFi positions for a given account address\n */\nexport function buildPositionFetcher() {\n return async (accountAddress: string): Promise<DefiPositionResponse[]> => {\n const defiPositionsResponse = await fetch(\n `${DEFI_POSITIONS_API_URL}/positions/${accountAddress}`,\n );\n\n if (defiPositionsResponse.status !== 200) {\n throw new Error(\n `Unable to fetch defi positions - HTTP ${defiPositionsResponse.status}`,\n );\n }\n\n return (await defiPositionsResponse.json()).data;\n };\n}\n"]}
1
+ {"version":3,"file":"fetch-positions.cjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":";;;AAyDA,gDAAgD;AACnC,QAAA,sBAAsB,GACjC,6CAA6C,CAAC;AAEhD;;;;GAIG;AACH,SAAgB,oBAAoB;IAClC,OAAO,KAAK,EAAE,cAAsB,EAAmC,EAAE;QACvE,MAAM,qBAAqB,GAAG,MAAM,KAAK,CACvC,GAAG,8BAAsB,cAAc,cAAc,EAAE,CACxD,CAAC;QAEF,IAAI,qBAAqB,CAAC,MAAM,KAAK,GAAG,EAAE;YACxC,MAAM,IAAI,KAAK,CACb,yCAAyC,qBAAqB,CAAC,MAAM,EAAE,CACxE,CAAC;SACH;QAED,OAAO,CAAC,MAAM,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACnD,CAAC,CAAC;AACJ,CAAC;AAdD,oDAcC","sourcesContent":["export type DefiPositionResponse = AdapterResponse<{\n tokens: ProtocolToken[];\n}>;\n\ntype ProtocolDetails = {\n chainId: number;\n protocolId: string;\n productId: string;\n protocolDisplayName: string;\n name: string;\n description: string;\n iconUrl: string;\n siteUrl: string;\n positionType: PositionType;\n metadata?: {\n groupPositions?: boolean;\n };\n};\n\ntype AdapterResponse<ProtocolResponse> =\n | (ProtocolDetails & {\n chainName: string;\n } & (\n | (ProtocolResponse & { success: true })\n | (AdapterErrorResponse & { success: false })\n ))\n | (AdapterErrorResponse & { success: false });\n\ntype AdapterErrorResponse = {\n error: {\n message: string;\n };\n};\n\nexport type PositionType = 'supply' | 'borrow' | 'stake' | 'reward';\n\nexport type ProtocolToken = Balance & {\n type: 'protocol';\n tokenId?: string;\n};\n\nexport type Underlying = Balance & {\n type: 'underlying' | 'underlying-claimable';\n iconUrl: string;\n};\n\nexport type Balance = {\n address: string;\n name: string;\n symbol: string;\n decimals: number;\n balanceRaw: string;\n balance: number;\n price?: number;\n tokens?: Underlying[];\n};\n\n// TODO: Update with prod API URL when available\nexport const DEFI_POSITIONS_API_URL =\n 'https://defiadapters.dev-api.cx.metamask.io';\n\n/**\n * Builds a function that fetches DeFi positions for a given account address\n *\n * @returns A function that fetches DeFi positions for a given account address\n */\nexport function buildPositionFetcher() {\n return async (accountAddress: string): Promise<DefiPositionResponse[]> => {\n const defiPositionsResponse = await fetch(\n `${DEFI_POSITIONS_API_URL}/positions/${accountAddress}`,\n );\n\n if (defiPositionsResponse.status !== 200) {\n throw new Error(\n `Unable to fetch defi positions - HTTP ${defiPositionsResponse.status}`,\n );\n }\n\n return (await defiPositionsResponse.json()).data;\n };\n}\n"]}
@@ -5,6 +5,7 @@ type ProtocolDetails = {
5
5
  chainId: number;
6
6
  protocolId: string;
7
7
  productId: string;
8
+ protocolDisplayName: string;
8
9
  name: string;
9
10
  description: string;
10
11
  iconUrl: string;
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-positions.d.cts","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG,eAAe,CAAC;IACjD,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,CAAC,gBAAgB,IACjC,CAAC,eAAe,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,CACE,CAAC,gBAAgB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC,GACtC,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAC9C,CAAC,GACJ,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAEhD,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG;IACjC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB,CAAC;AAGF,eAAO,MAAM,sBAAsB,gDACY,CAAC;AAEhD;;;;GAIG;AACH,wBAAgB,oBAAoB,qBACJ,MAAM,KAAG,QAAQ,oBAAoB,EAAE,CAAC,CAavE"}
1
+ {"version":3,"file":"fetch-positions.d.cts","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG,eAAe,CAAC;IACjD,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,CAAC,gBAAgB,IACjC,CAAC,eAAe,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,CACE,CAAC,gBAAgB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC,GACtC,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAC9C,CAAC,GACJ,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAEhD,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG;IACjC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB,CAAC;AAGF,eAAO,MAAM,sBAAsB,gDACY,CAAC;AAEhD;;;;GAIG;AACH,wBAAgB,oBAAoB,qBACJ,MAAM,KAAG,QAAQ,oBAAoB,EAAE,CAAC,CAavE"}
@@ -5,6 +5,7 @@ type ProtocolDetails = {
5
5
  chainId: number;
6
6
  protocolId: string;
7
7
  productId: string;
8
+ protocolDisplayName: string;
8
9
  name: string;
9
10
  description: string;
10
11
  iconUrl: string;
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-positions.d.mts","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG,eAAe,CAAC;IACjD,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,CAAC,gBAAgB,IACjC,CAAC,eAAe,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,CACE,CAAC,gBAAgB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC,GACtC,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAC9C,CAAC,GACJ,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAEhD,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG;IACjC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB,CAAC;AAGF,eAAO,MAAM,sBAAsB,gDACY,CAAC;AAEhD;;;;GAIG;AACH,wBAAgB,oBAAoB,qBACJ,MAAM,KAAG,QAAQ,oBAAoB,EAAE,CAAC,CAavE"}
1
+ {"version":3,"file":"fetch-positions.d.mts","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG,eAAe,CAAC;IACjD,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,CAAC,gBAAgB,IACjC,CAAC,eAAe,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,CACE,CAAC,gBAAgB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC,GACtC,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAC9C,CAAC,GACJ,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAEhD,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG;IACjC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB,CAAC;AAGF,eAAO,MAAM,sBAAsB,gDACY,CAAC;AAEhD;;;;GAIG;AACH,wBAAgB,oBAAoB,qBACJ,MAAM,KAAG,QAAQ,oBAAoB,EAAE,CAAC,CAavE"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-positions.mjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAwDA,gDAAgD;AAChD,MAAM,CAAC,MAAM,sBAAsB,GACjC,6CAA6C,CAAC;AAEhD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,KAAK,EAAE,cAAsB,EAAmC,EAAE;QACvE,MAAM,qBAAqB,GAAG,MAAM,KAAK,CACvC,GAAG,sBAAsB,cAAc,cAAc,EAAE,CACxD,CAAC;QAEF,IAAI,qBAAqB,CAAC,MAAM,KAAK,GAAG,EAAE;YACxC,MAAM,IAAI,KAAK,CACb,yCAAyC,qBAAqB,CAAC,MAAM,EAAE,CACxE,CAAC;SACH;QAED,OAAO,CAAC,MAAM,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACnD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["export type DefiPositionResponse = AdapterResponse<{\n tokens: ProtocolToken[];\n}>;\n\ntype ProtocolDetails = {\n chainId: number;\n protocolId: string;\n productId: string;\n name: string;\n description: string;\n iconUrl: string;\n siteUrl: string;\n positionType: PositionType;\n metadata?: {\n groupPositions?: boolean;\n };\n};\n\ntype AdapterResponse<ProtocolResponse> =\n | (ProtocolDetails & {\n chainName: string;\n } & (\n | (ProtocolResponse & { success: true })\n | (AdapterErrorResponse & { success: false })\n ))\n | (AdapterErrorResponse & { success: false });\n\ntype AdapterErrorResponse = {\n error: {\n message: string;\n };\n};\n\nexport type PositionType = 'supply' | 'borrow' | 'stake' | 'reward';\n\nexport type ProtocolToken = Balance & {\n type: 'protocol';\n tokenId?: string;\n};\n\nexport type Underlying = Balance & {\n type: 'underlying' | 'underlying-claimable';\n iconUrl: string;\n};\n\nexport type Balance = {\n address: string;\n name: string;\n symbol: string;\n decimals: number;\n balanceRaw: string;\n balance: number;\n price?: number;\n tokens?: Underlying[];\n};\n\n// TODO: Update with prod API URL when available\nexport const DEFI_POSITIONS_API_URL =\n 'https://defiadapters.dev-api.cx.metamask.io';\n\n/**\n * Builds a function that fetches DeFi positions for a given account address\n *\n * @returns A function that fetches DeFi positions for a given account address\n */\nexport function buildPositionFetcher() {\n return async (accountAddress: string): Promise<DefiPositionResponse[]> => {\n const defiPositionsResponse = await fetch(\n `${DEFI_POSITIONS_API_URL}/positions/${accountAddress}`,\n );\n\n if (defiPositionsResponse.status !== 200) {\n throw new Error(\n `Unable to fetch defi positions - HTTP ${defiPositionsResponse.status}`,\n );\n }\n\n return (await defiPositionsResponse.json()).data;\n };\n}\n"]}
1
+ {"version":3,"file":"fetch-positions.mjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAyDA,gDAAgD;AAChD,MAAM,CAAC,MAAM,sBAAsB,GACjC,6CAA6C,CAAC;AAEhD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,KAAK,EAAE,cAAsB,EAAmC,EAAE;QACvE,MAAM,qBAAqB,GAAG,MAAM,KAAK,CACvC,GAAG,sBAAsB,cAAc,cAAc,EAAE,CACxD,CAAC;QAEF,IAAI,qBAAqB,CAAC,MAAM,KAAK,GAAG,EAAE;YACxC,MAAM,IAAI,KAAK,CACb,yCAAyC,qBAAqB,CAAC,MAAM,EAAE,CACxE,CAAC;SACH;QAED,OAAO,CAAC,MAAM,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACnD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["export type DefiPositionResponse = AdapterResponse<{\n tokens: ProtocolToken[];\n}>;\n\ntype ProtocolDetails = {\n chainId: number;\n protocolId: string;\n productId: string;\n protocolDisplayName: string;\n name: string;\n description: string;\n iconUrl: string;\n siteUrl: string;\n positionType: PositionType;\n metadata?: {\n groupPositions?: boolean;\n };\n};\n\ntype AdapterResponse<ProtocolResponse> =\n | (ProtocolDetails & {\n chainName: string;\n } & (\n | (ProtocolResponse & { success: true })\n | (AdapterErrorResponse & { success: false })\n ))\n | (AdapterErrorResponse & { success: false });\n\ntype AdapterErrorResponse = {\n error: {\n message: string;\n };\n};\n\nexport type PositionType = 'supply' | 'borrow' | 'stake' | 'reward';\n\nexport type ProtocolToken = Balance & {\n type: 'protocol';\n tokenId?: string;\n};\n\nexport type Underlying = Balance & {\n type: 'underlying' | 'underlying-claimable';\n iconUrl: string;\n};\n\nexport type Balance = {\n address: string;\n name: string;\n symbol: string;\n decimals: number;\n balanceRaw: string;\n balance: number;\n price?: number;\n tokens?: Underlying[];\n};\n\n// TODO: Update with prod API URL when available\nexport const DEFI_POSITIONS_API_URL =\n 'https://defiadapters.dev-api.cx.metamask.io';\n\n/**\n * Builds a function that fetches DeFi positions for a given account address\n *\n * @returns A function that fetches DeFi positions for a given account address\n */\nexport function buildPositionFetcher() {\n return async (accountAddress: string): Promise<DefiPositionResponse[]> => {\n const defiPositionsResponse = await fetch(\n `${DEFI_POSITIONS_API_URL}/positions/${accountAddress}`,\n );\n\n if (defiPositionsResponse.status !== 200) {\n throw new Error(\n `Unable to fetch defi positions - HTTP ${defiPositionsResponse.status}`,\n );\n }\n\n return (await defiPositionsResponse.json()).data;\n };\n}\n"]}
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.groupDeFiPositions = void 0;
4
4
  const controller_utils_1 = require("@metamask/controller-utils");
5
- const lodash_1 = require("lodash");
6
5
  /**
7
6
  *
8
7
  * @param defiPositionsResponse - The response from the defi positions API
@@ -14,7 +13,7 @@ function groupDeFiPositions(defiPositionsResponse) {
14
13
  if (!position.success) {
15
14
  continue;
16
15
  }
17
- const { chainId, protocolId, iconUrl, positionType } = position;
16
+ const { chainId, protocolId, iconUrl, positionType, protocolDisplayName } = position;
18
17
  const chain = (0, controller_utils_1.toHex)(chainId);
19
18
  if (!groupedDeFiPositions[chain]) {
20
19
  groupedDeFiPositions[chain] = {
@@ -26,7 +25,7 @@ function groupDeFiPositions(defiPositionsResponse) {
26
25
  if (!chainData.protocols[protocolId]) {
27
26
  chainData.protocols[protocolId] = {
28
27
  protocolDetails: {
29
- name: (0, lodash_1.upperFirst)((0, lodash_1.camelCase)(protocolId)),
28
+ name: protocolDisplayName,
30
29
  iconUrl,
31
30
  },
32
31
  aggregatedMarketValue: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"group-defi-positions.cjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/group-defi-positions.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { upperFirst, camelCase } from 'lodash';\n\nimport type {\n DefiPositionResponse,\n PositionType,\n ProtocolToken,\n Underlying,\n Balance,\n} from './fetch-positions';\n\nexport type GroupedDeFiPositions = {\n aggregatedMarketValue: number;\n protocols: {\n [protocolId: string]: {\n protocolDetails: { name: string; iconUrl: string };\n aggregatedMarketValue: number;\n positionTypes: {\n [key in PositionType]?: {\n aggregatedMarketValue: number;\n positions: ProtocolTokenWithMarketValue[][];\n };\n };\n };\n };\n};\n\nexport type ProtocolTokenWithMarketValue = Omit<ProtocolToken, 'tokens'> & {\n marketValue?: number;\n tokens: UnderlyingWithMarketValue[];\n};\n\nexport type UnderlyingWithMarketValue = Omit<Underlying, 'tokens'> & {\n marketValue?: number;\n};\n\n/**\n *\n * @param defiPositionsResponse - The response from the defi positions API\n * @returns The grouped positions that get assigned to the state\n */\nexport function groupDeFiPositions(\n defiPositionsResponse: DefiPositionResponse[],\n): {\n [key: Hex]: GroupedDeFiPositions;\n} {\n const groupedDeFiPositions: { [key: Hex]: GroupedDeFiPositions } = {};\n\n for (const position of defiPositionsResponse) {\n if (!position.success) {\n continue;\n }\n\n const { chainId, protocolId, iconUrl, positionType } = position;\n\n const chain = toHex(chainId);\n\n if (!groupedDeFiPositions[chain]) {\n groupedDeFiPositions[chain] = {\n aggregatedMarketValue: 0,\n protocols: {},\n };\n }\n\n const chainData = groupedDeFiPositions[chain];\n\n if (!chainData.protocols[protocolId]) {\n chainData.protocols[protocolId] = {\n protocolDetails: {\n name: upperFirst(camelCase(protocolId)),\n iconUrl,\n },\n aggregatedMarketValue: 0,\n positionTypes: {},\n };\n }\n\n const protocolData = chainData.protocols[protocolId];\n\n let positionTypeData = protocolData.positionTypes[positionType];\n if (!positionTypeData) {\n positionTypeData = {\n aggregatedMarketValue: 0,\n positions: [],\n };\n protocolData.positionTypes[positionType] = positionTypeData;\n }\n\n for (const protocolToken of position.tokens) {\n const token = processToken(protocolToken) as ProtocolTokenWithMarketValue;\n\n // If groupPositions is true, we group all positions of the same type\n if (position.metadata?.groupPositions) {\n if (positionTypeData.positions.length === 0) {\n positionTypeData.positions.push([token]);\n } else {\n positionTypeData.positions[0].push(token);\n }\n } else {\n positionTypeData.positions.push([token]);\n }\n\n if (token.marketValue) {\n const multiplier = position.positionType === 'borrow' ? -1 : 1;\n\n positionTypeData.aggregatedMarketValue += token.marketValue;\n protocolData.aggregatedMarketValue += token.marketValue * multiplier;\n chainData.aggregatedMarketValue += token.marketValue * multiplier;\n }\n }\n }\n\n return groupedDeFiPositions;\n}\n\n/**\n *\n * @param tokenBalance - The token balance that is going to be processed\n * @returns The processed token balance\n */\nfunction processToken<T extends Balance>(\n tokenBalance: T,\n): T & {\n marketValue?: number;\n tokens?: UnderlyingWithMarketValue[];\n} {\n if (!tokenBalance.tokens) {\n return {\n ...tokenBalance,\n marketValue: tokenBalance.price\n ? tokenBalance.balance * tokenBalance.price\n : undefined,\n };\n }\n\n const processedTokens = tokenBalance.tokens.map((t) => {\n const { tokens, ...tokenWithoutUnderlyings } = processToken(t);\n\n return tokenWithoutUnderlyings;\n });\n\n const marketValue = processedTokens.reduce(\n (acc, t) =>\n acc === undefined || t.marketValue === undefined\n ? undefined\n : acc + t.marketValue,\n 0 as number | undefined,\n );\n\n return {\n ...tokenBalance,\n marketValue,\n tokens: processedTokens,\n };\n}\n"]}
1
+ {"version":3,"file":"group-defi-positions.cjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/group-defi-positions.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\n\nimport type {\n DefiPositionResponse,\n PositionType,\n ProtocolToken,\n Underlying,\n Balance,\n} from './fetch-positions';\n\nexport type GroupedDeFiPositions = {\n aggregatedMarketValue: number;\n protocols: {\n [protocolId: string]: {\n protocolDetails: { name: string; iconUrl: string };\n aggregatedMarketValue: number;\n positionTypes: {\n [key in PositionType]?: {\n aggregatedMarketValue: number;\n positions: ProtocolTokenWithMarketValue[][];\n };\n };\n };\n };\n};\n\nexport type ProtocolTokenWithMarketValue = Omit<ProtocolToken, 'tokens'> & {\n marketValue?: number;\n tokens: UnderlyingWithMarketValue[];\n};\n\nexport type UnderlyingWithMarketValue = Omit<Underlying, 'tokens'> & {\n marketValue?: number;\n};\n\n/**\n *\n * @param defiPositionsResponse - The response from the defi positions API\n * @returns The grouped positions that get assigned to the state\n */\nexport function groupDeFiPositions(\n defiPositionsResponse: DefiPositionResponse[],\n): {\n [key: Hex]: GroupedDeFiPositions;\n} {\n const groupedDeFiPositions: { [key: Hex]: GroupedDeFiPositions } = {};\n\n for (const position of defiPositionsResponse) {\n if (!position.success) {\n continue;\n }\n\n const { chainId, protocolId, iconUrl, positionType, protocolDisplayName } =\n position;\n\n const chain = toHex(chainId);\n\n if (!groupedDeFiPositions[chain]) {\n groupedDeFiPositions[chain] = {\n aggregatedMarketValue: 0,\n protocols: {},\n };\n }\n\n const chainData = groupedDeFiPositions[chain];\n\n if (!chainData.protocols[protocolId]) {\n chainData.protocols[protocolId] = {\n protocolDetails: {\n name: protocolDisplayName,\n iconUrl,\n },\n aggregatedMarketValue: 0,\n positionTypes: {},\n };\n }\n\n const protocolData = chainData.protocols[protocolId];\n\n let positionTypeData = protocolData.positionTypes[positionType];\n if (!positionTypeData) {\n positionTypeData = {\n aggregatedMarketValue: 0,\n positions: [],\n };\n protocolData.positionTypes[positionType] = positionTypeData;\n }\n\n for (const protocolToken of position.tokens) {\n const token = processToken(protocolToken) as ProtocolTokenWithMarketValue;\n\n // If groupPositions is true, we group all positions of the same type\n if (position.metadata?.groupPositions) {\n if (positionTypeData.positions.length === 0) {\n positionTypeData.positions.push([token]);\n } else {\n positionTypeData.positions[0].push(token);\n }\n } else {\n positionTypeData.positions.push([token]);\n }\n\n if (token.marketValue) {\n const multiplier = position.positionType === 'borrow' ? -1 : 1;\n\n positionTypeData.aggregatedMarketValue += token.marketValue;\n protocolData.aggregatedMarketValue += token.marketValue * multiplier;\n chainData.aggregatedMarketValue += token.marketValue * multiplier;\n }\n }\n }\n\n return groupedDeFiPositions;\n}\n\n/**\n *\n * @param tokenBalance - The token balance that is going to be processed\n * @returns The processed token balance\n */\nfunction processToken<T extends Balance>(\n tokenBalance: T,\n): T & {\n marketValue?: number;\n tokens?: UnderlyingWithMarketValue[];\n} {\n if (!tokenBalance.tokens) {\n return {\n ...tokenBalance,\n marketValue: tokenBalance.price\n ? tokenBalance.balance * tokenBalance.price\n : undefined,\n };\n }\n\n const processedTokens = tokenBalance.tokens.map((t) => {\n const { tokens, ...tokenWithoutUnderlyings } = processToken(t);\n\n return tokenWithoutUnderlyings;\n });\n\n const marketValue = processedTokens.reduce(\n (acc, t) =>\n acc === undefined || t.marketValue === undefined\n ? undefined\n : acc + t.marketValue,\n 0 as number | undefined,\n );\n\n return {\n ...tokenBalance,\n marketValue,\n tokens: processedTokens,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"group-defi-positions.d.cts","sourceRoot":"","sources":["../../src/DeFiPositionsController/group-defi-positions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EACV,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,UAAU,EAEX,8BAA0B;AAE3B,MAAM,MAAM,oBAAoB,GAAG;IACjC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE;QACT,CAAC,UAAU,EAAE,MAAM,GAAG;YACpB,eAAe,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC;YACnD,qBAAqB,EAAE,MAAM,CAAC;YAC9B,aAAa,EAAE;iBACZ,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE;oBACtB,qBAAqB,EAAE,MAAM,CAAC;oBAC9B,SAAS,EAAE,4BAA4B,EAAE,EAAE,CAAC;iBAC7C;aACF,CAAC;SACH,CAAC;KACH,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,GAAG;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,yBAAyB,EAAE,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,qBAAqB,EAAE,oBAAoB,EAAE,GAC5C;IACD,CAAC,GAAG,EAAE,GAAG,GAAG,oBAAoB,CAAC;CAClC,CAoEA"}
1
+ {"version":3,"file":"group-defi-positions.d.cts","sourceRoot":"","sources":["../../src/DeFiPositionsController/group-defi-positions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAE3C,OAAO,KAAK,EACV,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,UAAU,EAEX,8BAA0B;AAE3B,MAAM,MAAM,oBAAoB,GAAG;IACjC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE;QACT,CAAC,UAAU,EAAE,MAAM,GAAG;YACpB,eAAe,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC;YACnD,qBAAqB,EAAE,MAAM,CAAC;YAC9B,aAAa,EAAE;iBACZ,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE;oBACtB,qBAAqB,EAAE,MAAM,CAAC;oBAC9B,SAAS,EAAE,4BAA4B,EAAE,EAAE,CAAC;iBAC7C;aACF,CAAC;SACH,CAAC;KACH,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,GAAG;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,yBAAyB,EAAE,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,qBAAqB,EAAE,oBAAoB,EAAE,GAC5C;IACD,CAAC,GAAG,EAAE,GAAG,GAAG,oBAAoB,CAAC;CAClC,CAqEA"}
@@ -1 +1 @@
1
- {"version":3,"file":"group-defi-positions.d.mts","sourceRoot":"","sources":["../../src/DeFiPositionsController/group-defi-positions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAG3C,OAAO,KAAK,EACV,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,UAAU,EAEX,8BAA0B;AAE3B,MAAM,MAAM,oBAAoB,GAAG;IACjC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE;QACT,CAAC,UAAU,EAAE,MAAM,GAAG;YACpB,eAAe,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC;YACnD,qBAAqB,EAAE,MAAM,CAAC;YAC9B,aAAa,EAAE;iBACZ,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE;oBACtB,qBAAqB,EAAE,MAAM,CAAC;oBAC9B,SAAS,EAAE,4BAA4B,EAAE,EAAE,CAAC;iBAC7C;aACF,CAAC;SACH,CAAC;KACH,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,GAAG;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,yBAAyB,EAAE,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,qBAAqB,EAAE,oBAAoB,EAAE,GAC5C;IACD,CAAC,GAAG,EAAE,GAAG,GAAG,oBAAoB,CAAC;CAClC,CAoEA"}
1
+ {"version":3,"file":"group-defi-positions.d.mts","sourceRoot":"","sources":["../../src/DeFiPositionsController/group-defi-positions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAE3C,OAAO,KAAK,EACV,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,UAAU,EAEX,8BAA0B;AAE3B,MAAM,MAAM,oBAAoB,GAAG;IACjC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE;QACT,CAAC,UAAU,EAAE,MAAM,GAAG;YACpB,eAAe,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC;YACnD,qBAAqB,EAAE,MAAM,CAAC;YAC9B,aAAa,EAAE;iBACZ,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE;oBACtB,qBAAqB,EAAE,MAAM,CAAC;oBAC9B,SAAS,EAAE,4BAA4B,EAAE,EAAE,CAAC;iBAC7C;aACF,CAAC;SACH,CAAC;KACH,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,GAAG;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,yBAAyB,EAAE,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,qBAAqB,EAAE,oBAAoB,EAAE,GAC5C;IACD,CAAC,GAAG,EAAE,GAAG,GAAG,oBAAoB,CAAC;CAClC,CAqEA"}
@@ -1,6 +1,4 @@
1
1
  import { toHex } from "@metamask/controller-utils";
2
- import $lodash from "lodash";
3
- const { upperFirst, camelCase } = $lodash;
4
2
  /**
5
3
  *
6
4
  * @param defiPositionsResponse - The response from the defi positions API
@@ -12,7 +10,7 @@ export function groupDeFiPositions(defiPositionsResponse) {
12
10
  if (!position.success) {
13
11
  continue;
14
12
  }
15
- const { chainId, protocolId, iconUrl, positionType } = position;
13
+ const { chainId, protocolId, iconUrl, positionType, protocolDisplayName } = position;
16
14
  const chain = toHex(chainId);
17
15
  if (!groupedDeFiPositions[chain]) {
18
16
  groupedDeFiPositions[chain] = {
@@ -24,7 +22,7 @@ export function groupDeFiPositions(defiPositionsResponse) {
24
22
  if (!chainData.protocols[protocolId]) {
25
23
  chainData.protocols[protocolId] = {
26
24
  protocolDetails: {
27
- name: upperFirst(camelCase(protocolId)),
25
+ name: protocolDisplayName,
28
26
  iconUrl,
29
27
  },
30
28
  aggregatedMarketValue: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"group-defi-positions.mjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/group-defi-positions.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { upperFirst, camelCase } from 'lodash';\n\nimport type {\n DefiPositionResponse,\n PositionType,\n ProtocolToken,\n Underlying,\n Balance,\n} from './fetch-positions';\n\nexport type GroupedDeFiPositions = {\n aggregatedMarketValue: number;\n protocols: {\n [protocolId: string]: {\n protocolDetails: { name: string; iconUrl: string };\n aggregatedMarketValue: number;\n positionTypes: {\n [key in PositionType]?: {\n aggregatedMarketValue: number;\n positions: ProtocolTokenWithMarketValue[][];\n };\n };\n };\n };\n};\n\nexport type ProtocolTokenWithMarketValue = Omit<ProtocolToken, 'tokens'> & {\n marketValue?: number;\n tokens: UnderlyingWithMarketValue[];\n};\n\nexport type UnderlyingWithMarketValue = Omit<Underlying, 'tokens'> & {\n marketValue?: number;\n};\n\n/**\n *\n * @param defiPositionsResponse - The response from the defi positions API\n * @returns The grouped positions that get assigned to the state\n */\nexport function groupDeFiPositions(\n defiPositionsResponse: DefiPositionResponse[],\n): {\n [key: Hex]: GroupedDeFiPositions;\n} {\n const groupedDeFiPositions: { [key: Hex]: GroupedDeFiPositions } = {};\n\n for (const position of defiPositionsResponse) {\n if (!position.success) {\n continue;\n }\n\n const { chainId, protocolId, iconUrl, positionType } = position;\n\n const chain = toHex(chainId);\n\n if (!groupedDeFiPositions[chain]) {\n groupedDeFiPositions[chain] = {\n aggregatedMarketValue: 0,\n protocols: {},\n };\n }\n\n const chainData = groupedDeFiPositions[chain];\n\n if (!chainData.protocols[protocolId]) {\n chainData.protocols[protocolId] = {\n protocolDetails: {\n name: upperFirst(camelCase(protocolId)),\n iconUrl,\n },\n aggregatedMarketValue: 0,\n positionTypes: {},\n };\n }\n\n const protocolData = chainData.protocols[protocolId];\n\n let positionTypeData = protocolData.positionTypes[positionType];\n if (!positionTypeData) {\n positionTypeData = {\n aggregatedMarketValue: 0,\n positions: [],\n };\n protocolData.positionTypes[positionType] = positionTypeData;\n }\n\n for (const protocolToken of position.tokens) {\n const token = processToken(protocolToken) as ProtocolTokenWithMarketValue;\n\n // If groupPositions is true, we group all positions of the same type\n if (position.metadata?.groupPositions) {\n if (positionTypeData.positions.length === 0) {\n positionTypeData.positions.push([token]);\n } else {\n positionTypeData.positions[0].push(token);\n }\n } else {\n positionTypeData.positions.push([token]);\n }\n\n if (token.marketValue) {\n const multiplier = position.positionType === 'borrow' ? -1 : 1;\n\n positionTypeData.aggregatedMarketValue += token.marketValue;\n protocolData.aggregatedMarketValue += token.marketValue * multiplier;\n chainData.aggregatedMarketValue += token.marketValue * multiplier;\n }\n }\n }\n\n return groupedDeFiPositions;\n}\n\n/**\n *\n * @param tokenBalance - The token balance that is going to be processed\n * @returns The processed token balance\n */\nfunction processToken<T extends Balance>(\n tokenBalance: T,\n): T & {\n marketValue?: number;\n tokens?: UnderlyingWithMarketValue[];\n} {\n if (!tokenBalance.tokens) {\n return {\n ...tokenBalance,\n marketValue: tokenBalance.price\n ? tokenBalance.balance * tokenBalance.price\n : undefined,\n };\n }\n\n const processedTokens = tokenBalance.tokens.map((t) => {\n const { tokens, ...tokenWithoutUnderlyings } = processToken(t);\n\n return tokenWithoutUnderlyings;\n });\n\n const marketValue = processedTokens.reduce(\n (acc, t) =>\n acc === undefined || t.marketValue === undefined\n ? undefined\n : acc + t.marketValue,\n 0 as number | undefined,\n );\n\n return {\n ...tokenBalance,\n marketValue,\n tokens: processedTokens,\n };\n}\n"]}
1
+ {"version":3,"file":"group-defi-positions.mjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/group-defi-positions.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\n\nimport type {\n DefiPositionResponse,\n PositionType,\n ProtocolToken,\n Underlying,\n Balance,\n} from './fetch-positions';\n\nexport type GroupedDeFiPositions = {\n aggregatedMarketValue: number;\n protocols: {\n [protocolId: string]: {\n protocolDetails: { name: string; iconUrl: string };\n aggregatedMarketValue: number;\n positionTypes: {\n [key in PositionType]?: {\n aggregatedMarketValue: number;\n positions: ProtocolTokenWithMarketValue[][];\n };\n };\n };\n };\n};\n\nexport type ProtocolTokenWithMarketValue = Omit<ProtocolToken, 'tokens'> & {\n marketValue?: number;\n tokens: UnderlyingWithMarketValue[];\n};\n\nexport type UnderlyingWithMarketValue = Omit<Underlying, 'tokens'> & {\n marketValue?: number;\n};\n\n/**\n *\n * @param defiPositionsResponse - The response from the defi positions API\n * @returns The grouped positions that get assigned to the state\n */\nexport function groupDeFiPositions(\n defiPositionsResponse: DefiPositionResponse[],\n): {\n [key: Hex]: GroupedDeFiPositions;\n} {\n const groupedDeFiPositions: { [key: Hex]: GroupedDeFiPositions } = {};\n\n for (const position of defiPositionsResponse) {\n if (!position.success) {\n continue;\n }\n\n const { chainId, protocolId, iconUrl, positionType, protocolDisplayName } =\n position;\n\n const chain = toHex(chainId);\n\n if (!groupedDeFiPositions[chain]) {\n groupedDeFiPositions[chain] = {\n aggregatedMarketValue: 0,\n protocols: {},\n };\n }\n\n const chainData = groupedDeFiPositions[chain];\n\n if (!chainData.protocols[protocolId]) {\n chainData.protocols[protocolId] = {\n protocolDetails: {\n name: protocolDisplayName,\n iconUrl,\n },\n aggregatedMarketValue: 0,\n positionTypes: {},\n };\n }\n\n const protocolData = chainData.protocols[protocolId];\n\n let positionTypeData = protocolData.positionTypes[positionType];\n if (!positionTypeData) {\n positionTypeData = {\n aggregatedMarketValue: 0,\n positions: [],\n };\n protocolData.positionTypes[positionType] = positionTypeData;\n }\n\n for (const protocolToken of position.tokens) {\n const token = processToken(protocolToken) as ProtocolTokenWithMarketValue;\n\n // If groupPositions is true, we group all positions of the same type\n if (position.metadata?.groupPositions) {\n if (positionTypeData.positions.length === 0) {\n positionTypeData.positions.push([token]);\n } else {\n positionTypeData.positions[0].push(token);\n }\n } else {\n positionTypeData.positions.push([token]);\n }\n\n if (token.marketValue) {\n const multiplier = position.positionType === 'borrow' ? -1 : 1;\n\n positionTypeData.aggregatedMarketValue += token.marketValue;\n protocolData.aggregatedMarketValue += token.marketValue * multiplier;\n chainData.aggregatedMarketValue += token.marketValue * multiplier;\n }\n }\n }\n\n return groupedDeFiPositions;\n}\n\n/**\n *\n * @param tokenBalance - The token balance that is going to be processed\n * @returns The processed token balance\n */\nfunction processToken<T extends Balance>(\n tokenBalance: T,\n): T & {\n marketValue?: number;\n tokens?: UnderlyingWithMarketValue[];\n} {\n if (!tokenBalance.tokens) {\n return {\n ...tokenBalance,\n marketValue: tokenBalance.price\n ? tokenBalance.balance * tokenBalance.price\n : undefined,\n };\n }\n\n const processedTokens = tokenBalance.tokens.map((t) => {\n const { tokens, ...tokenWithoutUnderlyings } = processToken(t);\n\n return tokenWithoutUnderlyings;\n });\n\n const marketValue = processedTokens.reduce(\n (acc, t) =>\n acc === undefined || t.marketValue === undefined\n ? undefined\n : acc + t.marketValue,\n 0 as number | undefined,\n );\n\n return {\n ...tokenBalance,\n marketValue,\n tokens: processedTokens,\n };\n}\n"]}
@@ -151,9 +151,6 @@ class MultichainAssetsRatesController extends (0, polling_controller_1.StaticInt
151
151
  async fetchHistoricalPricesForAsset(asset) {
152
152
  const releaseLock = await __classPrivateFieldGet(this, _MultichainAssetsRatesController_mutex, "f").acquire();
153
153
  return (async () => {
154
- if (!this.isActive) {
155
- return;
156
- }
157
154
  const currentCaipCurrency = constant_1.MAP_CAIP_CURRENCIES[__classPrivateFieldGet(this, _MultichainAssetsRatesController_currentCurrency, "f")] ?? constant_1.MAP_CAIP_CURRENCIES.usd;
158
155
  // Check if we already have historical prices for this asset and currency
159
156
  const historicalPriceExpirationTime = this.state.historicalPrices[asset]?.[__classPrivateFieldGet(this, _MultichainAssetsRatesController_currentCurrency, "f")]
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAssetsRatesController.cjs","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerListMultichainAccountsAction,\n AccountsControllerAccountAddedEvent,\n AccountsControllerGetSelectedMultichainAccountAction,\n} from '@metamask/accounts-controller';\nimport type {\n RestrictedMessenger,\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n} from '@metamask/base-controller';\nimport { type CaipAssetType, isEvmAccountType } from '@metamask/keyring-api';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { HandleSnapRequest } from '@metamask/snaps-controllers';\nimport type {\n SnapId,\n AssetConversion,\n OnAssetsConversionArguments,\n OnAssetsConversionResponse,\n OnAssetHistoricalPriceArguments,\n OnAssetHistoricalPriceResponse,\n HistoricalPriceIntervals,\n} from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Mutex } from 'async-mutex';\nimport type { Draft } from 'immer';\n\nimport { MAP_CAIP_CURRENCIES } from './constant';\nimport type {\n CurrencyRateState,\n CurrencyRateStateChange,\n GetCurrencyRateState,\n} from '../CurrencyRateController';\nimport type {\n MultichainAssetsControllerGetStateAction,\n MultichainAssetsControllerState,\n MultichainAssetsControllerStateChangeEvent,\n} from '../MultichainAssetsController';\n\n/**\n * The name of the MultichainAssetsRatesController.\n */\nconst controllerName = 'MultichainAssetsRatesController';\n\n// This is temporary until its exported from snap\ntype HistoricalPrice = {\n intervals: HistoricalPriceIntervals;\n // The UNIX timestamp of when the historical price was last updated.\n updateTime: number;\n // The UNIX timestamp of when the historical price will expire.\n expirationTime?: number;\n};\n\n/**\n * State used by the MultichainAssetsRatesController to cache token conversion rates.\n */\nexport type MultichainAssetsRatesControllerState = {\n conversionRates: Record<CaipAssetType, AssetConversion>;\n historicalPrices: Record<CaipAssetType, Record<string, HistoricalPrice>>; // string being the current currency we fetched historical prices for\n};\n\n/**\n * Returns the state of the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n MultichainAssetsRatesControllerState\n >;\n\n/**\n * Action to update the rates of all supported tokens.\n */\nexport type MultichainAssetsRatesControllerUpdateRatesAction = {\n type: `${typeof controllerName}:updateAssetsRates`;\n handler: MultichainAssetsRatesController['updateAssetsRates'];\n};\n\n/**\n * Constructs the default {@link MultichainAssetsRatesController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link MultichainAssetsRatesController} state.\n */\nexport function getDefaultMultichainAssetsRatesControllerState(): MultichainAssetsRatesControllerState {\n return { conversionRates: {}, historicalPrices: {} };\n}\n\n/**\n * Event emitted when the state of the MultichainAssetsRatesController changes.\n */\nexport type MultichainAssetsRatesControllerStateChange =\n ControllerStateChangeEvent<\n typeof controllerName,\n MultichainAssetsRatesControllerState\n >;\n\n/**\n * Actions exposed by the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerActions =\n | MultichainAssetsRatesControllerGetStateAction\n | MultichainAssetsRatesControllerUpdateRatesAction;\n\n/**\n * Events emitted by MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerEvents =\n MultichainAssetsRatesControllerStateChange;\n\n/**\n * Actions that this controller is allowed to call.\n */\nexport type AllowedActions =\n | HandleSnapRequest\n | AccountsControllerListMultichainAccountsAction\n | GetCurrencyRateState\n | MultichainAssetsControllerGetStateAction\n | AccountsControllerGetSelectedMultichainAccountAction;\n\n/**\n * Events that this controller is allowed to subscribe to.\n */\nexport type AllowedEvents =\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent\n | AccountsControllerAccountAddedEvent\n | CurrencyRateStateChange\n | MultichainAssetsControllerStateChangeEvent;\n\n/**\n * Messenger type for the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n MultichainAssetsRatesControllerActions | AllowedActions,\n MultichainAssetsRatesControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * The input for starting polling in MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesPollingInput = {\n accountId: string;\n};\n\nconst metadata = {\n conversionRates: { persist: true, anonymous: true },\n historicalPrices: { persist: false, anonymous: true },\n};\n\n/**\n * Controller that manages multichain token conversion rates.\n *\n * This controller polls for token conversion rates and updates its state.\n */\nexport class MultichainAssetsRatesController extends StaticIntervalPollingController<MultichainAssetsRatesPollingInput>()<\n typeof controllerName,\n MultichainAssetsRatesControllerState,\n MultichainAssetsRatesControllerMessenger\n> {\n readonly #mutex = new Mutex();\n\n #currentCurrency: CurrencyRateState['currentCurrency'];\n\n #accountsAssets: MultichainAssetsControllerState['accountsAssets'];\n\n #isUnlocked = true;\n\n /**\n * Creates an instance of MultichainAssetsRatesController.\n *\n * @param options - Constructor options.\n * @param options.interval - The polling interval in milliseconds.\n * @param options.state - The initial state.\n * @param options.messenger - A reference to the messaging system.\n */\n constructor({\n interval = 18000,\n state = {},\n messenger,\n }: {\n interval?: number;\n state?: Partial<MultichainAssetsRatesControllerState>;\n messenger: MultichainAssetsRatesControllerMessenger;\n }) {\n super({\n name: controllerName,\n messenger,\n state: {\n ...getDefaultMultichainAssetsRatesControllerState(),\n ...state,\n },\n metadata,\n });\n\n this.setIntervalLength(interval);\n\n // Subscribe to keyring lock/unlock events.\n this.messagingSystem.subscribe('KeyringController:lock', () => {\n this.#isUnlocked = false;\n });\n this.messagingSystem.subscribe('KeyringController:unlock', () => {\n this.#isUnlocked = true;\n });\n\n ({ accountsAssets: this.#accountsAssets } = this.messagingSystem.call(\n 'MultichainAssetsController:getState',\n ));\n\n ({ currentCurrency: this.#currentCurrency } = this.messagingSystem.call(\n 'CurrencyRateController:getState',\n ));\n\n this.messagingSystem.subscribe(\n 'CurrencyRateController:stateChange',\n async (currencyRatesState: CurrencyRateState) => {\n this.#currentCurrency = currencyRatesState.currentCurrency;\n await this.updateAssetsRates();\n },\n );\n\n this.messagingSystem.subscribe(\n 'MultichainAssetsController:stateChange',\n async (multichainAssetsState: MultichainAssetsControllerState) => {\n this.#accountsAssets = multichainAssetsState.accountsAssets;\n await this.updateAssetsRates();\n },\n );\n }\n\n /**\n * Executes a poll by updating token conversion rates for the current account.\n *\n * @returns A promise that resolves when the polling completes.\n */\n async _executePoll(): Promise<void> {\n await this.updateAssetsRates();\n }\n\n /**\n * Determines whether the controller is active.\n *\n * @returns True if the keyring is unlocked; otherwise, false.\n */\n get isActive(): boolean {\n return this.#isUnlocked;\n }\n\n /**\n * Checks if an account is a non-EVM account with a Snap.\n *\n * @param account - The account to check.\n * @returns True if the account is non-EVM and has Snap metadata; otherwise, false.\n */\n #isNonEvmAccount(account: InternalAccount): boolean {\n return (\n !isEvmAccountType(account.type) && account.metadata.snap !== undefined\n );\n }\n\n /**\n * Retrieves all multichain accounts from the AccountsController.\n *\n * @returns An array of internal accounts.\n */\n #listMultichainAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n }\n\n /**\n * Filters and returns non-EVM accounts that should have balances.\n *\n * @returns An array of non-EVM internal accounts.\n */\n #listAccounts(): InternalAccount[] {\n const accounts = this.#listMultichainAccounts();\n return accounts.filter((account) => this.#isNonEvmAccount(account));\n }\n\n /**\n * Updates token conversion rates for each non-EVM account.\n *\n * @returns A promise that resolves when the rates are updated.\n */\n async updateAssetsRates(): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n\n return (async () => {\n if (!this.isActive) {\n return;\n }\n const accounts = this.#listAccounts();\n\n for (const account of accounts) {\n const assets = this.#getAssetsForAccount(account.id);\n\n if (assets?.length === 0) {\n continue;\n }\n\n // Build the conversions array\n const conversions = this.#buildConversions(assets);\n\n // Retrieve rates from Snap\n const accountRates: OnAssetsConversionResponse =\n (await this.#handleSnapRequest({\n snapId: account?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetsConversion,\n params: {\n ...conversions,\n includeMarketData: true,\n },\n })) as OnAssetsConversionResponse;\n\n // Flatten nested rates if needed\n const flattenedRates = this.#flattenRates(accountRates);\n\n // Build the updatedRates object for these assets\n const updatedRates = this.#buildUpdatedRates(assets, flattenedRates);\n // Apply these updated rates to controller state\n this.#applyUpdatedRates(updatedRates);\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Fetches historical prices for the current account\n *\n * @param asset - The asset to fetch historical prices for.\n * @returns The historical prices.\n */\n async fetchHistoricalPricesForAsset(asset: CaipAssetType): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n return (async () => {\n if (!this.isActive) {\n return;\n }\n const currentCaipCurrency =\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ?? MAP_CAIP_CURRENCIES.usd;\n // Check if we already have historical prices for this asset and currency\n const historicalPriceExpirationTime =\n this.state.historicalPrices[asset]?.[this.#currentCurrency]\n ?.expirationTime ?? null;\n\n const historicalPriceHasExpired =\n historicalPriceExpirationTime &&\n historicalPriceExpirationTime < Date.now();\n\n if (historicalPriceHasExpired === false) {\n return;\n }\n\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n\n const historicalPricesResponse = await this.#handleSnapRequest({\n snapId: selectedAccount?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetHistoricalPrice,\n params: {\n from: asset,\n to: currentCaipCurrency,\n },\n });\n\n // skip state update if no historical prices are returned\n if (!historicalPricesResponse) {\n return;\n }\n\n this.update((state) => {\n state.historicalPrices = {\n ...state.historicalPrices,\n [asset]: {\n ...state.historicalPrices[asset],\n [this.#currentCurrency]: (\n historicalPricesResponse as OnAssetHistoricalPriceResponse\n )?.historicalPrice,\n },\n };\n });\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Returns the array of CAIP-19 assets for the given account ID.\n * If none are found, returns an empty array.\n *\n * @param accountId - The account ID to get the assets for.\n * @returns An array of CAIP-19 assets.\n */\n #getAssetsForAccount(accountId: string): CaipAssetType[] {\n return this.#accountsAssets?.[accountId] ?? [];\n }\n\n /**\n * Builds a conversions array (from each asset → the current currency).\n *\n * @param assets - The assets to build the conversions for.\n * @returns A conversions array.\n */\n #buildConversions(assets: CaipAssetType[]): OnAssetsConversionArguments {\n const currency =\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ?? MAP_CAIP_CURRENCIES.usd;\n return {\n conversions: assets.map((asset) => ({\n from: asset,\n to: currency,\n })),\n };\n }\n\n /**\n * Flattens any nested structure in the conversion rates returned by Snap.\n *\n * @param assetsConversionResponse - The conversion rates to flatten.\n * @returns A flattened rates object.\n */\n #flattenRates(\n assetsConversionResponse: OnAssetsConversionResponse,\n ): Record<CaipAssetType, AssetConversion | null> {\n const { conversionRates } = assetsConversionResponse;\n\n return Object.fromEntries(\n Object.entries(conversionRates).map(([asset, nestedObj]) => {\n // e.g., nestedObj might look like: { \"swift:0/iso4217:EUR\": { rate, conversionTime } }\n const singleValue = Object.values(nestedObj)[0];\n return [asset, singleValue];\n }),\n );\n }\n\n /**\n * Builds a rates object that covers all given assets, ensuring that\n * any asset not returned by Snap is set to null for both `rate` and `conversionTime`.\n *\n * @param assets - The assets to build the rates for.\n * @param flattenedRates - The rates to merge.\n * @returns A rates object that covers all given assets.\n */\n #buildUpdatedRates(\n assets: CaipAssetType[],\n flattenedRates: Record<CaipAssetType, AssetConversion | null>,\n ): Record<string, AssetConversion & { currency: CaipAssetType }> {\n const updatedRates: Record<\n CaipAssetType,\n AssetConversion & { currency: CaipAssetType }\n > = {};\n\n for (const asset of assets) {\n if (flattenedRates[asset]) {\n updatedRates[asset] = {\n ...(flattenedRates[asset] as AssetConversion),\n currency:\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ??\n MAP_CAIP_CURRENCIES.usd,\n };\n }\n }\n return updatedRates;\n }\n\n /**\n * Merges the new rates into the controller’s state.\n *\n * @param updatedRates - The new rates to merge.\n */\n #applyUpdatedRates(\n updatedRates: Record<\n string,\n { rate: string | null; conversionTime: number | null }\n >,\n ): void {\n this.update((state: Draft<MultichainAssetsRatesControllerState>) => {\n state.conversionRates = {\n ...state.conversionRates,\n ...updatedRates,\n };\n });\n }\n\n /**\n * Forwards a Snap request to the SnapController.\n *\n * @param args - The request parameters.\n * @param args.snapId - The ID of the Snap.\n * @param args.handler - The handler type.\n * @param args.params - The asset conversions.\n * @returns A promise that resolves with the account rates.\n */\n async #handleSnapRequest({\n snapId,\n handler,\n params,\n }: {\n snapId: SnapId;\n handler: HandlerType;\n params: OnAssetsConversionArguments | OnAssetHistoricalPriceArguments;\n }): Promise<OnAssetsConversionResponse | OnAssetHistoricalPriceResponse> {\n return this.messagingSystem.call('SnapController:handleRequest', {\n snapId,\n origin: 'metamask',\n handler,\n request: {\n jsonrpc: '2.0',\n method: handler,\n params,\n },\n }) as Promise<OnAssetsConversionResponse | OnAssetHistoricalPriceResponse>;\n }\n}\n"]}
1
+ {"version":3,"file":"MultichainAssetsRatesController.cjs","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerListMultichainAccountsAction,\n AccountsControllerAccountAddedEvent,\n AccountsControllerGetSelectedMultichainAccountAction,\n} from '@metamask/accounts-controller';\nimport type {\n RestrictedMessenger,\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n} from '@metamask/base-controller';\nimport { type CaipAssetType, isEvmAccountType } from '@metamask/keyring-api';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { HandleSnapRequest } from '@metamask/snaps-controllers';\nimport type {\n SnapId,\n AssetConversion,\n OnAssetsConversionArguments,\n OnAssetsConversionResponse,\n OnAssetHistoricalPriceArguments,\n OnAssetHistoricalPriceResponse,\n HistoricalPriceIntervals,\n} from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Mutex } from 'async-mutex';\nimport type { Draft } from 'immer';\n\nimport { MAP_CAIP_CURRENCIES } from './constant';\nimport type {\n CurrencyRateState,\n CurrencyRateStateChange,\n GetCurrencyRateState,\n} from '../CurrencyRateController';\nimport type {\n MultichainAssetsControllerGetStateAction,\n MultichainAssetsControllerState,\n MultichainAssetsControllerStateChangeEvent,\n} from '../MultichainAssetsController';\n\n/**\n * The name of the MultichainAssetsRatesController.\n */\nconst controllerName = 'MultichainAssetsRatesController';\n\n// This is temporary until its exported from snap\ntype HistoricalPrice = {\n intervals: HistoricalPriceIntervals;\n // The UNIX timestamp of when the historical price was last updated.\n updateTime: number;\n // The UNIX timestamp of when the historical price will expire.\n expirationTime?: number;\n};\n\n/**\n * State used by the MultichainAssetsRatesController to cache token conversion rates.\n */\nexport type MultichainAssetsRatesControllerState = {\n conversionRates: Record<CaipAssetType, AssetConversion>;\n historicalPrices: Record<CaipAssetType, Record<string, HistoricalPrice>>; // string being the current currency we fetched historical prices for\n};\n\n/**\n * Returns the state of the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n MultichainAssetsRatesControllerState\n >;\n\n/**\n * Action to update the rates of all supported tokens.\n */\nexport type MultichainAssetsRatesControllerUpdateRatesAction = {\n type: `${typeof controllerName}:updateAssetsRates`;\n handler: MultichainAssetsRatesController['updateAssetsRates'];\n};\n\n/**\n * Constructs the default {@link MultichainAssetsRatesController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link MultichainAssetsRatesController} state.\n */\nexport function getDefaultMultichainAssetsRatesControllerState(): MultichainAssetsRatesControllerState {\n return { conversionRates: {}, historicalPrices: {} };\n}\n\n/**\n * Event emitted when the state of the MultichainAssetsRatesController changes.\n */\nexport type MultichainAssetsRatesControllerStateChange =\n ControllerStateChangeEvent<\n typeof controllerName,\n MultichainAssetsRatesControllerState\n >;\n\n/**\n * Actions exposed by the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerActions =\n | MultichainAssetsRatesControllerGetStateAction\n | MultichainAssetsRatesControllerUpdateRatesAction;\n\n/**\n * Events emitted by MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerEvents =\n MultichainAssetsRatesControllerStateChange;\n\n/**\n * Actions that this controller is allowed to call.\n */\nexport type AllowedActions =\n | HandleSnapRequest\n | AccountsControllerListMultichainAccountsAction\n | GetCurrencyRateState\n | MultichainAssetsControllerGetStateAction\n | AccountsControllerGetSelectedMultichainAccountAction;\n\n/**\n * Events that this controller is allowed to subscribe to.\n */\nexport type AllowedEvents =\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent\n | AccountsControllerAccountAddedEvent\n | CurrencyRateStateChange\n | MultichainAssetsControllerStateChangeEvent;\n\n/**\n * Messenger type for the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n MultichainAssetsRatesControllerActions | AllowedActions,\n MultichainAssetsRatesControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * The input for starting polling in MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesPollingInput = {\n accountId: string;\n};\n\nconst metadata = {\n conversionRates: { persist: true, anonymous: true },\n historicalPrices: { persist: false, anonymous: true },\n};\n\n/**\n * Controller that manages multichain token conversion rates.\n *\n * This controller polls for token conversion rates and updates its state.\n */\nexport class MultichainAssetsRatesController extends StaticIntervalPollingController<MultichainAssetsRatesPollingInput>()<\n typeof controllerName,\n MultichainAssetsRatesControllerState,\n MultichainAssetsRatesControllerMessenger\n> {\n readonly #mutex = new Mutex();\n\n #currentCurrency: CurrencyRateState['currentCurrency'];\n\n #accountsAssets: MultichainAssetsControllerState['accountsAssets'];\n\n #isUnlocked = true;\n\n /**\n * Creates an instance of MultichainAssetsRatesController.\n *\n * @param options - Constructor options.\n * @param options.interval - The polling interval in milliseconds.\n * @param options.state - The initial state.\n * @param options.messenger - A reference to the messaging system.\n */\n constructor({\n interval = 18000,\n state = {},\n messenger,\n }: {\n interval?: number;\n state?: Partial<MultichainAssetsRatesControllerState>;\n messenger: MultichainAssetsRatesControllerMessenger;\n }) {\n super({\n name: controllerName,\n messenger,\n state: {\n ...getDefaultMultichainAssetsRatesControllerState(),\n ...state,\n },\n metadata,\n });\n\n this.setIntervalLength(interval);\n\n // Subscribe to keyring lock/unlock events.\n this.messagingSystem.subscribe('KeyringController:lock', () => {\n this.#isUnlocked = false;\n });\n this.messagingSystem.subscribe('KeyringController:unlock', () => {\n this.#isUnlocked = true;\n });\n\n ({ accountsAssets: this.#accountsAssets } = this.messagingSystem.call(\n 'MultichainAssetsController:getState',\n ));\n\n ({ currentCurrency: this.#currentCurrency } = this.messagingSystem.call(\n 'CurrencyRateController:getState',\n ));\n\n this.messagingSystem.subscribe(\n 'CurrencyRateController:stateChange',\n async (currencyRatesState: CurrencyRateState) => {\n this.#currentCurrency = currencyRatesState.currentCurrency;\n await this.updateAssetsRates();\n },\n );\n\n this.messagingSystem.subscribe(\n 'MultichainAssetsController:stateChange',\n async (multichainAssetsState: MultichainAssetsControllerState) => {\n this.#accountsAssets = multichainAssetsState.accountsAssets;\n await this.updateAssetsRates();\n },\n );\n }\n\n /**\n * Executes a poll by updating token conversion rates for the current account.\n *\n * @returns A promise that resolves when the polling completes.\n */\n async _executePoll(): Promise<void> {\n await this.updateAssetsRates();\n }\n\n /**\n * Determines whether the controller is active.\n *\n * @returns True if the keyring is unlocked; otherwise, false.\n */\n get isActive(): boolean {\n return this.#isUnlocked;\n }\n\n /**\n * Checks if an account is a non-EVM account with a Snap.\n *\n * @param account - The account to check.\n * @returns True if the account is non-EVM and has Snap metadata; otherwise, false.\n */\n #isNonEvmAccount(account: InternalAccount): boolean {\n return (\n !isEvmAccountType(account.type) && account.metadata.snap !== undefined\n );\n }\n\n /**\n * Retrieves all multichain accounts from the AccountsController.\n *\n * @returns An array of internal accounts.\n */\n #listMultichainAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n }\n\n /**\n * Filters and returns non-EVM accounts that should have balances.\n *\n * @returns An array of non-EVM internal accounts.\n */\n #listAccounts(): InternalAccount[] {\n const accounts = this.#listMultichainAccounts();\n return accounts.filter((account) => this.#isNonEvmAccount(account));\n }\n\n /**\n * Updates token conversion rates for each non-EVM account.\n *\n * @returns A promise that resolves when the rates are updated.\n */\n async updateAssetsRates(): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n\n return (async () => {\n if (!this.isActive) {\n return;\n }\n const accounts = this.#listAccounts();\n\n for (const account of accounts) {\n const assets = this.#getAssetsForAccount(account.id);\n\n if (assets?.length === 0) {\n continue;\n }\n\n // Build the conversions array\n const conversions = this.#buildConversions(assets);\n\n // Retrieve rates from Snap\n const accountRates: OnAssetsConversionResponse =\n (await this.#handleSnapRequest({\n snapId: account?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetsConversion,\n params: {\n ...conversions,\n includeMarketData: true,\n },\n })) as OnAssetsConversionResponse;\n\n // Flatten nested rates if needed\n const flattenedRates = this.#flattenRates(accountRates);\n\n // Build the updatedRates object for these assets\n const updatedRates = this.#buildUpdatedRates(assets, flattenedRates);\n // Apply these updated rates to controller state\n this.#applyUpdatedRates(updatedRates);\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Fetches historical prices for the current account\n *\n * @param asset - The asset to fetch historical prices for.\n * @returns The historical prices.\n */\n async fetchHistoricalPricesForAsset(asset: CaipAssetType): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n return (async () => {\n const currentCaipCurrency =\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ?? MAP_CAIP_CURRENCIES.usd;\n // Check if we already have historical prices for this asset and currency\n const historicalPriceExpirationTime =\n this.state.historicalPrices[asset]?.[this.#currentCurrency]\n ?.expirationTime ?? null;\n\n const historicalPriceHasExpired =\n historicalPriceExpirationTime &&\n historicalPriceExpirationTime < Date.now();\n\n if (historicalPriceHasExpired === false) {\n return;\n }\n\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n\n const historicalPricesResponse = await this.#handleSnapRequest({\n snapId: selectedAccount?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetHistoricalPrice,\n params: {\n from: asset,\n to: currentCaipCurrency,\n },\n });\n\n // skip state update if no historical prices are returned\n if (!historicalPricesResponse) {\n return;\n }\n\n this.update((state) => {\n state.historicalPrices = {\n ...state.historicalPrices,\n [asset]: {\n ...state.historicalPrices[asset],\n [this.#currentCurrency]: (\n historicalPricesResponse as OnAssetHistoricalPriceResponse\n )?.historicalPrice,\n },\n };\n });\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Returns the array of CAIP-19 assets for the given account ID.\n * If none are found, returns an empty array.\n *\n * @param accountId - The account ID to get the assets for.\n * @returns An array of CAIP-19 assets.\n */\n #getAssetsForAccount(accountId: string): CaipAssetType[] {\n return this.#accountsAssets?.[accountId] ?? [];\n }\n\n /**\n * Builds a conversions array (from each asset → the current currency).\n *\n * @param assets - The assets to build the conversions for.\n * @returns A conversions array.\n */\n #buildConversions(assets: CaipAssetType[]): OnAssetsConversionArguments {\n const currency =\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ?? MAP_CAIP_CURRENCIES.usd;\n return {\n conversions: assets.map((asset) => ({\n from: asset,\n to: currency,\n })),\n };\n }\n\n /**\n * Flattens any nested structure in the conversion rates returned by Snap.\n *\n * @param assetsConversionResponse - The conversion rates to flatten.\n * @returns A flattened rates object.\n */\n #flattenRates(\n assetsConversionResponse: OnAssetsConversionResponse,\n ): Record<CaipAssetType, AssetConversion | null> {\n const { conversionRates } = assetsConversionResponse;\n\n return Object.fromEntries(\n Object.entries(conversionRates).map(([asset, nestedObj]) => {\n // e.g., nestedObj might look like: { \"swift:0/iso4217:EUR\": { rate, conversionTime } }\n const singleValue = Object.values(nestedObj)[0];\n return [asset, singleValue];\n }),\n );\n }\n\n /**\n * Builds a rates object that covers all given assets, ensuring that\n * any asset not returned by Snap is set to null for both `rate` and `conversionTime`.\n *\n * @param assets - The assets to build the rates for.\n * @param flattenedRates - The rates to merge.\n * @returns A rates object that covers all given assets.\n */\n #buildUpdatedRates(\n assets: CaipAssetType[],\n flattenedRates: Record<CaipAssetType, AssetConversion | null>,\n ): Record<string, AssetConversion & { currency: CaipAssetType }> {\n const updatedRates: Record<\n CaipAssetType,\n AssetConversion & { currency: CaipAssetType }\n > = {};\n\n for (const asset of assets) {\n if (flattenedRates[asset]) {\n updatedRates[asset] = {\n ...(flattenedRates[asset] as AssetConversion),\n currency:\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ??\n MAP_CAIP_CURRENCIES.usd,\n };\n }\n }\n return updatedRates;\n }\n\n /**\n * Merges the new rates into the controller’s state.\n *\n * @param updatedRates - The new rates to merge.\n */\n #applyUpdatedRates(\n updatedRates: Record<\n string,\n { rate: string | null; conversionTime: number | null }\n >,\n ): void {\n this.update((state: Draft<MultichainAssetsRatesControllerState>) => {\n state.conversionRates = {\n ...state.conversionRates,\n ...updatedRates,\n };\n });\n }\n\n /**\n * Forwards a Snap request to the SnapController.\n *\n * @param args - The request parameters.\n * @param args.snapId - The ID of the Snap.\n * @param args.handler - The handler type.\n * @param args.params - The asset conversions.\n * @returns A promise that resolves with the account rates.\n */\n async #handleSnapRequest({\n snapId,\n handler,\n params,\n }: {\n snapId: SnapId;\n handler: HandlerType;\n params: OnAssetsConversionArguments | OnAssetHistoricalPriceArguments;\n }): Promise<OnAssetsConversionResponse | OnAssetHistoricalPriceResponse> {\n return this.messagingSystem.call('SnapController:handleRequest', {\n snapId,\n origin: 'metamask',\n handler,\n request: {\n jsonrpc: '2.0',\n method: handler,\n params,\n },\n }) as Promise<OnAssetsConversionResponse | OnAssetHistoricalPriceResponse>;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAssetsRatesController.d.cts","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MultichainAssetsRatesController.d.cts","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAssetsRatesController.d.mts","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MultichainAssetsRatesController.d.mts","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"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"}
@@ -147,9 +147,6 @@ export class MultichainAssetsRatesController extends StaticIntervalPollingContro
147
147
  async fetchHistoricalPricesForAsset(asset) {
148
148
  const releaseLock = await __classPrivateFieldGet(this, _MultichainAssetsRatesController_mutex, "f").acquire();
149
149
  return (async () => {
150
- if (!this.isActive) {
151
- return;
152
- }
153
150
  const currentCaipCurrency = MAP_CAIP_CURRENCIES[__classPrivateFieldGet(this, _MultichainAssetsRatesController_currentCurrency, "f")] ?? MAP_CAIP_CURRENCIES.usd;
154
151
  // Check if we already have historical prices for this asset and currency
155
152
  const historicalPriceExpirationTime = this.state.historicalPrices[asset]?.[__classPrivateFieldGet(this, _MultichainAssetsRatesController_currentCurrency, "f")]
@@ -1 +1 @@
1
- {"version":3,"file":"MultichainAssetsRatesController.mjs","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerListMultichainAccountsAction,\n AccountsControllerAccountAddedEvent,\n AccountsControllerGetSelectedMultichainAccountAction,\n} from '@metamask/accounts-controller';\nimport type {\n RestrictedMessenger,\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n} from '@metamask/base-controller';\nimport { type CaipAssetType, isEvmAccountType } from '@metamask/keyring-api';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { HandleSnapRequest } from '@metamask/snaps-controllers';\nimport type {\n SnapId,\n AssetConversion,\n OnAssetsConversionArguments,\n OnAssetsConversionResponse,\n OnAssetHistoricalPriceArguments,\n OnAssetHistoricalPriceResponse,\n HistoricalPriceIntervals,\n} from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Mutex } from 'async-mutex';\nimport type { Draft } from 'immer';\n\nimport { MAP_CAIP_CURRENCIES } from './constant';\nimport type {\n CurrencyRateState,\n CurrencyRateStateChange,\n GetCurrencyRateState,\n} from '../CurrencyRateController';\nimport type {\n MultichainAssetsControllerGetStateAction,\n MultichainAssetsControllerState,\n MultichainAssetsControllerStateChangeEvent,\n} from '../MultichainAssetsController';\n\n/**\n * The name of the MultichainAssetsRatesController.\n */\nconst controllerName = 'MultichainAssetsRatesController';\n\n// This is temporary until its exported from snap\ntype HistoricalPrice = {\n intervals: HistoricalPriceIntervals;\n // The UNIX timestamp of when the historical price was last updated.\n updateTime: number;\n // The UNIX timestamp of when the historical price will expire.\n expirationTime?: number;\n};\n\n/**\n * State used by the MultichainAssetsRatesController to cache token conversion rates.\n */\nexport type MultichainAssetsRatesControllerState = {\n conversionRates: Record<CaipAssetType, AssetConversion>;\n historicalPrices: Record<CaipAssetType, Record<string, HistoricalPrice>>; // string being the current currency we fetched historical prices for\n};\n\n/**\n * Returns the state of the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n MultichainAssetsRatesControllerState\n >;\n\n/**\n * Action to update the rates of all supported tokens.\n */\nexport type MultichainAssetsRatesControllerUpdateRatesAction = {\n type: `${typeof controllerName}:updateAssetsRates`;\n handler: MultichainAssetsRatesController['updateAssetsRates'];\n};\n\n/**\n * Constructs the default {@link MultichainAssetsRatesController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link MultichainAssetsRatesController} state.\n */\nexport function getDefaultMultichainAssetsRatesControllerState(): MultichainAssetsRatesControllerState {\n return { conversionRates: {}, historicalPrices: {} };\n}\n\n/**\n * Event emitted when the state of the MultichainAssetsRatesController changes.\n */\nexport type MultichainAssetsRatesControllerStateChange =\n ControllerStateChangeEvent<\n typeof controllerName,\n MultichainAssetsRatesControllerState\n >;\n\n/**\n * Actions exposed by the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerActions =\n | MultichainAssetsRatesControllerGetStateAction\n | MultichainAssetsRatesControllerUpdateRatesAction;\n\n/**\n * Events emitted by MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerEvents =\n MultichainAssetsRatesControllerStateChange;\n\n/**\n * Actions that this controller is allowed to call.\n */\nexport type AllowedActions =\n | HandleSnapRequest\n | AccountsControllerListMultichainAccountsAction\n | GetCurrencyRateState\n | MultichainAssetsControllerGetStateAction\n | AccountsControllerGetSelectedMultichainAccountAction;\n\n/**\n * Events that this controller is allowed to subscribe to.\n */\nexport type AllowedEvents =\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent\n | AccountsControllerAccountAddedEvent\n | CurrencyRateStateChange\n | MultichainAssetsControllerStateChangeEvent;\n\n/**\n * Messenger type for the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n MultichainAssetsRatesControllerActions | AllowedActions,\n MultichainAssetsRatesControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * The input for starting polling in MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesPollingInput = {\n accountId: string;\n};\n\nconst metadata = {\n conversionRates: { persist: true, anonymous: true },\n historicalPrices: { persist: false, anonymous: true },\n};\n\n/**\n * Controller that manages multichain token conversion rates.\n *\n * This controller polls for token conversion rates and updates its state.\n */\nexport class MultichainAssetsRatesController extends StaticIntervalPollingController<MultichainAssetsRatesPollingInput>()<\n typeof controllerName,\n MultichainAssetsRatesControllerState,\n MultichainAssetsRatesControllerMessenger\n> {\n readonly #mutex = new Mutex();\n\n #currentCurrency: CurrencyRateState['currentCurrency'];\n\n #accountsAssets: MultichainAssetsControllerState['accountsAssets'];\n\n #isUnlocked = true;\n\n /**\n * Creates an instance of MultichainAssetsRatesController.\n *\n * @param options - Constructor options.\n * @param options.interval - The polling interval in milliseconds.\n * @param options.state - The initial state.\n * @param options.messenger - A reference to the messaging system.\n */\n constructor({\n interval = 18000,\n state = {},\n messenger,\n }: {\n interval?: number;\n state?: Partial<MultichainAssetsRatesControllerState>;\n messenger: MultichainAssetsRatesControllerMessenger;\n }) {\n super({\n name: controllerName,\n messenger,\n state: {\n ...getDefaultMultichainAssetsRatesControllerState(),\n ...state,\n },\n metadata,\n });\n\n this.setIntervalLength(interval);\n\n // Subscribe to keyring lock/unlock events.\n this.messagingSystem.subscribe('KeyringController:lock', () => {\n this.#isUnlocked = false;\n });\n this.messagingSystem.subscribe('KeyringController:unlock', () => {\n this.#isUnlocked = true;\n });\n\n ({ accountsAssets: this.#accountsAssets } = this.messagingSystem.call(\n 'MultichainAssetsController:getState',\n ));\n\n ({ currentCurrency: this.#currentCurrency } = this.messagingSystem.call(\n 'CurrencyRateController:getState',\n ));\n\n this.messagingSystem.subscribe(\n 'CurrencyRateController:stateChange',\n async (currencyRatesState: CurrencyRateState) => {\n this.#currentCurrency = currencyRatesState.currentCurrency;\n await this.updateAssetsRates();\n },\n );\n\n this.messagingSystem.subscribe(\n 'MultichainAssetsController:stateChange',\n async (multichainAssetsState: MultichainAssetsControllerState) => {\n this.#accountsAssets = multichainAssetsState.accountsAssets;\n await this.updateAssetsRates();\n },\n );\n }\n\n /**\n * Executes a poll by updating token conversion rates for the current account.\n *\n * @returns A promise that resolves when the polling completes.\n */\n async _executePoll(): Promise<void> {\n await this.updateAssetsRates();\n }\n\n /**\n * Determines whether the controller is active.\n *\n * @returns True if the keyring is unlocked; otherwise, false.\n */\n get isActive(): boolean {\n return this.#isUnlocked;\n }\n\n /**\n * Checks if an account is a non-EVM account with a Snap.\n *\n * @param account - The account to check.\n * @returns True if the account is non-EVM and has Snap metadata; otherwise, false.\n */\n #isNonEvmAccount(account: InternalAccount): boolean {\n return (\n !isEvmAccountType(account.type) && account.metadata.snap !== undefined\n );\n }\n\n /**\n * Retrieves all multichain accounts from the AccountsController.\n *\n * @returns An array of internal accounts.\n */\n #listMultichainAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n }\n\n /**\n * Filters and returns non-EVM accounts that should have balances.\n *\n * @returns An array of non-EVM internal accounts.\n */\n #listAccounts(): InternalAccount[] {\n const accounts = this.#listMultichainAccounts();\n return accounts.filter((account) => this.#isNonEvmAccount(account));\n }\n\n /**\n * Updates token conversion rates for each non-EVM account.\n *\n * @returns A promise that resolves when the rates are updated.\n */\n async updateAssetsRates(): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n\n return (async () => {\n if (!this.isActive) {\n return;\n }\n const accounts = this.#listAccounts();\n\n for (const account of accounts) {\n const assets = this.#getAssetsForAccount(account.id);\n\n if (assets?.length === 0) {\n continue;\n }\n\n // Build the conversions array\n const conversions = this.#buildConversions(assets);\n\n // Retrieve rates from Snap\n const accountRates: OnAssetsConversionResponse =\n (await this.#handleSnapRequest({\n snapId: account?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetsConversion,\n params: {\n ...conversions,\n includeMarketData: true,\n },\n })) as OnAssetsConversionResponse;\n\n // Flatten nested rates if needed\n const flattenedRates = this.#flattenRates(accountRates);\n\n // Build the updatedRates object for these assets\n const updatedRates = this.#buildUpdatedRates(assets, flattenedRates);\n // Apply these updated rates to controller state\n this.#applyUpdatedRates(updatedRates);\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Fetches historical prices for the current account\n *\n * @param asset - The asset to fetch historical prices for.\n * @returns The historical prices.\n */\n async fetchHistoricalPricesForAsset(asset: CaipAssetType): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n return (async () => {\n if (!this.isActive) {\n return;\n }\n const currentCaipCurrency =\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ?? MAP_CAIP_CURRENCIES.usd;\n // Check if we already have historical prices for this asset and currency\n const historicalPriceExpirationTime =\n this.state.historicalPrices[asset]?.[this.#currentCurrency]\n ?.expirationTime ?? null;\n\n const historicalPriceHasExpired =\n historicalPriceExpirationTime &&\n historicalPriceExpirationTime < Date.now();\n\n if (historicalPriceHasExpired === false) {\n return;\n }\n\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n\n const historicalPricesResponse = await this.#handleSnapRequest({\n snapId: selectedAccount?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetHistoricalPrice,\n params: {\n from: asset,\n to: currentCaipCurrency,\n },\n });\n\n // skip state update if no historical prices are returned\n if (!historicalPricesResponse) {\n return;\n }\n\n this.update((state) => {\n state.historicalPrices = {\n ...state.historicalPrices,\n [asset]: {\n ...state.historicalPrices[asset],\n [this.#currentCurrency]: (\n historicalPricesResponse as OnAssetHistoricalPriceResponse\n )?.historicalPrice,\n },\n };\n });\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Returns the array of CAIP-19 assets for the given account ID.\n * If none are found, returns an empty array.\n *\n * @param accountId - The account ID to get the assets for.\n * @returns An array of CAIP-19 assets.\n */\n #getAssetsForAccount(accountId: string): CaipAssetType[] {\n return this.#accountsAssets?.[accountId] ?? [];\n }\n\n /**\n * Builds a conversions array (from each asset → the current currency).\n *\n * @param assets - The assets to build the conversions for.\n * @returns A conversions array.\n */\n #buildConversions(assets: CaipAssetType[]): OnAssetsConversionArguments {\n const currency =\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ?? MAP_CAIP_CURRENCIES.usd;\n return {\n conversions: assets.map((asset) => ({\n from: asset,\n to: currency,\n })),\n };\n }\n\n /**\n * Flattens any nested structure in the conversion rates returned by Snap.\n *\n * @param assetsConversionResponse - The conversion rates to flatten.\n * @returns A flattened rates object.\n */\n #flattenRates(\n assetsConversionResponse: OnAssetsConversionResponse,\n ): Record<CaipAssetType, AssetConversion | null> {\n const { conversionRates } = assetsConversionResponse;\n\n return Object.fromEntries(\n Object.entries(conversionRates).map(([asset, nestedObj]) => {\n // e.g., nestedObj might look like: { \"swift:0/iso4217:EUR\": { rate, conversionTime } }\n const singleValue = Object.values(nestedObj)[0];\n return [asset, singleValue];\n }),\n );\n }\n\n /**\n * Builds a rates object that covers all given assets, ensuring that\n * any asset not returned by Snap is set to null for both `rate` and `conversionTime`.\n *\n * @param assets - The assets to build the rates for.\n * @param flattenedRates - The rates to merge.\n * @returns A rates object that covers all given assets.\n */\n #buildUpdatedRates(\n assets: CaipAssetType[],\n flattenedRates: Record<CaipAssetType, AssetConversion | null>,\n ): Record<string, AssetConversion & { currency: CaipAssetType }> {\n const updatedRates: Record<\n CaipAssetType,\n AssetConversion & { currency: CaipAssetType }\n > = {};\n\n for (const asset of assets) {\n if (flattenedRates[asset]) {\n updatedRates[asset] = {\n ...(flattenedRates[asset] as AssetConversion),\n currency:\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ??\n MAP_CAIP_CURRENCIES.usd,\n };\n }\n }\n return updatedRates;\n }\n\n /**\n * Merges the new rates into the controller’s state.\n *\n * @param updatedRates - The new rates to merge.\n */\n #applyUpdatedRates(\n updatedRates: Record<\n string,\n { rate: string | null; conversionTime: number | null }\n >,\n ): void {\n this.update((state: Draft<MultichainAssetsRatesControllerState>) => {\n state.conversionRates = {\n ...state.conversionRates,\n ...updatedRates,\n };\n });\n }\n\n /**\n * Forwards a Snap request to the SnapController.\n *\n * @param args - The request parameters.\n * @param args.snapId - The ID of the Snap.\n * @param args.handler - The handler type.\n * @param args.params - The asset conversions.\n * @returns A promise that resolves with the account rates.\n */\n async #handleSnapRequest({\n snapId,\n handler,\n params,\n }: {\n snapId: SnapId;\n handler: HandlerType;\n params: OnAssetsConversionArguments | OnAssetHistoricalPriceArguments;\n }): Promise<OnAssetsConversionResponse | OnAssetHistoricalPriceResponse> {\n return this.messagingSystem.call('SnapController:handleRequest', {\n snapId,\n origin: 'metamask',\n handler,\n request: {\n jsonrpc: '2.0',\n method: handler,\n params,\n },\n }) as Promise<OnAssetsConversionResponse | OnAssetHistoricalPriceResponse>;\n }\n}\n"]}
1
+ {"version":3,"file":"MultichainAssetsRatesController.mjs","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerListMultichainAccountsAction,\n AccountsControllerAccountAddedEvent,\n AccountsControllerGetSelectedMultichainAccountAction,\n} from '@metamask/accounts-controller';\nimport type {\n RestrictedMessenger,\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n} from '@metamask/base-controller';\nimport { type CaipAssetType, isEvmAccountType } from '@metamask/keyring-api';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { HandleSnapRequest } from '@metamask/snaps-controllers';\nimport type {\n SnapId,\n AssetConversion,\n OnAssetsConversionArguments,\n OnAssetsConversionResponse,\n OnAssetHistoricalPriceArguments,\n OnAssetHistoricalPriceResponse,\n HistoricalPriceIntervals,\n} from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Mutex } from 'async-mutex';\nimport type { Draft } from 'immer';\n\nimport { MAP_CAIP_CURRENCIES } from './constant';\nimport type {\n CurrencyRateState,\n CurrencyRateStateChange,\n GetCurrencyRateState,\n} from '../CurrencyRateController';\nimport type {\n MultichainAssetsControllerGetStateAction,\n MultichainAssetsControllerState,\n MultichainAssetsControllerStateChangeEvent,\n} from '../MultichainAssetsController';\n\n/**\n * The name of the MultichainAssetsRatesController.\n */\nconst controllerName = 'MultichainAssetsRatesController';\n\n// This is temporary until its exported from snap\ntype HistoricalPrice = {\n intervals: HistoricalPriceIntervals;\n // The UNIX timestamp of when the historical price was last updated.\n updateTime: number;\n // The UNIX timestamp of when the historical price will expire.\n expirationTime?: number;\n};\n\n/**\n * State used by the MultichainAssetsRatesController to cache token conversion rates.\n */\nexport type MultichainAssetsRatesControllerState = {\n conversionRates: Record<CaipAssetType, AssetConversion>;\n historicalPrices: Record<CaipAssetType, Record<string, HistoricalPrice>>; // string being the current currency we fetched historical prices for\n};\n\n/**\n * Returns the state of the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerGetStateAction =\n ControllerGetStateAction<\n typeof controllerName,\n MultichainAssetsRatesControllerState\n >;\n\n/**\n * Action to update the rates of all supported tokens.\n */\nexport type MultichainAssetsRatesControllerUpdateRatesAction = {\n type: `${typeof controllerName}:updateAssetsRates`;\n handler: MultichainAssetsRatesController['updateAssetsRates'];\n};\n\n/**\n * Constructs the default {@link MultichainAssetsRatesController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link MultichainAssetsRatesController} state.\n */\nexport function getDefaultMultichainAssetsRatesControllerState(): MultichainAssetsRatesControllerState {\n return { conversionRates: {}, historicalPrices: {} };\n}\n\n/**\n * Event emitted when the state of the MultichainAssetsRatesController changes.\n */\nexport type MultichainAssetsRatesControllerStateChange =\n ControllerStateChangeEvent<\n typeof controllerName,\n MultichainAssetsRatesControllerState\n >;\n\n/**\n * Actions exposed by the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerActions =\n | MultichainAssetsRatesControllerGetStateAction\n | MultichainAssetsRatesControllerUpdateRatesAction;\n\n/**\n * Events emitted by MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerEvents =\n MultichainAssetsRatesControllerStateChange;\n\n/**\n * Actions that this controller is allowed to call.\n */\nexport type AllowedActions =\n | HandleSnapRequest\n | AccountsControllerListMultichainAccountsAction\n | GetCurrencyRateState\n | MultichainAssetsControllerGetStateAction\n | AccountsControllerGetSelectedMultichainAccountAction;\n\n/**\n * Events that this controller is allowed to subscribe to.\n */\nexport type AllowedEvents =\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent\n | AccountsControllerAccountAddedEvent\n | CurrencyRateStateChange\n | MultichainAssetsControllerStateChangeEvent;\n\n/**\n * Messenger type for the MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n MultichainAssetsRatesControllerActions | AllowedActions,\n MultichainAssetsRatesControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * The input for starting polling in MultichainAssetsRatesController.\n */\nexport type MultichainAssetsRatesPollingInput = {\n accountId: string;\n};\n\nconst metadata = {\n conversionRates: { persist: true, anonymous: true },\n historicalPrices: { persist: false, anonymous: true },\n};\n\n/**\n * Controller that manages multichain token conversion rates.\n *\n * This controller polls for token conversion rates and updates its state.\n */\nexport class MultichainAssetsRatesController extends StaticIntervalPollingController<MultichainAssetsRatesPollingInput>()<\n typeof controllerName,\n MultichainAssetsRatesControllerState,\n MultichainAssetsRatesControllerMessenger\n> {\n readonly #mutex = new Mutex();\n\n #currentCurrency: CurrencyRateState['currentCurrency'];\n\n #accountsAssets: MultichainAssetsControllerState['accountsAssets'];\n\n #isUnlocked = true;\n\n /**\n * Creates an instance of MultichainAssetsRatesController.\n *\n * @param options - Constructor options.\n * @param options.interval - The polling interval in milliseconds.\n * @param options.state - The initial state.\n * @param options.messenger - A reference to the messaging system.\n */\n constructor({\n interval = 18000,\n state = {},\n messenger,\n }: {\n interval?: number;\n state?: Partial<MultichainAssetsRatesControllerState>;\n messenger: MultichainAssetsRatesControllerMessenger;\n }) {\n super({\n name: controllerName,\n messenger,\n state: {\n ...getDefaultMultichainAssetsRatesControllerState(),\n ...state,\n },\n metadata,\n });\n\n this.setIntervalLength(interval);\n\n // Subscribe to keyring lock/unlock events.\n this.messagingSystem.subscribe('KeyringController:lock', () => {\n this.#isUnlocked = false;\n });\n this.messagingSystem.subscribe('KeyringController:unlock', () => {\n this.#isUnlocked = true;\n });\n\n ({ accountsAssets: this.#accountsAssets } = this.messagingSystem.call(\n 'MultichainAssetsController:getState',\n ));\n\n ({ currentCurrency: this.#currentCurrency } = this.messagingSystem.call(\n 'CurrencyRateController:getState',\n ));\n\n this.messagingSystem.subscribe(\n 'CurrencyRateController:stateChange',\n async (currencyRatesState: CurrencyRateState) => {\n this.#currentCurrency = currencyRatesState.currentCurrency;\n await this.updateAssetsRates();\n },\n );\n\n this.messagingSystem.subscribe(\n 'MultichainAssetsController:stateChange',\n async (multichainAssetsState: MultichainAssetsControllerState) => {\n this.#accountsAssets = multichainAssetsState.accountsAssets;\n await this.updateAssetsRates();\n },\n );\n }\n\n /**\n * Executes a poll by updating token conversion rates for the current account.\n *\n * @returns A promise that resolves when the polling completes.\n */\n async _executePoll(): Promise<void> {\n await this.updateAssetsRates();\n }\n\n /**\n * Determines whether the controller is active.\n *\n * @returns True if the keyring is unlocked; otherwise, false.\n */\n get isActive(): boolean {\n return this.#isUnlocked;\n }\n\n /**\n * Checks if an account is a non-EVM account with a Snap.\n *\n * @param account - The account to check.\n * @returns True if the account is non-EVM and has Snap metadata; otherwise, false.\n */\n #isNonEvmAccount(account: InternalAccount): boolean {\n return (\n !isEvmAccountType(account.type) && account.metadata.snap !== undefined\n );\n }\n\n /**\n * Retrieves all multichain accounts from the AccountsController.\n *\n * @returns An array of internal accounts.\n */\n #listMultichainAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n }\n\n /**\n * Filters and returns non-EVM accounts that should have balances.\n *\n * @returns An array of non-EVM internal accounts.\n */\n #listAccounts(): InternalAccount[] {\n const accounts = this.#listMultichainAccounts();\n return accounts.filter((account) => this.#isNonEvmAccount(account));\n }\n\n /**\n * Updates token conversion rates for each non-EVM account.\n *\n * @returns A promise that resolves when the rates are updated.\n */\n async updateAssetsRates(): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n\n return (async () => {\n if (!this.isActive) {\n return;\n }\n const accounts = this.#listAccounts();\n\n for (const account of accounts) {\n const assets = this.#getAssetsForAccount(account.id);\n\n if (assets?.length === 0) {\n continue;\n }\n\n // Build the conversions array\n const conversions = this.#buildConversions(assets);\n\n // Retrieve rates from Snap\n const accountRates: OnAssetsConversionResponse =\n (await this.#handleSnapRequest({\n snapId: account?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetsConversion,\n params: {\n ...conversions,\n includeMarketData: true,\n },\n })) as OnAssetsConversionResponse;\n\n // Flatten nested rates if needed\n const flattenedRates = this.#flattenRates(accountRates);\n\n // Build the updatedRates object for these assets\n const updatedRates = this.#buildUpdatedRates(assets, flattenedRates);\n // Apply these updated rates to controller state\n this.#applyUpdatedRates(updatedRates);\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Fetches historical prices for the current account\n *\n * @param asset - The asset to fetch historical prices for.\n * @returns The historical prices.\n */\n async fetchHistoricalPricesForAsset(asset: CaipAssetType): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n return (async () => {\n const currentCaipCurrency =\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ?? MAP_CAIP_CURRENCIES.usd;\n // Check if we already have historical prices for this asset and currency\n const historicalPriceExpirationTime =\n this.state.historicalPrices[asset]?.[this.#currentCurrency]\n ?.expirationTime ?? null;\n\n const historicalPriceHasExpired =\n historicalPriceExpirationTime &&\n historicalPriceExpirationTime < Date.now();\n\n if (historicalPriceHasExpired === false) {\n return;\n }\n\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n\n const historicalPricesResponse = await this.#handleSnapRequest({\n snapId: selectedAccount?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetHistoricalPrice,\n params: {\n from: asset,\n to: currentCaipCurrency,\n },\n });\n\n // skip state update if no historical prices are returned\n if (!historicalPricesResponse) {\n return;\n }\n\n this.update((state) => {\n state.historicalPrices = {\n ...state.historicalPrices,\n [asset]: {\n ...state.historicalPrices[asset],\n [this.#currentCurrency]: (\n historicalPricesResponse as OnAssetHistoricalPriceResponse\n )?.historicalPrice,\n },\n };\n });\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Returns the array of CAIP-19 assets for the given account ID.\n * If none are found, returns an empty array.\n *\n * @param accountId - The account ID to get the assets for.\n * @returns An array of CAIP-19 assets.\n */\n #getAssetsForAccount(accountId: string): CaipAssetType[] {\n return this.#accountsAssets?.[accountId] ?? [];\n }\n\n /**\n * Builds a conversions array (from each asset → the current currency).\n *\n * @param assets - The assets to build the conversions for.\n * @returns A conversions array.\n */\n #buildConversions(assets: CaipAssetType[]): OnAssetsConversionArguments {\n const currency =\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ?? MAP_CAIP_CURRENCIES.usd;\n return {\n conversions: assets.map((asset) => ({\n from: asset,\n to: currency,\n })),\n };\n }\n\n /**\n * Flattens any nested structure in the conversion rates returned by Snap.\n *\n * @param assetsConversionResponse - The conversion rates to flatten.\n * @returns A flattened rates object.\n */\n #flattenRates(\n assetsConversionResponse: OnAssetsConversionResponse,\n ): Record<CaipAssetType, AssetConversion | null> {\n const { conversionRates } = assetsConversionResponse;\n\n return Object.fromEntries(\n Object.entries(conversionRates).map(([asset, nestedObj]) => {\n // e.g., nestedObj might look like: { \"swift:0/iso4217:EUR\": { rate, conversionTime } }\n const singleValue = Object.values(nestedObj)[0];\n return [asset, singleValue];\n }),\n );\n }\n\n /**\n * Builds a rates object that covers all given assets, ensuring that\n * any asset not returned by Snap is set to null for both `rate` and `conversionTime`.\n *\n * @param assets - The assets to build the rates for.\n * @param flattenedRates - The rates to merge.\n * @returns A rates object that covers all given assets.\n */\n #buildUpdatedRates(\n assets: CaipAssetType[],\n flattenedRates: Record<CaipAssetType, AssetConversion | null>,\n ): Record<string, AssetConversion & { currency: CaipAssetType }> {\n const updatedRates: Record<\n CaipAssetType,\n AssetConversion & { currency: CaipAssetType }\n > = {};\n\n for (const asset of assets) {\n if (flattenedRates[asset]) {\n updatedRates[asset] = {\n ...(flattenedRates[asset] as AssetConversion),\n currency:\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ??\n MAP_CAIP_CURRENCIES.usd,\n };\n }\n }\n return updatedRates;\n }\n\n /**\n * Merges the new rates into the controller’s state.\n *\n * @param updatedRates - The new rates to merge.\n */\n #applyUpdatedRates(\n updatedRates: Record<\n string,\n { rate: string | null; conversionTime: number | null }\n >,\n ): void {\n this.update((state: Draft<MultichainAssetsRatesControllerState>) => {\n state.conversionRates = {\n ...state.conversionRates,\n ...updatedRates,\n };\n });\n }\n\n /**\n * Forwards a Snap request to the SnapController.\n *\n * @param args - The request parameters.\n * @param args.snapId - The ID of the Snap.\n * @param args.handler - The handler type.\n * @param args.params - The asset conversions.\n * @returns A promise that resolves with the account rates.\n */\n async #handleSnapRequest({\n snapId,\n handler,\n params,\n }: {\n snapId: SnapId;\n handler: HandlerType;\n params: OnAssetsConversionArguments | OnAssetHistoricalPriceArguments;\n }): Promise<OnAssetsConversionResponse | OnAssetHistoricalPriceResponse> {\n return this.messagingSystem.call('SnapController:handleRequest', {\n snapId,\n origin: 'metamask',\n handler,\n request: {\n jsonrpc: '2.0',\n method: handler,\n params,\n },\n }) as Promise<OnAssetsConversionResponse | OnAssetHistoricalPriceResponse>;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/assets-controllers",
3
- "version": "56.0.0-preview-eeefabb3",
3
+ "version": "57.0.0-preview-6c44e568",
4
4
  "description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -113,7 +113,7 @@
113
113
  "@metamask/permission-controller": "^11.0.0",
114
114
  "@metamask/preferences-controller": "^17.0.0",
115
115
  "@metamask/providers": "^21.0.0",
116
- "@metamask/snaps-controllers": "^11.2.1",
116
+ "@metamask/snaps-controllers": "^11.0.0",
117
117
  "@metamask/transaction-controller": "^54.0.0",
118
118
  "webextension-polyfill": "^0.10.0 || ^0.11.0 || ^0.12.0"
119
119
  },