@metamask/assets-controllers 85.0.0 → 87.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/dist/AccountTrackerController.cjs +43 -13
  3. package/dist/AccountTrackerController.cjs.map +1 -1
  4. package/dist/AccountTrackerController.d.cts +17 -6
  5. package/dist/AccountTrackerController.d.cts.map +1 -1
  6. package/dist/AccountTrackerController.d.mts +17 -6
  7. package/dist/AccountTrackerController.d.mts.map +1 -1
  8. package/dist/AccountTrackerController.mjs +43 -13
  9. package/dist/AccountTrackerController.mjs.map +1 -1
  10. package/dist/DeFiPositionsController/DeFiPositionsController.cjs +25 -36
  11. package/dist/DeFiPositionsController/DeFiPositionsController.cjs.map +1 -1
  12. package/dist/DeFiPositionsController/DeFiPositionsController.d.cts +3 -4
  13. package/dist/DeFiPositionsController/DeFiPositionsController.d.cts.map +1 -1
  14. package/dist/DeFiPositionsController/DeFiPositionsController.d.mts +3 -4
  15. package/dist/DeFiPositionsController/DeFiPositionsController.d.mts.map +1 -1
  16. package/dist/DeFiPositionsController/DeFiPositionsController.mjs +25 -36
  17. package/dist/DeFiPositionsController/DeFiPositionsController.mjs.map +1 -1
  18. package/dist/DeFiPositionsController/fetch-positions.cjs +4 -1
  19. package/dist/DeFiPositionsController/fetch-positions.cjs.map +1 -1
  20. package/dist/DeFiPositionsController/fetch-positions.d.cts.map +1 -1
  21. package/dist/DeFiPositionsController/fetch-positions.d.mts.map +1 -1
  22. package/dist/DeFiPositionsController/fetch-positions.mjs +4 -1
  23. package/dist/DeFiPositionsController/fetch-positions.mjs.map +1 -1
  24. package/dist/MultichainAssetsController/MultichainAssetsController.cjs +58 -0
  25. package/dist/MultichainAssetsController/MultichainAssetsController.cjs.map +1 -1
  26. package/dist/MultichainAssetsController/MultichainAssetsController.d.cts +15 -1
  27. package/dist/MultichainAssetsController/MultichainAssetsController.d.cts.map +1 -1
  28. package/dist/MultichainAssetsController/MultichainAssetsController.d.mts +15 -1
  29. package/dist/MultichainAssetsController/MultichainAssetsController.d.mts.map +1 -1
  30. package/dist/MultichainAssetsController/MultichainAssetsController.mjs +58 -0
  31. package/dist/MultichainAssetsController/MultichainAssetsController.mjs.map +1 -1
  32. package/dist/MultichainBalancesController/MultichainBalancesController.cjs +8 -0
  33. package/dist/MultichainBalancesController/MultichainBalancesController.cjs.map +1 -1
  34. package/dist/MultichainBalancesController/MultichainBalancesController.d.cts.map +1 -1
  35. package/dist/MultichainBalancesController/MultichainBalancesController.d.mts.map +1 -1
  36. package/dist/MultichainBalancesController/MultichainBalancesController.mjs +8 -0
  37. package/dist/MultichainBalancesController/MultichainBalancesController.mjs.map +1 -1
  38. package/dist/TokensController.cjs +3 -3
  39. package/dist/TokensController.cjs.map +1 -1
  40. package/dist/TokensController.d.cts.map +1 -1
  41. package/dist/TokensController.d.mts.map +1 -1
  42. package/dist/TokensController.mjs +3 -3
  43. package/dist/TokensController.mjs.map +1 -1
  44. package/dist/index.cjs +3 -1
  45. package/dist/index.cjs.map +1 -1
  46. package/dist/index.d.cts +2 -1
  47. package/dist/index.d.cts.map +1 -1
  48. package/dist/index.d.mts +2 -1
  49. package/dist/index.d.mts.map +1 -1
  50. package/dist/index.mjs +1 -0
  51. package/dist/index.mjs.map +1 -1
  52. package/dist/selectors/token-selectors.cjs +1 -6
  53. package/dist/selectors/token-selectors.cjs.map +1 -1
  54. package/dist/selectors/token-selectors.d.cts +1 -1
  55. package/dist/selectors/token-selectors.d.cts.map +1 -1
  56. package/dist/selectors/token-selectors.d.mts +1 -1
  57. package/dist/selectors/token-selectors.d.mts.map +1 -1
  58. package/dist/selectors/token-selectors.mjs +1 -6
  59. package/dist/selectors/token-selectors.mjs.map +1 -1
  60. package/dist/token-service.cjs +49 -1
  61. package/dist/token-service.cjs.map +1 -1
  62. package/dist/token-service.d.cts +16 -1
  63. package/dist/token-service.d.cts.map +1 -1
  64. package/dist/token-service.d.mts +16 -1
  65. package/dist/token-service.d.mts.map +1 -1
  66. package/dist/token-service.mjs +48 -1
  67. package/dist/token-service.mjs.map +1 -1
  68. package/dist/utils/timeout-with-retry.cjs +34 -0
  69. package/dist/utils/timeout-with-retry.cjs.map +1 -0
  70. package/dist/utils/timeout-with-retry.d.cts +9 -0
  71. package/dist/utils/timeout-with-retry.d.cts.map +1 -0
  72. package/dist/utils/timeout-with-retry.d.mts +9 -0
  73. package/dist/utils/timeout-with-retry.d.mts.map +1 -0
  74. package/dist/utils/timeout-with-retry.mjs +30 -0
  75. package/dist/utils/timeout-with-retry.mjs.map +1 -0
  76. package/package.json +5 -3
