@metamask/assets-controller 10.2.1 → 11.1.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.
- package/CHANGELOG.md +34 -1
- package/LICENSE +1 -0
- package/dist/AssetsController-method-action-types.cjs.map +1 -1
- package/dist/AssetsController-method-action-types.d.cts +23 -1
- package/dist/AssetsController-method-action-types.d.cts.map +1 -1
- package/dist/AssetsController-method-action-types.d.mts +23 -1
- package/dist/AssetsController-method-action-types.d.mts.map +1 -1
- package/dist/AssetsController-method-action-types.mjs.map +1 -1
- package/dist/AssetsController.cjs +103 -55
- package/dist/AssetsController.cjs.map +1 -1
- package/dist/AssetsController.d.cts +26 -9
- package/dist/AssetsController.d.cts.map +1 -1
- package/dist/AssetsController.d.mts +26 -9
- package/dist/AssetsController.d.mts.map +1 -1
- package/dist/AssetsController.mjs +103 -55
- package/dist/AssetsController.mjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.cjs +95 -9
- package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.d.cts +8 -1
- package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.d.mts +8 -1
- package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -1
- package/dist/data-sources/AccountsApiDataSource.mjs +95 -9
- package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
- package/dist/data-sources/TokenDataSource.cjs +73 -12
- package/dist/data-sources/TokenDataSource.cjs.map +1 -1
- package/dist/data-sources/TokenDataSource.d.cts +4 -1
- package/dist/data-sources/TokenDataSource.d.cts.map +1 -1
- package/dist/data-sources/TokenDataSource.d.mts +4 -1
- package/dist/data-sources/TokenDataSource.d.mts.map +1 -1
- package/dist/data-sources/TokenDataSource.mjs +73 -12
- package/dist/data-sources/TokenDataSource.mjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.cjs +86 -27
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.cjs.map +1 -1
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.cts +4 -3
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.cts.map +1 -1
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.mts +4 -3
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.mts.map +1 -1
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.mjs +86 -27
- package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/utils/formatExchangeRatesForBridge.cjs +36 -7
- package/dist/utils/formatExchangeRatesForBridge.cjs.map +1 -1
- package/dist/utils/formatExchangeRatesForBridge.d.cts +20 -14
- package/dist/utils/formatExchangeRatesForBridge.d.cts.map +1 -1
- package/dist/utils/formatExchangeRatesForBridge.d.mts +20 -14
- package/dist/utils/formatExchangeRatesForBridge.d.mts.map +1 -1
- package/dist/utils/formatExchangeRatesForBridge.mjs +34 -5
- package/dist/utils/formatExchangeRatesForBridge.mjs.map +1 -1
- package/dist/utils/formatStateForTransactionPay.cjs +56 -9
- package/dist/utils/formatStateForTransactionPay.cjs.map +1 -1
- package/dist/utils/formatStateForTransactionPay.d.cts +23 -17
- package/dist/utils/formatStateForTransactionPay.d.cts.map +1 -1
- package/dist/utils/formatStateForTransactionPay.d.mts +23 -17
- package/dist/utils/formatStateForTransactionPay.d.mts.map +1 -1
- package/dist/utils/formatStateForTransactionPay.mjs +54 -7
- package/dist/utils/formatStateForTransactionPay.mjs.map +1 -1
- package/dist/utils/index.cjs +4 -1
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +5 -5
- package/dist/utils/index.d.cts.map +1 -1
- package/dist/utils/index.d.mts +5 -5
- package/dist/utils/index.d.mts.map +1 -1
- package/dist/utils/index.mjs +3 -3
- package/dist/utils/index.mjs.map +1 -1
- package/dist/utils/normalizeAssetId.cjs +17 -3
- package/dist/utils/normalizeAssetId.cjs.map +1 -1
- package/dist/utils/normalizeAssetId.d.cts +10 -1
- package/dist/utils/normalizeAssetId.d.cts.map +1 -1
- package/dist/utils/normalizeAssetId.d.mts +10 -1
- package/dist/utils/normalizeAssetId.d.mts.map +1 -1
- package/dist/utils/normalizeAssetId.mjs +19 -1
- package/dist/utils/normalizeAssetId.mjs.map +1 -1
- package/package.json +7 -4
|
@@ -11,27 +11,33 @@ export type BridgeExchangeRatesFormat = {
|
|
|
11
11
|
marketData: TokenRatesControllerState['marketData'];
|
|
12
12
|
currentCurrency: string;
|
|
13
13
|
};
|
|
14
|
+
/** Parameters accepted by {@link formatExchangeRatesForBridge}. */
|
|
15
|
+
export type FormatExchangeRatesForBridgeParams = {
|
|
16
|
+
assetsInfo: Record<string, AssetMetadata>;
|
|
17
|
+
assetsPrice: Record<string, AssetPrice>;
|
|
18
|
+
selectedCurrency: string;
|
|
19
|
+
nativeAssetIdentifiers: Record<string, string>;
|
|
20
|
+
networkConfigurationsByChainId?: Record<string, {
|
|
21
|
+
nativeCurrency?: string;
|
|
22
|
+
}>;
|
|
23
|
+
};
|
|
14
24
|
/**
|
|
15
25
|
* Converts AssetsController state (assetsPrice, selectedCurrency) into the
|
|
16
26
|
* same format the bridge expects from MultichainAssetsRatesController,
|
|
17
27
|
* CurrencyRateController, and TokenRatesController so the bridge can use
|
|
18
28
|
* a single action when useAssetsControllerForRates is true.
|
|
19
29
|
*
|
|
30
|
+
* Memoized on input identity for BaseController state slices (`===`) and
|
|
31
|
+
* lodash `isEqual` for rebuilt maps (`nativeAssetIdentifiers`). Bridge quote
|
|
32
|
+
* / rate paths call this repeatedly while assets state is unchanged; recomputing
|
|
33
|
+
* runs keccak256 (`toChecksumAddress`) and CAIP parsing per priced asset.
|
|
34
|
+
*
|
|
20
35
|
* @param params - Conversion parameters.
|
|
21
|
-
* @param params.assetsInfo - Metadata map keyed by CAIP-19 asset ID; used to determine native assets via `type === 'native'`.
|
|
22
|
-
* @param params.assetsPrice - Map of CAIP-19 asset ID to price data (must include both `price` and `usdPrice`).
|
|
23
|
-
* @param params.selectedCurrency - ISO 4217 currency code (e.g. 'usd').
|
|
24
|
-
* @param params.nativeAssetIdentifiers - Map of CAIP-2 chain ID to native asset ID. Used for EVM native lookups.
|
|
25
|
-
* @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').
|
|
26
36
|
* @returns Bridge-compatible conversionRates, currencyRates, marketData, currentCurrency.
|
|
27
37
|
*/
|
|
28
|
-
export declare function formatExchangeRatesForBridge(params:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
networkConfigurationsByChainId?: Record<string, {
|
|
34
|
-
nativeCurrency?: string;
|
|
35
|
-
}>;
|
|
36
|
-
}): BridgeExchangeRatesFormat;
|
|
38
|
+
export declare function formatExchangeRatesForBridge(params: FormatExchangeRatesForBridgeParams): BridgeExchangeRatesFormat;
|
|
39
|
+
/**
|
|
40
|
+
* Clears the {@link formatExchangeRatesForBridge} memoize cache. Exported for tests.
|
|
41
|
+
*/
|
|
42
|
+
export declare function clearFormatExchangeRatesForBridgeCacheForTesting(): void;
|
|
37
43
|
//# sourceMappingURL=formatExchangeRatesForBridge.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatExchangeRatesForBridge.d.mts","sourceRoot":"","sources":["../../src/utils/formatExchangeRatesForBridge.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EAGjB,oCAAoC,EACpC,yBAAyB,EAE1B,qCAAqC;
|
|
1
|
+
{"version":3,"file":"formatExchangeRatesForBridge.d.mts","sourceRoot":"","sources":["../../src/utils/formatExchangeRatesForBridge.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EAGjB,oCAAoC,EACpC,yBAAyB,EAE1B,qCAAqC;AAKtC,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EAGX,qBAAiB;AAElB;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,eAAe,EAAE,oCAAoC,CAAC,iBAAiB,CAAC,CAAC;IACzE,aAAa,EAAE,iBAAiB,CAAC,eAAe,CAAC,CAAC;IAClD,UAAU,EAAE,yBAAyB,CAAC,YAAY,CAAC,CAAC;IACpD,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,mEAAmE;AACnE,MAAM,MAAM,kCAAkC,GAAG;IAC/C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,8BAA8B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9E,CAAC;AAOF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,kCAAkC,GACzC,yBAAyB,CAkB3B;AAED;;GAEG;AACH,wBAAgB,gDAAgD,IAAI,IAAI,CAEvE"}
|
|
@@ -2,21 +2,50 @@ import { toChecksumAddress } from "@ethereumjs/util";
|
|
|
2
2
|
import { MAP_CAIP_CURRENCIES, getNativeTokenAddress } from "@metamask/assets-controllers";
|
|
3
3
|
import { KnownCaipNamespace, numberToHex } from "@metamask/utils";
|
|
4
4
|
import { parseCaipAssetType, parseCaipChainId } from "@metamask/utils";
|
|
5
|
+
import $lodash from "lodash";
|
|
6
|
+
const { isEqual } = $lodash;
|
|
7
|
+
let lastCall = null;
|
|
5
8
|
/**
|
|
6
9
|
* Converts AssetsController state (assetsPrice, selectedCurrency) into the
|
|
7
10
|
* same format the bridge expects from MultichainAssetsRatesController,
|
|
8
11
|
* CurrencyRateController, and TokenRatesController so the bridge can use
|
|
9
12
|
* a single action when useAssetsControllerForRates is true.
|
|
10
13
|
*
|
|
14
|
+
* Memoized on input identity for BaseController state slices (`===`) and
|
|
15
|
+
* lodash `isEqual` for rebuilt maps (`nativeAssetIdentifiers`). Bridge quote
|
|
16
|
+
* / rate paths call this repeatedly while assets state is unchanged; recomputing
|
|
17
|
+
* runs keccak256 (`toChecksumAddress`) and CAIP parsing per priced asset.
|
|
18
|
+
*
|
|
11
19
|
* @param params - Conversion parameters.
|
|
12
|
-
* @param params.assetsInfo - Metadata map keyed by CAIP-19 asset ID; used to determine native assets via `type === 'native'`.
|
|
13
|
-
* @param params.assetsPrice - Map of CAIP-19 asset ID to price data (must include both `price` and `usdPrice`).
|
|
14
|
-
* @param params.selectedCurrency - ISO 4217 currency code (e.g. 'usd').
|
|
15
|
-
* @param params.nativeAssetIdentifiers - Map of CAIP-2 chain ID to native asset ID. Used for EVM native lookups.
|
|
16
|
-
* @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').
|
|
17
20
|
* @returns Bridge-compatible conversionRates, currencyRates, marketData, currentCurrency.
|
|
18
21
|
*/
|
|
19
22
|
export function formatExchangeRatesForBridge(params) {
|
|
23
|
+
if (lastCall?.params.assetsInfo === params.assetsInfo &&
|
|
24
|
+
lastCall.params.assetsPrice === params.assetsPrice &&
|
|
25
|
+
lastCall.params.selectedCurrency === params.selectedCurrency &&
|
|
26
|
+
lastCall.params.networkConfigurationsByChainId ===
|
|
27
|
+
params.networkConfigurationsByChainId &&
|
|
28
|
+
isEqual(lastCall.params.nativeAssetIdentifiers, params.nativeAssetIdentifiers)) {
|
|
29
|
+
return lastCall.result;
|
|
30
|
+
}
|
|
31
|
+
const result = computeExchangeRatesForBridge(params);
|
|
32
|
+
lastCall = { params, result };
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Clears the {@link formatExchangeRatesForBridge} memoize cache. Exported for tests.
|
|
37
|
+
*/
|
|
38
|
+
export function clearFormatExchangeRatesForBridgeCacheForTesting() {
|
|
39
|
+
lastCall = null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Performs the actual exchange-rate conversion for
|
|
43
|
+
* {@link formatExchangeRatesForBridge}.
|
|
44
|
+
*
|
|
45
|
+
* @param params - Conversion parameters.
|
|
46
|
+
* @returns Bridge-compatible rates.
|
|
47
|
+
*/
|
|
48
|
+
function computeExchangeRatesForBridge(params) {
|
|
20
49
|
const { assetsInfo, assetsPrice, selectedCurrency, nativeAssetIdentifiers, networkConfigurationsByChainId = {}, } = params;
|
|
21
50
|
const conversionRates = {};
|
|
22
51
|
const currencyRates = {};
|
|
@@ -1 +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 {\n CurrencyRateState,\n MAP_CAIP_CURRENCIES,\n MarketDataDetails,\n MultichainAssetsRatesControllerState,\n TokenRatesControllerState,\n getNativeTokenAddress,\n} from '@metamask/assets-controllers';\nimport { Hex, KnownCaipNamespace, numberToHex } from '@metamask/utils';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\n\nimport type {\n AssetMetadata,\n AssetPrice,\n FungibleAssetPrice,\n Caip19AssetId,\n} from '../types';\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: MultichainAssetsRatesControllerState['conversionRates'];\n currencyRates: CurrencyRateState['currencyRates'];\n marketData: TokenRatesControllerState['marketData'];\n currentCurrency: string;\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.assetsInfo - Metadata map keyed by CAIP-19 asset ID; used to determine native assets via `type === 'native'`.\n * @param params.assetsPrice - Map of CAIP-19 asset ID to price data (must include both `price` and `usdPrice`).\n * @param params.selectedCurrency - ISO 4217 currency code (e.g. 'usd').\n * @param params.nativeAssetIdentifiers - Map of CAIP-2 chain ID to native asset ID. 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 * @returns Bridge-compatible conversionRates, currencyRates, marketData, currentCurrency.\n */\nexport function formatExchangeRatesForBridge(params: {\n assetsInfo: Record<string, AssetMetadata>;\n assetsPrice: Record<string, AssetPrice>;\n selectedCurrency: string;\n nativeAssetIdentifiers: Record<string, string>;\n networkConfigurationsByChainId?: Record<string, { nativeCurrency?: string }>;\n}): BridgeExchangeRatesFormat {\n const {\n assetsInfo,\n assetsPrice,\n selectedCurrency,\n nativeAssetIdentifiers,\n networkConfigurationsByChainId = {},\n } = params;\n const conversionRates: MultichainAssetsRatesControllerState['conversionRates'] =\n {};\n const currencyRates: CurrencyRateState['currencyRates'] = {};\n const marketData: TokenRatesControllerState['marketData'] = {};\n\n const currencyCaip = MAP_CAIP_CURRENCIES[selectedCurrency.toLowerCase()];\n if (!currencyCaip) {\n return {\n conversionRates: {},\n currencyRates: {},\n marketData: {},\n currentCurrency: selectedCurrency,\n };\n }\n\n const fungibleAssetsPrice = Object.entries(assetsPrice).reduce<\n Record<Caip19AssetId, FungibleAssetPrice>\n >((acc, [assetId, priceData]) => {\n if (priceData.assetPriceType === 'fungible') {\n acc[assetId as Caip19AssetId] = priceData;\n }\n return acc;\n }, {});\n\n for (const [assetId, priceData] of Object.entries(fungibleAssetsPrice)) {\n const { price, usdPrice, lastUpdated } = priceData;\n if (price < 0) {\n continue;\n }\n\n const lastUpdatedInSeconds = lastUpdated / 1000;\n const expirationOffsetInSeconds = 60;\n const expirationTime = lastUpdatedInSeconds + expirationOffsetInSeconds;\n\n try {\n const isNative = assetsInfo[assetId]?.type === 'native';\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n\n if (chainIdParsed.namespace === KnownCaipNamespace.Eip155) {\n const chainIdHex = numberToHex(parseInt(chainIdParsed.reference, 10));\n\n const nativeAssetId = (\n isNative ? assetId : nativeAssetIdentifiers[parsed.chainId]\n ) as Caip19AssetId | undefined;\n\n const nativeCurrencySymbol =\n networkConfigurationsByChainId[chainIdHex]?.nativeCurrency;\n\n const nativeAssetUsdPrice =\n nativeAssetId && fungibleAssetsPrice[nativeAssetId]?.usdPrice;\n\n if (\n !nativeAssetId ||\n !nativeCurrencySymbol ||\n nativeAssetUsdPrice === undefined\n ) {\n // If we do not have a native asset for that chain or a price for it, the asset needs to be skipped\n continue;\n }\n\n let tokenAddress: Hex | undefined;\n if (parsed.assetNamespace === 'erc20') {\n tokenAddress = toChecksumAddress(parsed.assetReference);\n } else if (isNative) {\n tokenAddress = toChecksumAddress(getNativeTokenAddress(chainIdHex));\n }\n\n if (tokenAddress) {\n const priceInNative =\n nativeAssetUsdPrice > 0 ? usdPrice / nativeAssetUsdPrice : usdPrice;\n if (!marketData[chainIdHex]) {\n marketData[chainIdHex] = {};\n }\n marketData[chainIdHex][tokenAddress] = {\n ...priceData,\n price: priceInNative,\n currency: nativeCurrencySymbol,\n assetId,\n chainId: chainIdHex,\n tokenAddress,\n } as MarketDataDetails;\n }\n\n if (isNative) {\n currencyRates[nativeCurrencySymbol] = {\n conversionDate: lastUpdatedInSeconds,\n conversionRate: price,\n usdConversionRate: usdPrice,\n };\n }\n } else {\n conversionRates[assetId as Caip19AssetId] = {\n rate: String(price),\n currency: currencyCaip,\n conversionTime: lastUpdatedInSeconds,\n expirationTime,\n marketData: {\n fungible: true,\n allTimeHigh: `${priceData.allTimeHigh}`,\n allTimeLow: `${priceData.allTimeLow}`,\n circulatingSupply: `${priceData.circulatingSupply}`,\n marketCap: `${priceData.marketCap}`,\n totalVolume: `${priceData.totalVolume}`,\n pricePercentChange: {\n PT1H: priceData.pricePercentChange1h as number,\n P1D: priceData.pricePercentChange1d as number,\n P7D: priceData.pricePercentChange7d as number,\n P14D: priceData.pricePercentChange14d as number,\n P30D: priceData.pricePercentChange30d as number,\n P200D: priceData.pricePercentChange200d as number,\n P1Y: priceData.pricePercentChange1y as number,\n },\n },\n } as MultichainAssetsRatesControllerState['conversionRates'][Caip19AssetId];\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"]}
|
|
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 {\n CurrencyRateState,\n MAP_CAIP_CURRENCIES,\n MarketDataDetails,\n MultichainAssetsRatesControllerState,\n TokenRatesControllerState,\n getNativeTokenAddress,\n} from '@metamask/assets-controllers';\nimport { Hex, KnownCaipNamespace, numberToHex } from '@metamask/utils';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\nimport { isEqual } from 'lodash';\n\nimport type {\n AssetMetadata,\n AssetPrice,\n FungibleAssetPrice,\n Caip19AssetId,\n} from '../types';\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: MultichainAssetsRatesControllerState['conversionRates'];\n currencyRates: CurrencyRateState['currencyRates'];\n marketData: TokenRatesControllerState['marketData'];\n currentCurrency: string;\n};\n\n/** Parameters accepted by {@link formatExchangeRatesForBridge}. */\nexport type FormatExchangeRatesForBridgeParams = {\n assetsInfo: Record<string, AssetMetadata>;\n assetsPrice: Record<string, AssetPrice>;\n selectedCurrency: string;\n nativeAssetIdentifiers: Record<string, string>;\n networkConfigurationsByChainId?: Record<string, { nativeCurrency?: string }>;\n};\n\nlet lastCall: {\n params: FormatExchangeRatesForBridgeParams;\n result: BridgeExchangeRatesFormat;\n} | null = null;\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 * Memoized on input identity for BaseController state slices (`===`) and\n * lodash `isEqual` for rebuilt maps (`nativeAssetIdentifiers`). Bridge quote\n * / rate paths call this repeatedly while assets state is unchanged; recomputing\n * runs keccak256 (`toChecksumAddress`) and CAIP parsing per priced asset.\n *\n * @param params - Conversion parameters.\n * @returns Bridge-compatible conversionRates, currencyRates, marketData, currentCurrency.\n */\nexport function formatExchangeRatesForBridge(\n params: FormatExchangeRatesForBridgeParams,\n): BridgeExchangeRatesFormat {\n if (\n lastCall?.params.assetsInfo === params.assetsInfo &&\n lastCall.params.assetsPrice === params.assetsPrice &&\n lastCall.params.selectedCurrency === params.selectedCurrency &&\n lastCall.params.networkConfigurationsByChainId ===\n params.networkConfigurationsByChainId &&\n isEqual(\n lastCall.params.nativeAssetIdentifiers,\n params.nativeAssetIdentifiers,\n )\n ) {\n return lastCall.result;\n }\n\n const result = computeExchangeRatesForBridge(params);\n lastCall = { params, result };\n return result;\n}\n\n/**\n * Clears the {@link formatExchangeRatesForBridge} memoize cache. Exported for tests.\n */\nexport function clearFormatExchangeRatesForBridgeCacheForTesting(): void {\n lastCall = null;\n}\n\n/**\n * Performs the actual exchange-rate conversion for\n * {@link formatExchangeRatesForBridge}.\n *\n * @param params - Conversion parameters.\n * @returns Bridge-compatible rates.\n */\nfunction computeExchangeRatesForBridge(\n params: FormatExchangeRatesForBridgeParams,\n): BridgeExchangeRatesFormat {\n const {\n assetsInfo,\n assetsPrice,\n selectedCurrency,\n nativeAssetIdentifiers,\n networkConfigurationsByChainId = {},\n } = params;\n const conversionRates: MultichainAssetsRatesControllerState['conversionRates'] =\n {};\n const currencyRates: CurrencyRateState['currencyRates'] = {};\n const marketData: TokenRatesControllerState['marketData'] = {};\n\n const currencyCaip = MAP_CAIP_CURRENCIES[selectedCurrency.toLowerCase()];\n if (!currencyCaip) {\n return {\n conversionRates: {},\n currencyRates: {},\n marketData: {},\n currentCurrency: selectedCurrency,\n };\n }\n\n const fungibleAssetsPrice = Object.entries(assetsPrice).reduce<\n Record<Caip19AssetId, FungibleAssetPrice>\n >((acc, [assetId, priceData]) => {\n if (priceData.assetPriceType === 'fungible') {\n acc[assetId as Caip19AssetId] = priceData;\n }\n return acc;\n }, {});\n\n for (const [assetId, priceData] of Object.entries(fungibleAssetsPrice)) {\n const { price, usdPrice, lastUpdated } = priceData;\n if (price < 0) {\n continue;\n }\n\n const lastUpdatedInSeconds = lastUpdated / 1000;\n const expirationOffsetInSeconds = 60;\n const expirationTime = lastUpdatedInSeconds + expirationOffsetInSeconds;\n\n try {\n const isNative = assetsInfo[assetId]?.type === 'native';\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n\n if (chainIdParsed.namespace === KnownCaipNamespace.Eip155) {\n const chainIdHex = numberToHex(parseInt(chainIdParsed.reference, 10));\n\n const nativeAssetId = (\n isNative ? assetId : nativeAssetIdentifiers[parsed.chainId]\n ) as Caip19AssetId | undefined;\n\n const nativeCurrencySymbol =\n networkConfigurationsByChainId[chainIdHex]?.nativeCurrency;\n\n const nativeAssetUsdPrice =\n nativeAssetId && fungibleAssetsPrice[nativeAssetId]?.usdPrice;\n\n if (\n !nativeAssetId ||\n !nativeCurrencySymbol ||\n nativeAssetUsdPrice === undefined\n ) {\n // If we do not have a native asset for that chain or a price for it, the asset needs to be skipped\n continue;\n }\n\n let tokenAddress: Hex | undefined;\n if (parsed.assetNamespace === 'erc20') {\n tokenAddress = toChecksumAddress(parsed.assetReference);\n } else if (isNative) {\n tokenAddress = toChecksumAddress(getNativeTokenAddress(chainIdHex));\n }\n\n if (tokenAddress) {\n const priceInNative =\n nativeAssetUsdPrice > 0 ? usdPrice / nativeAssetUsdPrice : usdPrice;\n if (!marketData[chainIdHex]) {\n marketData[chainIdHex] = {};\n }\n marketData[chainIdHex][tokenAddress] = {\n ...priceData,\n price: priceInNative,\n currency: nativeCurrencySymbol,\n assetId,\n chainId: chainIdHex,\n tokenAddress,\n } as MarketDataDetails;\n }\n\n if (isNative) {\n currencyRates[nativeCurrencySymbol] = {\n conversionDate: lastUpdatedInSeconds,\n conversionRate: price,\n usdConversionRate: usdPrice,\n };\n }\n } else {\n conversionRates[assetId as Caip19AssetId] = {\n rate: String(price),\n currency: currencyCaip,\n conversionTime: lastUpdatedInSeconds,\n expirationTime,\n marketData: {\n fungible: true,\n allTimeHigh: `${priceData.allTimeHigh}`,\n allTimeLow: `${priceData.allTimeLow}`,\n circulatingSupply: `${priceData.circulatingSupply}`,\n marketCap: `${priceData.marketCap}`,\n totalVolume: `${priceData.totalVolume}`,\n pricePercentChange: {\n PT1H: priceData.pricePercentChange1h as number,\n P1D: priceData.pricePercentChange1d as number,\n P7D: priceData.pricePercentChange7d as number,\n P14D: priceData.pricePercentChange14d as number,\n P30D: priceData.pricePercentChange30d as number,\n P200D: priceData.pricePercentChange200d as number,\n P1Y: priceData.pricePercentChange1y as number,\n },\n },\n } as MultichainAssetsRatesControllerState['conversionRates'][Caip19AssetId];\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"]}
|
|
@@ -1,36 +1,84 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatStateForTransactionPay = void 0;
|
|
3
|
+
exports.clearFormatStateForTransactionPayCacheForTesting = exports.formatStateForTransactionPay = void 0;
|
|
4
4
|
const util_1 = require("@ethereumjs/util");
|
|
5
5
|
const assets_controllers_1 = require("@metamask/assets-controllers");
|
|
6
6
|
const utils_1 = require("@metamask/utils");
|
|
7
7
|
const utils_2 = require("@metamask/utils");
|
|
8
|
+
const lodash_1 = require("lodash");
|
|
8
9
|
const formatExchangeRatesForBridge_1 = require("./formatExchangeRatesForBridge.cjs");
|
|
9
10
|
function amountToHex(amount) {
|
|
10
11
|
const hexString = BigInt(amount).toString(16);
|
|
11
12
|
return `0x${hexString}`;
|
|
12
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Determines whether two sets of {@link formatStateForTransactionPay}
|
|
16
|
+
* parameters are identical for memoization purposes.
|
|
17
|
+
*
|
|
18
|
+
* State slices (`assetsBalance`, `assetsInfo`, `assetsPrice`,
|
|
19
|
+
* `networkConfigurationsByChainId`) are compared by reference since
|
|
20
|
+
* BaseController state updates are immutable. The `accounts` and
|
|
21
|
+
* `nativeAssetIdentifiers` inputs are rebuilt on every call, so they are
|
|
22
|
+
* compared by value instead.
|
|
23
|
+
*
|
|
24
|
+
* @param a - Previous parameters.
|
|
25
|
+
* @param b - Next parameters.
|
|
26
|
+
* @returns True if the parameters are identical.
|
|
27
|
+
*/
|
|
28
|
+
function isTransactionPayParamsIdentical(a, b) {
|
|
29
|
+
return (a.assetsBalance === b.assetsBalance &&
|
|
30
|
+
a.assetsInfo === b.assetsInfo &&
|
|
31
|
+
a.assetsPrice === b.assetsPrice &&
|
|
32
|
+
a.selectedCurrency === b.selectedCurrency &&
|
|
33
|
+
a.networkConfigurationsByChainId === b.networkConfigurationsByChainId &&
|
|
34
|
+
(0, lodash_1.isEqual)(a.accounts, b.accounts) &&
|
|
35
|
+
(0, lodash_1.isEqual)(a.nativeAssetIdentifiers, b.nativeAssetIdentifiers));
|
|
36
|
+
}
|
|
13
37
|
function getAmountFromBalance(balance) {
|
|
14
38
|
return typeof balance === 'object' && balance !== null && 'amount' in balance
|
|
15
39
|
? String(balance.amount)
|
|
16
40
|
: '0';
|
|
17
41
|
}
|
|
42
|
+
let lastCall = null;
|
|
18
43
|
/**
|
|
19
44
|
* Converts AssetsController state into the legacy format consumed by
|
|
20
45
|
* transaction-pay-controller (TokenBalancesController, AccountTrackerController,
|
|
21
46
|
* TokensController, TokenRatesController, CurrencyRateController shapes).
|
|
22
47
|
*
|
|
48
|
+
* The last result is memoized on input identity: this function is invoked (via
|
|
49
|
+
* `AssetsController:getStateForTransactionPay`) on every
|
|
50
|
+
* `TransactionController:stateChange`, but its inputs only change when the
|
|
51
|
+
* assets pipeline updates. Recomputing runs keccak256 (`toChecksumAddress`)
|
|
52
|
+
* per asset per call, which dominates CPU profiles during transaction
|
|
53
|
+
* approval.
|
|
54
|
+
*
|
|
23
55
|
* @param params - Conversion parameters.
|
|
24
|
-
* @param params.assetsBalance - Per-account balances by asset ID.
|
|
25
|
-
* @param params.assetsInfo - Metadata by asset ID.
|
|
26
|
-
* @param params.assetsPrice - Prices by asset ID.
|
|
27
|
-
* @param params.selectedCurrency - Current currency code.
|
|
28
|
-
* @param params.accounts - List of accounts (id + address) to map state for.
|
|
29
|
-
* @param params.nativeAssetIdentifiers - Map of CAIP-2 chain ID to native asset ID. Used for EVM native lookups.
|
|
30
|
-
* @param params.networkConfigurationsByChainId - Optional chain ID to network config (for native symbol).
|
|
31
56
|
* @returns Legacy-compatible state for transaction-pay-controller.
|
|
32
57
|
*/
|
|
33
58
|
function formatStateForTransactionPay(params) {
|
|
59
|
+
if (lastCall && isTransactionPayParamsIdentical(lastCall.params, params)) {
|
|
60
|
+
return lastCall.result;
|
|
61
|
+
}
|
|
62
|
+
const result = computeStateForTransactionPay(params);
|
|
63
|
+
lastCall = { params, result: Object.freeze(result) };
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
exports.formatStateForTransactionPay = formatStateForTransactionPay;
|
|
67
|
+
/**
|
|
68
|
+
* Clears the {@link formatStateForTransactionPay} memoize cache. Exported for tests.
|
|
69
|
+
*/
|
|
70
|
+
function clearFormatStateForTransactionPayCacheForTesting() {
|
|
71
|
+
lastCall = null;
|
|
72
|
+
}
|
|
73
|
+
exports.clearFormatStateForTransactionPayCacheForTesting = clearFormatStateForTransactionPayCacheForTesting;
|
|
74
|
+
/**
|
|
75
|
+
* Performs the actual state conversion for
|
|
76
|
+
* {@link formatStateForTransactionPay}.
|
|
77
|
+
*
|
|
78
|
+
* @param params - Conversion parameters.
|
|
79
|
+
* @returns Legacy-compatible state for transaction-pay-controller.
|
|
80
|
+
*/
|
|
81
|
+
function computeStateForTransactionPay(params) {
|
|
34
82
|
var _a, _b;
|
|
35
83
|
const { assetsBalance, assetsInfo, assetsPrice, selectedCurrency, accounts, nativeAssetIdentifiers, networkConfigurationsByChainId = {}, } = params;
|
|
36
84
|
const tokenBalances = {};
|
|
@@ -123,5 +171,4 @@ function formatStateForTransactionPay(params) {
|
|
|
123
171
|
currentCurrency: exchangeRates.currentCurrency,
|
|
124
172
|
};
|
|
125
173
|
}
|
|
126
|
-
exports.formatStateForTransactionPay = formatStateForTransactionPay;
|
|
127
174
|
//# sourceMappingURL=formatStateForTransactionPay.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatStateForTransactionPay.cjs","sourceRoot":"","sources":["../../src/utils/formatStateForTransactionPay.ts"],"names":[],"mappings":"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","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { getNativeTokenAddress } from '@metamask/assets-controllers';\nimport { numberToHex } from '@metamask/utils';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\n\nimport type {\n AssetBalance,\n AssetMetadata,\n AssetPrice,\n Caip19AssetId,\n} from '../types';\nimport { formatExchangeRatesForBridge } from './formatExchangeRatesForBridge';\nimport type { BridgeExchangeRatesFormat } from './formatExchangeRatesForBridge';\n\n/** Account with id and address for mapping state to legacy format. */\nexport type AccountForLegacyFormat = { id: string; address: string };\n\n/**\n * Legacy Token shape expected by TokensController / transaction-pay-controller.\n */\nexport type LegacyToken = {\n address: string;\n decimals: number;\n symbol: string;\n name?: string;\n [key: string]: unknown;\n};\n\n/**\n * Legacy state shape that transaction-pay-controller reads from\n * TokenBalancesController, AccountTrackerController, TokensController,\n * TokenRatesController, and CurrencyRateController.\n */\nexport type TransactionPayLegacyFormat = {\n /** TokenBalancesController:getState().tokenBalances */\n tokenBalances: Record<string, Record<string, Record<string, `0x${string}`>>>;\n /** AccountTrackerController:getState().accountsByChainId */\n accountsByChainId: Record<\n string,\n Record<string, { balance: string; stakedBalance?: string }>\n >;\n /** TokensController:getState().allTokens (chainId -> key -> Token[]) */\n allTokens: Record<string, Record<string, LegacyToken[]>>;\n /** TokenRatesController:getState().marketData */\n marketData: BridgeExchangeRatesFormat['marketData'];\n /** CurrencyRateController:getState().currencyRates */\n currencyRates: BridgeExchangeRatesFormat['currencyRates'];\n /** CurrencyRateController:getState().currentCurrency */\n currentCurrency: string;\n};\n\nfunction amountToHex(amount: string): `0x${string}` {\n const hexString = BigInt(amount).toString(16);\n return `0x${hexString}`;\n}\n\nfunction getAmountFromBalance(balance: AssetBalance): string {\n return typeof balance === 'object' && balance !== null && 'amount' in balance\n ? String((balance as { amount: string }).amount)\n : '0';\n}\n\n/**\n * Converts AssetsController state into the legacy format consumed by\n * transaction-pay-controller (TokenBalancesController, AccountTrackerController,\n * TokensController, TokenRatesController, CurrencyRateController shapes).\n *\n * @param params - Conversion parameters.\n * @param params.assetsBalance - Per-account balances by asset ID.\n * @param params.assetsInfo - Metadata by asset ID.\n * @param params.assetsPrice - Prices by asset ID.\n * @param params.selectedCurrency - Current currency code.\n * @param params.accounts - List of accounts (id + address) to map state for.\n * @param params.nativeAssetIdentifiers - Map of CAIP-2 chain ID to native asset ID. Used for EVM native lookups.\n * @param params.networkConfigurationsByChainId - Optional chain ID to network config (for native symbol).\n * @returns Legacy-compatible state for transaction-pay-controller.\n */\nexport function formatStateForTransactionPay(params: {\n assetsBalance: Record<string, Record<string, AssetBalance>>;\n assetsInfo: Record<string, AssetMetadata>;\n assetsPrice: Record<string, AssetPrice>;\n selectedCurrency: string;\n accounts: AccountForLegacyFormat[];\n nativeAssetIdentifiers: Record<string, string>;\n networkConfigurationsByChainId?: Record<string, { nativeCurrency?: string }>;\n}): TransactionPayLegacyFormat {\n const {\n assetsBalance,\n assetsInfo,\n assetsPrice,\n selectedCurrency,\n accounts,\n nativeAssetIdentifiers,\n networkConfigurationsByChainId = {},\n } = params;\n\n const tokenBalances: TransactionPayLegacyFormat['tokenBalances'] = {};\n const accountsByChainId: TransactionPayLegacyFormat['accountsByChainId'] = {};\n const allTokensByChain: Record<string, LegacyToken[]> = {};\n\n for (const account of accounts) {\n const accountAddressLower = account.address.toLowerCase();\n const accountBalances = assetsBalance[account.id];\n if (!accountBalances) {\n continue;\n }\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n try {\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n if (chainIdParsed.namespace !== 'eip155') {\n continue;\n }\n const chainIdHex = numberToHex(parseInt(chainIdParsed.reference, 10));\n const amount = getAmountFromBalance(balance);\n const balanceHex = amountToHex(amount);\n\n if (assetsInfo[assetId]?.type === 'native') {\n const nativeAddress = toChecksumAddress(\n getNativeTokenAddress(chainIdHex),\n );\n const checksumAddress = toChecksumAddress(account.address);\n tokenBalances[accountAddressLower] ??= {};\n tokenBalances[accountAddressLower][chainIdHex] ??= {};\n tokenBalances[accountAddressLower][chainIdHex][nativeAddress] =\n balanceHex;\n accountsByChainId[chainIdHex] ??= {};\n accountsByChainId[chainIdHex][checksumAddress] = {\n balance: balanceHex,\n };\n } else if (parsed.assetNamespace === 'erc20') {\n const tokenAddress = toChecksumAddress(String(parsed.assetReference));\n tokenBalances[accountAddressLower] ??= {};\n tokenBalances[accountAddressLower][chainIdHex] ??= {};\n tokenBalances[accountAddressLower][chainIdHex][tokenAddress] =\n balanceHex;\n }\n } catch {\n // Skip malformed asset IDs\n }\n }\n }\n\n for (const [assetId, metadata] of Object.entries(assetsInfo)) {\n try {\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n if (chainIdParsed.namespace !== 'eip155') {\n continue;\n }\n const chainIdHex = numberToHex(parseInt(chainIdParsed.reference, 10));\n const address =\n metadata.type === 'native'\n ? getNativeTokenAddress(chainIdHex)\n : toChecksumAddress(String(parsed.assetReference));\n const token: LegacyToken = {\n address,\n decimals: metadata.decimals,\n symbol: metadata.symbol,\n name: metadata.name,\n };\n allTokensByChain[chainIdHex] ??= [];\n if (\n !allTokensByChain[chainIdHex].some(\n (existing) =>\n existing.address.toLowerCase() === address.toLowerCase(),\n )\n ) {\n allTokensByChain[chainIdHex].push(token);\n }\n } catch {\n // Skip malformed asset IDs\n }\n }\n\n const allTokens: TransactionPayLegacyFormat['allTokens'] = {};\n for (const [chainId, tokens] of Object.entries(allTokensByChain)) {\n allTokens[chainId] = { '': tokens };\n }\n\n const exchangeRates = formatExchangeRatesForBridge({\n assetsInfo,\n assetsPrice,\n selectedCurrency,\n nativeAssetIdentifiers,\n networkConfigurationsByChainId,\n });\n\n return {\n tokenBalances,\n accountsByChainId,\n allTokens,\n marketData: exchangeRates.marketData,\n currencyRates: exchangeRates.currencyRates,\n currentCurrency: exchangeRates.currentCurrency,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"formatStateForTransactionPay.cjs","sourceRoot":"","sources":["../../src/utils/formatStateForTransactionPay.ts"],"names":[],"mappings":"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","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { getNativeTokenAddress } from '@metamask/assets-controllers';\nimport { numberToHex } from '@metamask/utils';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\nimport { isEqual } from 'lodash';\n\nimport type {\n AssetBalance,\n AssetMetadata,\n AssetPrice,\n Caip19AssetId,\n} from '../types';\nimport { formatExchangeRatesForBridge } from './formatExchangeRatesForBridge';\nimport type { BridgeExchangeRatesFormat } from './formatExchangeRatesForBridge';\n\n/** Account with id and address for mapping state to legacy format. */\nexport type AccountForLegacyFormat = { id: string; address: string };\n\n/**\n * Legacy Token shape expected by TokensController / transaction-pay-controller.\n */\nexport type LegacyToken = {\n address: string;\n decimals: number;\n symbol: string;\n name?: string;\n [key: string]: unknown;\n};\n\n/**\n * Legacy state shape that transaction-pay-controller reads from\n * TokenBalancesController, AccountTrackerController, TokensController,\n * TokenRatesController, and CurrencyRateController.\n */\nexport type TransactionPayLegacyFormat = {\n /** TokenBalancesController:getState().tokenBalances */\n tokenBalances: Record<string, Record<string, Record<string, `0x${string}`>>>;\n /** AccountTrackerController:getState().accountsByChainId */\n accountsByChainId: Record<\n string,\n Record<string, { balance: string; stakedBalance?: string }>\n >;\n /** TokensController:getState().allTokens (chainId -> key -> Token[]) */\n allTokens: Record<string, Record<string, LegacyToken[]>>;\n /** TokenRatesController:getState().marketData */\n marketData: BridgeExchangeRatesFormat['marketData'];\n /** CurrencyRateController:getState().currencyRates */\n currencyRates: BridgeExchangeRatesFormat['currencyRates'];\n /** CurrencyRateController:getState().currentCurrency */\n currentCurrency: string;\n};\n\n/** Parameters accepted by {@link formatStateForTransactionPay}. */\nexport type FormatStateForTransactionPayParams = {\n assetsBalance: Record<string, Record<string, AssetBalance>>;\n assetsInfo: Record<string, AssetMetadata>;\n assetsPrice: Record<string, AssetPrice>;\n selectedCurrency: string;\n accounts: AccountForLegacyFormat[];\n nativeAssetIdentifiers: Record<string, string>;\n networkConfigurationsByChainId?: Record<string, { nativeCurrency?: string }>;\n};\n\nfunction amountToHex(amount: string): `0x${string}` {\n const hexString = BigInt(amount).toString(16);\n return `0x${hexString}`;\n}\n\n/**\n * Determines whether two sets of {@link formatStateForTransactionPay}\n * parameters are identical for memoization purposes.\n *\n * State slices (`assetsBalance`, `assetsInfo`, `assetsPrice`,\n * `networkConfigurationsByChainId`) are compared by reference since\n * BaseController state updates are immutable. The `accounts` and\n * `nativeAssetIdentifiers` inputs are rebuilt on every call, so they are\n * compared by value instead.\n *\n * @param a - Previous parameters.\n * @param b - Next parameters.\n * @returns True if the parameters are identical.\n */\nfunction isTransactionPayParamsIdentical(\n a: FormatStateForTransactionPayParams,\n b: FormatStateForTransactionPayParams,\n): boolean {\n return (\n a.assetsBalance === b.assetsBalance &&\n a.assetsInfo === b.assetsInfo &&\n a.assetsPrice === b.assetsPrice &&\n a.selectedCurrency === b.selectedCurrency &&\n a.networkConfigurationsByChainId === b.networkConfigurationsByChainId &&\n isEqual(a.accounts, b.accounts) &&\n isEqual(a.nativeAssetIdentifiers, b.nativeAssetIdentifiers)\n );\n}\n\nfunction getAmountFromBalance(balance: AssetBalance): string {\n return typeof balance === 'object' && balance !== null && 'amount' in balance\n ? String((balance as { amount: string }).amount)\n : '0';\n}\n\nlet lastCall: {\n params: FormatStateForTransactionPayParams;\n result: TransactionPayLegacyFormat;\n} | null = null;\n\n/**\n * Converts AssetsController state into the legacy format consumed by\n * transaction-pay-controller (TokenBalancesController, AccountTrackerController,\n * TokensController, TokenRatesController, CurrencyRateController shapes).\n *\n * The last result is memoized on input identity: this function is invoked (via\n * `AssetsController:getStateForTransactionPay`) on every\n * `TransactionController:stateChange`, but its inputs only change when the\n * assets pipeline updates. Recomputing runs keccak256 (`toChecksumAddress`)\n * per asset per call, which dominates CPU profiles during transaction\n * approval.\n *\n * @param params - Conversion parameters.\n * @returns Legacy-compatible state for transaction-pay-controller.\n */\nexport function formatStateForTransactionPay(\n params: FormatStateForTransactionPayParams,\n): TransactionPayLegacyFormat {\n if (lastCall && isTransactionPayParamsIdentical(lastCall.params, params)) {\n return lastCall.result;\n }\n\n const result = computeStateForTransactionPay(params);\n lastCall = { params, result: Object.freeze(result) };\n return result;\n}\n\n/**\n * Clears the {@link formatStateForTransactionPay} memoize cache. Exported for tests.\n */\nexport function clearFormatStateForTransactionPayCacheForTesting(): void {\n lastCall = null;\n}\n\n/**\n * Performs the actual state conversion for\n * {@link formatStateForTransactionPay}.\n *\n * @param params - Conversion parameters.\n * @returns Legacy-compatible state for transaction-pay-controller.\n */\nfunction computeStateForTransactionPay(\n params: FormatStateForTransactionPayParams,\n): TransactionPayLegacyFormat {\n const {\n assetsBalance,\n assetsInfo,\n assetsPrice,\n selectedCurrency,\n accounts,\n nativeAssetIdentifiers,\n networkConfigurationsByChainId = {},\n } = params;\n\n const tokenBalances: TransactionPayLegacyFormat['tokenBalances'] = {};\n const accountsByChainId: TransactionPayLegacyFormat['accountsByChainId'] = {};\n const allTokensByChain: Record<string, LegacyToken[]> = {};\n\n for (const account of accounts) {\n const accountAddressLower = account.address.toLowerCase();\n const accountBalances = assetsBalance[account.id];\n if (!accountBalances) {\n continue;\n }\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n try {\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n if (chainIdParsed.namespace !== 'eip155') {\n continue;\n }\n const chainIdHex = numberToHex(parseInt(chainIdParsed.reference, 10));\n const amount = getAmountFromBalance(balance);\n const balanceHex = amountToHex(amount);\n\n if (assetsInfo[assetId]?.type === 'native') {\n const nativeAddress = toChecksumAddress(\n getNativeTokenAddress(chainIdHex),\n );\n const checksumAddress = toChecksumAddress(account.address);\n tokenBalances[accountAddressLower] ??= {};\n tokenBalances[accountAddressLower][chainIdHex] ??= {};\n tokenBalances[accountAddressLower][chainIdHex][nativeAddress] =\n balanceHex;\n accountsByChainId[chainIdHex] ??= {};\n accountsByChainId[chainIdHex][checksumAddress] = {\n balance: balanceHex,\n };\n } else if (parsed.assetNamespace === 'erc20') {\n const tokenAddress = toChecksumAddress(String(parsed.assetReference));\n tokenBalances[accountAddressLower] ??= {};\n tokenBalances[accountAddressLower][chainIdHex] ??= {};\n tokenBalances[accountAddressLower][chainIdHex][tokenAddress] =\n balanceHex;\n }\n } catch {\n // Skip malformed asset IDs\n }\n }\n }\n\n for (const [assetId, metadata] of Object.entries(assetsInfo)) {\n try {\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n if (chainIdParsed.namespace !== 'eip155') {\n continue;\n }\n const chainIdHex = numberToHex(parseInt(chainIdParsed.reference, 10));\n const address =\n metadata.type === 'native'\n ? getNativeTokenAddress(chainIdHex)\n : toChecksumAddress(String(parsed.assetReference));\n const token: LegacyToken = {\n address,\n decimals: metadata.decimals,\n symbol: metadata.symbol,\n name: metadata.name,\n };\n allTokensByChain[chainIdHex] ??= [];\n if (\n !allTokensByChain[chainIdHex].some(\n (existing) =>\n existing.address.toLowerCase() === address.toLowerCase(),\n )\n ) {\n allTokensByChain[chainIdHex].push(token);\n }\n } catch {\n // Skip malformed asset IDs\n }\n }\n\n const allTokens: TransactionPayLegacyFormat['allTokens'] = {};\n for (const [chainId, tokens] of Object.entries(allTokensByChain)) {\n allTokens[chainId] = { '': tokens };\n }\n\n const exchangeRates = formatExchangeRatesForBridge({\n assetsInfo,\n assetsPrice,\n selectedCurrency,\n nativeAssetIdentifiers,\n networkConfigurationsByChainId,\n });\n\n return {\n tokenBalances,\n accountsByChainId,\n allTokens,\n marketData: exchangeRates.marketData,\n currencyRates: exchangeRates.currencyRates,\n currentCurrency: exchangeRates.currentCurrency,\n };\n}\n"]}
|
|
@@ -37,22 +37,8 @@ export type TransactionPayLegacyFormat = {
|
|
|
37
37
|
/** CurrencyRateController:getState().currentCurrency */
|
|
38
38
|
currentCurrency: string;
|
|
39
39
|
};
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
-
* transaction-pay-controller (TokenBalancesController, AccountTrackerController,
|
|
43
|
-
* TokensController, TokenRatesController, CurrencyRateController shapes).
|
|
44
|
-
*
|
|
45
|
-
* @param params - Conversion parameters.
|
|
46
|
-
* @param params.assetsBalance - Per-account balances by asset ID.
|
|
47
|
-
* @param params.assetsInfo - Metadata by asset ID.
|
|
48
|
-
* @param params.assetsPrice - Prices by asset ID.
|
|
49
|
-
* @param params.selectedCurrency - Current currency code.
|
|
50
|
-
* @param params.accounts - List of accounts (id + address) to map state for.
|
|
51
|
-
* @param params.nativeAssetIdentifiers - Map of CAIP-2 chain ID to native asset ID. Used for EVM native lookups.
|
|
52
|
-
* @param params.networkConfigurationsByChainId - Optional chain ID to network config (for native symbol).
|
|
53
|
-
* @returns Legacy-compatible state for transaction-pay-controller.
|
|
54
|
-
*/
|
|
55
|
-
export declare function formatStateForTransactionPay(params: {
|
|
40
|
+
/** Parameters accepted by {@link formatStateForTransactionPay}. */
|
|
41
|
+
export type FormatStateForTransactionPayParams = {
|
|
56
42
|
assetsBalance: Record<string, Record<string, AssetBalance>>;
|
|
57
43
|
assetsInfo: Record<string, AssetMetadata>;
|
|
58
44
|
assetsPrice: Record<string, AssetPrice>;
|
|
@@ -62,5 +48,25 @@ export declare function formatStateForTransactionPay(params: {
|
|
|
62
48
|
networkConfigurationsByChainId?: Record<string, {
|
|
63
49
|
nativeCurrency?: string;
|
|
64
50
|
}>;
|
|
65
|
-
}
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Converts AssetsController state into the legacy format consumed by
|
|
54
|
+
* transaction-pay-controller (TokenBalancesController, AccountTrackerController,
|
|
55
|
+
* TokensController, TokenRatesController, CurrencyRateController shapes).
|
|
56
|
+
*
|
|
57
|
+
* The last result is memoized on input identity: this function is invoked (via
|
|
58
|
+
* `AssetsController:getStateForTransactionPay`) on every
|
|
59
|
+
* `TransactionController:stateChange`, but its inputs only change when the
|
|
60
|
+
* assets pipeline updates. Recomputing runs keccak256 (`toChecksumAddress`)
|
|
61
|
+
* per asset per call, which dominates CPU profiles during transaction
|
|
62
|
+
* approval.
|
|
63
|
+
*
|
|
64
|
+
* @param params - Conversion parameters.
|
|
65
|
+
* @returns Legacy-compatible state for transaction-pay-controller.
|
|
66
|
+
*/
|
|
67
|
+
export declare function formatStateForTransactionPay(params: FormatStateForTransactionPayParams): TransactionPayLegacyFormat;
|
|
68
|
+
/**
|
|
69
|
+
* Clears the {@link formatStateForTransactionPay} memoize cache. Exported for tests.
|
|
70
|
+
*/
|
|
71
|
+
export declare function clearFormatStateForTransactionPayCacheForTesting(): void;
|
|
66
72
|
//# sourceMappingURL=formatStateForTransactionPay.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatStateForTransactionPay.d.cts","sourceRoot":"","sources":["../../src/utils/formatStateForTransactionPay.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"formatStateForTransactionPay.d.cts","sourceRoot":"","sources":["../../src/utils/formatStateForTransactionPay.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,UAAU,EAEX,qBAAiB;AAElB,OAAO,KAAK,EAAE,yBAAyB,EAAE,2CAAuC;AAEhF,sEAAsE;AACtE,MAAM,MAAM,sBAAsB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC,uDAAuD;IACvD,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7E,4DAA4D;IAC5D,iBAAiB,EAAE,MAAM,CACvB,MAAM,EACN,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAC5D,CAAC;IACF,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;IACzD,iDAAiD;IACjD,UAAU,EAAE,yBAAyB,CAAC,YAAY,CAAC,CAAC;IACpD,sDAAsD;IACtD,aAAa,EAAE,yBAAyB,CAAC,eAAe,CAAC,CAAC;IAC1D,wDAAwD;IACxD,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,mEAAmE;AACnE,MAAM,MAAM,kCAAkC,GAAG;IAC/C,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5D,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,8BAA8B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9E,CAAC;AA+CF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,kCAAkC,GACzC,0BAA0B,CAQ5B;AAED;;GAEG;AACH,wBAAgB,gDAAgD,IAAI,IAAI,CAEvE"}
|
|
@@ -37,22 +37,8 @@ export type TransactionPayLegacyFormat = {
|
|
|
37
37
|
/** CurrencyRateController:getState().currentCurrency */
|
|
38
38
|
currentCurrency: string;
|
|
39
39
|
};
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
-
* transaction-pay-controller (TokenBalancesController, AccountTrackerController,
|
|
43
|
-
* TokensController, TokenRatesController, CurrencyRateController shapes).
|
|
44
|
-
*
|
|
45
|
-
* @param params - Conversion parameters.
|
|
46
|
-
* @param params.assetsBalance - Per-account balances by asset ID.
|
|
47
|
-
* @param params.assetsInfo - Metadata by asset ID.
|
|
48
|
-
* @param params.assetsPrice - Prices by asset ID.
|
|
49
|
-
* @param params.selectedCurrency - Current currency code.
|
|
50
|
-
* @param params.accounts - List of accounts (id + address) to map state for.
|
|
51
|
-
* @param params.nativeAssetIdentifiers - Map of CAIP-2 chain ID to native asset ID. Used for EVM native lookups.
|
|
52
|
-
* @param params.networkConfigurationsByChainId - Optional chain ID to network config (for native symbol).
|
|
53
|
-
* @returns Legacy-compatible state for transaction-pay-controller.
|
|
54
|
-
*/
|
|
55
|
-
export declare function formatStateForTransactionPay(params: {
|
|
40
|
+
/** Parameters accepted by {@link formatStateForTransactionPay}. */
|
|
41
|
+
export type FormatStateForTransactionPayParams = {
|
|
56
42
|
assetsBalance: Record<string, Record<string, AssetBalance>>;
|
|
57
43
|
assetsInfo: Record<string, AssetMetadata>;
|
|
58
44
|
assetsPrice: Record<string, AssetPrice>;
|
|
@@ -62,5 +48,25 @@ export declare function formatStateForTransactionPay(params: {
|
|
|
62
48
|
networkConfigurationsByChainId?: Record<string, {
|
|
63
49
|
nativeCurrency?: string;
|
|
64
50
|
}>;
|
|
65
|
-
}
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Converts AssetsController state into the legacy format consumed by
|
|
54
|
+
* transaction-pay-controller (TokenBalancesController, AccountTrackerController,
|
|
55
|
+
* TokensController, TokenRatesController, CurrencyRateController shapes).
|
|
56
|
+
*
|
|
57
|
+
* The last result is memoized on input identity: this function is invoked (via
|
|
58
|
+
* `AssetsController:getStateForTransactionPay`) on every
|
|
59
|
+
* `TransactionController:stateChange`, but its inputs only change when the
|
|
60
|
+
* assets pipeline updates. Recomputing runs keccak256 (`toChecksumAddress`)
|
|
61
|
+
* per asset per call, which dominates CPU profiles during transaction
|
|
62
|
+
* approval.
|
|
63
|
+
*
|
|
64
|
+
* @param params - Conversion parameters.
|
|
65
|
+
* @returns Legacy-compatible state for transaction-pay-controller.
|
|
66
|
+
*/
|
|
67
|
+
export declare function formatStateForTransactionPay(params: FormatStateForTransactionPayParams): TransactionPayLegacyFormat;
|
|
68
|
+
/**
|
|
69
|
+
* Clears the {@link formatStateForTransactionPay} memoize cache. Exported for tests.
|
|
70
|
+
*/
|
|
71
|
+
export declare function clearFormatStateForTransactionPayCacheForTesting(): void;
|
|
66
72
|
//# sourceMappingURL=formatStateForTransactionPay.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatStateForTransactionPay.d.mts","sourceRoot":"","sources":["../../src/utils/formatStateForTransactionPay.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"formatStateForTransactionPay.d.mts","sourceRoot":"","sources":["../../src/utils/formatStateForTransactionPay.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,UAAU,EAEX,qBAAiB;AAElB,OAAO,KAAK,EAAE,yBAAyB,EAAE,2CAAuC;AAEhF,sEAAsE;AACtE,MAAM,MAAM,sBAAsB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC,uDAAuD;IACvD,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7E,4DAA4D;IAC5D,iBAAiB,EAAE,MAAM,CACvB,MAAM,EACN,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAC5D,CAAC;IACF,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;IACzD,iDAAiD;IACjD,UAAU,EAAE,yBAAyB,CAAC,YAAY,CAAC,CAAC;IACpD,sDAAsD;IACtD,aAAa,EAAE,yBAAyB,CAAC,eAAe,CAAC,CAAC;IAC1D,wDAAwD;IACxD,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,mEAAmE;AACnE,MAAM,MAAM,kCAAkC,GAAG;IAC/C,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5D,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,8BAA8B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9E,CAAC;AA+CF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,kCAAkC,GACzC,0BAA0B,CAQ5B;AAED;;GAEG;AACH,wBAAgB,gDAAgD,IAAI,IAAI,CAEvE"}
|
|
@@ -2,32 +2,79 @@ import { toChecksumAddress } from "@ethereumjs/util";
|
|
|
2
2
|
import { getNativeTokenAddress } from "@metamask/assets-controllers";
|
|
3
3
|
import { numberToHex } from "@metamask/utils";
|
|
4
4
|
import { parseCaipAssetType, parseCaipChainId } from "@metamask/utils";
|
|
5
|
+
import $lodash from "lodash";
|
|
6
|
+
const { isEqual } = $lodash;
|
|
5
7
|
import { formatExchangeRatesForBridge } from "./formatExchangeRatesForBridge.mjs";
|
|
6
8
|
function amountToHex(amount) {
|
|
7
9
|
const hexString = BigInt(amount).toString(16);
|
|
8
10
|
return `0x${hexString}`;
|
|
9
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Determines whether two sets of {@link formatStateForTransactionPay}
|
|
14
|
+
* parameters are identical for memoization purposes.
|
|
15
|
+
*
|
|
16
|
+
* State slices (`assetsBalance`, `assetsInfo`, `assetsPrice`,
|
|
17
|
+
* `networkConfigurationsByChainId`) are compared by reference since
|
|
18
|
+
* BaseController state updates are immutable. The `accounts` and
|
|
19
|
+
* `nativeAssetIdentifiers` inputs are rebuilt on every call, so they are
|
|
20
|
+
* compared by value instead.
|
|
21
|
+
*
|
|
22
|
+
* @param a - Previous parameters.
|
|
23
|
+
* @param b - Next parameters.
|
|
24
|
+
* @returns True if the parameters are identical.
|
|
25
|
+
*/
|
|
26
|
+
function isTransactionPayParamsIdentical(a, b) {
|
|
27
|
+
return (a.assetsBalance === b.assetsBalance &&
|
|
28
|
+
a.assetsInfo === b.assetsInfo &&
|
|
29
|
+
a.assetsPrice === b.assetsPrice &&
|
|
30
|
+
a.selectedCurrency === b.selectedCurrency &&
|
|
31
|
+
a.networkConfigurationsByChainId === b.networkConfigurationsByChainId &&
|
|
32
|
+
isEqual(a.accounts, b.accounts) &&
|
|
33
|
+
isEqual(a.nativeAssetIdentifiers, b.nativeAssetIdentifiers));
|
|
34
|
+
}
|
|
10
35
|
function getAmountFromBalance(balance) {
|
|
11
36
|
return typeof balance === 'object' && balance !== null && 'amount' in balance
|
|
12
37
|
? String(balance.amount)
|
|
13
38
|
: '0';
|
|
14
39
|
}
|
|
40
|
+
let lastCall = null;
|
|
15
41
|
/**
|
|
16
42
|
* Converts AssetsController state into the legacy format consumed by
|
|
17
43
|
* transaction-pay-controller (TokenBalancesController, AccountTrackerController,
|
|
18
44
|
* TokensController, TokenRatesController, CurrencyRateController shapes).
|
|
19
45
|
*
|
|
46
|
+
* The last result is memoized on input identity: this function is invoked (via
|
|
47
|
+
* `AssetsController:getStateForTransactionPay`) on every
|
|
48
|
+
* `TransactionController:stateChange`, but its inputs only change when the
|
|
49
|
+
* assets pipeline updates. Recomputing runs keccak256 (`toChecksumAddress`)
|
|
50
|
+
* per asset per call, which dominates CPU profiles during transaction
|
|
51
|
+
* approval.
|
|
52
|
+
*
|
|
20
53
|
* @param params - Conversion parameters.
|
|
21
|
-
* @param params.assetsBalance - Per-account balances by asset ID.
|
|
22
|
-
* @param params.assetsInfo - Metadata by asset ID.
|
|
23
|
-
* @param params.assetsPrice - Prices by asset ID.
|
|
24
|
-
* @param params.selectedCurrency - Current currency code.
|
|
25
|
-
* @param params.accounts - List of accounts (id + address) to map state for.
|
|
26
|
-
* @param params.nativeAssetIdentifiers - Map of CAIP-2 chain ID to native asset ID. Used for EVM native lookups.
|
|
27
|
-
* @param params.networkConfigurationsByChainId - Optional chain ID to network config (for native symbol).
|
|
28
54
|
* @returns Legacy-compatible state for transaction-pay-controller.
|
|
29
55
|
*/
|
|
30
56
|
export function formatStateForTransactionPay(params) {
|
|
57
|
+
if (lastCall && isTransactionPayParamsIdentical(lastCall.params, params)) {
|
|
58
|
+
return lastCall.result;
|
|
59
|
+
}
|
|
60
|
+
const result = computeStateForTransactionPay(params);
|
|
61
|
+
lastCall = { params, result: Object.freeze(result) };
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Clears the {@link formatStateForTransactionPay} memoize cache. Exported for tests.
|
|
66
|
+
*/
|
|
67
|
+
export function clearFormatStateForTransactionPayCacheForTesting() {
|
|
68
|
+
lastCall = null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Performs the actual state conversion for
|
|
72
|
+
* {@link formatStateForTransactionPay}.
|
|
73
|
+
*
|
|
74
|
+
* @param params - Conversion parameters.
|
|
75
|
+
* @returns Legacy-compatible state for transaction-pay-controller.
|
|
76
|
+
*/
|
|
77
|
+
function computeStateForTransactionPay(params) {
|
|
31
78
|
var _a, _b;
|
|
32
79
|
const { assetsBalance, assetsInfo, assetsPrice, selectedCurrency, accounts, nativeAssetIdentifiers, networkConfigurationsByChainId = {}, } = params;
|
|
33
80
|
const tokenBalances = {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatStateForTransactionPay.mjs","sourceRoot":"","sources":["../../src/utils/formatStateForTransactionPay.ts"],"names":[],"mappings":"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","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { getNativeTokenAddress } from '@metamask/assets-controllers';\nimport { numberToHex } from '@metamask/utils';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\n\nimport type {\n AssetBalance,\n AssetMetadata,\n AssetPrice,\n Caip19AssetId,\n} from '../types';\nimport { formatExchangeRatesForBridge } from './formatExchangeRatesForBridge';\nimport type { BridgeExchangeRatesFormat } from './formatExchangeRatesForBridge';\n\n/** Account with id and address for mapping state to legacy format. */\nexport type AccountForLegacyFormat = { id: string; address: string };\n\n/**\n * Legacy Token shape expected by TokensController / transaction-pay-controller.\n */\nexport type LegacyToken = {\n address: string;\n decimals: number;\n symbol: string;\n name?: string;\n [key: string]: unknown;\n};\n\n/**\n * Legacy state shape that transaction-pay-controller reads from\n * TokenBalancesController, AccountTrackerController, TokensController,\n * TokenRatesController, and CurrencyRateController.\n */\nexport type TransactionPayLegacyFormat = {\n /** TokenBalancesController:getState().tokenBalances */\n tokenBalances: Record<string, Record<string, Record<string, `0x${string}`>>>;\n /** AccountTrackerController:getState().accountsByChainId */\n accountsByChainId: Record<\n string,\n Record<string, { balance: string; stakedBalance?: string }>\n >;\n /** TokensController:getState().allTokens (chainId -> key -> Token[]) */\n allTokens: Record<string, Record<string, LegacyToken[]>>;\n /** TokenRatesController:getState().marketData */\n marketData: BridgeExchangeRatesFormat['marketData'];\n /** CurrencyRateController:getState().currencyRates */\n currencyRates: BridgeExchangeRatesFormat['currencyRates'];\n /** CurrencyRateController:getState().currentCurrency */\n currentCurrency: string;\n};\n\nfunction amountToHex(amount: string): `0x${string}` {\n const hexString = BigInt(amount).toString(16);\n return `0x${hexString}`;\n}\n\nfunction getAmountFromBalance(balance: AssetBalance): string {\n return typeof balance === 'object' && balance !== null && 'amount' in balance\n ? String((balance as { amount: string }).amount)\n : '0';\n}\n\n/**\n * Converts AssetsController state into the legacy format consumed by\n * transaction-pay-controller (TokenBalancesController, AccountTrackerController,\n * TokensController, TokenRatesController, CurrencyRateController shapes).\n *\n * @param params - Conversion parameters.\n * @param params.assetsBalance - Per-account balances by asset ID.\n * @param params.assetsInfo - Metadata by asset ID.\n * @param params.assetsPrice - Prices by asset ID.\n * @param params.selectedCurrency - Current currency code.\n * @param params.accounts - List of accounts (id + address) to map state for.\n * @param params.nativeAssetIdentifiers - Map of CAIP-2 chain ID to native asset ID. Used for EVM native lookups.\n * @param params.networkConfigurationsByChainId - Optional chain ID to network config (for native symbol).\n * @returns Legacy-compatible state for transaction-pay-controller.\n */\nexport function formatStateForTransactionPay(params: {\n assetsBalance: Record<string, Record<string, AssetBalance>>;\n assetsInfo: Record<string, AssetMetadata>;\n assetsPrice: Record<string, AssetPrice>;\n selectedCurrency: string;\n accounts: AccountForLegacyFormat[];\n nativeAssetIdentifiers: Record<string, string>;\n networkConfigurationsByChainId?: Record<string, { nativeCurrency?: string }>;\n}): TransactionPayLegacyFormat {\n const {\n assetsBalance,\n assetsInfo,\n assetsPrice,\n selectedCurrency,\n accounts,\n nativeAssetIdentifiers,\n networkConfigurationsByChainId = {},\n } = params;\n\n const tokenBalances: TransactionPayLegacyFormat['tokenBalances'] = {};\n const accountsByChainId: TransactionPayLegacyFormat['accountsByChainId'] = {};\n const allTokensByChain: Record<string, LegacyToken[]> = {};\n\n for (const account of accounts) {\n const accountAddressLower = account.address.toLowerCase();\n const accountBalances = assetsBalance[account.id];\n if (!accountBalances) {\n continue;\n }\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n try {\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n if (chainIdParsed.namespace !== 'eip155') {\n continue;\n }\n const chainIdHex = numberToHex(parseInt(chainIdParsed.reference, 10));\n const amount = getAmountFromBalance(balance);\n const balanceHex = amountToHex(amount);\n\n if (assetsInfo[assetId]?.type === 'native') {\n const nativeAddress = toChecksumAddress(\n getNativeTokenAddress(chainIdHex),\n );\n const checksumAddress = toChecksumAddress(account.address);\n tokenBalances[accountAddressLower] ??= {};\n tokenBalances[accountAddressLower][chainIdHex] ??= {};\n tokenBalances[accountAddressLower][chainIdHex][nativeAddress] =\n balanceHex;\n accountsByChainId[chainIdHex] ??= {};\n accountsByChainId[chainIdHex][checksumAddress] = {\n balance: balanceHex,\n };\n } else if (parsed.assetNamespace === 'erc20') {\n const tokenAddress = toChecksumAddress(String(parsed.assetReference));\n tokenBalances[accountAddressLower] ??= {};\n tokenBalances[accountAddressLower][chainIdHex] ??= {};\n tokenBalances[accountAddressLower][chainIdHex][tokenAddress] =\n balanceHex;\n }\n } catch {\n // Skip malformed asset IDs\n }\n }\n }\n\n for (const [assetId, metadata] of Object.entries(assetsInfo)) {\n try {\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n if (chainIdParsed.namespace !== 'eip155') {\n continue;\n }\n const chainIdHex = numberToHex(parseInt(chainIdParsed.reference, 10));\n const address =\n metadata.type === 'native'\n ? getNativeTokenAddress(chainIdHex)\n : toChecksumAddress(String(parsed.assetReference));\n const token: LegacyToken = {\n address,\n decimals: metadata.decimals,\n symbol: metadata.symbol,\n name: metadata.name,\n };\n allTokensByChain[chainIdHex] ??= [];\n if (\n !allTokensByChain[chainIdHex].some(\n (existing) =>\n existing.address.toLowerCase() === address.toLowerCase(),\n )\n ) {\n allTokensByChain[chainIdHex].push(token);\n }\n } catch {\n // Skip malformed asset IDs\n }\n }\n\n const allTokens: TransactionPayLegacyFormat['allTokens'] = {};\n for (const [chainId, tokens] of Object.entries(allTokensByChain)) {\n allTokens[chainId] = { '': tokens };\n }\n\n const exchangeRates = formatExchangeRatesForBridge({\n assetsInfo,\n assetsPrice,\n selectedCurrency,\n nativeAssetIdentifiers,\n networkConfigurationsByChainId,\n });\n\n return {\n tokenBalances,\n accountsByChainId,\n allTokens,\n marketData: exchangeRates.marketData,\n currencyRates: exchangeRates.currencyRates,\n currentCurrency: exchangeRates.currentCurrency,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"formatStateForTransactionPay.mjs","sourceRoot":"","sources":["../../src/utils/formatStateForTransactionPay.ts"],"names":[],"mappings":"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","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { getNativeTokenAddress } from '@metamask/assets-controllers';\nimport { numberToHex } from '@metamask/utils';\nimport { parseCaipAssetType, parseCaipChainId } from '@metamask/utils';\nimport { isEqual } from 'lodash';\n\nimport type {\n AssetBalance,\n AssetMetadata,\n AssetPrice,\n Caip19AssetId,\n} from '../types';\nimport { formatExchangeRatesForBridge } from './formatExchangeRatesForBridge';\nimport type { BridgeExchangeRatesFormat } from './formatExchangeRatesForBridge';\n\n/** Account with id and address for mapping state to legacy format. */\nexport type AccountForLegacyFormat = { id: string; address: string };\n\n/**\n * Legacy Token shape expected by TokensController / transaction-pay-controller.\n */\nexport type LegacyToken = {\n address: string;\n decimals: number;\n symbol: string;\n name?: string;\n [key: string]: unknown;\n};\n\n/**\n * Legacy state shape that transaction-pay-controller reads from\n * TokenBalancesController, AccountTrackerController, TokensController,\n * TokenRatesController, and CurrencyRateController.\n */\nexport type TransactionPayLegacyFormat = {\n /** TokenBalancesController:getState().tokenBalances */\n tokenBalances: Record<string, Record<string, Record<string, `0x${string}`>>>;\n /** AccountTrackerController:getState().accountsByChainId */\n accountsByChainId: Record<\n string,\n Record<string, { balance: string; stakedBalance?: string }>\n >;\n /** TokensController:getState().allTokens (chainId -> key -> Token[]) */\n allTokens: Record<string, Record<string, LegacyToken[]>>;\n /** TokenRatesController:getState().marketData */\n marketData: BridgeExchangeRatesFormat['marketData'];\n /** CurrencyRateController:getState().currencyRates */\n currencyRates: BridgeExchangeRatesFormat['currencyRates'];\n /** CurrencyRateController:getState().currentCurrency */\n currentCurrency: string;\n};\n\n/** Parameters accepted by {@link formatStateForTransactionPay}. */\nexport type FormatStateForTransactionPayParams = {\n assetsBalance: Record<string, Record<string, AssetBalance>>;\n assetsInfo: Record<string, AssetMetadata>;\n assetsPrice: Record<string, AssetPrice>;\n selectedCurrency: string;\n accounts: AccountForLegacyFormat[];\n nativeAssetIdentifiers: Record<string, string>;\n networkConfigurationsByChainId?: Record<string, { nativeCurrency?: string }>;\n};\n\nfunction amountToHex(amount: string): `0x${string}` {\n const hexString = BigInt(amount).toString(16);\n return `0x${hexString}`;\n}\n\n/**\n * Determines whether two sets of {@link formatStateForTransactionPay}\n * parameters are identical for memoization purposes.\n *\n * State slices (`assetsBalance`, `assetsInfo`, `assetsPrice`,\n * `networkConfigurationsByChainId`) are compared by reference since\n * BaseController state updates are immutable. The `accounts` and\n * `nativeAssetIdentifiers` inputs are rebuilt on every call, so they are\n * compared by value instead.\n *\n * @param a - Previous parameters.\n * @param b - Next parameters.\n * @returns True if the parameters are identical.\n */\nfunction isTransactionPayParamsIdentical(\n a: FormatStateForTransactionPayParams,\n b: FormatStateForTransactionPayParams,\n): boolean {\n return (\n a.assetsBalance === b.assetsBalance &&\n a.assetsInfo === b.assetsInfo &&\n a.assetsPrice === b.assetsPrice &&\n a.selectedCurrency === b.selectedCurrency &&\n a.networkConfigurationsByChainId === b.networkConfigurationsByChainId &&\n isEqual(a.accounts, b.accounts) &&\n isEqual(a.nativeAssetIdentifiers, b.nativeAssetIdentifiers)\n );\n}\n\nfunction getAmountFromBalance(balance: AssetBalance): string {\n return typeof balance === 'object' && balance !== null && 'amount' in balance\n ? String((balance as { amount: string }).amount)\n : '0';\n}\n\nlet lastCall: {\n params: FormatStateForTransactionPayParams;\n result: TransactionPayLegacyFormat;\n} | null = null;\n\n/**\n * Converts AssetsController state into the legacy format consumed by\n * transaction-pay-controller (TokenBalancesController, AccountTrackerController,\n * TokensController, TokenRatesController, CurrencyRateController shapes).\n *\n * The last result is memoized on input identity: this function is invoked (via\n * `AssetsController:getStateForTransactionPay`) on every\n * `TransactionController:stateChange`, but its inputs only change when the\n * assets pipeline updates. Recomputing runs keccak256 (`toChecksumAddress`)\n * per asset per call, which dominates CPU profiles during transaction\n * approval.\n *\n * @param params - Conversion parameters.\n * @returns Legacy-compatible state for transaction-pay-controller.\n */\nexport function formatStateForTransactionPay(\n params: FormatStateForTransactionPayParams,\n): TransactionPayLegacyFormat {\n if (lastCall && isTransactionPayParamsIdentical(lastCall.params, params)) {\n return lastCall.result;\n }\n\n const result = computeStateForTransactionPay(params);\n lastCall = { params, result: Object.freeze(result) };\n return result;\n}\n\n/**\n * Clears the {@link formatStateForTransactionPay} memoize cache. Exported for tests.\n */\nexport function clearFormatStateForTransactionPayCacheForTesting(): void {\n lastCall = null;\n}\n\n/**\n * Performs the actual state conversion for\n * {@link formatStateForTransactionPay}.\n *\n * @param params - Conversion parameters.\n * @returns Legacy-compatible state for transaction-pay-controller.\n */\nfunction computeStateForTransactionPay(\n params: FormatStateForTransactionPayParams,\n): TransactionPayLegacyFormat {\n const {\n assetsBalance,\n assetsInfo,\n assetsPrice,\n selectedCurrency,\n accounts,\n nativeAssetIdentifiers,\n networkConfigurationsByChainId = {},\n } = params;\n\n const tokenBalances: TransactionPayLegacyFormat['tokenBalances'] = {};\n const accountsByChainId: TransactionPayLegacyFormat['accountsByChainId'] = {};\n const allTokensByChain: Record<string, LegacyToken[]> = {};\n\n for (const account of accounts) {\n const accountAddressLower = account.address.toLowerCase();\n const accountBalances = assetsBalance[account.id];\n if (!accountBalances) {\n continue;\n }\n\n for (const [assetId, balance] of Object.entries(accountBalances)) {\n try {\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n if (chainIdParsed.namespace !== 'eip155') {\n continue;\n }\n const chainIdHex = numberToHex(parseInt(chainIdParsed.reference, 10));\n const amount = getAmountFromBalance(balance);\n const balanceHex = amountToHex(amount);\n\n if (assetsInfo[assetId]?.type === 'native') {\n const nativeAddress = toChecksumAddress(\n getNativeTokenAddress(chainIdHex),\n );\n const checksumAddress = toChecksumAddress(account.address);\n tokenBalances[accountAddressLower] ??= {};\n tokenBalances[accountAddressLower][chainIdHex] ??= {};\n tokenBalances[accountAddressLower][chainIdHex][nativeAddress] =\n balanceHex;\n accountsByChainId[chainIdHex] ??= {};\n accountsByChainId[chainIdHex][checksumAddress] = {\n balance: balanceHex,\n };\n } else if (parsed.assetNamespace === 'erc20') {\n const tokenAddress = toChecksumAddress(String(parsed.assetReference));\n tokenBalances[accountAddressLower] ??= {};\n tokenBalances[accountAddressLower][chainIdHex] ??= {};\n tokenBalances[accountAddressLower][chainIdHex][tokenAddress] =\n balanceHex;\n }\n } catch {\n // Skip malformed asset IDs\n }\n }\n }\n\n for (const [assetId, metadata] of Object.entries(assetsInfo)) {\n try {\n const parsed = parseCaipAssetType(assetId as Caip19AssetId);\n const chainIdParsed = parseCaipChainId(parsed.chainId);\n if (chainIdParsed.namespace !== 'eip155') {\n continue;\n }\n const chainIdHex = numberToHex(parseInt(chainIdParsed.reference, 10));\n const address =\n metadata.type === 'native'\n ? getNativeTokenAddress(chainIdHex)\n : toChecksumAddress(String(parsed.assetReference));\n const token: LegacyToken = {\n address,\n decimals: metadata.decimals,\n symbol: metadata.symbol,\n name: metadata.name,\n };\n allTokensByChain[chainIdHex] ??= [];\n if (\n !allTokensByChain[chainIdHex].some(\n (existing) =>\n existing.address.toLowerCase() === address.toLowerCase(),\n )\n ) {\n allTokensByChain[chainIdHex].push(token);\n }\n } catch {\n // Skip malformed asset IDs\n }\n }\n\n const allTokens: TransactionPayLegacyFormat['allTokens'] = {};\n for (const [chainId, tokens] of Object.entries(allTokensByChain)) {\n allTokens[chainId] = { '': tokens };\n }\n\n const exchangeRates = formatExchangeRatesForBridge({\n assetsInfo,\n assetsPrice,\n selectedCurrency,\n nativeAssetIdentifiers,\n networkConfigurationsByChainId,\n });\n\n return {\n tokenBalances,\n accountsByChainId,\n allTokens,\n marketData: exchangeRates.marketData,\n currencyRates: exchangeRates.currencyRates,\n currentCurrency: exchangeRates.currentCurrency,\n };\n}\n"]}
|