@metamask/assets-controllers 69.0.0 → 70.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/dist/MultichainAssetsRatesController/MultichainAssetsRatesController.cjs +45 -7
- package/dist/MultichainAssetsRatesController/MultichainAssetsRatesController.cjs.map +1 -1
- package/dist/MultichainAssetsRatesController/MultichainAssetsRatesController.d.cts +8 -2
- package/dist/MultichainAssetsRatesController/MultichainAssetsRatesController.d.cts.map +1 -1
- package/dist/MultichainAssetsRatesController/MultichainAssetsRatesController.d.mts +8 -2
- package/dist/MultichainAssetsRatesController/MultichainAssetsRatesController.d.mts.map +1 -1
- package/dist/MultichainAssetsRatesController/MultichainAssetsRatesController.mjs +46 -7
- package/dist/MultichainAssetsRatesController/MultichainAssetsRatesController.mjs.map +1 -1
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [70.0.1]
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Bump `@metamask/controller-utils` from `^11.10.0` to `^11.11.0` ([#6069](https://github.com/MetaMask/core/pull/6069))
|
|
15
|
+
- This upgrade includes performance improvements to checksum hex address normalization
|
|
16
|
+
- Bump `@metamask/utils` from `^11.2.0` to `^11.4.2` ([#6054](https://github.com/MetaMask/core/pull/6054))
|
|
17
|
+
|
|
18
|
+
## [70.0.0]
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **BREAKING:** Bump peer dependency `@metamask/snaps-controllers` from `^12.0.0` to `^14.0.0` ([#6035](https://github.com/MetaMask/core/pull/6035))
|
|
23
|
+
- Update `MultichainAssetsRatesController` to use the new `onAssetsMarketData` handler in addition of `onAssetsConversion` to get marketData ([#6035](https://github.com/MetaMask/core/pull/6035))
|
|
24
|
+
- This change improves the handler interface for fetching asset market data from Snaps
|
|
25
|
+
- Bump `@metamask/snaps-sdk` from `^7.1.0` to `^9.0.0` ([#6035](https://github.com/MetaMask/core/pull/6035))
|
|
26
|
+
- Bump `@metamask/snaps-utils` from `^9.4.0` to `^11.0.0` ([#6035](https://github.com/MetaMask/core/pull/6035))
|
|
27
|
+
|
|
10
28
|
## [69.0.0]
|
|
11
29
|
|
|
12
30
|
### Changed
|
|
@@ -1735,7 +1753,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1735
1753
|
|
|
1736
1754
|
- Use Ethers for AssetsContractController ([#845](https://github.com/MetaMask/core/pull/845))
|
|
1737
1755
|
|
|
1738
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@
|
|
1756
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@70.0.1...HEAD
|
|
1757
|
+
[70.0.1]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@70.0.0...@metamask/assets-controllers@70.0.1
|
|
1758
|
+
[70.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@69.0.0...@metamask/assets-controllers@70.0.0
|
|
1739
1759
|
[69.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@68.2.0...@metamask/assets-controllers@69.0.0
|
|
1740
1760
|
[68.2.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@68.1.0...@metamask/assets-controllers@68.2.0
|
|
1741
1761
|
[68.1.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@68.0.0...@metamask/assets-controllers@68.1.0
|
|
@@ -10,13 +10,14 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _MultichainAssetsRatesController_instances, _MultichainAssetsRatesController_mutex, _MultichainAssetsRatesController_currentCurrency, _MultichainAssetsRatesController_accountsAssets, _MultichainAssetsRatesController_isUnlocked, _MultichainAssetsRatesController_isNonEvmAccount, _MultichainAssetsRatesController_listMultichainAccounts, _MultichainAssetsRatesController_listAccounts, _MultichainAssetsRatesController_getUpdatedRatesFor, _MultichainAssetsRatesController_updateAssetsRatesForNewAssets, _MultichainAssetsRatesController_getAccount, _MultichainAssetsRatesController_getAssetsForAccount, _MultichainAssetsRatesController_buildConversions, _MultichainAssetsRatesController_flattenRates, _MultichainAssetsRatesController_buildUpdatedRates, _MultichainAssetsRatesController_applyUpdatedRates, _MultichainAssetsRatesController_handleSnapRequest;
|
|
13
|
+
var _MultichainAssetsRatesController_instances, _MultichainAssetsRatesController_mutex, _MultichainAssetsRatesController_currentCurrency, _MultichainAssetsRatesController_accountsAssets, _MultichainAssetsRatesController_isUnlocked, _MultichainAssetsRatesController_isNonEvmAccount, _MultichainAssetsRatesController_listMultichainAccounts, _MultichainAssetsRatesController_listAccounts, _MultichainAssetsRatesController_getUpdatedRatesFor, _MultichainAssetsRatesController_updateAssetsRatesForNewAssets, _MultichainAssetsRatesController_getAccount, _MultichainAssetsRatesController_getAssetsForAccount, _MultichainAssetsRatesController_buildConversions, _MultichainAssetsRatesController_flattenRates, _MultichainAssetsRatesController_buildUpdatedRates, _MultichainAssetsRatesController_applyUpdatedRates, _MultichainAssetsRatesController_handleSnapRequest, _MultichainAssetsRatesController_mergeMarketDataIntoConversionRates;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.MultichainAssetsRatesController = exports.getDefaultMultichainAssetsRatesControllerState = void 0;
|
|
16
16
|
const keyring_api_1 = require("@metamask/keyring-api");
|
|
17
17
|
const polling_controller_1 = require("@metamask/polling-controller");
|
|
18
18
|
const snaps_utils_1 = require("@metamask/snaps-utils");
|
|
19
19
|
const async_mutex_1 = require("async-mutex");
|
|
20
|
+
const lodash_1 = require("lodash");
|
|
20
21
|
const constant_1 = require("./constant.cjs");
|
|
21
22
|
/**
|
|
22
23
|
* The name of the MultichainAssetsRatesController.
|
|
@@ -196,16 +197,26 @@ _MultichainAssetsRatesController_mutex = new WeakMap(), _MultichainAssetsRatesCo
|
|
|
196
197
|
// Build the conversions array
|
|
197
198
|
const conversions = __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_buildConversions).call(this, assets);
|
|
198
199
|
// Retrieve rates from Snap
|
|
199
|
-
const
|
|
200
|
+
const accountRatesResponse = (await __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_handleSnapRequest).call(this, {
|
|
200
201
|
snapId: account?.metadata.snap?.id,
|
|
201
202
|
handler: snaps_utils_1.HandlerType.OnAssetsConversion,
|
|
202
|
-
params:
|
|
203
|
-
...conversions,
|
|
204
|
-
includeMarketData: true,
|
|
205
|
-
},
|
|
203
|
+
params: conversions,
|
|
206
204
|
}));
|
|
205
|
+
// Prepare assets param for onAssetsMarketData
|
|
206
|
+
const currentCurrencyCaip = constant_1.MAP_CAIP_CURRENCIES[__classPrivateFieldGet(this, _MultichainAssetsRatesController_currentCurrency, "f")] ?? constant_1.MAP_CAIP_CURRENCIES.usd;
|
|
207
|
+
const assetsParam = {
|
|
208
|
+
assets: assets.map((asset) => ({ asset, unit: currentCurrencyCaip })),
|
|
209
|
+
};
|
|
210
|
+
// Retrieve Market Data from Snap
|
|
211
|
+
const marketDataResponse = (await __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_handleSnapRequest).call(this, {
|
|
212
|
+
snapId: account?.metadata.snap?.id,
|
|
213
|
+
handler: snaps_utils_1.HandlerType.OnAssetsMarketData,
|
|
214
|
+
params: assetsParam,
|
|
215
|
+
}));
|
|
216
|
+
// Merge market data into conversion rates if available
|
|
217
|
+
const mergedRates = __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_mergeMarketDataIntoConversionRates).call(this, accountRatesResponse, marketDataResponse);
|
|
207
218
|
// Flatten nested rates if needed
|
|
208
|
-
const flattenedRates = __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_flattenRates).call(this,
|
|
219
|
+
const flattenedRates = __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_flattenRates).call(this, mergedRates);
|
|
209
220
|
// Build the updatedRates object for these assets
|
|
210
221
|
const updatedRates = __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_buildUpdatedRates).call(this, assets, flattenedRates);
|
|
211
222
|
return updatedRates;
|
|
@@ -301,5 +312,32 @@ async function _MultichainAssetsRatesController_handleSnapRequest({ snapId, hand
|
|
|
301
312
|
params,
|
|
302
313
|
},
|
|
303
314
|
});
|
|
315
|
+
}, _MultichainAssetsRatesController_mergeMarketDataIntoConversionRates = function _MultichainAssetsRatesController_mergeMarketDataIntoConversionRates(accountRatesResponse, marketDataResponse) {
|
|
316
|
+
// Early return if no market data to merge
|
|
317
|
+
if (!marketDataResponse?.marketData) {
|
|
318
|
+
return accountRatesResponse;
|
|
319
|
+
}
|
|
320
|
+
const result = (0, lodash_1.cloneDeep)(accountRatesResponse);
|
|
321
|
+
const { conversionRates } = result;
|
|
322
|
+
const { marketData } = marketDataResponse;
|
|
323
|
+
// Iterate through each asset in market data
|
|
324
|
+
for (const [assetId, currencyData] of Object.entries(marketData)) {
|
|
325
|
+
const typedAssetId = assetId;
|
|
326
|
+
// Iterate through each currency for this asset
|
|
327
|
+
for (const [currency, marketDataForCurrency] of Object.entries(currencyData)) {
|
|
328
|
+
const typedCurrency = currency;
|
|
329
|
+
// Check if this currency exists in conversion rates for this asset
|
|
330
|
+
const existingRate = conversionRates[typedAssetId][typedCurrency];
|
|
331
|
+
if (!existingRate) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
// Merge market data into the existing conversion rate
|
|
335
|
+
conversionRates[typedAssetId][typedCurrency] = {
|
|
336
|
+
...existingRate,
|
|
337
|
+
marketData: marketDataForCurrency ?? undefined,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return result;
|
|
304
342
|
};
|
|
305
343
|
//# sourceMappingURL=MultichainAssetsRatesController.cjs.map
|
|
@@ -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 MultichainAssetsControllerAccountAssetListUpdatedEvent,\n MultichainAssetsControllerState,\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 | MultichainAssetsControllerAccountAssetListUpdatedEvent;\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 readonly #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:accountAssetListUpdated',\n async ({ assets }) => {\n const newAccountAssets = Object.entries(assets).map(\n ([accountId, { added }]) => ({\n accountId,\n assets: [...added],\n }),\n );\n // TODO; removed can be used in future for further cleanup\n await this.#updateAssetsRatesForNewAssets(newAccountAssets);\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 const rates = await this.#getUpdatedRatesFor(account, assets);\n // Apply these updated rates to controller state\n this.#applyUpdatedRates(rates);\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n async #getUpdatedRatesFor(\n account: InternalAccount,\n assets: CaipAssetType[],\n ): Promise<Record<string, AssetConversion & { currency: CaipAssetType }>> {\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 return updatedRates;\n }\n\n /**\n * Fetches historical prices for the current account\n *\n * @param asset - The asset to fetch historical prices for.\n * @param account - optional account to fetch historical prices for\n * @returns The historical prices.\n */\n async fetchHistoricalPricesForAsset(\n asset: CaipAssetType,\n account?: InternalAccount,\n ): 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;\n\n const historicalPriceHasExpired =\n historicalPriceExpirationTime &&\n historicalPriceExpirationTime < Date.now();\n\n if (historicalPriceHasExpired === false) {\n return;\n }\n\n const selectedAccount =\n account ??\n this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n try {\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 } catch {\n throw new Error(\n `Failed to fetch historical prices for asset: ${asset}`,\n );\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Updates the conversion rates for new assets.\n *\n * @param accounts - The accounts to update the conversion rates for.\n * @returns A promise that resolves when the rates are updated.\n */\n async #updateAssetsRatesForNewAssets(\n accounts: {\n accountId: string;\n assets: CaipAssetType[];\n }[],\n ): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n\n return (async () => {\n if (!this.isActive) {\n return;\n }\n const allNewRates: Record<\n string,\n { rate: string | null; conversionTime: number | null }\n > = {};\n\n for (const { accountId, assets } of accounts) {\n const account = this.#getAccount(accountId);\n\n const rates = await this.#getUpdatedRatesFor(account, assets);\n // Track new rates\n for (const [asset, rate] of Object.entries(rates)) {\n allNewRates[asset] = rate;\n }\n }\n\n this.#applyUpdatedRates(allNewRates);\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Get a non-EVM account from its ID.\n *\n * @param accountId - The account ID.\n * @returns The non-EVM account.\n */\n #getAccount(accountId: string): InternalAccount {\n const account: InternalAccount | undefined = this.#listAccounts().find(\n (multichainAccount) => multichainAccount.id === accountId,\n );\n\n if (!account) {\n throw new Error(`Unknown account: ${accountId}`);\n }\n\n return account;\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 if (Object.keys(updatedRates).length === 0) {\n return;\n }\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 OnAssetHistoricalPriceArguments,\n OnAssetHistoricalPriceResponse,\n HistoricalPriceIntervals,\n OnAssetsMarketDataArguments,\n OnAssetsMarketDataResponse,\n FungibleAssetMarketData,\n OnAssetsConversionResponse,\n} from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Mutex } from 'async-mutex';\nimport type { Draft } from 'immer';\nimport { cloneDeep } from 'lodash';\n\nimport { MAP_CAIP_CURRENCIES } from './constant';\nimport type {\n CurrencyRateState,\n CurrencyRateStateChange,\n GetCurrencyRateState,\n} from '../CurrencyRateController';\nimport type {\n MultichainAssetsControllerGetStateAction,\n MultichainAssetsControllerAccountAssetListUpdatedEvent,\n MultichainAssetsControllerState,\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, UnifiedAssetConversion>;\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\ntype UnifiedAssetConversion = AssetConversion & {\n marketData?: FungibleAssetMarketData;\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 | MultichainAssetsControllerAccountAssetListUpdatedEvent;\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\nexport type ConversionRatesWithMarketData = {\n conversionRates: Record<\n CaipAssetType,\n Record<CaipAssetType, UnifiedAssetConversion | null>\n >;\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 readonly #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:accountAssetListUpdated',\n async ({ assets }) => {\n const newAccountAssets = Object.entries(assets).map(\n ([accountId, { added }]) => ({\n accountId,\n assets: [...added],\n }),\n );\n // TODO; removed can be used in future for further cleanup\n await this.#updateAssetsRatesForNewAssets(newAccountAssets);\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 const rates = await this.#getUpdatedRatesFor(account, assets);\n // Apply these updated rates to controller state\n this.#applyUpdatedRates(rates);\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n async #getUpdatedRatesFor(\n account: InternalAccount,\n assets: CaipAssetType[],\n ): Promise<\n Record<string, UnifiedAssetConversion & { currency: CaipAssetType }>\n > {\n // Build the conversions array\n const conversions = this.#buildConversions(assets);\n\n // Retrieve rates from Snap\n const accountRatesResponse = (await this.#handleSnapRequest({\n snapId: account?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetsConversion,\n params: conversions,\n })) as OnAssetsConversionResponse;\n\n // Prepare assets param for onAssetsMarketData\n const currentCurrencyCaip =\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ?? MAP_CAIP_CURRENCIES.usd;\n const assetsParam = {\n assets: assets.map((asset) => ({ asset, unit: currentCurrencyCaip })),\n };\n\n // Retrieve Market Data from Snap\n const marketDataResponse = (await this.#handleSnapRequest({\n snapId: account?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetsMarketData,\n params: assetsParam as OnAssetsMarketDataArguments,\n })) as OnAssetsMarketDataResponse;\n\n // Merge market data into conversion rates if available\n const mergedRates = this.#mergeMarketDataIntoConversionRates(\n accountRatesResponse,\n marketDataResponse,\n );\n\n // Flatten nested rates if needed\n const flattenedRates = this.#flattenRates(mergedRates);\n\n // Build the updatedRates object for these assets\n const updatedRates = this.#buildUpdatedRates(assets, flattenedRates);\n\n return updatedRates;\n }\n\n /**\n * Fetches historical prices for the current account\n *\n * @param asset - The asset to fetch historical prices for.\n * @param account - optional account to fetch historical prices for\n * @returns The historical prices.\n */\n async fetchHistoricalPricesForAsset(\n asset: CaipAssetType,\n account?: InternalAccount,\n ): 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;\n\n const historicalPriceHasExpired =\n historicalPriceExpirationTime &&\n historicalPriceExpirationTime < Date.now();\n\n if (historicalPriceHasExpired === false) {\n return;\n }\n\n const selectedAccount =\n account ??\n this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n try {\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 } catch {\n throw new Error(\n `Failed to fetch historical prices for asset: ${asset}`,\n );\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Updates the conversion rates for new assets.\n *\n * @param accounts - The accounts to update the conversion rates for.\n * @returns A promise that resolves when the rates are updated.\n */\n async #updateAssetsRatesForNewAssets(\n accounts: {\n accountId: string;\n assets: CaipAssetType[];\n }[],\n ): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n\n return (async () => {\n if (!this.isActive) {\n return;\n }\n const allNewRates: Record<\n string,\n UnifiedAssetConversion & { currency: CaipAssetType }\n > = {};\n\n for (const { accountId, assets } of accounts) {\n const account = this.#getAccount(accountId);\n\n const rates = await this.#getUpdatedRatesFor(account, assets);\n // Track new rates\n for (const [asset, rate] of Object.entries(rates)) {\n allNewRates[asset] = rate;\n }\n }\n\n this.#applyUpdatedRates(allNewRates);\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Get a non-EVM account from its ID.\n *\n * @param accountId - The account ID.\n * @returns The non-EVM account.\n */\n #getAccount(accountId: string): InternalAccount {\n const account: InternalAccount | undefined = this.#listAccounts().find(\n (multichainAccount) => multichainAccount.id === accountId,\n );\n\n if (!account) {\n throw new Error(`Unknown account: ${accountId}`);\n }\n\n return account;\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: ConversionRatesWithMarketData,\n ): Record<CaipAssetType, UnifiedAssetConversion | 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, UnifiedAssetConversion | null>,\n ): Record<string, UnifiedAssetConversion & { currency: CaipAssetType }> {\n const updatedRates: Record<\n CaipAssetType,\n UnifiedAssetConversion & { currency: CaipAssetType }\n > = {};\n\n for (const asset of assets) {\n if (flattenedRates[asset]) {\n updatedRates[asset] = {\n ...(flattenedRates[asset] as UnifiedAssetConversion),\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 UnifiedAssetConversion & { currency: CaipAssetType }\n >,\n ): void {\n if (Object.keys(updatedRates).length === 0) {\n return;\n }\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:\n | OnAssetsConversionArguments\n | OnAssetHistoricalPriceArguments\n | OnAssetsMarketDataArguments;\n }): Promise<\n | OnAssetsConversionResponse\n | OnAssetHistoricalPriceResponse\n | OnAssetsMarketDataResponse\n | null\n > {\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<\n | OnAssetsConversionResponse\n | OnAssetHistoricalPriceResponse\n | OnAssetsMarketDataResponse\n | null\n >;\n }\n\n #mergeMarketDataIntoConversionRates(\n accountRatesResponse: OnAssetsConversionResponse,\n marketDataResponse: OnAssetsMarketDataResponse,\n ): ConversionRatesWithMarketData {\n // Early return if no market data to merge\n if (!marketDataResponse?.marketData) {\n return accountRatesResponse;\n }\n\n const result: ConversionRatesWithMarketData =\n cloneDeep(accountRatesResponse);\n const { conversionRates } = result;\n const { marketData } = marketDataResponse;\n\n // Iterate through each asset in market data\n for (const [assetId, currencyData] of Object.entries(marketData)) {\n const typedAssetId = assetId as CaipAssetType;\n\n // Iterate through each currency for this asset\n for (const [currency, marketDataForCurrency] of Object.entries(\n currencyData,\n )) {\n const typedCurrency = currency as CaipAssetType;\n\n // Check if this currency exists in conversion rates for this asset\n const existingRate = conversionRates[typedAssetId][typedCurrency];\n if (!existingRate) {\n continue;\n }\n\n // Merge market data into the existing conversion rate\n conversionRates[typedAssetId][typedCurrency] = {\n ...existingRate,\n marketData: marketDataForCurrency ?? undefined,\n };\n }\n }\n\n return result;\n }\n}\n"]}
|
|
@@ -4,7 +4,7 @@ import { type CaipAssetType } from "@metamask/keyring-api";
|
|
|
4
4
|
import type { KeyringControllerLockEvent, KeyringControllerUnlockEvent } from "@metamask/keyring-controller";
|
|
5
5
|
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
6
6
|
import type { HandleSnapRequest } from "@metamask/snaps-controllers";
|
|
7
|
-
import type { AssetConversion, HistoricalPriceIntervals } from "@metamask/snaps-sdk";
|
|
7
|
+
import type { AssetConversion, HistoricalPriceIntervals, FungibleAssetMarketData } from "@metamask/snaps-sdk";
|
|
8
8
|
import type { CurrencyRateStateChange, GetCurrencyRateState } from "../CurrencyRateController.cjs";
|
|
9
9
|
import type { MultichainAssetsControllerGetStateAction, MultichainAssetsControllerAccountAssetListUpdatedEvent } from "../MultichainAssetsController/index.cjs";
|
|
10
10
|
/**
|
|
@@ -20,7 +20,7 @@ type HistoricalPrice = {
|
|
|
20
20
|
* State used by the MultichainAssetsRatesController to cache token conversion rates.
|
|
21
21
|
*/
|
|
22
22
|
export type MultichainAssetsRatesControllerState = {
|
|
23
|
-
conversionRates: Record<CaipAssetType,
|
|
23
|
+
conversionRates: Record<CaipAssetType, UnifiedAssetConversion>;
|
|
24
24
|
historicalPrices: Record<CaipAssetType, Record<string, HistoricalPrice>>;
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
@@ -34,6 +34,9 @@ export type MultichainAssetsRatesControllerUpdateRatesAction = {
|
|
|
34
34
|
type: `${typeof controllerName}:updateAssetsRates`;
|
|
35
35
|
handler: MultichainAssetsRatesController['updateAssetsRates'];
|
|
36
36
|
};
|
|
37
|
+
type UnifiedAssetConversion = AssetConversion & {
|
|
38
|
+
marketData?: FungibleAssetMarketData;
|
|
39
|
+
};
|
|
37
40
|
/**
|
|
38
41
|
* Constructs the default {@link MultichainAssetsRatesController} state. This allows
|
|
39
42
|
* consumers to provide a partial state object when initializing the controller
|
|
@@ -73,6 +76,9 @@ export type MultichainAssetsRatesControllerMessenger = RestrictedMessenger<typeo
|
|
|
73
76
|
export type MultichainAssetsRatesPollingInput = {
|
|
74
77
|
accountId: string;
|
|
75
78
|
};
|
|
79
|
+
export type ConversionRatesWithMarketData = {
|
|
80
|
+
conversionRates: Record<CaipAssetType, Record<CaipAssetType, UnifiedAssetConversion | null>>;
|
|
81
|
+
};
|
|
76
82
|
declare const MultichainAssetsRatesController_base: (abstract new (...args: any[]) => {
|
|
77
83
|
readonly "__#14@#intervalIds": Record<string, NodeJS.Timeout>;
|
|
78
84
|
"__#14@#intervalLength": number | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainAssetsRatesController.d.cts","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8CAA8C,EAC9C,mCAAmC,EACnC,oDAAoD,EACrD,sCAAsC;AACvC,OAAO,KAAK,EACV,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACzB,kCAAkC;AACnC,OAAO,EAAE,KAAK,aAAa,EAAoB,8BAA8B;AAC7E,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,qCAAqC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,oCAAoC;AACrE,OAAO,KAAK,EAEV,eAAe,
|
|
1
|
+
{"version":3,"file":"MultichainAssetsRatesController.d.cts","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { type CaipAssetType } from "@metamask/keyring-api";
|
|
|
4
4
|
import type { KeyringControllerLockEvent, KeyringControllerUnlockEvent } from "@metamask/keyring-controller";
|
|
5
5
|
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
6
6
|
import type { HandleSnapRequest } from "@metamask/snaps-controllers";
|
|
7
|
-
import type { AssetConversion, HistoricalPriceIntervals } from "@metamask/snaps-sdk";
|
|
7
|
+
import type { AssetConversion, HistoricalPriceIntervals, FungibleAssetMarketData } from "@metamask/snaps-sdk";
|
|
8
8
|
import type { CurrencyRateStateChange, GetCurrencyRateState } from "../CurrencyRateController.mjs";
|
|
9
9
|
import type { MultichainAssetsControllerGetStateAction, MultichainAssetsControllerAccountAssetListUpdatedEvent } from "../MultichainAssetsController/index.mjs";
|
|
10
10
|
/**
|
|
@@ -20,7 +20,7 @@ type HistoricalPrice = {
|
|
|
20
20
|
* State used by the MultichainAssetsRatesController to cache token conversion rates.
|
|
21
21
|
*/
|
|
22
22
|
export type MultichainAssetsRatesControllerState = {
|
|
23
|
-
conversionRates: Record<CaipAssetType,
|
|
23
|
+
conversionRates: Record<CaipAssetType, UnifiedAssetConversion>;
|
|
24
24
|
historicalPrices: Record<CaipAssetType, Record<string, HistoricalPrice>>;
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
@@ -34,6 +34,9 @@ export type MultichainAssetsRatesControllerUpdateRatesAction = {
|
|
|
34
34
|
type: `${typeof controllerName}:updateAssetsRates`;
|
|
35
35
|
handler: MultichainAssetsRatesController['updateAssetsRates'];
|
|
36
36
|
};
|
|
37
|
+
type UnifiedAssetConversion = AssetConversion & {
|
|
38
|
+
marketData?: FungibleAssetMarketData;
|
|
39
|
+
};
|
|
37
40
|
/**
|
|
38
41
|
* Constructs the default {@link MultichainAssetsRatesController} state. This allows
|
|
39
42
|
* consumers to provide a partial state object when initializing the controller
|
|
@@ -73,6 +76,9 @@ export type MultichainAssetsRatesControllerMessenger = RestrictedMessenger<typeo
|
|
|
73
76
|
export type MultichainAssetsRatesPollingInput = {
|
|
74
77
|
accountId: string;
|
|
75
78
|
};
|
|
79
|
+
export type ConversionRatesWithMarketData = {
|
|
80
|
+
conversionRates: Record<CaipAssetType, Record<CaipAssetType, UnifiedAssetConversion | null>>;
|
|
81
|
+
};
|
|
76
82
|
declare const MultichainAssetsRatesController_base: (abstract new (...args: any[]) => {
|
|
77
83
|
readonly "__#14@#intervalIds": Record<string, NodeJS.Timeout>;
|
|
78
84
|
"__#14@#intervalLength": number | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainAssetsRatesController.d.mts","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8CAA8C,EAC9C,mCAAmC,EACnC,oDAAoD,EACrD,sCAAsC;AACvC,OAAO,KAAK,EACV,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACzB,kCAAkC;AACnC,OAAO,EAAE,KAAK,aAAa,EAAoB,8BAA8B;AAC7E,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,qCAAqC;AACtC,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,oCAAoC;AACrE,OAAO,KAAK,EAEV,eAAe,
|
|
1
|
+
{"version":3,"file":"MultichainAssetsRatesController.d.mts","sourceRoot":"","sources":["../../src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,11 +9,13 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _MultichainAssetsRatesController_instances, _MultichainAssetsRatesController_mutex, _MultichainAssetsRatesController_currentCurrency, _MultichainAssetsRatesController_accountsAssets, _MultichainAssetsRatesController_isUnlocked, _MultichainAssetsRatesController_isNonEvmAccount, _MultichainAssetsRatesController_listMultichainAccounts, _MultichainAssetsRatesController_listAccounts, _MultichainAssetsRatesController_getUpdatedRatesFor, _MultichainAssetsRatesController_updateAssetsRatesForNewAssets, _MultichainAssetsRatesController_getAccount, _MultichainAssetsRatesController_getAssetsForAccount, _MultichainAssetsRatesController_buildConversions, _MultichainAssetsRatesController_flattenRates, _MultichainAssetsRatesController_buildUpdatedRates, _MultichainAssetsRatesController_applyUpdatedRates, _MultichainAssetsRatesController_handleSnapRequest;
|
|
12
|
+
var _MultichainAssetsRatesController_instances, _MultichainAssetsRatesController_mutex, _MultichainAssetsRatesController_currentCurrency, _MultichainAssetsRatesController_accountsAssets, _MultichainAssetsRatesController_isUnlocked, _MultichainAssetsRatesController_isNonEvmAccount, _MultichainAssetsRatesController_listMultichainAccounts, _MultichainAssetsRatesController_listAccounts, _MultichainAssetsRatesController_getUpdatedRatesFor, _MultichainAssetsRatesController_updateAssetsRatesForNewAssets, _MultichainAssetsRatesController_getAccount, _MultichainAssetsRatesController_getAssetsForAccount, _MultichainAssetsRatesController_buildConversions, _MultichainAssetsRatesController_flattenRates, _MultichainAssetsRatesController_buildUpdatedRates, _MultichainAssetsRatesController_applyUpdatedRates, _MultichainAssetsRatesController_handleSnapRequest, _MultichainAssetsRatesController_mergeMarketDataIntoConversionRates;
|
|
13
13
|
import { isEvmAccountType } from "@metamask/keyring-api";
|
|
14
14
|
import { StaticIntervalPollingController } from "@metamask/polling-controller";
|
|
15
15
|
import { HandlerType } from "@metamask/snaps-utils";
|
|
16
16
|
import { Mutex } from "async-mutex";
|
|
17
|
+
import $lodash from "lodash";
|
|
18
|
+
const { cloneDeep } = $lodash;
|
|
17
19
|
import { MAP_CAIP_CURRENCIES } from "./constant.mjs";
|
|
18
20
|
/**
|
|
19
21
|
* The name of the MultichainAssetsRatesController.
|
|
@@ -191,16 +193,26 @@ _MultichainAssetsRatesController_mutex = new WeakMap(), _MultichainAssetsRatesCo
|
|
|
191
193
|
// Build the conversions array
|
|
192
194
|
const conversions = __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_buildConversions).call(this, assets);
|
|
193
195
|
// Retrieve rates from Snap
|
|
194
|
-
const
|
|
196
|
+
const accountRatesResponse = (await __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_handleSnapRequest).call(this, {
|
|
195
197
|
snapId: account?.metadata.snap?.id,
|
|
196
198
|
handler: HandlerType.OnAssetsConversion,
|
|
197
|
-
params:
|
|
198
|
-
...conversions,
|
|
199
|
-
includeMarketData: true,
|
|
200
|
-
},
|
|
199
|
+
params: conversions,
|
|
201
200
|
}));
|
|
201
|
+
// Prepare assets param for onAssetsMarketData
|
|
202
|
+
const currentCurrencyCaip = MAP_CAIP_CURRENCIES[__classPrivateFieldGet(this, _MultichainAssetsRatesController_currentCurrency, "f")] ?? MAP_CAIP_CURRENCIES.usd;
|
|
203
|
+
const assetsParam = {
|
|
204
|
+
assets: assets.map((asset) => ({ asset, unit: currentCurrencyCaip })),
|
|
205
|
+
};
|
|
206
|
+
// Retrieve Market Data from Snap
|
|
207
|
+
const marketDataResponse = (await __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_handleSnapRequest).call(this, {
|
|
208
|
+
snapId: account?.metadata.snap?.id,
|
|
209
|
+
handler: HandlerType.OnAssetsMarketData,
|
|
210
|
+
params: assetsParam,
|
|
211
|
+
}));
|
|
212
|
+
// Merge market data into conversion rates if available
|
|
213
|
+
const mergedRates = __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_mergeMarketDataIntoConversionRates).call(this, accountRatesResponse, marketDataResponse);
|
|
202
214
|
// Flatten nested rates if needed
|
|
203
|
-
const flattenedRates = __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_flattenRates).call(this,
|
|
215
|
+
const flattenedRates = __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_flattenRates).call(this, mergedRates);
|
|
204
216
|
// Build the updatedRates object for these assets
|
|
205
217
|
const updatedRates = __classPrivateFieldGet(this, _MultichainAssetsRatesController_instances, "m", _MultichainAssetsRatesController_buildUpdatedRates).call(this, assets, flattenedRates);
|
|
206
218
|
return updatedRates;
|
|
@@ -296,5 +308,32 @@ async function _MultichainAssetsRatesController_handleSnapRequest({ snapId, hand
|
|
|
296
308
|
params,
|
|
297
309
|
},
|
|
298
310
|
});
|
|
311
|
+
}, _MultichainAssetsRatesController_mergeMarketDataIntoConversionRates = function _MultichainAssetsRatesController_mergeMarketDataIntoConversionRates(accountRatesResponse, marketDataResponse) {
|
|
312
|
+
// Early return if no market data to merge
|
|
313
|
+
if (!marketDataResponse?.marketData) {
|
|
314
|
+
return accountRatesResponse;
|
|
315
|
+
}
|
|
316
|
+
const result = cloneDeep(accountRatesResponse);
|
|
317
|
+
const { conversionRates } = result;
|
|
318
|
+
const { marketData } = marketDataResponse;
|
|
319
|
+
// Iterate through each asset in market data
|
|
320
|
+
for (const [assetId, currencyData] of Object.entries(marketData)) {
|
|
321
|
+
const typedAssetId = assetId;
|
|
322
|
+
// Iterate through each currency for this asset
|
|
323
|
+
for (const [currency, marketDataForCurrency] of Object.entries(currencyData)) {
|
|
324
|
+
const typedCurrency = currency;
|
|
325
|
+
// Check if this currency exists in conversion rates for this asset
|
|
326
|
+
const existingRate = conversionRates[typedAssetId][typedCurrency];
|
|
327
|
+
if (!existingRate) {
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
// Merge market data into the existing conversion rate
|
|
331
|
+
conversionRates[typedAssetId][typedCurrency] = {
|
|
332
|
+
...existingRate,
|
|
333
|
+
marketData: marketDataForCurrency ?? undefined,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return result;
|
|
299
338
|
};
|
|
300
339
|
//# sourceMappingURL=MultichainAssetsRatesController.mjs.map
|
|
@@ -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 MultichainAssetsControllerAccountAssetListUpdatedEvent,\n MultichainAssetsControllerState,\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 | MultichainAssetsControllerAccountAssetListUpdatedEvent;\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 readonly #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:accountAssetListUpdated',\n async ({ assets }) => {\n const newAccountAssets = Object.entries(assets).map(\n ([accountId, { added }]) => ({\n accountId,\n assets: [...added],\n }),\n );\n // TODO; removed can be used in future for further cleanup\n await this.#updateAssetsRatesForNewAssets(newAccountAssets);\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 const rates = await this.#getUpdatedRatesFor(account, assets);\n // Apply these updated rates to controller state\n this.#applyUpdatedRates(rates);\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n async #getUpdatedRatesFor(\n account: InternalAccount,\n assets: CaipAssetType[],\n ): Promise<Record<string, AssetConversion & { currency: CaipAssetType }>> {\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 return updatedRates;\n }\n\n /**\n * Fetches historical prices for the current account\n *\n * @param asset - The asset to fetch historical prices for.\n * @param account - optional account to fetch historical prices for\n * @returns The historical prices.\n */\n async fetchHistoricalPricesForAsset(\n asset: CaipAssetType,\n account?: InternalAccount,\n ): 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;\n\n const historicalPriceHasExpired =\n historicalPriceExpirationTime &&\n historicalPriceExpirationTime < Date.now();\n\n if (historicalPriceHasExpired === false) {\n return;\n }\n\n const selectedAccount =\n account ??\n this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n try {\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 } catch {\n throw new Error(\n `Failed to fetch historical prices for asset: ${asset}`,\n );\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Updates the conversion rates for new assets.\n *\n * @param accounts - The accounts to update the conversion rates for.\n * @returns A promise that resolves when the rates are updated.\n */\n async #updateAssetsRatesForNewAssets(\n accounts: {\n accountId: string;\n assets: CaipAssetType[];\n }[],\n ): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n\n return (async () => {\n if (!this.isActive) {\n return;\n }\n const allNewRates: Record<\n string,\n { rate: string | null; conversionTime: number | null }\n > = {};\n\n for (const { accountId, assets } of accounts) {\n const account = this.#getAccount(accountId);\n\n const rates = await this.#getUpdatedRatesFor(account, assets);\n // Track new rates\n for (const [asset, rate] of Object.entries(rates)) {\n allNewRates[asset] = rate;\n }\n }\n\n this.#applyUpdatedRates(allNewRates);\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Get a non-EVM account from its ID.\n *\n * @param accountId - The account ID.\n * @returns The non-EVM account.\n */\n #getAccount(accountId: string): InternalAccount {\n const account: InternalAccount | undefined = this.#listAccounts().find(\n (multichainAccount) => multichainAccount.id === accountId,\n );\n\n if (!account) {\n throw new Error(`Unknown account: ${accountId}`);\n }\n\n return account;\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 if (Object.keys(updatedRates).length === 0) {\n return;\n }\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 OnAssetHistoricalPriceArguments,\n OnAssetHistoricalPriceResponse,\n HistoricalPriceIntervals,\n OnAssetsMarketDataArguments,\n OnAssetsMarketDataResponse,\n FungibleAssetMarketData,\n OnAssetsConversionResponse,\n} from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Mutex } from 'async-mutex';\nimport type { Draft } from 'immer';\nimport { cloneDeep } from 'lodash';\n\nimport { MAP_CAIP_CURRENCIES } from './constant';\nimport type {\n CurrencyRateState,\n CurrencyRateStateChange,\n GetCurrencyRateState,\n} from '../CurrencyRateController';\nimport type {\n MultichainAssetsControllerGetStateAction,\n MultichainAssetsControllerAccountAssetListUpdatedEvent,\n MultichainAssetsControllerState,\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, UnifiedAssetConversion>;\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\ntype UnifiedAssetConversion = AssetConversion & {\n marketData?: FungibleAssetMarketData;\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 | MultichainAssetsControllerAccountAssetListUpdatedEvent;\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\nexport type ConversionRatesWithMarketData = {\n conversionRates: Record<\n CaipAssetType,\n Record<CaipAssetType, UnifiedAssetConversion | null>\n >;\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 readonly #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:accountAssetListUpdated',\n async ({ assets }) => {\n const newAccountAssets = Object.entries(assets).map(\n ([accountId, { added }]) => ({\n accountId,\n assets: [...added],\n }),\n );\n // TODO; removed can be used in future for further cleanup\n await this.#updateAssetsRatesForNewAssets(newAccountAssets);\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 const rates = await this.#getUpdatedRatesFor(account, assets);\n // Apply these updated rates to controller state\n this.#applyUpdatedRates(rates);\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n async #getUpdatedRatesFor(\n account: InternalAccount,\n assets: CaipAssetType[],\n ): Promise<\n Record<string, UnifiedAssetConversion & { currency: CaipAssetType }>\n > {\n // Build the conversions array\n const conversions = this.#buildConversions(assets);\n\n // Retrieve rates from Snap\n const accountRatesResponse = (await this.#handleSnapRequest({\n snapId: account?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetsConversion,\n params: conversions,\n })) as OnAssetsConversionResponse;\n\n // Prepare assets param for onAssetsMarketData\n const currentCurrencyCaip =\n MAP_CAIP_CURRENCIES[this.#currentCurrency] ?? MAP_CAIP_CURRENCIES.usd;\n const assetsParam = {\n assets: assets.map((asset) => ({ asset, unit: currentCurrencyCaip })),\n };\n\n // Retrieve Market Data from Snap\n const marketDataResponse = (await this.#handleSnapRequest({\n snapId: account?.metadata.snap?.id as SnapId,\n handler: HandlerType.OnAssetsMarketData,\n params: assetsParam as OnAssetsMarketDataArguments,\n })) as OnAssetsMarketDataResponse;\n\n // Merge market data into conversion rates if available\n const mergedRates = this.#mergeMarketDataIntoConversionRates(\n accountRatesResponse,\n marketDataResponse,\n );\n\n // Flatten nested rates if needed\n const flattenedRates = this.#flattenRates(mergedRates);\n\n // Build the updatedRates object for these assets\n const updatedRates = this.#buildUpdatedRates(assets, flattenedRates);\n\n return updatedRates;\n }\n\n /**\n * Fetches historical prices for the current account\n *\n * @param asset - The asset to fetch historical prices for.\n * @param account - optional account to fetch historical prices for\n * @returns The historical prices.\n */\n async fetchHistoricalPricesForAsset(\n asset: CaipAssetType,\n account?: InternalAccount,\n ): 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;\n\n const historicalPriceHasExpired =\n historicalPriceExpirationTime &&\n historicalPriceExpirationTime < Date.now();\n\n if (historicalPriceHasExpired === false) {\n return;\n }\n\n const selectedAccount =\n account ??\n this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n try {\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 } catch {\n throw new Error(\n `Failed to fetch historical prices for asset: ${asset}`,\n );\n }\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Updates the conversion rates for new assets.\n *\n * @param accounts - The accounts to update the conversion rates for.\n * @returns A promise that resolves when the rates are updated.\n */\n async #updateAssetsRatesForNewAssets(\n accounts: {\n accountId: string;\n assets: CaipAssetType[];\n }[],\n ): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n\n return (async () => {\n if (!this.isActive) {\n return;\n }\n const allNewRates: Record<\n string,\n UnifiedAssetConversion & { currency: CaipAssetType }\n > = {};\n\n for (const { accountId, assets } of accounts) {\n const account = this.#getAccount(accountId);\n\n const rates = await this.#getUpdatedRatesFor(account, assets);\n // Track new rates\n for (const [asset, rate] of Object.entries(rates)) {\n allNewRates[asset] = rate;\n }\n }\n\n this.#applyUpdatedRates(allNewRates);\n })().finally(() => {\n releaseLock();\n });\n }\n\n /**\n * Get a non-EVM account from its ID.\n *\n * @param accountId - The account ID.\n * @returns The non-EVM account.\n */\n #getAccount(accountId: string): InternalAccount {\n const account: InternalAccount | undefined = this.#listAccounts().find(\n (multichainAccount) => multichainAccount.id === accountId,\n );\n\n if (!account) {\n throw new Error(`Unknown account: ${accountId}`);\n }\n\n return account;\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: ConversionRatesWithMarketData,\n ): Record<CaipAssetType, UnifiedAssetConversion | 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, UnifiedAssetConversion | null>,\n ): Record<string, UnifiedAssetConversion & { currency: CaipAssetType }> {\n const updatedRates: Record<\n CaipAssetType,\n UnifiedAssetConversion & { currency: CaipAssetType }\n > = {};\n\n for (const asset of assets) {\n if (flattenedRates[asset]) {\n updatedRates[asset] = {\n ...(flattenedRates[asset] as UnifiedAssetConversion),\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 UnifiedAssetConversion & { currency: CaipAssetType }\n >,\n ): void {\n if (Object.keys(updatedRates).length === 0) {\n return;\n }\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:\n | OnAssetsConversionArguments\n | OnAssetHistoricalPriceArguments\n | OnAssetsMarketDataArguments;\n }): Promise<\n | OnAssetsConversionResponse\n | OnAssetHistoricalPriceResponse\n | OnAssetsMarketDataResponse\n | null\n > {\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<\n | OnAssetsConversionResponse\n | OnAssetHistoricalPriceResponse\n | OnAssetsMarketDataResponse\n | null\n >;\n }\n\n #mergeMarketDataIntoConversionRates(\n accountRatesResponse: OnAssetsConversionResponse,\n marketDataResponse: OnAssetsMarketDataResponse,\n ): ConversionRatesWithMarketData {\n // Early return if no market data to merge\n if (!marketDataResponse?.marketData) {\n return accountRatesResponse;\n }\n\n const result: ConversionRatesWithMarketData =\n cloneDeep(accountRatesResponse);\n const { conversionRates } = result;\n const { marketData } = marketDataResponse;\n\n // Iterate through each asset in market data\n for (const [assetId, currencyData] of Object.entries(marketData)) {\n const typedAssetId = assetId as CaipAssetType;\n\n // Iterate through each currency for this asset\n for (const [currency, marketDataForCurrency] of Object.entries(\n currencyData,\n )) {\n const typedCurrency = currency as CaipAssetType;\n\n // Check if this currency exists in conversion rates for this asset\n const existingRate = conversionRates[typedAssetId][typedCurrency];\n if (!existingRate) {\n continue;\n }\n\n // Merge market data into the existing conversion rate\n conversionRates[typedAssetId][typedCurrency] = {\n ...existingRate,\n marketData: marketDataForCurrency ?? undefined,\n };\n }\n }\n\n return result;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask/assets-controllers",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "70.0.1",
|
|
4
4
|
"description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
@@ -56,14 +56,15 @@
|
|
|
56
56
|
"@metamask/abi-utils": "^2.0.3",
|
|
57
57
|
"@metamask/base-controller": "^8.0.1",
|
|
58
58
|
"@metamask/contract-metadata": "^2.4.0",
|
|
59
|
-
"@metamask/controller-utils": "^11.
|
|
59
|
+
"@metamask/controller-utils": "^11.11.0",
|
|
60
60
|
"@metamask/eth-query": "^4.0.0",
|
|
61
61
|
"@metamask/keyring-api": "^18.0.0",
|
|
62
62
|
"@metamask/metamask-eth-abis": "^3.1.1",
|
|
63
63
|
"@metamask/polling-controller": "^14.0.0",
|
|
64
64
|
"@metamask/rpc-errors": "^7.0.2",
|
|
65
|
-
"@metamask/snaps-
|
|
66
|
-
"@metamask/utils": "^11.
|
|
65
|
+
"@metamask/snaps-sdk": "^9.0.0",
|
|
66
|
+
"@metamask/snaps-utils": "^11.0.0",
|
|
67
|
+
"@metamask/utils": "^11.4.2",
|
|
67
68
|
"@types/bn.js": "^5.1.5",
|
|
68
69
|
"@types/uuid": "^8.3.0",
|
|
69
70
|
"async-mutex": "^0.5.0",
|
|
@@ -81,17 +82,16 @@
|
|
|
81
82
|
"@metamask/approval-controller": "^7.1.3",
|
|
82
83
|
"@metamask/auto-changelog": "^3.4.4",
|
|
83
84
|
"@metamask/ethjs-provider-http": "^0.3.0",
|
|
84
|
-
"@metamask/keyring-controller": "^22.0
|
|
85
|
+
"@metamask/keyring-controller": "^22.1.0",
|
|
85
86
|
"@metamask/keyring-internal-api": "^6.2.0",
|
|
86
87
|
"@metamask/keyring-snap-client": "^5.0.0",
|
|
87
88
|
"@metamask/network-controller": "^24.0.0",
|
|
88
89
|
"@metamask/permission-controller": "^11.0.6",
|
|
89
90
|
"@metamask/phishing-controller": "^12.6.0",
|
|
90
|
-
"@metamask/preferences-controller": "^18.1
|
|
91
|
+
"@metamask/preferences-controller": "^18.4.1",
|
|
91
92
|
"@metamask/providers": "^22.1.0",
|
|
92
|
-
"@metamask/snaps-controllers": "^
|
|
93
|
-
"@metamask/
|
|
94
|
-
"@metamask/transaction-controller": "^58.0.0",
|
|
93
|
+
"@metamask/snaps-controllers": "^14.0.1",
|
|
94
|
+
"@metamask/transaction-controller": "^58.1.1",
|
|
95
95
|
"@types/jest": "^27.4.1",
|
|
96
96
|
"@types/lodash": "^4.14.191",
|
|
97
97
|
"@types/node": "^16.18.54",
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
"@metamask/phishing-controller": "^12.5.0",
|
|
116
116
|
"@metamask/preferences-controller": "^18.0.0",
|
|
117
117
|
"@metamask/providers": "^22.0.0",
|
|
118
|
-
"@metamask/snaps-controllers": "^
|
|
118
|
+
"@metamask/snaps-controllers": "^14.0.0",
|
|
119
119
|
"@metamask/transaction-controller": "^58.0.0",
|
|
120
120
|
"webextension-polyfill": "^0.10.0 || ^0.11.0 || ^0.12.0"
|
|
121
121
|
},
|