@metamask/assets-controller 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/dist/AssetsController-method-action-types.cjs.map +1 -1
  3. package/dist/AssetsController-method-action-types.d.cts +16 -1
  4. package/dist/AssetsController-method-action-types.d.cts.map +1 -1
  5. package/dist/AssetsController-method-action-types.d.mts +16 -1
  6. package/dist/AssetsController-method-action-types.d.mts.map +1 -1
  7. package/dist/AssetsController-method-action-types.mjs.map +1 -1
  8. package/dist/AssetsController.cjs +25 -1
  9. package/dist/AssetsController.cjs.map +1 -1
  10. package/dist/AssetsController.d.cts +15 -0
  11. package/dist/AssetsController.d.cts.map +1 -1
  12. package/dist/AssetsController.d.mts +15 -0
  13. package/dist/AssetsController.d.mts.map +1 -1
  14. package/dist/AssetsController.mjs +25 -1
  15. package/dist/AssetsController.mjs.map +1 -1
  16. package/dist/data-sources/AccountsApiDataSource.cjs +1 -1
  17. package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
  18. package/dist/data-sources/AccountsApiDataSource.mjs +1 -1
  19. package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
  20. package/dist/index.cjs +3 -2
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +3 -2
  23. package/dist/index.d.cts.map +1 -1
  24. package/dist/index.d.mts +3 -2
  25. package/dist/index.d.mts.map +1 -1
  26. package/dist/index.mjs +1 -1
  27. package/dist/index.mjs.map +1 -1
  28. package/dist/utils/formatExchangeRatesForBridge.cjs +123 -0
  29. package/dist/utils/formatExchangeRatesForBridge.cjs.map +1 -0
  30. package/dist/utils/formatExchangeRatesForBridge.d.cts +65 -0
  31. package/dist/utils/formatExchangeRatesForBridge.d.cts.map +1 -0
  32. package/dist/utils/formatExchangeRatesForBridge.d.mts +65 -0
  33. package/dist/utils/formatExchangeRatesForBridge.d.mts.map +1 -0
  34. package/dist/utils/formatExchangeRatesForBridge.mjs +119 -0
  35. package/dist/utils/formatExchangeRatesForBridge.mjs.map +1 -0
  36. package/dist/utils/index.cjs +8 -0
  37. package/dist/utils/index.cjs.map +1 -0
  38. package/dist/utils/index.d.cts +4 -0
  39. package/dist/utils/index.d.cts.map +1 -0
  40. package/dist/utils/index.d.mts +4 -0
  41. package/dist/utils/index.d.mts.map +1 -0
  42. package/dist/utils/index.mjs +3 -0
  43. package/dist/utils/index.mjs.map +1 -0
  44. package/dist/{utils.cjs → utils/normalizeAssetId.cjs} +1 -1
  45. package/dist/utils/normalizeAssetId.cjs.map +1 -0
  46. package/dist/{utils.d.mts → utils/normalizeAssetId.d.cts} +2 -2
  47. package/dist/utils/normalizeAssetId.d.cts.map +1 -0
  48. package/dist/{utils.d.cts → utils/normalizeAssetId.d.mts} +2 -2
  49. package/dist/utils/normalizeAssetId.d.mts.map +1 -0
  50. package/dist/{utils.mjs → utils/normalizeAssetId.mjs} +1 -1
  51. package/dist/utils/normalizeAssetId.mjs.map +1 -0
  52. package/package.json +1 -1
  53. package/dist/utils.cjs.map +0 -1
  54. package/dist/utils.d.cts.map +0 -1
  55. package/dist/utils.d.mts.map +0 -1
  56. package/dist/utils.mjs.map +0 -1
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatExchangeRatesForBridge = void 0;
4
+ const util_1 = require("@ethereumjs/util");
5
+ const assets_controllers_1 = require("@metamask/assets-controllers");
6
+ const utils_1 = require("@metamask/utils");
7
+ const utils_2 = require("@metamask/utils");
8
+ function getPriceNumber(price) {
9
+ return typeof price === 'object' && price !== null && 'price' in price
10
+ ? Number(price.price)
11
+ : Number.NaN;
12
+ }
13
+ /**
14
+ * Converts AssetsController state (assetsPrice, selectedCurrency) into the
15
+ * same format the bridge expects from MultichainAssetsRatesController,
16
+ * CurrencyRateController, and TokenRatesController so the bridge can use
17
+ * a single action when useAssetsControllerForRates is true.
18
+ *
19
+ * @param params - Conversion parameters.
20
+ * @param params.assetsPrice - Map of CAIP-19 asset ID to price data. Prices are in USD.
21
+ * @param params.selectedCurrency - ISO 4217 currency code (e.g. 'usd').
22
+ * @param params.nativeAssetIdentifiers - Optional map of CAIP-2 chain ID to native asset ID (e.g. from NetworkEnablementController state). When provided, used for EVM native lookups.
23
+ * @param params.networkConfigurationsByChainId - Optional map of Hex chain ID to network config (e.g. from NetworkController state). Used to resolve native currency symbol via `nativeCurrency`; keys are Hex (e.g. '0x1').
24
+ * @param params.usdToSelectedCurrencyRate - Optional rate: 1 USD = this many units of selected currency. Required for correct bridge USD conversion when selectedCurrency is not 'usd'. When omitted and selectedCurrency !== 'usd', currencyRates will use the same value for conversionRate and usdConversionRate (ratio 1), which produces incorrect USD rates.
25
+ * @returns Bridge-compatible conversionRates, currencyRates, marketData, currentCurrency.
26
+ */
27
+ function formatExchangeRatesForBridge(params) {
28
+ const { assetsPrice, selectedCurrency, nativeAssetIdentifiers = {}, networkConfigurationsByChainId = {}, usdToSelectedCurrencyRate, } = params;
29
+ const conversionRates = {};
30
+ const currencyRates = {};
31
+ const marketData = {};
32
+ // Same as MultichainAssetsRatesController: resolve CAIP currency from selectedCurrency, default to USD
33
+ const currencyCaip = assets_controllers_1.MAP_CAIP_CURRENCIES[selectedCurrency.toLowerCase()] ??
34
+ assets_controllers_1.MAP_CAIP_CURRENCIES.usd;
35
+ const expirationOffset = 60;
36
+ // Price in assetsPrice is in USD. For bridge: conversionRate = in user's currency, usdConversionRate = in USD.
37
+ const isUsd = selectedCurrency.toLowerCase() === 'usd';
38
+ const rateUserCurrencyPerUsd = isUsd ? 1 : (usdToSelectedCurrencyRate ?? 1);
39
+ for (const [assetId, priceData] of Object.entries(assetsPrice)) {
40
+ const price = getPriceNumber(priceData);
41
+ if (Number.isNaN(price) || price < 0) {
42
+ continue;
43
+ }
44
+ const lastUpdated = typeof priceData === 'object' &&
45
+ priceData !== null &&
46
+ 'lastUpdated' in priceData
47
+ ? Number(priceData.lastUpdated)
48
+ : Date.now();
49
+ const conversionTime = lastUpdated > 1e12 ? lastUpdated / 1000 : lastUpdated;
50
+ const expirationTime = conversionTime + expirationOffset;
51
+ try {
52
+ const parsed = (0, utils_2.parseCaipAssetType)(assetId);
53
+ const chainIdParsed = (0, utils_2.parseCaipChainId)(parsed.chainId);
54
+ const chainRef = chainIdParsed.reference;
55
+ // conversionRates: only non-EVM assets (bridge uses this for non-EVM chains). Rate in selected currency.
56
+ if (chainIdParsed.namespace !== 'eip155') {
57
+ const priceInUserCurrency = price * rateUserCurrencyPerUsd;
58
+ conversionRates[assetId] = {
59
+ rate: String(priceInUserCurrency),
60
+ currency: currencyCaip,
61
+ conversionTime,
62
+ expirationTime,
63
+ marketData: typeof priceData === 'object' && priceData !== null
64
+ ? priceData
65
+ : undefined,
66
+ };
67
+ }
68
+ if (chainIdParsed.namespace === 'eip155') {
69
+ const chainIdHex = (0, utils_1.numberToHex)(parseInt(chainRef, 10));
70
+ const nativeAssetId = nativeAssetIdentifiers[parsed.chainId] ?? null;
71
+ const symbol = networkConfigurationsByChainId[chainIdHex]?.nativeCurrency ?? 'ETH';
72
+ const nativePrice = nativeAssetId && assetsPrice[nativeAssetId]
73
+ ? getPriceNumber(assetsPrice[nativeAssetId])
74
+ : Number.NaN;
75
+ let tokenAddress = null;
76
+ if (parsed.assetNamespace === 'erc20') {
77
+ tokenAddress = (0, util_1.toChecksumAddress)(String(parsed.assetReference));
78
+ }
79
+ else if (parsed.assetNamespace === 'slip44') {
80
+ tokenAddress = '0x0000000000000000000000000000000000000000';
81
+ }
82
+ if (tokenAddress && nativeAssetId) {
83
+ const priceInNative = !Number.isNaN(nativePrice) && nativePrice > 0
84
+ ? price / nativePrice
85
+ : price;
86
+ if (!marketData[chainIdHex]) {
87
+ marketData[chainIdHex] = {};
88
+ }
89
+ const baseMarketData = typeof priceData === 'object' && priceData !== null
90
+ ? priceData
91
+ : {};
92
+ marketData[chainIdHex][tokenAddress] = {
93
+ ...baseMarketData,
94
+ price: priceInNative,
95
+ currency: symbol,
96
+ assetId,
97
+ chainId: chainIdHex,
98
+ tokenAddress,
99
+ };
100
+ }
101
+ if (parsed.assetNamespace === 'slip44' && nativeAssetId) {
102
+ // conversionRate = native price in user's currency; usdConversionRate = native price in USD (bridge uses ratio for USD conversion)
103
+ currencyRates[symbol] = {
104
+ conversionDate: conversionTime,
105
+ conversionRate: price * rateUserCurrencyPerUsd,
106
+ usdConversionRate: price,
107
+ };
108
+ }
109
+ }
110
+ }
111
+ catch {
112
+ // Skip malformed asset IDs
113
+ }
114
+ }
115
+ return {
116
+ conversionRates,
117
+ currencyRates,
118
+ marketData,
119
+ currentCurrency: selectedCurrency,
120
+ };
121
+ }
122
+ exports.formatExchangeRatesForBridge = formatExchangeRatesForBridge;
123
+ //# sourceMappingURL=formatExchangeRatesForBridge.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatExchangeRatesForBridge.cjs","sourceRoot":"","sources":["../../src/utils/formatExchangeRatesForBridge.ts"],"names":[],"mappings":"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","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { MAP_CAIP_CURRENCIES } from '@metamask/assets-controllers';\nimport { numberToHex } from '@metamask/utils';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\n\nimport type { AssetPrice, Caip19AssetId } from '../types';\n\n/**\n * Bridge-compatible conversion rate entry (MultichainAssetsRatesController shape).\n */\nexport type BridgeConversionRateEntry = {\n rate: string;\n currency?: string;\n conversionTime?: number;\n expirationTime?: number;\n marketData?: Record<string, unknown>;\n};\n\n/**\n * Bridge-compatible currency rate entry (CurrencyRateController shape).\n */\nexport type BridgeCurrencyRateEntry = {\n conversionDate: number;\n conversionRate: number;\n usdConversionRate: number;\n};\n\n/**\n * Bridge-compatible market data entry (TokenRatesController marketData shape).\n */\nexport type BridgeMarketDataEntry = {\n price: number;\n currency: string;\n assetId?: string;\n chainId?: string;\n tokenAddress?: string;\n [key: string]: unknown;\n};\n\n/**\n * Exchange rates in the format expected by the bridge controller:\n * conversionRates (MultichainAssetsRatesController) + currencyRates (CurrencyRateController)\n * + marketData (TokenRatesController) + currentCurrency.\n */\nexport type BridgeExchangeRatesFormat = {\n conversionRates: Record<string, BridgeConversionRateEntry>;\n currencyRates: Record<string, BridgeCurrencyRateEntry>;\n marketData: Record<string, Record<string, BridgeMarketDataEntry>>;\n currentCurrency: string;\n};\n\nfunction getPriceNumber(price: AssetPrice): number {\n return typeof price === 'object' && price !== null && 'price' in price\n ? Number((price as { price: number }).price)\n : Number.NaN;\n}\n\n/**\n * Converts AssetsController state (assetsPrice, selectedCurrency) into the\n * same format the bridge expects from MultichainAssetsRatesController,\n * CurrencyRateController, and TokenRatesController so the bridge can use\n * a single action when useAssetsControllerForRates is true.\n *\n * @param params - Conversion parameters.\n * @param params.assetsPrice - Map of CAIP-19 asset ID to price data. Prices are in USD.\n * @param params.selectedCurrency - ISO 4217 currency code (e.g. 'usd').\n * @param params.nativeAssetIdentifiers - Optional map of CAIP-2 chain ID to native asset ID (e.g. from NetworkEnablementController state). When provided, used for EVM native lookups.\n * @param params.networkConfigurationsByChainId - Optional map of Hex chain ID to network config (e.g. from NetworkController state). Used to resolve native currency symbol via `nativeCurrency`; keys are Hex (e.g. '0x1').\n * @param params.usdToSelectedCurrencyRate - Optional rate: 1 USD = this many units of selected currency. Required for correct bridge USD conversion when selectedCurrency is not 'usd'. When omitted and selectedCurrency !== 'usd', currencyRates will use the same value for conversionRate and usdConversionRate (ratio 1), which produces incorrect USD rates.\n * @returns Bridge-compatible conversionRates, currencyRates, marketData, currentCurrency.\n */\nexport function formatExchangeRatesForBridge(params: {\n assetsPrice: Record<string, AssetPrice>;\n selectedCurrency: string;\n nativeAssetIdentifiers?: Record<string, string>;\n networkConfigurationsByChainId?: Record<string, { nativeCurrency?: string }>;\n usdToSelectedCurrencyRate?: number;\n}): BridgeExchangeRatesFormat {\n const {\n assetsPrice,\n selectedCurrency,\n nativeAssetIdentifiers = {},\n networkConfigurationsByChainId = {},\n usdToSelectedCurrencyRate,\n } = params;\n const conversionRates: Record<string, BridgeConversionRateEntry> = {};\n const currencyRates: Record<string, BridgeCurrencyRateEntry> = {};\n const marketData: Record<string, Record<string, BridgeMarketDataEntry>> = {};\n\n // Same as MultichainAssetsRatesController: resolve CAIP currency from selectedCurrency, default to USD\n const currencyCaip =\n MAP_CAIP_CURRENCIES[selectedCurrency.toLowerCase()] ??\n MAP_CAIP_CURRENCIES.usd;\n\n const expirationOffset = 60;\n\n // Price in assetsPrice is in USD. For bridge: conversionRate = in user's currency, usdConversionRate = in USD.\n const isUsd = selectedCurrency.toLowerCase() === 'usd';\n const rateUserCurrencyPerUsd = isUsd ? 1 : (usdToSelectedCurrencyRate ?? 1);\n\n for (const [assetId, priceData] of Object.entries(assetsPrice)) {\n const price = getPriceNumber(priceData);\n if (Number.isNaN(price) || price < 0) {\n continue;\n }\n\n const lastUpdated =\n typeof priceData === 'object' &&\n priceData !== null &&\n 'lastUpdated' in priceData\n ? Number((priceData as { lastUpdated: number }).lastUpdated)\n : Date.now();\n const conversionTime =\n lastUpdated > 1e12 ? lastUpdated / 1000 : lastUpdated;\n const expirationTime = conversionTime + expirationOffset;\n\n try {\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n const chainRef = chainIdParsed.reference;\n\n // conversionRates: only non-EVM assets (bridge uses this for non-EVM chains). Rate in selected currency.\n if (chainIdParsed.namespace !== 'eip155') {\n const priceInUserCurrency = price * rateUserCurrencyPerUsd;\n conversionRates[assetId] = {\n rate: String(priceInUserCurrency),\n currency: currencyCaip,\n conversionTime,\n expirationTime,\n marketData:\n typeof priceData === 'object' && priceData !== null\n ? (priceData as Record<string, unknown>)\n : undefined,\n };\n }\n\n if (chainIdParsed.namespace === 'eip155') {\n const chainIdHex = numberToHex(parseInt(chainRef, 10));\n const nativeAssetId = nativeAssetIdentifiers[parsed.chainId] ?? null;\n const symbol =\n networkConfigurationsByChainId[chainIdHex]?.nativeCurrency ?? 'ETH';\n const nativePrice =\n nativeAssetId && assetsPrice[nativeAssetId]\n ? getPriceNumber(assetsPrice[nativeAssetId])\n : Number.NaN;\n\n let tokenAddress: string | null = null;\n if (parsed.assetNamespace === 'erc20') {\n tokenAddress = toChecksumAddress(String(parsed.assetReference));\n } else if (parsed.assetNamespace === 'slip44') {\n tokenAddress = '0x0000000000000000000000000000000000000000';\n }\n\n if (tokenAddress && nativeAssetId) {\n const priceInNative =\n !Number.isNaN(nativePrice) && nativePrice > 0\n ? price / nativePrice\n : price;\n if (!marketData[chainIdHex]) {\n marketData[chainIdHex] = {};\n }\n const baseMarketData =\n typeof priceData === 'object' && priceData !== null\n ? (priceData as Record<string, unknown>)\n : {};\n marketData[chainIdHex][tokenAddress] = {\n ...baseMarketData,\n price: priceInNative,\n currency: symbol,\n assetId,\n chainId: chainIdHex,\n tokenAddress,\n };\n }\n\n if (parsed.assetNamespace === 'slip44' && nativeAssetId) {\n // conversionRate = native price in user's currency; usdConversionRate = native price in USD (bridge uses ratio for USD conversion)\n currencyRates[symbol] = {\n conversionDate: conversionTime,\n conversionRate: price * rateUserCurrencyPerUsd,\n usdConversionRate: price,\n };\n }\n }\n } catch {\n // Skip malformed asset IDs\n }\n }\n\n return {\n conversionRates,\n currencyRates,\n marketData,\n currentCurrency: selectedCurrency,\n };\n}\n"]}
@@ -0,0 +1,65 @@
1
+ import type { AssetPrice } from "../types.cjs";
2
+ /**
3
+ * Bridge-compatible conversion rate entry (MultichainAssetsRatesController shape).
4
+ */
5
+ export type BridgeConversionRateEntry = {
6
+ rate: string;
7
+ currency?: string;
8
+ conversionTime?: number;
9
+ expirationTime?: number;
10
+ marketData?: Record<string, unknown>;
11
+ };
12
+ /**
13
+ * Bridge-compatible currency rate entry (CurrencyRateController shape).
14
+ */
15
+ export type BridgeCurrencyRateEntry = {
16
+ conversionDate: number;
17
+ conversionRate: number;
18
+ usdConversionRate: number;
19
+ };
20
+ /**
21
+ * Bridge-compatible market data entry (TokenRatesController marketData shape).
22
+ */
23
+ export type BridgeMarketDataEntry = {
24
+ price: number;
25
+ currency: string;
26
+ assetId?: string;
27
+ chainId?: string;
28
+ tokenAddress?: string;
29
+ [key: string]: unknown;
30
+ };
31
+ /**
32
+ * Exchange rates in the format expected by the bridge controller:
33
+ * conversionRates (MultichainAssetsRatesController) + currencyRates (CurrencyRateController)
34
+ * + marketData (TokenRatesController) + currentCurrency.
35
+ */
36
+ export type BridgeExchangeRatesFormat = {
37
+ conversionRates: Record<string, BridgeConversionRateEntry>;
38
+ currencyRates: Record<string, BridgeCurrencyRateEntry>;
39
+ marketData: Record<string, Record<string, BridgeMarketDataEntry>>;
40
+ currentCurrency: string;
41
+ };
42
+ /**
43
+ * Converts AssetsController state (assetsPrice, selectedCurrency) into the
44
+ * same format the bridge expects from MultichainAssetsRatesController,
45
+ * CurrencyRateController, and TokenRatesController so the bridge can use
46
+ * a single action when useAssetsControllerForRates is true.
47
+ *
48
+ * @param params - Conversion parameters.
49
+ * @param params.assetsPrice - Map of CAIP-19 asset ID to price data. Prices are in USD.
50
+ * @param params.selectedCurrency - ISO 4217 currency code (e.g. 'usd').
51
+ * @param params.nativeAssetIdentifiers - Optional map of CAIP-2 chain ID to native asset ID (e.g. from NetworkEnablementController state). When provided, used for EVM native lookups.
52
+ * @param params.networkConfigurationsByChainId - Optional map of Hex chain ID to network config (e.g. from NetworkController state). Used to resolve native currency symbol via `nativeCurrency`; keys are Hex (e.g. '0x1').
53
+ * @param params.usdToSelectedCurrencyRate - Optional rate: 1 USD = this many units of selected currency. Required for correct bridge USD conversion when selectedCurrency is not 'usd'. When omitted and selectedCurrency !== 'usd', currencyRates will use the same value for conversionRate and usdConversionRate (ratio 1), which produces incorrect USD rates.
54
+ * @returns Bridge-compatible conversionRates, currencyRates, marketData, currentCurrency.
55
+ */
56
+ export declare function formatExchangeRatesForBridge(params: {
57
+ assetsPrice: Record<string, AssetPrice>;
58
+ selectedCurrency: string;
59
+ nativeAssetIdentifiers?: Record<string, string>;
60
+ networkConfigurationsByChainId?: Record<string, {
61
+ nativeCurrency?: string;
62
+ }>;
63
+ usdToSelectedCurrencyRate?: number;
64
+ }): BridgeExchangeRatesFormat;
65
+ //# sourceMappingURL=formatExchangeRatesForBridge.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatExchangeRatesForBridge.d.cts","sourceRoot":"","sources":["../../src/utils/formatExchangeRatesForBridge.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAiB,qBAAiB;AAE1D;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IAC3D,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IACvD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC;IAClE,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAQF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE;IACnD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,8BAA8B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7E,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC,GAAG,yBAAyB,CAsH5B"}
@@ -0,0 +1,65 @@
1
+ import type { AssetPrice } from "../types.mjs";
2
+ /**
3
+ * Bridge-compatible conversion rate entry (MultichainAssetsRatesController shape).
4
+ */
5
+ export type BridgeConversionRateEntry = {
6
+ rate: string;
7
+ currency?: string;
8
+ conversionTime?: number;
9
+ expirationTime?: number;
10
+ marketData?: Record<string, unknown>;
11
+ };
12
+ /**
13
+ * Bridge-compatible currency rate entry (CurrencyRateController shape).
14
+ */
15
+ export type BridgeCurrencyRateEntry = {
16
+ conversionDate: number;
17
+ conversionRate: number;
18
+ usdConversionRate: number;
19
+ };
20
+ /**
21
+ * Bridge-compatible market data entry (TokenRatesController marketData shape).
22
+ */
23
+ export type BridgeMarketDataEntry = {
24
+ price: number;
25
+ currency: string;
26
+ assetId?: string;
27
+ chainId?: string;
28
+ tokenAddress?: string;
29
+ [key: string]: unknown;
30
+ };
31
+ /**
32
+ * Exchange rates in the format expected by the bridge controller:
33
+ * conversionRates (MultichainAssetsRatesController) + currencyRates (CurrencyRateController)
34
+ * + marketData (TokenRatesController) + currentCurrency.
35
+ */
36
+ export type BridgeExchangeRatesFormat = {
37
+ conversionRates: Record<string, BridgeConversionRateEntry>;
38
+ currencyRates: Record<string, BridgeCurrencyRateEntry>;
39
+ marketData: Record<string, Record<string, BridgeMarketDataEntry>>;
40
+ currentCurrency: string;
41
+ };
42
+ /**
43
+ * Converts AssetsController state (assetsPrice, selectedCurrency) into the
44
+ * same format the bridge expects from MultichainAssetsRatesController,
45
+ * CurrencyRateController, and TokenRatesController so the bridge can use
46
+ * a single action when useAssetsControllerForRates is true.
47
+ *
48
+ * @param params - Conversion parameters.
49
+ * @param params.assetsPrice - Map of CAIP-19 asset ID to price data. Prices are in USD.
50
+ * @param params.selectedCurrency - ISO 4217 currency code (e.g. 'usd').
51
+ * @param params.nativeAssetIdentifiers - Optional map of CAIP-2 chain ID to native asset ID (e.g. from NetworkEnablementController state). When provided, used for EVM native lookups.
52
+ * @param params.networkConfigurationsByChainId - Optional map of Hex chain ID to network config (e.g. from NetworkController state). Used to resolve native currency symbol via `nativeCurrency`; keys are Hex (e.g. '0x1').
53
+ * @param params.usdToSelectedCurrencyRate - Optional rate: 1 USD = this many units of selected currency. Required for correct bridge USD conversion when selectedCurrency is not 'usd'. When omitted and selectedCurrency !== 'usd', currencyRates will use the same value for conversionRate and usdConversionRate (ratio 1), which produces incorrect USD rates.
54
+ * @returns Bridge-compatible conversionRates, currencyRates, marketData, currentCurrency.
55
+ */
56
+ export declare function formatExchangeRatesForBridge(params: {
57
+ assetsPrice: Record<string, AssetPrice>;
58
+ selectedCurrency: string;
59
+ nativeAssetIdentifiers?: Record<string, string>;
60
+ networkConfigurationsByChainId?: Record<string, {
61
+ nativeCurrency?: string;
62
+ }>;
63
+ usdToSelectedCurrencyRate?: number;
64
+ }): BridgeExchangeRatesFormat;
65
+ //# sourceMappingURL=formatExchangeRatesForBridge.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatExchangeRatesForBridge.d.mts","sourceRoot":"","sources":["../../src/utils/formatExchangeRatesForBridge.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAiB,qBAAiB;AAE1D;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IAC3D,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IACvD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC;IAClE,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAQF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE;IACnD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChD,8BAA8B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7E,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC,GAAG,yBAAyB,CAsH5B"}
@@ -0,0 +1,119 @@
1
+ import { toChecksumAddress } from "@ethereumjs/util";
2
+ import { MAP_CAIP_CURRENCIES } from "@metamask/assets-controllers";
3
+ import { numberToHex } from "@metamask/utils";
4
+ import { parseCaipAssetType, parseCaipChainId } from "@metamask/utils";
5
+ function getPriceNumber(price) {
6
+ return typeof price === 'object' && price !== null && 'price' in price
7
+ ? Number(price.price)
8
+ : Number.NaN;
9
+ }
10
+ /**
11
+ * Converts AssetsController state (assetsPrice, selectedCurrency) into the
12
+ * same format the bridge expects from MultichainAssetsRatesController,
13
+ * CurrencyRateController, and TokenRatesController so the bridge can use
14
+ * a single action when useAssetsControllerForRates is true.
15
+ *
16
+ * @param params - Conversion parameters.
17
+ * @param params.assetsPrice - Map of CAIP-19 asset ID to price data. Prices are in USD.
18
+ * @param params.selectedCurrency - ISO 4217 currency code (e.g. 'usd').
19
+ * @param params.nativeAssetIdentifiers - Optional map of CAIP-2 chain ID to native asset ID (e.g. from NetworkEnablementController state). When provided, used for EVM native lookups.
20
+ * @param params.networkConfigurationsByChainId - Optional map of Hex chain ID to network config (e.g. from NetworkController state). Used to resolve native currency symbol via `nativeCurrency`; keys are Hex (e.g. '0x1').
21
+ * @param params.usdToSelectedCurrencyRate - Optional rate: 1 USD = this many units of selected currency. Required for correct bridge USD conversion when selectedCurrency is not 'usd'. When omitted and selectedCurrency !== 'usd', currencyRates will use the same value for conversionRate and usdConversionRate (ratio 1), which produces incorrect USD rates.
22
+ * @returns Bridge-compatible conversionRates, currencyRates, marketData, currentCurrency.
23
+ */
24
+ export function formatExchangeRatesForBridge(params) {
25
+ const { assetsPrice, selectedCurrency, nativeAssetIdentifiers = {}, networkConfigurationsByChainId = {}, usdToSelectedCurrencyRate, } = params;
26
+ const conversionRates = {};
27
+ const currencyRates = {};
28
+ const marketData = {};
29
+ // Same as MultichainAssetsRatesController: resolve CAIP currency from selectedCurrency, default to USD
30
+ const currencyCaip = MAP_CAIP_CURRENCIES[selectedCurrency.toLowerCase()] ??
31
+ MAP_CAIP_CURRENCIES.usd;
32
+ const expirationOffset = 60;
33
+ // Price in assetsPrice is in USD. For bridge: conversionRate = in user's currency, usdConversionRate = in USD.
34
+ const isUsd = selectedCurrency.toLowerCase() === 'usd';
35
+ const rateUserCurrencyPerUsd = isUsd ? 1 : (usdToSelectedCurrencyRate ?? 1);
36
+ for (const [assetId, priceData] of Object.entries(assetsPrice)) {
37
+ const price = getPriceNumber(priceData);
38
+ if (Number.isNaN(price) || price < 0) {
39
+ continue;
40
+ }
41
+ const lastUpdated = typeof priceData === 'object' &&
42
+ priceData !== null &&
43
+ 'lastUpdated' in priceData
44
+ ? Number(priceData.lastUpdated)
45
+ : Date.now();
46
+ const conversionTime = lastUpdated > 1e12 ? lastUpdated / 1000 : lastUpdated;
47
+ const expirationTime = conversionTime + expirationOffset;
48
+ try {
49
+ const parsed = parseCaipAssetType(assetId);
50
+ const chainIdParsed = parseCaipChainId(parsed.chainId);
51
+ const chainRef = chainIdParsed.reference;
52
+ // conversionRates: only non-EVM assets (bridge uses this for non-EVM chains). Rate in selected currency.
53
+ if (chainIdParsed.namespace !== 'eip155') {
54
+ const priceInUserCurrency = price * rateUserCurrencyPerUsd;
55
+ conversionRates[assetId] = {
56
+ rate: String(priceInUserCurrency),
57
+ currency: currencyCaip,
58
+ conversionTime,
59
+ expirationTime,
60
+ marketData: typeof priceData === 'object' && priceData !== null
61
+ ? priceData
62
+ : undefined,
63
+ };
64
+ }
65
+ if (chainIdParsed.namespace === 'eip155') {
66
+ const chainIdHex = numberToHex(parseInt(chainRef, 10));
67
+ const nativeAssetId = nativeAssetIdentifiers[parsed.chainId] ?? null;
68
+ const symbol = networkConfigurationsByChainId[chainIdHex]?.nativeCurrency ?? 'ETH';
69
+ const nativePrice = nativeAssetId && assetsPrice[nativeAssetId]
70
+ ? getPriceNumber(assetsPrice[nativeAssetId])
71
+ : Number.NaN;
72
+ let tokenAddress = null;
73
+ if (parsed.assetNamespace === 'erc20') {
74
+ tokenAddress = toChecksumAddress(String(parsed.assetReference));
75
+ }
76
+ else if (parsed.assetNamespace === 'slip44') {
77
+ tokenAddress = '0x0000000000000000000000000000000000000000';
78
+ }
79
+ if (tokenAddress && nativeAssetId) {
80
+ const priceInNative = !Number.isNaN(nativePrice) && nativePrice > 0
81
+ ? price / nativePrice
82
+ : price;
83
+ if (!marketData[chainIdHex]) {
84
+ marketData[chainIdHex] = {};
85
+ }
86
+ const baseMarketData = typeof priceData === 'object' && priceData !== null
87
+ ? priceData
88
+ : {};
89
+ marketData[chainIdHex][tokenAddress] = {
90
+ ...baseMarketData,
91
+ price: priceInNative,
92
+ currency: symbol,
93
+ assetId,
94
+ chainId: chainIdHex,
95
+ tokenAddress,
96
+ };
97
+ }
98
+ if (parsed.assetNamespace === 'slip44' && nativeAssetId) {
99
+ // conversionRate = native price in user's currency; usdConversionRate = native price in USD (bridge uses ratio for USD conversion)
100
+ currencyRates[symbol] = {
101
+ conversionDate: conversionTime,
102
+ conversionRate: price * rateUserCurrencyPerUsd,
103
+ usdConversionRate: price,
104
+ };
105
+ }
106
+ }
107
+ }
108
+ catch {
109
+ // Skip malformed asset IDs
110
+ }
111
+ }
112
+ return {
113
+ conversionRates,
114
+ currencyRates,
115
+ marketData,
116
+ currentCurrency: selectedCurrency,
117
+ };
118
+ }
119
+ //# sourceMappingURL=formatExchangeRatesForBridge.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatExchangeRatesForBridge.mjs","sourceRoot":"","sources":["../../src/utils/formatExchangeRatesForBridge.ts"],"names":[],"mappings":"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","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { MAP_CAIP_CURRENCIES } from '@metamask/assets-controllers';\nimport { numberToHex } from '@metamask/utils';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\n\nimport type { AssetPrice, Caip19AssetId } from '../types';\n\n/**\n * Bridge-compatible conversion rate entry (MultichainAssetsRatesController shape).\n */\nexport type BridgeConversionRateEntry = {\n rate: string;\n currency?: string;\n conversionTime?: number;\n expirationTime?: number;\n marketData?: Record<string, unknown>;\n};\n\n/**\n * Bridge-compatible currency rate entry (CurrencyRateController shape).\n */\nexport type BridgeCurrencyRateEntry = {\n conversionDate: number;\n conversionRate: number;\n usdConversionRate: number;\n};\n\n/**\n * Bridge-compatible market data entry (TokenRatesController marketData shape).\n */\nexport type BridgeMarketDataEntry = {\n price: number;\n currency: string;\n assetId?: string;\n chainId?: string;\n tokenAddress?: string;\n [key: string]: unknown;\n};\n\n/**\n * Exchange rates in the format expected by the bridge controller:\n * conversionRates (MultichainAssetsRatesController) + currencyRates (CurrencyRateController)\n * + marketData (TokenRatesController) + currentCurrency.\n */\nexport type BridgeExchangeRatesFormat = {\n conversionRates: Record<string, BridgeConversionRateEntry>;\n currencyRates: Record<string, BridgeCurrencyRateEntry>;\n marketData: Record<string, Record<string, BridgeMarketDataEntry>>;\n currentCurrency: string;\n};\n\nfunction getPriceNumber(price: AssetPrice): number {\n return typeof price === 'object' && price !== null && 'price' in price\n ? Number((price as { price: number }).price)\n : Number.NaN;\n}\n\n/**\n * Converts AssetsController state (assetsPrice, selectedCurrency) into the\n * same format the bridge expects from MultichainAssetsRatesController,\n * CurrencyRateController, and TokenRatesController so the bridge can use\n * a single action when useAssetsControllerForRates is true.\n *\n * @param params - Conversion parameters.\n * @param params.assetsPrice - Map of CAIP-19 asset ID to price data. Prices are in USD.\n * @param params.selectedCurrency - ISO 4217 currency code (e.g. 'usd').\n * @param params.nativeAssetIdentifiers - Optional map of CAIP-2 chain ID to native asset ID (e.g. from NetworkEnablementController state). When provided, used for EVM native lookups.\n * @param params.networkConfigurationsByChainId - Optional map of Hex chain ID to network config (e.g. from NetworkController state). Used to resolve native currency symbol via `nativeCurrency`; keys are Hex (e.g. '0x1').\n * @param params.usdToSelectedCurrencyRate - Optional rate: 1 USD = this many units of selected currency. Required for correct bridge USD conversion when selectedCurrency is not 'usd'. When omitted and selectedCurrency !== 'usd', currencyRates will use the same value for conversionRate and usdConversionRate (ratio 1), which produces incorrect USD rates.\n * @returns Bridge-compatible conversionRates, currencyRates, marketData, currentCurrency.\n */\nexport function formatExchangeRatesForBridge(params: {\n assetsPrice: Record<string, AssetPrice>;\n selectedCurrency: string;\n nativeAssetIdentifiers?: Record<string, string>;\n networkConfigurationsByChainId?: Record<string, { nativeCurrency?: string }>;\n usdToSelectedCurrencyRate?: number;\n}): BridgeExchangeRatesFormat {\n const {\n assetsPrice,\n selectedCurrency,\n nativeAssetIdentifiers = {},\n networkConfigurationsByChainId = {},\n usdToSelectedCurrencyRate,\n } = params;\n const conversionRates: Record<string, BridgeConversionRateEntry> = {};\n const currencyRates: Record<string, BridgeCurrencyRateEntry> = {};\n const marketData: Record<string, Record<string, BridgeMarketDataEntry>> = {};\n\n // Same as MultichainAssetsRatesController: resolve CAIP currency from selectedCurrency, default to USD\n const currencyCaip =\n MAP_CAIP_CURRENCIES[selectedCurrency.toLowerCase()] ??\n MAP_CAIP_CURRENCIES.usd;\n\n const expirationOffset = 60;\n\n // Price in assetsPrice is in USD. For bridge: conversionRate = in user's currency, usdConversionRate = in USD.\n const isUsd = selectedCurrency.toLowerCase() === 'usd';\n const rateUserCurrencyPerUsd = isUsd ? 1 : (usdToSelectedCurrencyRate ?? 1);\n\n for (const [assetId, priceData] of Object.entries(assetsPrice)) {\n const price = getPriceNumber(priceData);\n if (Number.isNaN(price) || price < 0) {\n continue;\n }\n\n const lastUpdated =\n typeof priceData === 'object' &&\n priceData !== null &&\n 'lastUpdated' in priceData\n ? Number((priceData as { lastUpdated: number }).lastUpdated)\n : Date.now();\n const conversionTime =\n lastUpdated > 1e12 ? lastUpdated / 1000 : lastUpdated;\n const expirationTime = conversionTime + expirationOffset;\n\n try {\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n const chainRef = chainIdParsed.reference;\n\n // conversionRates: only non-EVM assets (bridge uses this for non-EVM chains). Rate in selected currency.\n if (chainIdParsed.namespace !== 'eip155') {\n const priceInUserCurrency = price * rateUserCurrencyPerUsd;\n conversionRates[assetId] = {\n rate: String(priceInUserCurrency),\n currency: currencyCaip,\n conversionTime,\n expirationTime,\n marketData:\n typeof priceData === 'object' && priceData !== null\n ? (priceData as Record<string, unknown>)\n : undefined,\n };\n }\n\n if (chainIdParsed.namespace === 'eip155') {\n const chainIdHex = numberToHex(parseInt(chainRef, 10));\n const nativeAssetId = nativeAssetIdentifiers[parsed.chainId] ?? null;\n const symbol =\n networkConfigurationsByChainId[chainIdHex]?.nativeCurrency ?? 'ETH';\n const nativePrice =\n nativeAssetId && assetsPrice[nativeAssetId]\n ? getPriceNumber(assetsPrice[nativeAssetId])\n : Number.NaN;\n\n let tokenAddress: string | null = null;\n if (parsed.assetNamespace === 'erc20') {\n tokenAddress = toChecksumAddress(String(parsed.assetReference));\n } else if (parsed.assetNamespace === 'slip44') {\n tokenAddress = '0x0000000000000000000000000000000000000000';\n }\n\n if (tokenAddress && nativeAssetId) {\n const priceInNative =\n !Number.isNaN(nativePrice) && nativePrice > 0\n ? price / nativePrice\n : price;\n if (!marketData[chainIdHex]) {\n marketData[chainIdHex] = {};\n }\n const baseMarketData =\n typeof priceData === 'object' && priceData !== null\n ? (priceData as Record<string, unknown>)\n : {};\n marketData[chainIdHex][tokenAddress] = {\n ...baseMarketData,\n price: priceInNative,\n currency: symbol,\n assetId,\n chainId: chainIdHex,\n tokenAddress,\n };\n }\n\n if (parsed.assetNamespace === 'slip44' && nativeAssetId) {\n // conversionRate = native price in user's currency; usdConversionRate = native price in USD (bridge uses ratio for USD conversion)\n currencyRates[symbol] = {\n conversionDate: conversionTime,\n conversionRate: price * rateUserCurrencyPerUsd,\n usdConversionRate: price,\n };\n }\n }\n } catch {\n // Skip malformed asset IDs\n }\n }\n\n return {\n conversionRates,\n currencyRates,\n marketData,\n currentCurrency: selectedCurrency,\n };\n}\n"]}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatExchangeRatesForBridge = exports.normalizeAssetId = void 0;
4
+ var normalizeAssetId_1 = require("./normalizeAssetId.cjs");
5
+ Object.defineProperty(exports, "normalizeAssetId", { enumerable: true, get: function () { return normalizeAssetId_1.normalizeAssetId; } });
6
+ var formatExchangeRatesForBridge_1 = require("./formatExchangeRatesForBridge.cjs");
7
+ Object.defineProperty(exports, "formatExchangeRatesForBridge", { enumerable: true, get: function () { return formatExchangeRatesForBridge_1.formatExchangeRatesForBridge; } });
8
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;AAAA,2DAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AACzB,mFAA8E;AAArE,4IAAA,4BAA4B,OAAA","sourcesContent":["export { normalizeAssetId } from './normalizeAssetId';\nexport { formatExchangeRatesForBridge } from './formatExchangeRatesForBridge';\nexport type {\n BridgeConversionRateEntry,\n BridgeCurrencyRateEntry,\n BridgeExchangeRatesFormat,\n BridgeMarketDataEntry,\n} from './formatExchangeRatesForBridge';\n"]}
@@ -0,0 +1,4 @@
1
+ export { normalizeAssetId } from "./normalizeAssetId.cjs";
2
+ export { formatExchangeRatesForBridge } from "./formatExchangeRatesForBridge.cjs";
3
+ export type { BridgeConversionRateEntry, BridgeCurrencyRateEntry, BridgeExchangeRatesFormat, BridgeMarketDataEntry, } from "./formatExchangeRatesForBridge.cjs";
4
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;AACtD,OAAO,EAAE,4BAA4B,EAAE,2CAAuC;AAC9E,YAAY,EACV,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,qBAAqB,GACtB,2CAAuC"}
@@ -0,0 +1,4 @@
1
+ export { normalizeAssetId } from "./normalizeAssetId.mjs";
2
+ export { formatExchangeRatesForBridge } from "./formatExchangeRatesForBridge.mjs";
3
+ export type { BridgeConversionRateEntry, BridgeCurrencyRateEntry, BridgeExchangeRatesFormat, BridgeMarketDataEntry, } from "./formatExchangeRatesForBridge.mjs";
4
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;AACtD,OAAO,EAAE,4BAA4B,EAAE,2CAAuC;AAC9E,YAAY,EACV,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,qBAAqB,GACtB,2CAAuC"}
@@ -0,0 +1,3 @@
1
+ export { normalizeAssetId } from "./normalizeAssetId.mjs";
2
+ export { formatExchangeRatesForBridge } from "./formatExchangeRatesForBridge.mjs";
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;AACtD,OAAO,EAAE,4BAA4B,EAAE,2CAAuC","sourcesContent":["export { normalizeAssetId } from './normalizeAssetId';\nexport { formatExchangeRatesForBridge } from './formatExchangeRatesForBridge';\nexport type {\n BridgeConversionRateEntry,\n BridgeCurrencyRateEntry,\n BridgeExchangeRatesFormat,\n BridgeMarketDataEntry,\n} from './formatExchangeRatesForBridge';\n"]}
@@ -25,4 +25,4 @@ function normalizeAssetId(assetId) {
25
25
  return assetId;
26
26
  }