@@ -1,4 +1,4 @@
1
- import { ChainId, convertHexToDecimal, timeoutFetch } from "@metamask/controller-utils";
1
+ import { ChainId, convertHexToDecimal, handleFetch, timeoutFetch } from "@metamask/controller-utils";
2
2
  import { isTokenListSupportedForNetwork } from "./assetsUtil.mjs";
3
3
  export const TOKEN_END_POINT_API = 'https://token.api.cx.metamask.io';
4
4
  export const TOKEN_METADATA_NO_SUPPORT_ERROR = 'TokenService Error: Network does not support fetchTokenMetadata';
@@ -26,6 +26,21 @@ function getTokenMetadataURL(chainId, tokenAddress) {
26
26
  // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
27
27
  return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(chainId)}?address=${tokenAddress}`;
28
28
  }
29
+ /**
30
+ * Get the token search URL for the given networks and search query.
31
+ *
32
+ * @param chainIds - Array of CAIP format chain IDs (e.g., 'eip155:1', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp').
33
+ * @param query - The search query (token name, symbol, or address).
34
+ * @param limit - Optional limit for the number of results (defaults to 10).
35
+ * @returns The token search URL.
36
+ */
37
+ function getTokenSearchURL(chainIds, query, limit = 10) {
38
+ const encodedQuery = encodeURIComponent(query);
39
+ const encodedChainIds = chainIds
40
+ .map((id) => encodeURIComponent(id))
41
+ .join(',');
42
+ return `${TOKEN_END_POINT_API}/tokens/search?chainIds=${encodedChainIds}&query=${encodedQuery}&limit=${limit}`;
43
+ }
29
44
  const tenSecondsInMilliseconds = 10000;
30
45
  // Token list averages 1.6 MB in size
31
46
  // timeoutFetch by default has a 500ms timeout, which will almost always timeout given the response size.
@@ -52,6 +67,38 @@ export async function fetchTokenListByChainId(chainId, abortSignal, { timeout =
52
67
  }
53
68
  return undefined;
54
69
  }
70
+ /**
71
+ * Search for tokens across one or more networks by query string using CAIP format chain IDs.
72
+ *
73
+ * @param chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).
74
+ * @param query - The search query (token name, symbol, or address).
75
+ * @param options - Additional fetch options.
76
+ * @param options.limit - The maximum number of results to return.
77
+ * @returns Object containing count and data array. Returns { count: 0, data: [] } if request fails.
78
+ */
79
+ export async function searchTokens(chainIds, query, { limit = 10 } = {}) {
80
+ if (chainIds.length === 0) {
81
+ return { count: 0, data: [] };
82
+ }
83
+ const tokenSearchURL = getTokenSearchURL(chainIds, query, limit);
84
+ try {
85
+ const result = await handleFetch(tokenSearchURL);
86
+ // The API returns an object with structure: { count: number, data: array, pageInfo: object }
87
+ if (result && typeof result === 'object' && Array.isArray(result.data)) {
88
+ return {
89
+ count: result.count || result.data.length,
90
+ data: result.data,
91
+ };
92
+ }
93
+ // Handle non-expected responses
94
+ return { count: 0, data: [] };
95
+ }
96
+ catch (error) {
97
+ // Handle 400 errors and other failures by returning count 0 and empty array
98
+ console.log('Search request failed:', error);
99
+ return { count: 0, data: [] };
100
+ }
101
+ }
55
102
  /**
56
103
  * Fetch metadata for the token address provided for a given network. This request is cancellable
57
104
  * using the abort signal passed in.
@@ -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 timeoutFetch,\n} from '@metamask/controller-utils';\nimport type { 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) {\n const occurrenceFloor = chainId === ChainId['linea-mainnet'] ? 1 : 3;\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `${TOKEN_END_POINT_API}/tokens/${convertHexToDecimal(\n chainId,\n )}?occurrenceFloor=${occurrenceFloor}&includeNativeAssets=false&includeTokenFees=false&includeAssetType=false&includeERC20Permit=false&includeStorage=false`;\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) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(\n chainId,\n )}?address=${tokenAddress}`;\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 elm.aggregators.includes('lineaTeam') || elm.aggregators.length >= 3,\n );\n }\n return result;\n }\n return undefined;\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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport async function fetchTokenMetadata<T>(\n chainId: Hex,\n tokenAddress: string,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<T | 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<T>;\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 };\n fetchOptions.headers = new window.Headers();\n fetchOptions.headers.set('Content-Type', 'application/json');\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 // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\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 { 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) {\n const occurrenceFloor = chainId === ChainId['linea-mainnet'] ? 1 : 3;\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `${TOKEN_END_POINT_API}/tokens/${convertHexToDecimal(\n chainId,\n )}?occurrenceFloor=${occurrenceFloor}&includeNativeAssets=false&includeTokenFees=false&includeAssetType=false&includeERC20Permit=false&includeStorage=false`;\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) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(\n chainId,\n )}?address=${tokenAddress}`;\n}\n\n/**\n * Get the token search URL for the given networks and search query.\n *\n * @param chainIds - Array of CAIP format chain IDs (e.g., 'eip155:1', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp').\n * @param query - The search query (token name, symbol, or address).\n * @param limit - Optional limit for the number of results (defaults to 10).\n * @returns The token search URL.\n */\nfunction getTokenSearchURL(chainIds: CaipChainId[], query: string, limit = 10) {\n const encodedQuery = encodeURIComponent(query);\n const encodedChainIds = chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n return `${TOKEN_END_POINT_API}/tokens/search?chainIds=${encodedChainIds}&query=${encodedQuery}&limit=${limit}`;\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 elm.aggregators.includes('lineaTeam') || elm.aggregators.length >= 3,\n );\n }\n return result;\n }\n return undefined;\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 * @returns Object containing count and data array. Returns { count: 0, data: [] } if request fails.\n */\nexport async function searchTokens(\n chainIds: CaipChainId[],\n query: string,\n { limit = 10 } = {},\n): Promise<{ count: number; data: unknown[] }> {\n if (chainIds.length === 0) {\n return { count: 0, data: [] };\n }\n\n const tokenSearchURL = getTokenSearchURL(chainIds, query, limit);\n\n try {\n const result = 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: [] };\n } catch (error) {\n // Handle 400 errors and other failures by returning count 0 and empty array\n console.log('Search request failed:', error);\n return { count: 0, data: [] };\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 */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport async function fetchTokenMetadata<T>(\n chainId: Hex,\n tokenAddress: string,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<T | 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<T>;\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 };\n fetchOptions.headers = new window.Headers();\n fetchOptions.headers.set('Content-Type', 'application/json');\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 // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n throw new Error(`TokenService Error: ${responseObj.error}`);\n }\n return responseObj;\n}\n"]}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.timeoutWithRetry = void 0;
4
+ const utils_1 = require("@metamask/utils");
5
+ const TIMEOUT_ERROR = new Error('timeout');
6
+ /**
7
+ *
8
+ * @param call - The async function to call.
9
+ * @param timeout - Timeout in milliseconds for each call attempt.
10
+ * @param maxRetries - Maximum number of retries on timeout.
11
+ * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.
12
+ */
13
+ // eslint-disable-next-line consistent-return
14
+ async function timeoutWithRetry(call, timeout, maxRetries) {
15
+ (0, utils_1.assert)(maxRetries >= 0, 'maxRetries must be greater than or equal to 0');
16
+ let attempt = 0;
17
+ while (attempt <= maxRetries) {
18
+ try {
19
+ return (await Promise.race([
20
+ call(),
21
+ new Promise((_resolve, reject) => setTimeout(() => reject(TIMEOUT_ERROR), timeout)),
22
+ ]));
23
+ }
24
+ catch (err) {
25
+ if (err === TIMEOUT_ERROR && attempt < maxRetries) {
26
+ attempt += 1;
27
+ continue;
28
+ }
29
+ throw err;
30
+ }
31
+ }
32
+ }
33
+ exports.timeoutWithRetry = timeoutWithRetry;
34
+ //# sourceMappingURL=timeout-with-retry.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout-with-retry.cjs","sourceRoot":"","sources":["../../src/utils/timeout-with-retry.ts"],"names":[],"mappings":";;;AAAA,2CAAyC;AAEzC,MAAM,aAAa,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;AAE3C;;;;;;GAMG;AACH,6CAA6C;AACtC,KAAK,UAAU,gBAAgB,CACpC,IAAO,EACP,OAAe,EACf,UAAkB;IAGlB,IAAA,cAAM,EAAC,UAAU,IAAI,CAAC,EAAE,+CAA+C,CAAC,CAAC;IAEzE,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,OAAO,OAAO,IAAI,UAAU,EAAE;QAC5B,IAAI;YACF,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC;gBACzB,IAAI,EAAE;gBACN,IAAI,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,CACjD;aACF,CAAC,CAA2B,CAAC;SAC/B;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,GAAG,KAAK,aAAa,IAAI,OAAO,GAAG,UAAU,EAAE;gBACjD,OAAO,IAAI,CAAC,CAAC;gBACb,SAAS;aACV;YACD,MAAM,GAAG,CAAC;SACX;KACF;AACH,CAAC;AA1BD,4CA0BC","sourcesContent":["import { assert } from '@metamask/utils';\n\nconst TIMEOUT_ERROR = new Error('timeout');\n\n/**\n *\n * @param call - The async function to call.\n * @param timeout - Timeout in milliseconds for each call attempt.\n * @param maxRetries - Maximum number of retries on timeout.\n * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.\n */\n// eslint-disable-next-line consistent-return\nexport async function timeoutWithRetry<T extends () => Promise<unknown>>(\n call: T,\n timeout: number,\n maxRetries: number,\n // @ts-expect-error TS2366: Assertion guarantees loop executes\n): Promise<Awaited<ReturnType<T>>> {\n assert(maxRetries >= 0, 'maxRetries must be greater than or equal to 0');\n\n let attempt = 0;\n\n while (attempt <= maxRetries) {\n try {\n return (await Promise.race([\n call(),\n new Promise((_resolve, reject) =>\n setTimeout(() => reject(TIMEOUT_ERROR), timeout),\n ),\n ])) as Awaited<ReturnType<T>>;\n } catch (err) {\n if (err === TIMEOUT_ERROR && attempt < maxRetries) {\n attempt += 1;\n continue;\n }\n throw err;\n }\n }\n}\n"]}
@@ -0,0 +1,9 @@
1
+ /**
2
+ *
3
+ * @param call - The async function to call.
4
+ * @param timeout - Timeout in milliseconds for each call attempt.
5
+ * @param maxRetries - Maximum number of retries on timeout.
6
+ * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.
7
+ */
8
+ export declare function timeoutWithRetry<T extends () => Promise<unknown>>(call: T, timeout: number, maxRetries: number): Promise<Awaited<ReturnType<T>>>;
9
+ //# sourceMappingURL=timeout-with-retry.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout-with-retry.d.cts","sourceRoot":"","sources":["../../src/utils/timeout-with-retry.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,MAAM,OAAO,CAAC,OAAO,CAAC,EACrE,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GAEjB,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAqBjC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ *
3
+ * @param call - The async function to call.
4
+ * @param timeout - Timeout in milliseconds for each call attempt.
5
+ * @param maxRetries - Maximum number of retries on timeout.
6
+ * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.
7
+ */
8
+ export declare function timeoutWithRetry<T extends () => Promise<unknown>>(call: T, timeout: number, maxRetries: number): Promise<Awaited<ReturnType<T>>>;
9
+ //# sourceMappingURL=timeout-with-retry.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout-with-retry.d.mts","sourceRoot":"","sources":["../../src/utils/timeout-with-retry.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,MAAM,OAAO,CAAC,OAAO,CAAC,EACrE,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GAEjB,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAqBjC"}
@@ -0,0 +1,30 @@
1
+ import { assert } from "@metamask/utils";
2
+ const TIMEOUT_ERROR = new Error('timeout');
3
+ /**
4
+ *
5
+ * @param call - The async function to call.
6
+ * @param timeout - Timeout in milliseconds for each call attempt.
7
+ * @param maxRetries - Maximum number of retries on timeout.
8
+ * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.
9
+ */
10
+ // eslint-disable-next-line consistent-return
11
+ export async function timeoutWithRetry(call, timeout, maxRetries) {
12
+ assert(maxRetries >= 0, 'maxRetries must be greater than or equal to 0');
13
+ let attempt = 0;
14
+ while (attempt <= maxRetries) {
15
+ try {
16
+ return (await Promise.race([
17
+ call(),
18
+ new Promise((_resolve, reject) => setTimeout(() => reject(TIMEOUT_ERROR), timeout)),
19
+ ]));
20
+ }
21
+ catch (err) {
22
+ if (err === TIMEOUT_ERROR && attempt < maxRetries) {
23
+ attempt += 1;
24
+ continue;
25
+ }
26
+ throw err;
27
+ }
28
+ }
29
+ }
30
+ //# sourceMappingURL=timeout-with-retry.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout-with-retry.mjs","sourceRoot":"","sources":["../../src/utils/timeout-with-retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,wBAAwB;AAEzC,MAAM,aAAa,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;AAE3C;;;;;;GAMG;AACH,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAO,EACP,OAAe,EACf,UAAkB;IAGlB,MAAM,CAAC,UAAU,IAAI,CAAC,EAAE,+CAA+C,CAAC,CAAC;IAEzE,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,OAAO,OAAO,IAAI,UAAU,EAAE;QAC5B,IAAI;YACF,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC;gBACzB,IAAI,EAAE;gBACN,IAAI,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,CACjD;aACF,CAAC,CAA2B,CAAC;SAC/B;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,GAAG,KAAK,aAAa,IAAI,OAAO,GAAG,UAAU,EAAE;gBACjD,OAAO,IAAI,CAAC,CAAC;gBACb,SAAS;aACV;YACD,MAAM,GAAG,CAAC;SACX;KACF;AACH,CAAC","sourcesContent":["import { assert } from '@metamask/utils';\n\nconst TIMEOUT_ERROR = new Error('timeout');\n\n/**\n *\n * @param call - The async function to call.\n * @param timeout - Timeout in milliseconds for each call attempt.\n * @param maxRetries - Maximum number of retries on timeout.\n * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.\n */\n// eslint-disable-next-line consistent-return\nexport async function timeoutWithRetry<T extends () => Promise<unknown>>(\n call: T,\n timeout: number,\n maxRetries: number,\n // @ts-expect-error TS2366: Assertion guarantees loop executes\n): Promise<Awaited<ReturnType<T>>> {\n assert(maxRetries >= 0, 'maxRetries must be greater than or equal to 0');\n\n let attempt = 0;\n\n while (attempt <= maxRetries) {\n try {\n return (await Promise.race([\n call(),\n new Promise((_resolve, reject) =>\n setTimeout(() => reject(TIMEOUT_ERROR), timeout),\n ),\n ])) as Awaited<ReturnType<T>>;\n } catch (err) {\n if (err === TIMEOUT_ERROR && attempt < maxRetries) {\n attempt += 1;\n continue;\n }\n throw err;\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/assets-controllers",
3
- "version": "85.0.0",
3
+ "version": "87.0.0",
4
4
  "description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -36,6 +36,7 @@
