@metamask/assets-controllers 100.0.2 → 100.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [100.0.3]
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Bump `@metamask/transaction-controller` from `^62.17.1` to `^62.18.0` ([#8005](https://github.com/MetaMask/core/pull/8005))
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Fix token search API parameter to use `first` instead of `limit` for pagination ([#8019](https://github.com/MetaMask/core/pull/8019))
|
|
19
|
+
- Clamp limit to a maximum of 50 results for regular queries
|
|
20
|
+
- Allow up to 500 results for Ondo token queries; limits exceeding 500 are clamped to 50
|
|
21
|
+
|
|
10
22
|
## [100.0.2]
|
|
11
23
|
|
|
12
24
|
### Changed
|
|
@@ -2718,7 +2730,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
2718
2730
|
|
|
2719
2731
|
- Use Ethers for AssetsContractController ([#845](https://github.com/MetaMask/core/pull/845))
|
|
2720
2732
|
|
|
2721
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@100.0.
|
|
2733
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@100.0.3...HEAD
|
|
2734
|
+
[100.0.3]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@100.0.2...@metamask/assets-controllers@100.0.3
|
|
2722
2735
|
[100.0.2]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@100.0.1...@metamask/assets-controllers@100.0.2
|
|
2723
2736
|
[100.0.1]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@100.0.0...@metamask/assets-controllers@100.0.1
|
|
2724
2737
|
[100.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@99.4.0...@metamask/assets-controllers@100.0.0
|
package/dist/token-service.cjs
CHANGED
|
@@ -40,7 +40,7 @@ function getTokenMetadataURL(chainId, tokenAddress) {
|
|
|
40
40
|
* @returns The token search URL.
|
|
41
41
|
*/
|
|
42
42
|
function getTokenSearchURL(options) {
|
|
43
|
-
const { chainIds, query, ...optionalParams } = options;
|
|
43
|
+
const { chainIds, query, limit, ...optionalParams } = options;
|
|
44
44
|
const encodedQuery = encodeURIComponent(query);
|
|
45
45
|
const encodedChainIds = chainIds
|
|
46
46
|
.map((id) => encodeURIComponent(id))
|
|
@@ -51,7 +51,20 @@ function getTokenSearchURL(options) {
|
|
|
51
51
|
queryParams.append(key, String(value));
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
|
-
|
|
54
|
+
let numberOfItems;
|
|
55
|
+
if (limit) {
|
|
56
|
+
if (limit <= 50) {
|
|
57
|
+
numberOfItems = limit;
|
|
58
|
+
}
|
|
59
|
+
else if (query.includes('Ondo') && limit <= 500) {
|
|
60
|
+
// There is an exception on the API side https://github.com/consensys-vertical-apps/va-mmcx-token-api/pull/287
|
|
61
|
+
numberOfItems = limit;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
numberOfItems = 50;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return `${exports.TOKEN_END_POINT_API}/tokens/search?networks=${encodedChainIds}&query=${encodedQuery}${numberOfItems ? `&first=${numberOfItems}` : ''}&${queryParams.toString()}`;
|
|
55
68
|
}
|
|
56
69
|
/**
|
|
57
70
|
* Get the trending tokens URL for the given networks and search query.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-service.cjs","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ChainId,\n convertHexToDecimal,\n handleFetch,\n timeoutFetch,\n} from '@metamask/controller-utils';\nimport type { CaipAssetType, CaipChainId, Hex } from '@metamask/utils';\n\nimport { isTokenListSupportedForNetwork } from './assetsUtil';\n\nexport const TOKEN_END_POINT_API = 'https://token.api.cx.metamask.io';\nexport const TOKEN_METADATA_NO_SUPPORT_ERROR =\n 'TokenService Error: Network does not support fetchTokenMetadata';\n\n/**\n * Get the tokens URL for a specific network.\n *\n * @param chainId - The chain ID of the network the tokens requested are on.\n * @returns The tokens URL.\n */\nfunction getTokensURL(chainId: Hex): string {\n const occurrenceFloor =\n chainId === ChainId['linea-mainnet'] ||\n chainId === ChainId['megaeth-mainnet']\n ? 1\n : 3;\n\n return `${TOKEN_END_POINT_API}/tokens/${convertHexToDecimal(\n chainId,\n )}?occurrenceFloor=${occurrenceFloor}&includeNativeAssets=false&includeTokenFees=false&includeAssetType=false&includeERC20Permit=false&includeStorage=false&includeRwaData=true`;\n}\n\n/**\n * Get the token metadata URL for the given network and token.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The token address.\n * @returns The token metadata URL.\n */\nfunction getTokenMetadataURL(chainId: Hex, tokenAddress: string): string {\n return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(\n chainId,\n )}?address=${tokenAddress}&includeRwaData=true`;\n}\n\n/**\n * The sort by field for trending tokens.\n */\nexport type SortTrendingBy =\n | 'm5_trending'\n | 'h1_trending'\n | 'h6_trending'\n | 'h24_trending';\n\n/**\n * Get the token search URL for the given networks and search query.\n *\n * @param options - Options for getting token search URL.\n * @param options.chainIds - Array of CAIP format chain IDs (e.g., 'eip155:1', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp').\n * @param options.query - The search query (token name, symbol, or address).\n * @param options.limit - Optional limit for the number of results (defaults to 10).\n * @param options.includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @returns The token search URL.\n */\nfunction getTokenSearchURL(options: {\n chainIds: CaipChainId[];\n query: string;\n limit?: number;\n includeMarketData?: boolean;\n includeRwaData?: boolean;\n}): string {\n const { chainIds, query, ...optionalParams } = options;\n const encodedQuery = encodeURIComponent(query);\n const encodedChainIds = chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n const queryParams = new URLSearchParams();\n Object.entries(optionalParams).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, String(value));\n }\n });\n return `${TOKEN_END_POINT_API}/tokens/search?networks=${encodedChainIds}&query=${encodedQuery}&${queryParams.toString()}`;\n}\n\n/**\n * Get the trending tokens URL for the given networks and search query.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param options.sort - The sort field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @param options.usePriceApiData - Optional flag to use price API data in the results (defaults to false).\n * @returns The trending tokens URL.\n */\nfunction getTrendingTokensURL(options: {\n chainIds: CaipChainId[];\n sort?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n excludeLabels?: string[];\n includeRwaData?: boolean;\n usePriceApiData?: boolean;\n}): string {\n const encodedChainIds = options.chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n // Add the rest of query params if they are defined\n const queryParams = new URLSearchParams();\n const { chainIds, excludeLabels, ...rest } = options;\n Object.entries(rest).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, String(value));\n }\n });\n\n // Handle excludeLabels separately to avoid encoding the commas\n // The API expects: excludeLabels=stable_coin,blue_chip (not %2C)\n const excludeLabelsParam =\n excludeLabels !== undefined && excludeLabels.length > 0\n ? `&excludeLabels=${excludeLabels.join(',')}`\n : '';\n\n return `${TOKEN_END_POINT_API}/v3/tokens/trending?chainIds=${encodedChainIds}${queryParams.toString() ? `&${queryParams.toString()}` : ''}${excludeLabelsParam}`;\n}\n\nconst tenSecondsInMilliseconds = 10_000;\n\n// Token list averages 1.6 MB in size\n// timeoutFetch by default has a 500ms timeout, which will almost always timeout given the response size.\nconst defaultTimeout = tenSecondsInMilliseconds;\n\n/**\n * Fetch the list of token metadata for a given network. This request is cancellable using the\n * abort signal passed in.\n *\n * @param chainId - The chain ID of the network the requested tokens are on.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token list, or `undefined` if the request was cancelled.\n */\nexport async function fetchTokenListByChainId(\n chainId: Hex,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<unknown> {\n const tokenURL = getTokensURL(chainId);\n const response = await queryApi(tokenURL, abortSignal, timeout);\n if (response) {\n const result = await parseJsonResponse(response);\n if (Array.isArray(result) && chainId === ChainId['linea-mainnet']) {\n return result.filter(\n (elm) =>\n Boolean(elm.aggregators.includes('lineaTeam')) ||\n elm.aggregators.length >= 3,\n );\n }\n return result;\n }\n return undefined;\n}\n\nexport type TokenRwaData = {\n market?: {\n nextOpen?: string;\n nextClose?: string;\n };\n nextPause?: {\n start?: string;\n end?: string;\n };\n ticker?: string;\n instrumentType?: string;\n};\n\nexport type TokenSearchItem = {\n assetId: CaipAssetType;\n name: string;\n symbol: string;\n decimals: number;\n /** Optional RWA data for tokens when includeRwaData is true */\n rwaData?: TokenRwaData;\n};\n\ntype SearchTokenOptions = {\n limit?: number;\n includeMarketData?: boolean;\n includeRwaData?: boolean;\n};\n\n/**\n * Search for tokens across one or more networks by query string using CAIP format chain IDs.\n *\n * @param chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param query - The search query (token name, symbol, or address).\n * @param options - Additional fetch options.\n * @param options.limit - The maximum number of results to return.\n * @param options.includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @returns Object containing count, data array, and an optional error message if the request failed.\n */\nexport async function searchTokens(\n chainIds: CaipChainId[],\n query: string,\n {\n limit = 10,\n includeMarketData = false,\n includeRwaData = true,\n }: SearchTokenOptions = {},\n): Promise<{ count: number; data: TokenSearchItem[]; error?: string }> {\n const tokenSearchURL = getTokenSearchURL({\n chainIds,\n query,\n limit,\n includeMarketData,\n includeRwaData,\n });\n\n try {\n const result: { count: number; data: TokenSearchItem[] } =\n await handleFetch(tokenSearchURL);\n\n // The API returns an object with structure: { count: number, data: array, pageInfo: object }\n if (result && typeof result === 'object' && Array.isArray(result.data)) {\n return {\n count: result.count ?? result.data.length,\n data: result.data,\n };\n }\n\n // Handle non-expected responses\n return { count: 0, data: [], error: 'Unexpected API response format' };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { count: 0, data: [], error: errorMessage };\n }\n}\n\n/**\n * The trending asset type.\n */\nexport type TrendingAsset = {\n assetId: string;\n name: string;\n symbol: string;\n decimals: number;\n price: string;\n aggregatedUsdVolume: number;\n marketCap: number;\n priceChangePct?: {\n m5?: string;\n m15?: string;\n m30?: string;\n h1?: string;\n h6?: string;\n h24?: string;\n };\n labels?: string[];\n /** Optional RWA data for tokens when includeRwaData is true */\n rwaData?: TokenRwaData;\n};\n\n/**\n * Get the trending tokens for the given chains.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - The chains to get the trending tokens for.\n * @param options.sortBy - The sort by field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to true).\n * @param options.usePriceApiData - Optional flag to use price API data in the results (defaults to true).\n * @returns The trending tokens.\n * @throws Will throw if the request fails.\n */\nexport async function getTrendingTokens({\n chainIds,\n sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n excludeLabels,\n includeRwaData = true,\n usePriceApiData = true,\n}: {\n chainIds: CaipChainId[];\n sortBy?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n excludeLabels?: string[];\n includeRwaData?: boolean;\n usePriceApiData?: boolean;\n}): Promise<TrendingAsset[]> {\n if (chainIds.length === 0) {\n console.error('No chains provided');\n return [];\n }\n\n const trendingTokensURL = getTrendingTokensURL({\n chainIds,\n sort: sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n excludeLabels,\n includeRwaData,\n usePriceApiData,\n });\n\n try {\n const result = await handleFetch(trendingTokensURL);\n\n // Validate that the API returned an array\n if (Array.isArray(result)) {\n return result;\n }\n\n // Handle non-expected responses\n console.error('Trending tokens API returned non-array response:', result);\n return [];\n } catch (error) {\n console.error('Trending tokens request failed:', error);\n return [];\n }\n}\n\n/**\n * Fetch metadata for the token address provided for a given network. This request is cancellable\n * using the abort signal passed in.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The address of the token to fetch metadata for.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token metadata, or `undefined` if the request was either aborted or failed.\n */\nexport async function fetchTokenMetadata<TReturn>(\n chainId: Hex,\n tokenAddress: string,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<TReturn | undefined> {\n if (!isTokenListSupportedForNetwork(chainId)) {\n throw new Error(TOKEN_METADATA_NO_SUPPORT_ERROR);\n }\n const tokenMetadataURL = getTokenMetadataURL(chainId, tokenAddress);\n const response = await queryApi(tokenMetadataURL, abortSignal, timeout);\n if (response) {\n return parseJsonResponse(response) as Promise<TReturn>;\n }\n return undefined;\n}\n\n/**\n * Perform fetch request against the api.\n *\n * @param apiURL - The URL of the API to fetch.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param timeout - The fetch timeout.\n * @returns Promise resolving request response.\n */\nasync function queryApi(\n apiURL: string,\n abortSignal: AbortSignal,\n timeout: number,\n): Promise<Response | undefined> {\n const fetchOptions: RequestInit = {\n referrer: apiURL,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n signal: abortSignal,\n cache: 'default',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n try {\n return await timeoutFetch(apiURL, fetchOptions, timeout);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n console.log('Request is aborted');\n }\n }\n return undefined;\n}\n\n/**\n * Parse an API response and return the response JSON data.\n *\n * @param apiResponse - The API response to parse.\n * @returns The response JSON data.\n * @throws Will throw if the response includes an error.\n */\nasync function parseJsonResponse(apiResponse: Response): Promise<unknown> {\n const responseObj = await apiResponse.json();\n // api may return errors as json without setting an error http status code\n if (responseObj?.error) {\n throw new Error(`TokenService Error: ${responseObj.error}`);\n }\n return responseObj;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"token-service.cjs","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ChainId,\n convertHexToDecimal,\n handleFetch,\n timeoutFetch,\n} from '@metamask/controller-utils';\nimport type { CaipAssetType, CaipChainId, Hex } from '@metamask/utils';\n\nimport { isTokenListSupportedForNetwork } from './assetsUtil';\n\nexport const TOKEN_END_POINT_API = 'https://token.api.cx.metamask.io';\nexport const TOKEN_METADATA_NO_SUPPORT_ERROR =\n 'TokenService Error: Network does not support fetchTokenMetadata';\n\n/**\n * Get the tokens URL for a specific network.\n *\n * @param chainId - The chain ID of the network the tokens requested are on.\n * @returns The tokens URL.\n */\nfunction getTokensURL(chainId: Hex): string {\n const occurrenceFloor =\n chainId === ChainId['linea-mainnet'] ||\n chainId === ChainId['megaeth-mainnet']\n ? 1\n : 3;\n\n return `${TOKEN_END_POINT_API}/tokens/${convertHexToDecimal(\n chainId,\n )}?occurrenceFloor=${occurrenceFloor}&includeNativeAssets=false&includeTokenFees=false&includeAssetType=false&includeERC20Permit=false&includeStorage=false&includeRwaData=true`;\n}\n\n/**\n * Get the token metadata URL for the given network and token.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The token address.\n * @returns The token metadata URL.\n */\nfunction getTokenMetadataURL(chainId: Hex, tokenAddress: string): string {\n return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(\n chainId,\n )}?address=${tokenAddress}&includeRwaData=true`;\n}\n\n/**\n * The sort by field for trending tokens.\n */\nexport type SortTrendingBy =\n | 'm5_trending'\n | 'h1_trending'\n | 'h6_trending'\n | 'h24_trending';\n\n/**\n * Get the token search URL for the given networks and search query.\n *\n * @param options - Options for getting token search URL.\n * @param options.chainIds - Array of CAIP format chain IDs (e.g., 'eip155:1', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp').\n * @param options.query - The search query (token name, symbol, or address).\n * @param options.limit - Optional limit for the number of results (defaults to 10).\n * @param options.includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @returns The token search URL.\n */\nfunction getTokenSearchURL(options: {\n chainIds: CaipChainId[];\n query: string;\n limit?: number;\n includeMarketData?: boolean;\n includeRwaData?: boolean;\n}): string {\n const { chainIds, query, limit, ...optionalParams } = options;\n const encodedQuery = encodeURIComponent(query);\n const encodedChainIds = chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n const queryParams = new URLSearchParams();\n Object.entries(optionalParams).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, String(value));\n }\n });\n\n let numberOfItems;\n if (limit) {\n if (limit <= 50) {\n numberOfItems = limit;\n } else if (query.includes('Ondo') && limit <= 500) {\n // There is an exception on the API side https://github.com/consensys-vertical-apps/va-mmcx-token-api/pull/287\n numberOfItems = limit;\n } else {\n numberOfItems = 50;\n }\n }\n\n return `${TOKEN_END_POINT_API}/tokens/search?networks=${encodedChainIds}&query=${encodedQuery}${numberOfItems ? `&first=${numberOfItems}` : ''}&${queryParams.toString()}`;\n}\n\n/**\n * Get the trending tokens URL for the given networks and search query.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param options.sort - The sort field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @param options.usePriceApiData - Optional flag to use price API data in the results (defaults to false).\n * @returns The trending tokens URL.\n */\nfunction getTrendingTokensURL(options: {\n chainIds: CaipChainId[];\n sort?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n excludeLabels?: string[];\n includeRwaData?: boolean;\n usePriceApiData?: boolean;\n}): string {\n const encodedChainIds = options.chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n // Add the rest of query params if they are defined\n const queryParams = new URLSearchParams();\n const { chainIds, excludeLabels, ...rest } = options;\n Object.entries(rest).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, String(value));\n }\n });\n\n // Handle excludeLabels separately to avoid encoding the commas\n // The API expects: excludeLabels=stable_coin,blue_chip (not %2C)\n const excludeLabelsParam =\n excludeLabels !== undefined && excludeLabels.length > 0\n ? `&excludeLabels=${excludeLabels.join(',')}`\n : '';\n\n return `${TOKEN_END_POINT_API}/v3/tokens/trending?chainIds=${encodedChainIds}${queryParams.toString() ? `&${queryParams.toString()}` : ''}${excludeLabelsParam}`;\n}\n\nconst tenSecondsInMilliseconds = 10_000;\n\n// Token list averages 1.6 MB in size\n// timeoutFetch by default has a 500ms timeout, which will almost always timeout given the response size.\nconst defaultTimeout = tenSecondsInMilliseconds;\n\n/**\n * Fetch the list of token metadata for a given network. This request is cancellable using the\n * abort signal passed in.\n *\n * @param chainId - The chain ID of the network the requested tokens are on.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token list, or `undefined` if the request was cancelled.\n */\nexport async function fetchTokenListByChainId(\n chainId: Hex,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<unknown> {\n const tokenURL = getTokensURL(chainId);\n const response = await queryApi(tokenURL, abortSignal, timeout);\n if (response) {\n const result = await parseJsonResponse(response);\n if (Array.isArray(result) && chainId === ChainId['linea-mainnet']) {\n return result.filter(\n (elm) =>\n Boolean(elm.aggregators.includes('lineaTeam')) ||\n elm.aggregators.length >= 3,\n );\n }\n return result;\n }\n return undefined;\n}\n\nexport type TokenRwaData = {\n market?: {\n nextOpen?: string;\n nextClose?: string;\n };\n nextPause?: {\n start?: string;\n end?: string;\n };\n ticker?: string;\n instrumentType?: string;\n};\n\nexport type TokenSearchItem = {\n assetId: CaipAssetType;\n name: string;\n symbol: string;\n decimals: number;\n /** Optional RWA data for tokens when includeRwaData is true */\n rwaData?: TokenRwaData;\n};\n\ntype SearchTokenOptions = {\n limit?: number;\n includeMarketData?: boolean;\n includeRwaData?: boolean;\n};\n\n/**\n * Search for tokens across one or more networks by query string using CAIP format chain IDs.\n *\n * @param chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param query - The search query (token name, symbol, or address).\n * @param options - Additional fetch options.\n * @param options.limit - The maximum number of results to return.\n * @param options.includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @returns Object containing count, data array, and an optional error message if the request failed.\n */\nexport async function searchTokens(\n chainIds: CaipChainId[],\n query: string,\n {\n limit = 10,\n includeMarketData = false,\n includeRwaData = true,\n }: SearchTokenOptions = {},\n): Promise<{ count: number; data: TokenSearchItem[]; error?: string }> {\n const tokenSearchURL = getTokenSearchURL({\n chainIds,\n query,\n limit,\n includeMarketData,\n includeRwaData,\n });\n\n try {\n const result: { count: number; data: TokenSearchItem[] } =\n await handleFetch(tokenSearchURL);\n\n // The API returns an object with structure: { count: number, data: array, pageInfo: object }\n if (result && typeof result === 'object' && Array.isArray(result.data)) {\n return {\n count: result.count ?? result.data.length,\n data: result.data,\n };\n }\n\n // Handle non-expected responses\n return { count: 0, data: [], error: 'Unexpected API response format' };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { count: 0, data: [], error: errorMessage };\n }\n}\n\n/**\n * The trending asset type.\n */\nexport type TrendingAsset = {\n assetId: string;\n name: string;\n symbol: string;\n decimals: number;\n price: string;\n aggregatedUsdVolume: number;\n marketCap: number;\n priceChangePct?: {\n m5?: string;\n m15?: string;\n m30?: string;\n h1?: string;\n h6?: string;\n h24?: string;\n };\n labels?: string[];\n /** Optional RWA data for tokens when includeRwaData is true */\n rwaData?: TokenRwaData;\n};\n\n/**\n * Get the trending tokens for the given chains.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - The chains to get the trending tokens for.\n * @param options.sortBy - The sort by field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to true).\n * @param options.usePriceApiData - Optional flag to use price API data in the results (defaults to true).\n * @returns The trending tokens.\n * @throws Will throw if the request fails.\n */\nexport async function getTrendingTokens({\n chainIds,\n sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n excludeLabels,\n includeRwaData = true,\n usePriceApiData = true,\n}: {\n chainIds: CaipChainId[];\n sortBy?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n excludeLabels?: string[];\n includeRwaData?: boolean;\n usePriceApiData?: boolean;\n}): Promise<TrendingAsset[]> {\n if (chainIds.length === 0) {\n console.error('No chains provided');\n return [];\n }\n\n const trendingTokensURL = getTrendingTokensURL({\n chainIds,\n sort: sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n excludeLabels,\n includeRwaData,\n usePriceApiData,\n });\n\n try {\n const result = await handleFetch(trendingTokensURL);\n\n // Validate that the API returned an array\n if (Array.isArray(result)) {\n return result;\n }\n\n // Handle non-expected responses\n console.error('Trending tokens API returned non-array response:', result);\n return [];\n } catch (error) {\n console.error('Trending tokens request failed:', error);\n return [];\n }\n}\n\n/**\n * Fetch metadata for the token address provided for a given network. This request is cancellable\n * using the abort signal passed in.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The address of the token to fetch metadata for.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token metadata, or `undefined` if the request was either aborted or failed.\n */\nexport async function fetchTokenMetadata<TReturn>(\n chainId: Hex,\n tokenAddress: string,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<TReturn | undefined> {\n if (!isTokenListSupportedForNetwork(chainId)) {\n throw new Error(TOKEN_METADATA_NO_SUPPORT_ERROR);\n }\n const tokenMetadataURL = getTokenMetadataURL(chainId, tokenAddress);\n const response = await queryApi(tokenMetadataURL, abortSignal, timeout);\n if (response) {\n return parseJsonResponse(response) as Promise<TReturn>;\n }\n return undefined;\n}\n\n/**\n * Perform fetch request against the api.\n *\n * @param apiURL - The URL of the API to fetch.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param timeout - The fetch timeout.\n * @returns Promise resolving request response.\n */\nasync function queryApi(\n apiURL: string,\n abortSignal: AbortSignal,\n timeout: number,\n): Promise<Response | undefined> {\n const fetchOptions: RequestInit = {\n referrer: apiURL,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n signal: abortSignal,\n cache: 'default',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n try {\n return await timeoutFetch(apiURL, fetchOptions, timeout);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n console.log('Request is aborted');\n }\n }\n return undefined;\n}\n\n/**\n * Parse an API response and return the response JSON data.\n *\n * @param apiResponse - The API response to parse.\n * @returns The response JSON data.\n * @throws Will throw if the response includes an error.\n */\nasync function parseJsonResponse(apiResponse: Response): Promise<unknown> {\n const responseObj = await apiResponse.json();\n // api may return errors as json without setting an error http status code\n if (responseObj?.error) {\n throw new Error(`TokenService Error: ${responseObj.error}`);\n }\n return responseObj;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-service.d.cts","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,EAAE,wBAAwB;AAIvE,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AACtE,eAAO,MAAM,+BAA+B,oEACuB,CAAC;AAiCpE;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,aAAa,GACb,aAAa,GACb,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"token-service.d.cts","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-service.d.mts","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,EAAE,wBAAwB;AAIvE,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AACtE,eAAO,MAAM,+BAA+B,oEACuB,CAAC;AAiCpE;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,aAAa,GACb,aAAa,GACb,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"token-service.d.mts","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"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"}
|
package/dist/token-service.mjs
CHANGED
|
@@ -37,7 +37,7 @@ function getTokenMetadataURL(chainId, tokenAddress) {
|
|
|
37
37
|
* @returns The token search URL.
|
|
38
38
|
*/
|
|
39
39
|
function getTokenSearchURL(options) {
|
|
40
|
-
const { chainIds, query, ...optionalParams } = options;
|
|
40
|
+
const { chainIds, query, limit, ...optionalParams } = options;
|
|
41
41
|
const encodedQuery = encodeURIComponent(query);
|
|
42
42
|
const encodedChainIds = chainIds
|
|
43
43
|
.map((id) => encodeURIComponent(id))
|
|
@@ -48,7 +48,20 @@ function getTokenSearchURL(options) {
|
|
|
48
48
|
queryParams.append(key, String(value));
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
|
-
|
|
51
|
+
let numberOfItems;
|
|
52
|
+
if (limit) {
|
|
53
|
+
if (limit <= 50) {
|
|
54
|
+
numberOfItems = limit;
|
|
55
|
+
}
|
|
56
|
+
else if (query.includes('Ondo') && limit <= 500) {
|
|
57
|
+
// There is an exception on the API side https://github.com/consensys-vertical-apps/va-mmcx-token-api/pull/287
|
|
58
|
+
numberOfItems = limit;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
numberOfItems = 50;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return `${TOKEN_END_POINT_API}/tokens/search?networks=${encodedChainIds}&query=${encodedQuery}${numberOfItems ? `&first=${numberOfItems}` : ''}&${queryParams.toString()}`;
|
|
52
65
|
}
|
|
53
66
|
/**
|
|
54
67
|
* Get the trending tokens URL for the given networks and search query.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-service.mjs","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ChainId,\n convertHexToDecimal,\n handleFetch,\n timeoutFetch,\n} from '@metamask/controller-utils';\nimport type { CaipAssetType, CaipChainId, Hex } from '@metamask/utils';\n\nimport { isTokenListSupportedForNetwork } from './assetsUtil';\n\nexport const TOKEN_END_POINT_API = 'https://token.api.cx.metamask.io';\nexport const TOKEN_METADATA_NO_SUPPORT_ERROR =\n 'TokenService Error: Network does not support fetchTokenMetadata';\n\n/**\n * Get the tokens URL for a specific network.\n *\n * @param chainId - The chain ID of the network the tokens requested are on.\n * @returns The tokens URL.\n */\nfunction getTokensURL(chainId: Hex): string {\n const occurrenceFloor =\n chainId === ChainId['linea-mainnet'] ||\n chainId === ChainId['megaeth-mainnet']\n ? 1\n : 3;\n\n return `${TOKEN_END_POINT_API}/tokens/${convertHexToDecimal(\n chainId,\n )}?occurrenceFloor=${occurrenceFloor}&includeNativeAssets=false&includeTokenFees=false&includeAssetType=false&includeERC20Permit=false&includeStorage=false&includeRwaData=true`;\n}\n\n/**\n * Get the token metadata URL for the given network and token.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The token address.\n * @returns The token metadata URL.\n */\nfunction getTokenMetadataURL(chainId: Hex, tokenAddress: string): string {\n return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(\n chainId,\n )}?address=${tokenAddress}&includeRwaData=true`;\n}\n\n/**\n * The sort by field for trending tokens.\n */\nexport type SortTrendingBy =\n | 'm5_trending'\n | 'h1_trending'\n | 'h6_trending'\n | 'h24_trending';\n\n/**\n * Get the token search URL for the given networks and search query.\n *\n * @param options - Options for getting token search URL.\n * @param options.chainIds - Array of CAIP format chain IDs (e.g., 'eip155:1', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp').\n * @param options.query - The search query (token name, symbol, or address).\n * @param options.limit - Optional limit for the number of results (defaults to 10).\n * @param options.includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @returns The token search URL.\n */\nfunction getTokenSearchURL(options: {\n chainIds: CaipChainId[];\n query: string;\n limit?: number;\n includeMarketData?: boolean;\n includeRwaData?: boolean;\n}): string {\n const { chainIds, query, ...optionalParams } = options;\n const encodedQuery = encodeURIComponent(query);\n const encodedChainIds = chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n const queryParams = new URLSearchParams();\n Object.entries(optionalParams).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, String(value));\n }\n });\n return `${TOKEN_END_POINT_API}/tokens/search?networks=${encodedChainIds}&query=${encodedQuery}&${queryParams.toString()}`;\n}\n\n/**\n * Get the trending tokens URL for the given networks and search query.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param options.sort - The sort field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @param options.usePriceApiData - Optional flag to use price API data in the results (defaults to false).\n * @returns The trending tokens URL.\n */\nfunction getTrendingTokensURL(options: {\n chainIds: CaipChainId[];\n sort?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n excludeLabels?: string[];\n includeRwaData?: boolean;\n usePriceApiData?: boolean;\n}): string {\n const encodedChainIds = options.chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n // Add the rest of query params if they are defined\n const queryParams = new URLSearchParams();\n const { chainIds, excludeLabels, ...rest } = options;\n Object.entries(rest).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, String(value));\n }\n });\n\n // Handle excludeLabels separately to avoid encoding the commas\n // The API expects: excludeLabels=stable_coin,blue_chip (not %2C)\n const excludeLabelsParam =\n excludeLabels !== undefined && excludeLabels.length > 0\n ? `&excludeLabels=${excludeLabels.join(',')}`\n : '';\n\n return `${TOKEN_END_POINT_API}/v3/tokens/trending?chainIds=${encodedChainIds}${queryParams.toString() ? `&${queryParams.toString()}` : ''}${excludeLabelsParam}`;\n}\n\nconst tenSecondsInMilliseconds = 10_000;\n\n// Token list averages 1.6 MB in size\n// timeoutFetch by default has a 500ms timeout, which will almost always timeout given the response size.\nconst defaultTimeout = tenSecondsInMilliseconds;\n\n/**\n * Fetch the list of token metadata for a given network. This request is cancellable using the\n * abort signal passed in.\n *\n * @param chainId - The chain ID of the network the requested tokens are on.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token list, or `undefined` if the request was cancelled.\n */\nexport async function fetchTokenListByChainId(\n chainId: Hex,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<unknown> {\n const tokenURL = getTokensURL(chainId);\n const response = await queryApi(tokenURL, abortSignal, timeout);\n if (response) {\n const result = await parseJsonResponse(response);\n if (Array.isArray(result) && chainId === ChainId['linea-mainnet']) {\n return result.filter(\n (elm) =>\n Boolean(elm.aggregators.includes('lineaTeam')) ||\n elm.aggregators.length >= 3,\n );\n }\n return result;\n }\n return undefined;\n}\n\nexport type TokenRwaData = {\n market?: {\n nextOpen?: string;\n nextClose?: string;\n };\n nextPause?: {\n start?: string;\n end?: string;\n };\n ticker?: string;\n instrumentType?: string;\n};\n\nexport type TokenSearchItem = {\n assetId: CaipAssetType;\n name: string;\n symbol: string;\n decimals: number;\n /** Optional RWA data for tokens when includeRwaData is true */\n rwaData?: TokenRwaData;\n};\n\ntype SearchTokenOptions = {\n limit?: number;\n includeMarketData?: boolean;\n includeRwaData?: boolean;\n};\n\n/**\n * Search for tokens across one or more networks by query string using CAIP format chain IDs.\n *\n * @param chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param query - The search query (token name, symbol, or address).\n * @param options - Additional fetch options.\n * @param options.limit - The maximum number of results to return.\n * @param options.includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @returns Object containing count, data array, and an optional error message if the request failed.\n */\nexport async function searchTokens(\n chainIds: CaipChainId[],\n query: string,\n {\n limit = 10,\n includeMarketData = false,\n includeRwaData = true,\n }: SearchTokenOptions = {},\n): Promise<{ count: number; data: TokenSearchItem[]; error?: string }> {\n const tokenSearchURL = getTokenSearchURL({\n chainIds,\n query,\n limit,\n includeMarketData,\n includeRwaData,\n });\n\n try {\n const result: { count: number; data: TokenSearchItem[] } =\n await handleFetch(tokenSearchURL);\n\n // The API returns an object with structure: { count: number, data: array, pageInfo: object }\n if (result && typeof result === 'object' && Array.isArray(result.data)) {\n return {\n count: result.count ?? result.data.length,\n data: result.data,\n };\n }\n\n // Handle non-expected responses\n return { count: 0, data: [], error: 'Unexpected API response format' };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { count: 0, data: [], error: errorMessage };\n }\n}\n\n/**\n * The trending asset type.\n */\nexport type TrendingAsset = {\n assetId: string;\n name: string;\n symbol: string;\n decimals: number;\n price: string;\n aggregatedUsdVolume: number;\n marketCap: number;\n priceChangePct?: {\n m5?: string;\n m15?: string;\n m30?: string;\n h1?: string;\n h6?: string;\n h24?: string;\n };\n labels?: string[];\n /** Optional RWA data for tokens when includeRwaData is true */\n rwaData?: TokenRwaData;\n};\n\n/**\n * Get the trending tokens for the given chains.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - The chains to get the trending tokens for.\n * @param options.sortBy - The sort by field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to true).\n * @param options.usePriceApiData - Optional flag to use price API data in the results (defaults to true).\n * @returns The trending tokens.\n * @throws Will throw if the request fails.\n */\nexport async function getTrendingTokens({\n chainIds,\n sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n excludeLabels,\n includeRwaData = true,\n usePriceApiData = true,\n}: {\n chainIds: CaipChainId[];\n sortBy?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n excludeLabels?: string[];\n includeRwaData?: boolean;\n usePriceApiData?: boolean;\n}): Promise<TrendingAsset[]> {\n if (chainIds.length === 0) {\n console.error('No chains provided');\n return [];\n }\n\n const trendingTokensURL = getTrendingTokensURL({\n chainIds,\n sort: sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n excludeLabels,\n includeRwaData,\n usePriceApiData,\n });\n\n try {\n const result = await handleFetch(trendingTokensURL);\n\n // Validate that the API returned an array\n if (Array.isArray(result)) {\n return result;\n }\n\n // Handle non-expected responses\n console.error('Trending tokens API returned non-array response:', result);\n return [];\n } catch (error) {\n console.error('Trending tokens request failed:', error);\n return [];\n }\n}\n\n/**\n * Fetch metadata for the token address provided for a given network. This request is cancellable\n * using the abort signal passed in.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The address of the token to fetch metadata for.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token metadata, or `undefined` if the request was either aborted or failed.\n */\nexport async function fetchTokenMetadata<TReturn>(\n chainId: Hex,\n tokenAddress: string,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<TReturn | undefined> {\n if (!isTokenListSupportedForNetwork(chainId)) {\n throw new Error(TOKEN_METADATA_NO_SUPPORT_ERROR);\n }\n const tokenMetadataURL = getTokenMetadataURL(chainId, tokenAddress);\n const response = await queryApi(tokenMetadataURL, abortSignal, timeout);\n if (response) {\n return parseJsonResponse(response) as Promise<TReturn>;\n }\n return undefined;\n}\n\n/**\n * Perform fetch request against the api.\n *\n * @param apiURL - The URL of the API to fetch.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param timeout - The fetch timeout.\n * @returns Promise resolving request response.\n */\nasync function queryApi(\n apiURL: string,\n abortSignal: AbortSignal,\n timeout: number,\n): Promise<Response | undefined> {\n const fetchOptions: RequestInit = {\n referrer: apiURL,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n signal: abortSignal,\n cache: 'default',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n try {\n return await timeoutFetch(apiURL, fetchOptions, timeout);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n console.log('Request is aborted');\n }\n }\n return undefined;\n}\n\n/**\n * Parse an API response and return the response JSON data.\n *\n * @param apiResponse - The API response to parse.\n * @returns The response JSON data.\n * @throws Will throw if the response includes an error.\n */\nasync function parseJsonResponse(apiResponse: Response): Promise<unknown> {\n const responseObj = await apiResponse.json();\n // api may return errors as json without setting an error http status code\n if (responseObj?.error) {\n throw new Error(`TokenService Error: ${responseObj.error}`);\n }\n return responseObj;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"token-service.mjs","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ChainId,\n convertHexToDecimal,\n handleFetch,\n timeoutFetch,\n} from '@metamask/controller-utils';\nimport type { CaipAssetType, CaipChainId, Hex } from '@metamask/utils';\n\nimport { isTokenListSupportedForNetwork } from './assetsUtil';\n\nexport const TOKEN_END_POINT_API = 'https://token.api.cx.metamask.io';\nexport const TOKEN_METADATA_NO_SUPPORT_ERROR =\n 'TokenService Error: Network does not support fetchTokenMetadata';\n\n/**\n * Get the tokens URL for a specific network.\n *\n * @param chainId - The chain ID of the network the tokens requested are on.\n * @returns The tokens URL.\n */\nfunction getTokensURL(chainId: Hex): string {\n const occurrenceFloor =\n chainId === ChainId['linea-mainnet'] ||\n chainId === ChainId['megaeth-mainnet']\n ? 1\n : 3;\n\n return `${TOKEN_END_POINT_API}/tokens/${convertHexToDecimal(\n chainId,\n )}?occurrenceFloor=${occurrenceFloor}&includeNativeAssets=false&includeTokenFees=false&includeAssetType=false&includeERC20Permit=false&includeStorage=false&includeRwaData=true`;\n}\n\n/**\n * Get the token metadata URL for the given network and token.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The token address.\n * @returns The token metadata URL.\n */\nfunction getTokenMetadataURL(chainId: Hex, tokenAddress: string): string {\n return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(\n chainId,\n )}?address=${tokenAddress}&includeRwaData=true`;\n}\n\n/**\n * The sort by field for trending tokens.\n */\nexport type SortTrendingBy =\n | 'm5_trending'\n | 'h1_trending'\n | 'h6_trending'\n | 'h24_trending';\n\n/**\n * Get the token search URL for the given networks and search query.\n *\n * @param options - Options for getting token search URL.\n * @param options.chainIds - Array of CAIP format chain IDs (e.g., 'eip155:1', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp').\n * @param options.query - The search query (token name, symbol, or address).\n * @param options.limit - Optional limit for the number of results (defaults to 10).\n * @param options.includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @returns The token search URL.\n */\nfunction getTokenSearchURL(options: {\n chainIds: CaipChainId[];\n query: string;\n limit?: number;\n includeMarketData?: boolean;\n includeRwaData?: boolean;\n}): string {\n const { chainIds, query, limit, ...optionalParams } = options;\n const encodedQuery = encodeURIComponent(query);\n const encodedChainIds = chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n const queryParams = new URLSearchParams();\n Object.entries(optionalParams).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, String(value));\n }\n });\n\n let numberOfItems;\n if (limit) {\n if (limit <= 50) {\n numberOfItems = limit;\n } else if (query.includes('Ondo') && limit <= 500) {\n // There is an exception on the API side https://github.com/consensys-vertical-apps/va-mmcx-token-api/pull/287\n numberOfItems = limit;\n } else {\n numberOfItems = 50;\n }\n }\n\n return `${TOKEN_END_POINT_API}/tokens/search?networks=${encodedChainIds}&query=${encodedQuery}${numberOfItems ? `&first=${numberOfItems}` : ''}&${queryParams.toString()}`;\n}\n\n/**\n * Get the trending tokens URL for the given networks and search query.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param options.sort - The sort field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @param options.usePriceApiData - Optional flag to use price API data in the results (defaults to false).\n * @returns The trending tokens URL.\n */\nfunction getTrendingTokensURL(options: {\n chainIds: CaipChainId[];\n sort?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n excludeLabels?: string[];\n includeRwaData?: boolean;\n usePriceApiData?: boolean;\n}): string {\n const encodedChainIds = options.chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n // Add the rest of query params if they are defined\n const queryParams = new URLSearchParams();\n const { chainIds, excludeLabels, ...rest } = options;\n Object.entries(rest).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, String(value));\n }\n });\n\n // Handle excludeLabels separately to avoid encoding the commas\n // The API expects: excludeLabels=stable_coin,blue_chip (not %2C)\n const excludeLabelsParam =\n excludeLabels !== undefined && excludeLabels.length > 0\n ? `&excludeLabels=${excludeLabels.join(',')}`\n : '';\n\n return `${TOKEN_END_POINT_API}/v3/tokens/trending?chainIds=${encodedChainIds}${queryParams.toString() ? `&${queryParams.toString()}` : ''}${excludeLabelsParam}`;\n}\n\nconst tenSecondsInMilliseconds = 10_000;\n\n// Token list averages 1.6 MB in size\n// timeoutFetch by default has a 500ms timeout, which will almost always timeout given the response size.\nconst defaultTimeout = tenSecondsInMilliseconds;\n\n/**\n * Fetch the list of token metadata for a given network. This request is cancellable using the\n * abort signal passed in.\n *\n * @param chainId - The chain ID of the network the requested tokens are on.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token list, or `undefined` if the request was cancelled.\n */\nexport async function fetchTokenListByChainId(\n chainId: Hex,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<unknown> {\n const tokenURL = getTokensURL(chainId);\n const response = await queryApi(tokenURL, abortSignal, timeout);\n if (response) {\n const result = await parseJsonResponse(response);\n if (Array.isArray(result) && chainId === ChainId['linea-mainnet']) {\n return result.filter(\n (elm) =>\n Boolean(elm.aggregators.includes('lineaTeam')) ||\n elm.aggregators.length >= 3,\n );\n }\n return result;\n }\n return undefined;\n}\n\nexport type TokenRwaData = {\n market?: {\n nextOpen?: string;\n nextClose?: string;\n };\n nextPause?: {\n start?: string;\n end?: string;\n };\n ticker?: string;\n instrumentType?: string;\n};\n\nexport type TokenSearchItem = {\n assetId: CaipAssetType;\n name: string;\n symbol: string;\n decimals: number;\n /** Optional RWA data for tokens when includeRwaData is true */\n rwaData?: TokenRwaData;\n};\n\ntype SearchTokenOptions = {\n limit?: number;\n includeMarketData?: boolean;\n includeRwaData?: boolean;\n};\n\n/**\n * Search for tokens across one or more networks by query string using CAIP format chain IDs.\n *\n * @param chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param query - The search query (token name, symbol, or address).\n * @param options - Additional fetch options.\n * @param options.limit - The maximum number of results to return.\n * @param options.includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to false).\n * @returns Object containing count, data array, and an optional error message if the request failed.\n */\nexport async function searchTokens(\n chainIds: CaipChainId[],\n query: string,\n {\n limit = 10,\n includeMarketData = false,\n includeRwaData = true,\n }: SearchTokenOptions = {},\n): Promise<{ count: number; data: TokenSearchItem[]; error?: string }> {\n const tokenSearchURL = getTokenSearchURL({\n chainIds,\n query,\n limit,\n includeMarketData,\n includeRwaData,\n });\n\n try {\n const result: { count: number; data: TokenSearchItem[] } =\n await handleFetch(tokenSearchURL);\n\n // The API returns an object with structure: { count: number, data: array, pageInfo: object }\n if (result && typeof result === 'object' && Array.isArray(result.data)) {\n return {\n count: result.count ?? result.data.length,\n data: result.data,\n };\n }\n\n // Handle non-expected responses\n return { count: 0, data: [], error: 'Unexpected API response format' };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { count: 0, data: [], error: errorMessage };\n }\n}\n\n/**\n * The trending asset type.\n */\nexport type TrendingAsset = {\n assetId: string;\n name: string;\n symbol: string;\n decimals: number;\n price: string;\n aggregatedUsdVolume: number;\n marketCap: number;\n priceChangePct?: {\n m5?: string;\n m15?: string;\n m30?: string;\n h1?: string;\n h6?: string;\n h24?: string;\n };\n labels?: string[];\n /** Optional RWA data for tokens when includeRwaData is true */\n rwaData?: TokenRwaData;\n};\n\n/**\n * Get the trending tokens for the given chains.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - The chains to get the trending tokens for.\n * @param options.sortBy - The sort by field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).\n * @param options.includeRwaData - Optional flag to include RWA data in the results (defaults to true).\n * @param options.usePriceApiData - Optional flag to use price API data in the results (defaults to true).\n * @returns The trending tokens.\n * @throws Will throw if the request fails.\n */\nexport async function getTrendingTokens({\n chainIds,\n sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n excludeLabels,\n includeRwaData = true,\n usePriceApiData = true,\n}: {\n chainIds: CaipChainId[];\n sortBy?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n excludeLabels?: string[];\n includeRwaData?: boolean;\n usePriceApiData?: boolean;\n}): Promise<TrendingAsset[]> {\n if (chainIds.length === 0) {\n console.error('No chains provided');\n return [];\n }\n\n const trendingTokensURL = getTrendingTokensURL({\n chainIds,\n sort: sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n excludeLabels,\n includeRwaData,\n usePriceApiData,\n });\n\n try {\n const result = await handleFetch(trendingTokensURL);\n\n // Validate that the API returned an array\n if (Array.isArray(result)) {\n return result;\n }\n\n // Handle non-expected responses\n console.error('Trending tokens API returned non-array response:', result);\n return [];\n } catch (error) {\n console.error('Trending tokens request failed:', error);\n return [];\n }\n}\n\n/**\n * Fetch metadata for the token address provided for a given network. This request is cancellable\n * using the abort signal passed in.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The address of the token to fetch metadata for.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token metadata, or `undefined` if the request was either aborted or failed.\n */\nexport async function fetchTokenMetadata<TReturn>(\n chainId: Hex,\n tokenAddress: string,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<TReturn | undefined> {\n if (!isTokenListSupportedForNetwork(chainId)) {\n throw new Error(TOKEN_METADATA_NO_SUPPORT_ERROR);\n }\n const tokenMetadataURL = getTokenMetadataURL(chainId, tokenAddress);\n const response = await queryApi(tokenMetadataURL, abortSignal, timeout);\n if (response) {\n return parseJsonResponse(response) as Promise<TReturn>;\n }\n return undefined;\n}\n\n/**\n * Perform fetch request against the api.\n *\n * @param apiURL - The URL of the API to fetch.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param timeout - The fetch timeout.\n * @returns Promise resolving request response.\n */\nasync function queryApi(\n apiURL: string,\n abortSignal: AbortSignal,\n timeout: number,\n): Promise<Response | undefined> {\n const fetchOptions: RequestInit = {\n referrer: apiURL,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n signal: abortSignal,\n cache: 'default',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n try {\n return await timeoutFetch(apiURL, fetchOptions, timeout);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n console.log('Request is aborted');\n }\n }\n return undefined;\n}\n\n/**\n * Parse an API response and return the response JSON data.\n *\n * @param apiResponse - The API response to parse.\n * @returns The response JSON data.\n * @throws Will throw if the response includes an error.\n */\nasync function parseJsonResponse(apiResponse: Response): Promise<unknown> {\n const responseObj = await apiResponse.json();\n // api may return errors as json without setting an error http status code\n if (responseObj?.error) {\n throw new Error(`TokenService Error: ${responseObj.error}`);\n }\n return responseObj;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask/assets-controllers",
|
|
3
|
-
"version": "100.0.
|
|
3
|
+
"version": "100.0.3",
|
|
4
4
|
"description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"build:docs": "typedoc",
|
|
41
41
|
"changelog:update": "../../scripts/update-changelog.sh @metamask/assets-controllers",
|
|
42
42
|
"changelog:validate": "../../scripts/validate-changelog.sh @metamask/assets-controllers",
|
|
43
|
-
"publish:preview": "yarn npm publish --tag preview",
|
|
44
43
|
"since-latest-release": "../../scripts/since-latest-release.sh",
|
|
45
44
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter",
|
|
46
45
|
"test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache",
|
|
@@ -80,7 +79,7 @@
|
|
|
80
79
|
"@metamask/snaps-sdk": "^10.3.0",
|
|
81
80
|
"@metamask/snaps-utils": "^11.7.0",
|
|
82
81
|
"@metamask/storage-service": "^1.0.0",
|
|
83
|
-
"@metamask/transaction-controller": "^62.
|
|
82
|
+
"@metamask/transaction-controller": "^62.18.0",
|
|
84
83
|
"@metamask/utils": "^11.9.0",
|
|
85
84
|
"@types/bn.js": "^5.1.5",
|
|
86
85
|
"@types/uuid": "^8.3.0",
|