27
27
  exports.normalizeAssetId = normalizeAssetId;
28
- //# sourceMappingURL=utils.cjs.map
28
+ //# sourceMappingURL=normalizeAssetId.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeAssetId.cjs","sourceRoot":"","sources":["../../src/utils/normalizeAssetId.ts"],"names":[],"mappings":";;;AAAA,2CAAqD;AACrD,2CAAuE;AAIvE;;;;;;;;;GASG;AACH,SAAgB,gBAAgB,CAAC,OAAsB;IACrD,MAAM,MAAM,GAAG,IAAA,0BAAkB,EAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,aAAa,GAAG,IAAA,wBAAgB,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEvD,oCAAoC;IACpC,IACE,aAAa,CAAC,SAAS,KAAK,QAAQ;QACpC,MAAM,CAAC,cAAc,KAAK,OAAO,EACjC,CAAC;QACD,MAAM,kBAAkB,GAAG,IAAA,wBAAiB,EAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACpE,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,cAAc,IAAI,kBAAkB,EAAmB,CAAC;IAC7F,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAdD,4CAcC","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\n\nimport type { Caip19AssetId } from '../types';\n\n/**\n * Normalizes a CAIP-19 asset ID by checksumming EVM addresses.\n * This ensures consistent asset IDs regardless of the data source format.\n *\n * For EVM ERC20 tokens (e.g., \"eip155:1/erc20:0x...\"), the address is checksummed.\n * All other asset types are returned unchanged.\n *\n * @param assetId - The CAIP-19 asset ID to normalize\n * @returns The normalized asset ID with checksummed address (for EVM tokens)\n */\nexport function normalizeAssetId(assetId: Caip19AssetId): Caip19AssetId {\n const parsed = parseCaipAssetType(assetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n\n // Only checksum EVM ERC20 addresses\n if (\n chainIdParsed.namespace === 'eip155' &&\n parsed.assetNamespace === 'erc20'\n ) {\n const checksummedAddress = toChecksumAddress(parsed.assetReference);\n return `${parsed.chainId}/${parsed.assetNamespace}:${checksummedAddress}` as Caip19AssetId;\n }\n\n return assetId;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { Caip19AssetId } from "./types.mjs";
1
+ import type { Caip19AssetId } from "../types.cjs";
2
2
  /**
3
3
  * Normalizes a CAIP-19 asset ID by checksumming EVM addresses.
4
4
  * This ensures consistent asset IDs regardless of the data source format.
@@ -10,4 +10,4 @@ import type { Caip19AssetId } from "./types.mjs";
10
10
  * @returns The normalized asset ID with checksummed address (for EVM tokens)
11
11
  */