36
36
  ],
37
37
  "scripts": {
38
38
  "build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
39
+ "build:all": "ts-bridge --project tsconfig.build.json --verbose --clean",
39
40
  "build:docs": "typedoc",
40
41
  "changelog:update": "../../scripts/update-changelog.sh @metamask/assets-controllers",
41
42
  "changelog:validate": "../../scripts/validate-changelog.sh @metamask/assets-controllers",
@@ -90,14 +91,15 @@
90
91
  "@metamask/keyring-controller": "^24.0.0",
91
92
  "@metamask/keyring-internal-api": "^9.0.0",
92
93
  "@metamask/keyring-snap-client": "^8.0.0",
93
- "@metamask/multichain-account-service": "^2.0.0",
94
+ "@metamask/multichain-account-service": "^2.1.0",
94
95
  "@metamask/network-controller": "^25.0.0",
95
96
  "@metamask/permission-controller": "^12.1.0",
96
97
  "@metamask/phishing-controller": "^15.0.0",
97
98
  "@metamask/preferences-controller": "^21.0.0",
98
99
  "@metamask/providers": "^22.1.0",
99
100
  "@metamask/snaps-controllers": "^14.0.1",
100
- "@metamask/transaction-controller": "^61.0.0",
101
+ "@metamask/transaction-controller": "^61.1.0",
102
+ "@ts-bridge/cli": "^0.6.4",
101
103
  "@types/jest": "^27.4.1",
102
104
  "@types/lodash": "^4.14.191",
103
105
  "@types/node": "^16.18.54",