12
12
  export declare function normalizeAssetId(assetId: Caip19AssetId): Caip19AssetId;
13
- //# sourceMappingURL=utils.d.mts.map
13
+ //# sourceMappingURL=normalizeAssetId.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeAssetId.d.cts","sourceRoot":"","sources":["../../src/utils/normalizeAssetId.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAiB;AAE9C;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CActE"}
@@ -1,4 +1,4 @@
1
- import type { Caip19AssetId } from "./types.cjs";
1
+ import type { Caip19AssetId } from "../types.mjs";
2
2
  /**
3
3
  * Normalizes a CAIP-19 asset ID by checksumming EVM addresses.
4
4
  * This ensures consistent asset IDs regardless of the data source format.
@@ -10,4 +10,4 @@ import type { Caip19AssetId } from "./types.cjs";
10
10
  * @returns The normalized asset ID with checksummed address (for EVM tokens)
11
11
  */
12
12
  export declare function normalizeAssetId(assetId: Caip19AssetId): Caip19AssetId;
13
- //# sourceMappingURL=utils.d.cts.map
13
+ //# sourceMappingURL=normalizeAssetId.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeAssetId.d.mts","sourceRoot":"","sources":["../../src/utils/normalizeAssetId.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAiB;AAE9C;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CActE"}
@@ -21,4 +21,4 @@ export function normalizeAssetId(assetId) {
21
21
  }
22
22
  return assetId;
23
23
  }
24
- //# sourceMappingURL=utils.mjs.map
24
+ //# sourceMappingURL=normalizeAssetId.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeAssetId.mjs","sourceRoot":"","sources":["../../src/utils/normalizeAssetId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,yBAAyB;AACrD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,wBAAwB;AAIvE;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAsB;IACrD,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEvD,oCAAoC;IACpC,IACE,aAAa,CAAC,SAAS,KAAK,QAAQ;QACpC,MAAM,CAAC,cAAc,KAAK,OAAO,EACjC,CAAC;QACD,MAAM,kBAAkB,GAAG,iBAAiB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACpE,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,cAAc,IAAI,kBAAkB,EAAmB,CAAC;IAC7F,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\n\nimport type { Caip19AssetId } from '../types';\n\n/**\n * Normalizes a CAIP-19 asset ID by checksumming EVM addresses.\n * This ensures consistent asset IDs regardless of the data source format.\n *\n * For EVM ERC20 tokens (e.g., \"eip155:1/erc20:0x...\"), the address is checksummed.\n * All other asset types are returned unchanged.\n *\n * @param assetId - The CAIP-19 asset ID to normalize\n * @returns The normalized asset ID with checksummed address (for EVM tokens)\n */\nexport function normalizeAssetId(assetId: Caip19AssetId): Caip19AssetId {\n const parsed = parseCaipAssetType(assetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n\n // Only checksum EVM ERC20 addresses\n if (\n chainIdParsed.namespace === 'eip155' &&\n parsed.assetNamespace === 'erc20'\n ) {\n const checksummedAddress = toChecksumAddress(parsed.assetReference);\n return `${parsed.chainId}/${parsed.assetNamespace}:${checksummedAddress}` as Caip19AssetId;\n }\n\n return assetId;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/assets-controller",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Tracks assets balances/prices and handles token detection across all digital assets",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.cjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AAAA,2CAAqD;AACrD,2CAAuE;AAIvE;;;;;;;;;GASG;AACH,SAAgB,gBAAgB,CAAC,OAAsB;IACrD,MAAM,MAAM,GAAG,IAAA,0BAAkB,EAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,aAAa,GAAG,IAAA,wBAAgB,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEvD,oCAAoC;IACpC,IACE,aAAa,CAAC,SAAS,KAAK,QAAQ;QACpC,MAAM,CAAC,cAAc,KAAK,OAAO,EACjC,CAAC;QACD,MAAM,kBAAkB,GAAG,IAAA,wBAAiB,EAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACpE,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,cAAc,IAAI,kBAAkB,EAAmB,CAAC;IAC7F,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAdD,4CAcC","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\n\nimport type { Caip19AssetId } from './types';\n\n/**\n * Normalizes a CAIP-19 asset ID by checksumming EVM addresses.\n * This ensures consistent asset IDs regardless of the data source format.\n *\n * For EVM ERC20 tokens (e.g., \"eip155:1/erc20:0x...\"), the address is checksummed.\n * All other asset types are returned unchanged.\n *\n * @param assetId - The CAIP-19 asset ID to normalize\n * @returns The normalized asset ID with checksummed address (for EVM tokens)\n */\nexport function normalizeAssetId(assetId: Caip19AssetId): Caip19AssetId {\n const parsed = parseCaipAssetType(assetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n\n // Only checksum EVM ERC20 addresses\n if (\n chainIdParsed.namespace === 'eip155' &&\n parsed.assetNamespace === 'erc20'\n ) {\n const checksummedAddress = toChecksumAddress(parsed.assetReference);\n return `${parsed.chainId}/${parsed.assetNamespace}:${checksummedAddress}` as Caip19AssetId;\n }\n\n return assetId;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.cts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAgB;AAE7C;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CActE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.mts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAgB;AAE7C;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CActE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,yBAAyB;AACrD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,wBAAwB;AAIvE;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAsB;IACrD,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEvD,oCAAoC;IACpC,IACE,aAAa,CAAC,SAAS,KAAK,QAAQ;QACpC,MAAM,CAAC,cAAc,KAAK,OAAO,EACjC,CAAC;QACD,MAAM,kBAAkB,GAAG,iBAAiB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACpE,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,cAAc,IAAI,kBAAkB,EAAmB,CAAC;IAC7F,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\n\nimport type { Caip19AssetId } from './types';\n\n/**\n * Normalizes a CAIP-19 asset ID by checksumming EVM addresses.\n * This ensures consistent asset IDs regardless of the data source format.\n *\n * For EVM ERC20 tokens (e.g., \"eip155:1/erc20:0x...\"), the address is checksummed.\n * All other asset types are returned unchanged.\n *\n * @param assetId - The CAIP-19 asset ID to normalize\n * @returns The normalized asset ID with checksummed address (for EVM tokens)\n */\nexport function normalizeAssetId(assetId: Caip19AssetId): Caip19AssetId {\n const parsed = parseCaipAssetType(assetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n\n // Only checksum EVM ERC20 addresses\n if (\n chainIdParsed.namespace === 'eip155' &&\n parsed.assetNamespace === 'erc20'\n ) {\n const checksummedAddress = toChecksumAddress(parsed.assetReference);\n return `${parsed.chainId}/${parsed.assetNamespace}:${checksummedAddress}` as Caip19AssetId;\n }\n\n return assetId;\n}\n"]}