@metamask-previews/assets-controller 4.0.0-preview-e19d3725e → 4.0.0-preview-c5f25f9

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 (68) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/AssetsController.cjs +28 -14
  3. package/dist/AssetsController.cjs.map +1 -1
  4. package/dist/AssetsController.d.cts +1 -2
  5. package/dist/AssetsController.d.cts.map +1 -1
  6. package/dist/AssetsController.d.mts +1 -2
  7. package/dist/AssetsController.d.mts.map +1 -1
  8. package/dist/AssetsController.mjs +28 -14
  9. package/dist/AssetsController.mjs.map +1 -1
  10. package/dist/data-sources/PriceDataSource.cjs +63 -38
  11. package/dist/data-sources/PriceDataSource.cjs.map +1 -1
  12. package/dist/data-sources/PriceDataSource.d.cts.map +1 -1
  13. package/dist/data-sources/PriceDataSource.d.mts.map +1 -1
  14. package/dist/data-sources/PriceDataSource.mjs +63 -38
  15. package/dist/data-sources/PriceDataSource.mjs.map +1 -1
  16. package/dist/data-sources/RpcDataSource.cjs +8 -63
  17. package/dist/data-sources/RpcDataSource.cjs.map +1 -1
  18. package/dist/data-sources/RpcDataSource.d.cts +1 -2
  19. package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
  20. package/dist/data-sources/RpcDataSource.d.mts +1 -2
  21. package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
  22. package/dist/data-sources/RpcDataSource.mjs +10 -65
  23. package/dist/data-sources/RpcDataSource.mjs.map +1 -1
  24. package/dist/data-sources/TokenDataSource.cjs +61 -30
  25. package/dist/data-sources/TokenDataSource.cjs.map +1 -1
  26. package/dist/data-sources/TokenDataSource.d.cts.map +1 -1
  27. package/dist/data-sources/TokenDataSource.d.mts.map +1 -1
  28. package/dist/data-sources/TokenDataSource.mjs +63 -32
  29. package/dist/data-sources/TokenDataSource.mjs.map +1 -1
  30. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.cjs +67 -0
  31. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.cjs.map +1 -0
  32. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.cts +23 -0
  33. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.cts.map +1 -0
  34. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.mts +23 -0
  35. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.mts.map +1 -0
  36. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.mjs +63 -0
  37. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.mjs.map +1 -0
  38. package/dist/data-sources/evm-rpc-services/clients/index.cjs +3 -1
  39. package/dist/data-sources/evm-rpc-services/clients/index.cjs.map +1 -1
  40. package/dist/data-sources/evm-rpc-services/clients/index.d.cts +1 -0
  41. package/dist/data-sources/evm-rpc-services/clients/index.d.cts.map +1 -1
  42. package/dist/data-sources/evm-rpc-services/clients/index.d.mts +1 -0
  43. package/dist/data-sources/evm-rpc-services/clients/index.d.mts.map +1 -1
  44. package/dist/data-sources/evm-rpc-services/clients/index.mjs +1 -0
  45. package/dist/data-sources/evm-rpc-services/clients/index.mjs.map +1 -1
  46. package/dist/data-sources/evm-rpc-services/index.cjs +2 -1
  47. package/dist/data-sources/evm-rpc-services/index.cjs.map +1 -1
  48. package/dist/data-sources/evm-rpc-services/index.d.cts +1 -1
  49. package/dist/data-sources/evm-rpc-services/index.d.cts.map +1 -1
  50. package/dist/data-sources/evm-rpc-services/index.d.mts +1 -1
  51. package/dist/data-sources/evm-rpc-services/index.d.mts.map +1 -1
  52. package/dist/data-sources/evm-rpc-services/index.mjs +1 -1
  53. package/dist/data-sources/evm-rpc-services/index.mjs.map +1 -1
  54. package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs +27 -48
  55. package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs.map +1 -1
  56. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts +12 -9
  57. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts.map +1 -1
  58. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts +12 -9
  59. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts.map +1 -1
  60. package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs +27 -48
  61. package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs.map +1 -1
  62. package/dist/data-sources/evm-rpc-services/services/index.cjs.map +1 -1
  63. package/dist/data-sources/evm-rpc-services/services/index.d.cts +1 -1
  64. package/dist/data-sources/evm-rpc-services/services/index.d.cts.map +1 -1
  65. package/dist/data-sources/evm-rpc-services/services/index.d.mts +1 -1
  66. package/dist/data-sources/evm-rpc-services/services/index.d.mts.map +1 -1
  67. package/dist/data-sources/evm-rpc-services/services/index.mjs.map +1 -1
  68. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokensApiClient.cjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/TokensApiClient.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAEA,MAAM,mBAAmB,GAAG,6CAA6C,CAAC;AAE1E,yDAAyD;AACzD,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAgB5B;;;GAGG;AACH,MAAa,eAAe;IAG1B,YAAY,MAA8B;QAFjC,yCAAgC;QAGvC,uBAAA,IAAI,0BAAU,MAAM,EAAE,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAA,CAAC;IACnE,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,cAAc,CAAC,UAAmB;QACtC,MAAM,cAAc,GAAG,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAChD,MAAM,WAAW,GAAG,UAAU,cAAc,EAAE,CAAC;QAE/C,MAAM,GAAG,GACP,GAAG,mBAAmB,IAAI,WAAW,SAAS;YAC9C,UAAU,gBAAgB,EAAE;YAC5B,0BAA0B;YAC1B,uBAAuB;YACvB,oBAAoB;YACpB,sBAAsB;YACtB,0BAA0B,CAAC;QAE7B,MAAM,QAAQ,GAAG,MAAM,uBAAA,IAAI,8BAAO,MAAX,IAAI,EAAQ,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,6BAA6B,QAAQ,CAAC,MAAM,QAAQ,WAAW,EAAE,CAClE,CAAC;QACJ,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6B,CAAC;QAErE,OAAO,IAAI;aACR,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;aAClD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,OAAO;gBACL,OAAO;gBACP,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;gBACzB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;gBACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;gBAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;aAC9B,CAAC;QACJ,CAAC,CAAC,CAAC;IACP,CAAC;CACF;AAlDD,0CAkDC","sourcesContent":["import type { ChainId, TokenListEntry } from '../types';\n\nconst TOKENS_API_BASE_URL = 'https://tokens.api.cx.metamask.io/v3/chains';\n\n/** How many tokens to request from the API per chain. */\nconst TOKENS_API_FIRST = 25;\n\n/** Shape of a single item in the Tokens API response `data` array. */\ntype ApiTokenData = {\n assetId: string;\n symbol?: string;\n name?: string;\n decimals?: number;\n occurrences?: number;\n};\n\nexport type TokensApiClientConfig = {\n /** Fetch function (defaults to globalThis.fetch). */\n fetch?: typeof globalThis.fetch;\n};\n\n/**\n * Client for the MetaMask Tokens API.\n * Fetches the top ERC-20 tokens for a given chain (occurrenceFloor=3, first=25).\n */\nexport class TokensApiClient {\n readonly #fetch: typeof globalThis.fetch;\n\n constructor(config?: TokensApiClientConfig) {\n this.#fetch = config?.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n /**\n * Fetch the list of top ERC-20 tokens for a chain from the Tokens API.\n * Only `erc20` assets are returned; native (`slip44`) entries are skipped.\n *\n * @param hexChainId - Chain ID in hex format (e.g. `'0x1'` for Ethereum mainnet).\n * @returns Array of token list entries with address and metadata.\n * @throws If the API responds with a non-2xx status.\n */\n async fetchTokenList(hexChainId: ChainId): Promise<TokenListEntry[]> {\n const chainIdDecimal = parseInt(hexChainId, 16);\n const caipChainId = `eip155:${chainIdDecimal}`;\n\n const url =\n `${TOKENS_API_BASE_URL}/${caipChainId}/assets` +\n `?first=${TOKENS_API_FIRST}` +\n `&includeOccurrences=true` +\n `&includeMetadata=true` +\n `&occurrenceFloor=3` +\n `&includeRwaData=true` +\n `&excludeDescription=true`;\n\n const response = await this.#fetch(url);\n if (!response.ok) {\n throw new Error(\n `Tokens API responded with ${response.status} for ${caipChainId}`,\n );\n }\n\n const { data } = (await response.json()) as { data: ApiTokenData[] };\n\n return data\n .filter((item) => item.assetId.includes('/erc20:'))\n .map((item) => {\n const address = item.assetId.split('/erc20:')[1];\n return {\n address,\n symbol: item.symbol ?? '',\n name: item.name ?? '',\n decimals: item.decimals ?? 18,\n occurrences: item.occurrences,\n };\n });\n }\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import type { ChainId, TokenListEntry } from "../types/index.cjs";
2
+ export type TokensApiClientConfig = {
3
+ /** Fetch function (defaults to globalThis.fetch). */
4
+ fetch?: typeof globalThis.fetch;
5
+ };
6
+ /**
7
+ * Client for the MetaMask Tokens API.
8
+ * Fetches the top ERC-20 tokens for a given chain (occurrenceFloor=3, first=25).
9
+ */
10
+ export declare class TokensApiClient {
11
+ #private;
12
+ constructor(config?: TokensApiClientConfig);
13
+ /**
14
+ * Fetch the list of top ERC-20 tokens for a chain from the Tokens API.
15
+ * Only `erc20` assets are returned; native (`slip44`) entries are skipped.
16
+ *
17
+ * @param hexChainId - Chain ID in hex format (e.g. `'0x1'` for Ethereum mainnet).
18
+ * @returns Array of token list entries with address and metadata.
19
+ * @throws If the API responds with a non-2xx status.
20
+ */
21
+ fetchTokenList(hexChainId: ChainId): Promise<TokenListEntry[]>;
22
+ }
23
+ //# sourceMappingURL=TokensApiClient.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokensApiClient.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/TokensApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,2BAAiB;AAgBxD,MAAM,MAAM,qBAAqB,GAAG;IAClC,qDAAqD;IACrD,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC,CAAC;AAEF;;;GAGG;AACH,qBAAa,eAAe;;gBAGd,MAAM,CAAC,EAAE,qBAAqB;IAI1C;;;;;;;OAOG;IACG,cAAc,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAmCrE"}
@@ -0,0 +1,23 @@
1
+ import type { ChainId, TokenListEntry } from "../types/index.mjs";
2
+ export type TokensApiClientConfig = {
3
+ /** Fetch function (defaults to globalThis.fetch). */
4
+ fetch?: typeof globalThis.fetch;
5
+ };
6
+ /**
7
+ * Client for the MetaMask Tokens API.
8
+ * Fetches the top ERC-20 tokens for a given chain (occurrenceFloor=3, first=25).
9
+ */
10
+ export declare class TokensApiClient {
11
+ #private;
12
+ constructor(config?: TokensApiClientConfig);
13
+ /**
14
+ * Fetch the list of top ERC-20 tokens for a chain from the Tokens API.
15
+ * Only `erc20` assets are returned; native (`slip44`) entries are skipped.
16
+ *
17
+ * @param hexChainId - Chain ID in hex format (e.g. `'0x1'` for Ethereum mainnet).
18
+ * @returns Array of token list entries with address and metadata.
19
+ * @throws If the API responds with a non-2xx status.
20
+ */
21
+ fetchTokenList(hexChainId: ChainId): Promise<TokenListEntry[]>;
22
+ }
23
+ //# sourceMappingURL=TokensApiClient.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokensApiClient.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/TokensApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,2BAAiB;AAgBxD,MAAM,MAAM,qBAAqB,GAAG;IAClC,qDAAqD;IACrD,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC,CAAC;AAEF;;;GAGG;AACH,qBAAa,eAAe;;gBAGd,MAAM,CAAC,EAAE,qBAAqB;IAI1C;;;;;;;OAOG;IACG,cAAc,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAmCrE"}
@@ -0,0 +1,63 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _TokensApiClient_fetch;
13
+ const TOKENS_API_BASE_URL = 'https://tokens.api.cx.metamask.io/v3/chains';
14
+ /** How many tokens to request from the API per chain. */
15
+ const TOKENS_API_FIRST = 25;
16
+ /**
17
+ * Client for the MetaMask Tokens API.
18
+ * Fetches the top ERC-20 tokens for a given chain (occurrenceFloor=3, first=25).
19
+ */
20
+ export class TokensApiClient {
21
+ constructor(config) {
22
+ _TokensApiClient_fetch.set(this, void 0);
23
+ __classPrivateFieldSet(this, _TokensApiClient_fetch, config?.fetch ?? globalThis.fetch.bind(globalThis), "f");
24
+ }
25
+ /**
26
+ * Fetch the list of top ERC-20 tokens for a chain from the Tokens API.
27
+ * Only `erc20` assets are returned; native (`slip44`) entries are skipped.
28
+ *
29
+ * @param hexChainId - Chain ID in hex format (e.g. `'0x1'` for Ethereum mainnet).
30
+ * @returns Array of token list entries with address and metadata.
31
+ * @throws If the API responds with a non-2xx status.
32
+ */
33
+ async fetchTokenList(hexChainId) {
34
+ const chainIdDecimal = parseInt(hexChainId, 16);
35
+ const caipChainId = `eip155:${chainIdDecimal}`;
36
+ const url = `${TOKENS_API_BASE_URL}/${caipChainId}/assets` +
37
+ `?first=${TOKENS_API_FIRST}` +
38
+ `&includeOccurrences=true` +
39
+ `&includeMetadata=true` +
40
+ `&occurrenceFloor=3` +
41
+ `&includeRwaData=true` +
42
+ `&excludeDescription=true`;
43
+ const response = await __classPrivateFieldGet(this, _TokensApiClient_fetch, "f").call(this, url);
44
+ if (!response.ok) {
45
+ throw new Error(`Tokens API responded with ${response.status} for ${caipChainId}`);
46
+ }
47
+ const { data } = (await response.json());
48
+ return data
49
+ .filter((item) => item.assetId.includes('/erc20:'))
50
+ .map((item) => {
51
+ const address = item.assetId.split('/erc20:')[1];
52
+ return {
53
+ address,
54
+ symbol: item.symbol ?? '',
55
+ name: item.name ?? '',
56
+ decimals: item.decimals ?? 18,
57
+ occurrences: item.occurrences,
58
+ };
59
+ });
60
+ }
61
+ }
62
+ _TokensApiClient_fetch = new WeakMap();
63
+ //# sourceMappingURL=TokensApiClient.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokensApiClient.mjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/TokensApiClient.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,MAAM,mBAAmB,GAAG,6CAA6C,CAAC;AAE1E,yDAAyD;AACzD,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAgB5B;;;GAGG;AACH,MAAM,OAAO,eAAe;IAG1B,YAAY,MAA8B;QAFjC,yCAAgC;QAGvC,uBAAA,IAAI,0BAAU,MAAM,EAAE,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAA,CAAC;IACnE,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,cAAc,CAAC,UAAmB;QACtC,MAAM,cAAc,GAAG,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAChD,MAAM,WAAW,GAAG,UAAU,cAAc,EAAE,CAAC;QAE/C,MAAM,GAAG,GACP,GAAG,mBAAmB,IAAI,WAAW,SAAS;YAC9C,UAAU,gBAAgB,EAAE;YAC5B,0BAA0B;YAC1B,uBAAuB;YACvB,oBAAoB;YACpB,sBAAsB;YACtB,0BAA0B,CAAC;QAE7B,MAAM,QAAQ,GAAG,MAAM,uBAAA,IAAI,8BAAO,MAAX,IAAI,EAAQ,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,6BAA6B,QAAQ,CAAC,MAAM,QAAQ,WAAW,EAAE,CAClE,CAAC;QACJ,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6B,CAAC;QAErE,OAAO,IAAI;aACR,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;aAClD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,OAAO;gBACL,OAAO;gBACP,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;gBACzB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;gBACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;gBAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;aAC9B,CAAC;QACJ,CAAC,CAAC,CAAC;IACP,CAAC;CACF","sourcesContent":["import type { ChainId, TokenListEntry } from '../types';\n\nconst TOKENS_API_BASE_URL = 'https://tokens.api.cx.metamask.io/v3/chains';\n\n/** How many tokens to request from the API per chain. */\nconst TOKENS_API_FIRST = 25;\n\n/** Shape of a single item in the Tokens API response `data` array. */\ntype ApiTokenData = {\n assetId: string;\n symbol?: string;\n name?: string;\n decimals?: number;\n occurrences?: number;\n};\n\nexport type TokensApiClientConfig = {\n /** Fetch function (defaults to globalThis.fetch). */\n fetch?: typeof globalThis.fetch;\n};\n\n/**\n * Client for the MetaMask Tokens API.\n * Fetches the top ERC-20 tokens for a given chain (occurrenceFloor=3, first=25).\n */\nexport class TokensApiClient {\n readonly #fetch: typeof globalThis.fetch;\n\n constructor(config?: TokensApiClientConfig) {\n this.#fetch = config?.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n /**\n * Fetch the list of top ERC-20 tokens for a chain from the Tokens API.\n * Only `erc20` assets are returned; native (`slip44`) entries are skipped.\n *\n * @param hexChainId - Chain ID in hex format (e.g. `'0x1'` for Ethereum mainnet).\n * @returns Array of token list entries with address and metadata.\n * @throws If the API responds with a non-2xx status.\n */\n async fetchTokenList(hexChainId: ChainId): Promise<TokenListEntry[]> {\n const chainIdDecimal = parseInt(hexChainId, 16);\n const caipChainId = `eip155:${chainIdDecimal}`;\n\n const url =\n `${TOKENS_API_BASE_URL}/${caipChainId}/assets` +\n `?first=${TOKENS_API_FIRST}` +\n `&includeOccurrences=true` +\n `&includeMetadata=true` +\n `&occurrenceFloor=3` +\n `&includeRwaData=true` +\n `&excludeDescription=true`;\n\n const response = await this.#fetch(url);\n if (!response.ok) {\n throw new Error(\n `Tokens API responded with ${response.status} for ${caipChainId}`,\n );\n }\n\n const { data } = (await response.json()) as { data: ApiTokenData[] };\n\n return data\n .filter((item) => item.assetId.includes('/erc20:'))\n .map((item) => {\n const address = item.assetId.split('/erc20:')[1];\n return {\n address,\n symbol: item.symbol ?? '',\n name: item.name ?? '',\n decimals: item.decimals ?? 18,\n occurrences: item.occurrences,\n };\n });\n }\n}\n"]}
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MulticallClient = exports.encodeAggregate3 = exports.decodeAggregate3Response = void 0;
3
+ exports.TokensApiClient = exports.MulticallClient = exports.encodeAggregate3 = exports.decodeAggregate3Response = void 0;
4
4
  var MulticallClient_1 = require("./MulticallClient.cjs");
5
5
  Object.defineProperty(exports, "decodeAggregate3Response", { enumerable: true, get: function () { return MulticallClient_1.decodeAggregate3Response; } });
6
6
  Object.defineProperty(exports, "encodeAggregate3", { enumerable: true, get: function () { return MulticallClient_1.encodeAggregate3; } });
7
7
  Object.defineProperty(exports, "MulticallClient", { enumerable: true, get: function () { return MulticallClient_1.MulticallClient; } });
8
+ var TokensApiClient_1 = require("./TokensApiClient.cjs");
9
+ Object.defineProperty(exports, "TokensApiClient", { enumerable: true, get: function () { return TokensApiClient_1.TokensApiClient; } });
8
10
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/index.ts"],"names":[],"mappings":";;;AAAA,yDAK2B;AAJzB,2HAAA,wBAAwB,OAAA;AACxB,mHAAA,gBAAgB,OAAA;AAChB,kHAAA,eAAe,OAAA","sourcesContent":["export {\n decodeAggregate3Response,\n encodeAggregate3,\n MulticallClient,\n type MulticallClientConfig,\n} from './MulticallClient';\n\n// Re-export provider types from types module\nexport type { GetProviderFunction, Provider } from '../types';\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/index.ts"],"names":[],"mappings":";;;AAAA,yDAK2B;AAJzB,2HAAA,wBAAwB,OAAA;AACxB,mHAAA,gBAAgB,OAAA;AAChB,kHAAA,eAAe,OAAA;AAIjB,yDAAgF;AAAvE,kHAAA,eAAe,OAAA","sourcesContent":["export {\n decodeAggregate3Response,\n encodeAggregate3,\n MulticallClient,\n type MulticallClientConfig,\n} from './MulticallClient';\n\nexport { TokensApiClient, type TokensApiClientConfig } from './TokensApiClient';\n\n// Re-export provider types from types module\nexport type { GetProviderFunction, Provider } from '../types';\n"]}
@@ -1,3 +1,4 @@
1
1
  export { decodeAggregate3Response, encodeAggregate3, MulticallClient, type MulticallClientConfig, } from "./MulticallClient.cjs";
2
+ export { TokensApiClient, type TokensApiClientConfig } from "./TokensApiClient.cjs";
2
3
  export type { GetProviderFunction, Provider } from "../types/index.cjs";
3
4
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,KAAK,qBAAqB,GAC3B,8BAA0B;AAG3B,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,2BAAiB"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,KAAK,qBAAqB,GAC3B,8BAA0B;AAE3B,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,8BAA0B;AAGhF,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,2BAAiB"}
@@ -1,3 +1,4 @@
1
1
  export { decodeAggregate3Response, encodeAggregate3, MulticallClient, type MulticallClientConfig, } from "./MulticallClient.mjs";
2
+ export { TokensApiClient, type TokensApiClientConfig } from "./TokensApiClient.mjs";
2
3
  export type { GetProviderFunction, Provider } from "../types/index.mjs";
3
4
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,KAAK,qBAAqB,GAC3B,8BAA0B;AAG3B,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,2BAAiB"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,KAAK,qBAAqB,GAC3B,8BAA0B;AAE3B,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,8BAA0B;AAGhF,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,2BAAiB"}
@@ -1,2 +1,3 @@
1
1
  export { decodeAggregate3Response, encodeAggregate3, MulticallClient } from "./MulticallClient.mjs";
2
+ export { TokensApiClient } from "./TokensApiClient.mjs";
2
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EAEhB,8BAA0B","sourcesContent":["export {\n decodeAggregate3Response,\n encodeAggregate3,\n MulticallClient,\n type MulticallClientConfig,\n} from './MulticallClient';\n\n// Re-export provider types from types module\nexport type { GetProviderFunction, Provider } from '../types';\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/clients/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EAEhB,8BAA0B;AAE3B,OAAO,EAAE,eAAe,EAA8B,8BAA0B","sourcesContent":["export {\n decodeAggregate3Response,\n encodeAggregate3,\n MulticallClient,\n type MulticallClientConfig,\n} from './MulticallClient';\n\nexport { TokensApiClient, type TokensApiClientConfig } from './TokensApiClient';\n\n// Re-export provider types from types module\nexport type { GetProviderFunction, Provider } from '../types';\n"]}
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.reduceInBatchesSerially = exports.divideIntoBatches = exports.isStakingContractAssetId = exports.getStakingContractAddress = exports.getSupportedStakingChainIds = exports.StakedBalanceFetcher = exports.TokenDetector = exports.BalanceFetcher = exports.MulticallClient = void 0;
3
+ exports.reduceInBatchesSerially = exports.divideIntoBatches = exports.isStakingContractAssetId = exports.getStakingContractAddress = exports.getSupportedStakingChainIds = exports.StakedBalanceFetcher = exports.TokenDetector = exports.BalanceFetcher = exports.TokensApiClient = exports.MulticallClient = void 0;
4
4
  var clients_1 = require("./clients/index.cjs");
5
5
  Object.defineProperty(exports, "MulticallClient", { enumerable: true, get: function () { return clients_1.MulticallClient; } });
6
+ Object.defineProperty(exports, "TokensApiClient", { enumerable: true, get: function () { return clients_1.TokensApiClient; } });
6
7
  var services_1 = require("./services/index.cjs");
7
8
  Object.defineProperty(exports, "BalanceFetcher", { enumerable: true, get: function () { return services_1.BalanceFetcher; } });
8
9
  Object.defineProperty(exports, "TokenDetector", { enumerable: true, get: function () { return services_1.TokenDetector; } });
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":";;;AAaA,+CAAwE;AAA/D,0GAAA,eAAe,OAAA;AACxB,iDAcoB;AAblB,0GAAA,cAAc,OAAA;AACd,yGAAA,aAAa,OAAA;AACb,gHAAA,oBAAoB,OAAA;AACpB,uHAAA,2BAA2B,OAAA;AAC3B,qHAAA,yBAAyB,OAAA;AACzB,oHAAA,wBAAwB,OAAA;AAS1B,2CAAqE;AAA5D,0GAAA,iBAAiB,OAAA;AAAE,gHAAA,uBAAuB,OAAA","sourcesContent":["export type {\n Address,\n AssetFetchEntry,\n AssetsBalanceState,\n ChainId,\n GetProviderFunction,\n Provider,\n BalanceOfRequest,\n BalanceOfResponse,\n TokenListState,\n BalanceFetchResult,\n TokenDetectionResult,\n} from './types';\nexport { MulticallClient, type MulticallClientConfig } from './clients';\nexport {\n BalanceFetcher,\n TokenDetector,\n StakedBalanceFetcher,\n getSupportedStakingChainIds,\n getStakingContractAddress,\n isStakingContractAssetId,\n type BalancePollingInput,\n type DetectionPollingInput,\n type StakedBalancePollingInput,\n type StakedBalanceFetchResult,\n type OnBalanceUpdateCallback,\n type OnDetectionUpdateCallback,\n type OnStakedBalanceUpdateCallback,\n} from './services';\nexport { divideIntoBatches, reduceInBatchesSerially } from './utils';\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":";;;AAaA,+CAKmB;AAJjB,0GAAA,eAAe,OAAA;AAEf,0GAAA,eAAe,OAAA;AAGjB,iDAcoB;AAblB,0GAAA,cAAc,OAAA;AACd,yGAAA,aAAa,OAAA;AACb,gHAAA,oBAAoB,OAAA;AACpB,uHAAA,2BAA2B,OAAA;AAC3B,qHAAA,yBAAyB,OAAA;AACzB,oHAAA,wBAAwB,OAAA;AAS1B,2CAAqE;AAA5D,0GAAA,iBAAiB,OAAA;AAAE,gHAAA,uBAAuB,OAAA","sourcesContent":["export type {\n Address,\n AssetFetchEntry,\n AssetsBalanceState,\n ChainId,\n GetProviderFunction,\n Provider,\n BalanceOfRequest,\n BalanceOfResponse,\n TokenListState,\n BalanceFetchResult,\n TokenDetectionResult,\n} from './types';\nexport {\n MulticallClient,\n type MulticallClientConfig,\n TokensApiClient,\n type TokensApiClientConfig,\n} from './clients';\nexport {\n BalanceFetcher,\n TokenDetector,\n StakedBalanceFetcher,\n getSupportedStakingChainIds,\n getStakingContractAddress,\n isStakingContractAssetId,\n type BalancePollingInput,\n type DetectionPollingInput,\n type StakedBalancePollingInput,\n type StakedBalanceFetchResult,\n type OnBalanceUpdateCallback,\n type OnDetectionUpdateCallback,\n type OnStakedBalanceUpdateCallback,\n} from './services';\nexport { divideIntoBatches, reduceInBatchesSerially } from './utils';\n"]}
@@ -1,5 +1,5 @@
1
1
  export type { Address, AssetFetchEntry, AssetsBalanceState, ChainId, GetProviderFunction, Provider, BalanceOfRequest, BalanceOfResponse, TokenListState, BalanceFetchResult, TokenDetectionResult, } from "./types/index.cjs";
2
- export { MulticallClient, type MulticallClientConfig } from "./clients/index.cjs";
2
+ export { MulticallClient, type MulticallClientConfig, TokensApiClient, type TokensApiClientConfig, } from "./clients/index.cjs";
3
3
  export { BalanceFetcher, TokenDetector, StakedBalanceFetcher, getSupportedStakingChainIds, getStakingContractAddress, isStakingContractAssetId, type BalancePollingInput, type DetectionPollingInput, type StakedBalancePollingInput, type StakedBalanceFetchResult, type OnBalanceUpdateCallback, type OnDetectionUpdateCallback, type OnStakedBalanceUpdateCallback, } from "./services/index.cjs";
4
4
  export { divideIntoBatches, reduceInBatchesSerially } from "./utils/index.cjs";
5
5
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,eAAe,EACf,kBAAkB,EAClB,OAAO,EACP,mBAAmB,EACnB,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,0BAAgB;AACjB,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,4BAAkB;AACxE,OAAO,EACL,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,6BAA6B,GACnC,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,eAAe,EACf,kBAAkB,EAClB,OAAO,EACP,mBAAmB,EACnB,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,0BAAgB;AACjB,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,EAC1B,eAAe,EACf,KAAK,qBAAqB,GAC3B,4BAAkB;AACnB,OAAO,EACL,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,6BAA6B,GACnC,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB"}
@@ -1,5 +1,5 @@
1
1
  export type { Address, AssetFetchEntry, AssetsBalanceState, ChainId, GetProviderFunction, Provider, BalanceOfRequest, BalanceOfResponse, TokenListState, BalanceFetchResult, TokenDetectionResult, } from "./types/index.mjs";
2
- export { MulticallClient, type MulticallClientConfig } from "./clients/index.mjs";
2
+ export { MulticallClient, type MulticallClientConfig, TokensApiClient, type TokensApiClientConfig, } from "./clients/index.mjs";
3
3
  export { BalanceFetcher, TokenDetector, StakedBalanceFetcher, getSupportedStakingChainIds, getStakingContractAddress, isStakingContractAssetId, type BalancePollingInput, type DetectionPollingInput, type StakedBalancePollingInput, type StakedBalanceFetchResult, type OnBalanceUpdateCallback, type OnDetectionUpdateCallback, type OnStakedBalanceUpdateCallback, } from "./services/index.mjs";
4
4
  export { divideIntoBatches, reduceInBatchesSerially } from "./utils/index.mjs";
5
5
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,eAAe,EACf,kBAAkB,EAClB,OAAO,EACP,mBAAmB,EACnB,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,0BAAgB;AACjB,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,4BAAkB;AACxE,OAAO,EACL,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,6BAA6B,GACnC,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,eAAe,EACf,kBAAkB,EAClB,OAAO,EACP,mBAAmB,EACnB,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,0BAAgB;AACjB,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,EAC1B,eAAe,EACf,KAAK,qBAAqB,GAC3B,4BAAkB;AACnB,OAAO,EACL,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,6BAA6B,GACnC,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB"}
@@ -1,4 +1,4 @@
1
- export { MulticallClient } from "./clients/index.mjs";
1
+ export { MulticallClient, TokensApiClient } from "./clients/index.mjs";
2
2
  export { BalanceFetcher, TokenDetector, StakedBalanceFetcher, getSupportedStakingChainIds, getStakingContractAddress, isStakingContractAssetId } from "./services/index.mjs";
3
3
  export { divideIntoBatches, reduceInBatchesSerially } from "./utils/index.mjs";
4
4
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAA8B,4BAAkB;AACxE,OAAO,EACL,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EAQzB,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB","sourcesContent":["export type {\n Address,\n AssetFetchEntry,\n AssetsBalanceState,\n ChainId,\n GetProviderFunction,\n Provider,\n BalanceOfRequest,\n BalanceOfResponse,\n TokenListState,\n BalanceFetchResult,\n TokenDetectionResult,\n} from './types';\nexport { MulticallClient, type MulticallClientConfig } from './clients';\nexport {\n BalanceFetcher,\n TokenDetector,\n StakedBalanceFetcher,\n getSupportedStakingChainIds,\n getStakingContractAddress,\n isStakingContractAssetId,\n type BalancePollingInput,\n type DetectionPollingInput,\n type StakedBalancePollingInput,\n type StakedBalanceFetchResult,\n type OnBalanceUpdateCallback,\n type OnDetectionUpdateCallback,\n type OnStakedBalanceUpdateCallback,\n} from './services';\nexport { divideIntoBatches, reduceInBatchesSerially } from './utils';\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,eAAe,EAEf,eAAe,EAEhB,4BAAkB;AACnB,OAAO,EACL,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EAQzB,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB","sourcesContent":["export type {\n Address,\n AssetFetchEntry,\n AssetsBalanceState,\n ChainId,\n GetProviderFunction,\n Provider,\n BalanceOfRequest,\n BalanceOfResponse,\n TokenListState,\n BalanceFetchResult,\n TokenDetectionResult,\n} from './types';\nexport {\n MulticallClient,\n type MulticallClientConfig,\n TokensApiClient,\n type TokensApiClientConfig,\n} from './clients';\nexport {\n BalanceFetcher,\n TokenDetector,\n StakedBalanceFetcher,\n getSupportedStakingChainIds,\n getStakingContractAddress,\n isStakingContractAssetId,\n type BalancePollingInput,\n type DetectionPollingInput,\n type StakedBalancePollingInput,\n type StakedBalanceFetchResult,\n type OnBalanceUpdateCallback,\n type OnDetectionUpdateCallback,\n type OnStakedBalanceUpdateCallback,\n} from './services';\nexport { divideIntoBatches, reduceInBatchesSerially } from './utils';\n"]}
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _TokenDetector_instances, _TokenDetector_multicallClient, _TokenDetector_messenger, _TokenDetector_config, _TokenDetector_onDetectionUpdate, _TokenDetector_processBalanceResponses, _TokenDetector_formatBalance, _TokenDetector_getTokenMetadata, _TokenDetector_createAsset;
13
+ var _TokenDetector_instances, _TokenDetector_multicallClient, _TokenDetector_tokensApiClient, _TokenDetector_config, _TokenDetector_tokenListCache, _TokenDetector_onDetectionUpdate, _TokenDetector_fetchAndCacheTokenList, _TokenDetector_processBalanceResponses, _TokenDetector_formatBalance, _TokenDetector_getTokenMetadata, _TokenDetector_createAsset;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.TokenDetector = void 0;
16
16
  const polling_controller_1 = require("@metamask/polling-controller");
@@ -18,25 +18,26 @@ const utils_1 = require("../utils/index.cjs");
18
18
  const DEFAULT_DETECTION_INTERVAL = 180000; // 3 minutes
19
19
  /**
20
20
  * TokenDetector - Detects tokens with non-zero balances via multicall.
21
+ * Fetches the token list from the Tokens API and uses multicall to check balances.
21
22
  * Extends StaticIntervalPollingControllerOnly for built-in polling support.
22
23
  */
23
24
  class TokenDetector extends (0, polling_controller_1.StaticIntervalPollingControllerOnly)() {
24
- constructor(multicallClient, messenger, config) {
25
+ constructor(multicallClient, tokensApiClient, config) {
25
26
  super();
26
27
  _TokenDetector_instances.add(this);
27
28
  _TokenDetector_multicallClient.set(this, void 0);
28
- _TokenDetector_messenger.set(this, void 0);
29
+ _TokenDetector_tokensApiClient.set(this, void 0);
29
30
  _TokenDetector_config.set(this, void 0);
31
+ _TokenDetector_tokenListCache.set(this, new Map());
30
32
  _TokenDetector_onDetectionUpdate.set(this, void 0);
31
33
  __classPrivateFieldSet(this, _TokenDetector_multicallClient, multicallClient, "f");
32
- __classPrivateFieldSet(this, _TokenDetector_messenger, messenger, "f");
34
+ __classPrivateFieldSet(this, _TokenDetector_tokensApiClient, tokensApiClient, "f");
33
35
  __classPrivateFieldSet(this, _TokenDetector_config, {
34
36
  tokenDetectionEnabled: config?.tokenDetectionEnabled ?? (() => true),
35
37
  useExternalService: config?.useExternalService ?? (() => true),
36
38
  defaultBatchSize: config?.defaultBatchSize ?? 300,
37
39
  defaultTimeoutMs: config?.defaultTimeoutMs ?? 30000,
38
40
  }, "f");
39
- // Set the polling interval
40
41
  this.setIntervalLength(config?.pollingInterval ?? DEFAULT_DETECTION_INTERVAL);
41
42
  }
42
43
  /**
@@ -54,35 +55,21 @@ class TokenDetector extends (0, polling_controller_1.StaticIntervalPollingContro
54
55
  * @param input - The polling input.
55
56
  */
56
57
  async _executePoll(input) {
57
- // Check if token list is available for this chain
58
- const tokensToCheck = this.getTokensToCheck(input.chainId);
59
- if (tokensToCheck.length === 0) {
60
- // No tokens in list for chain, will retry on next poll
61
- return;
62
- }
63
58
  const result = await this.detectTokens(input.chainId, input.accountId, input.accountAddress);
64
59
  if (__classPrivateFieldGet(this, _TokenDetector_onDetectionUpdate, "f") && result.detectedAssets.length > 0) {
65
60
  __classPrivateFieldGet(this, _TokenDetector_onDetectionUpdate, "f").call(this, result);
66
61
  }
67
62
  }
68
- getTokensToCheck(chainId) {
69
- const tokenListState = __classPrivateFieldGet(this, _TokenDetector_messenger, "f").call('TokenListController:getState');
70
- // Defensive check for tokensChainsCache
71
- if (!tokenListState?.tokensChainsCache) {
72
- return [];
73
- }
74
- // Try direct lookup first
75
- let chainCacheEntry = tokenListState.tokensChainsCache[chainId];
76
- // If not found, try normalizing the chain ID (e.g., 0x0a -> 0xa)
77
- if (!chainCacheEntry) {
78
- const normalizedChainId = `0x${parseInt(chainId, 16).toString(16)}`;
79
- chainCacheEntry = tokenListState.tokensChainsCache[normalizedChainId];
80
- }
81
- const chainTokenList = chainCacheEntry?.data;
82
- if (!chainTokenList) {
83
- return [];
84
- }
85
- return Object.keys(chainTokenList);
63
+ /**
64
+ * Fetch the list of token addresses to check for the given chain.
65
+ * Calls the Tokens API and caches the result for metadata lookups.
66
+ *
67
+ * @param chainId - Chain ID in hex format.
68
+ * @returns Array of token contract addresses.
69
+ */
70
+ async getTokensToCheck(chainId) {
71
+ const tokenList = await __classPrivateFieldGet(this, _TokenDetector_instances, "m", _TokenDetector_fetchAndCacheTokenList).call(this, chainId);
72
+ return tokenList.map((entry) => entry.address);
86
73
  }
87
74
  async detectTokens(chainId, accountId, accountAddress, options) {
88
75
  const tokenDetectionEnabled = options?.tokenDetectionEnabled ?? __classPrivateFieldGet(this, _TokenDetector_config, "f").tokenDetectionEnabled();
@@ -101,7 +88,7 @@ class TokenDetector extends (0, polling_controller_1.StaticIntervalPollingContro
101
88
  }
102
89
  const batchSize = options?.batchSize ?? __classPrivateFieldGet(this, _TokenDetector_config, "f").defaultBatchSize;
103
90
  const timestamp = Date.now();
104
- const tokensToCheck = this.getTokensToCheck(chainId);
91
+ const tokensToCheck = await this.getTokensToCheck(chainId);
105
92
  if (tokensToCheck.length === 0) {
106
93
  return {
107
94
  chainId,
@@ -142,7 +129,11 @@ class TokenDetector extends (0, polling_controller_1.StaticIntervalPollingContro
142
129
  }
143
130
  }
144
131
  exports.TokenDetector = TokenDetector;
145
- _TokenDetector_multicallClient = new WeakMap(), _TokenDetector_messenger = new WeakMap(), _TokenDetector_config = new WeakMap(), _TokenDetector_onDetectionUpdate = new WeakMap(), _TokenDetector_instances = new WeakSet(), _TokenDetector_processBalanceResponses = function _TokenDetector_processBalanceResponses(responses, accumulator, chainId, accountId, timestamp) {
132
+ _TokenDetector_multicallClient = new WeakMap(), _TokenDetector_tokensApiClient = new WeakMap(), _TokenDetector_config = new WeakMap(), _TokenDetector_tokenListCache = new WeakMap(), _TokenDetector_onDetectionUpdate = new WeakMap(), _TokenDetector_instances = new WeakSet(), _TokenDetector_fetchAndCacheTokenList = async function _TokenDetector_fetchAndCacheTokenList(chainId) {
133
+ const list = await __classPrivateFieldGet(this, _TokenDetector_tokensApiClient, "f").fetchTokenList(chainId);
134
+ __classPrivateFieldGet(this, _TokenDetector_tokenListCache, "f").set(chainId, list);
135
+ return list;
136
+ }, _TokenDetector_processBalanceResponses = function _TokenDetector_processBalanceResponses(responses, accumulator, chainId, accountId, timestamp) {
146
137
  const { detectedAssets, detectedBalances, zeroBalanceAddresses, failedAddresses, } = accumulator;
147
138
  for (const response of responses) {
148
139
  if (!response.success) {
@@ -195,25 +186,13 @@ _TokenDetector_multicallClient = new WeakMap(), _TokenDetector_messenger = new W
195
186
  return rawBalance;
196
187
  }
197
188
  }, _TokenDetector_getTokenMetadata = function _TokenDetector_getTokenMetadata(chainId, tokenAddress) {
198
- const tokenListState = __classPrivateFieldGet(this, _TokenDetector_messenger, "f").call('TokenListController:getState');
199
- if (!tokenListState?.tokensChainsCache) {
200
- return undefined;
201
- }
202
- const chainCacheEntry = tokenListState.tokensChainsCache[chainId];
203
- const chainTokenList = chainCacheEntry?.data;
204
- if (!chainTokenList) {
205
- return undefined;
206
- }
207
- if (chainTokenList[tokenAddress]) {
208
- return chainTokenList[tokenAddress];
209
- }
189
+ const list = __classPrivateFieldGet(this, _TokenDetector_tokenListCache, "f").get(chainId) ?? [];
210
190
  const lowerAddress = tokenAddress.toLowerCase();
211
- for (const [address, metadata] of Object.entries(chainTokenList)) {
212
- if (address.toLowerCase() === lowerAddress) {
213
- return metadata;
214
- }
191
+ const exact = list.find((entry) => entry.address === tokenAddress);
192
+ if (exact) {
193
+ return exact;
215
194
  }
216
- return undefined;
195
+ return list.find((entry) => entry.address.toLowerCase() === lowerAddress);
217
196
  }, _TokenDetector_createAsset = function _TokenDetector_createAsset(chainId, tokenAddress, metadata) {
218
197
  const chainIdDecimal = parseInt(chainId, 16);
219
198
  const assetId = `eip155:${chainIdDecimal}/erc20:${tokenAddress.toLowerCase()}`;
@@ -1 +1 @@
1
- {"version":3,"file":"TokenDetector.cjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/TokenDetector.ts"],"names":[],"mappings":"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","sourcesContent":["import { StaticIntervalPollingControllerOnly } from '@metamask/polling-controller';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport type { MulticallClient } from '../clients';\nimport type {\n AccountId,\n Address,\n Asset,\n AssetBalance,\n BalanceOfRequest,\n BalanceOfResponse,\n ChainId,\n TokenDetectionOptions,\n TokenDetectionResult,\n TokenListEntry,\n TokenListState,\n} from '../types';\nimport { reduceInBatchesSerially } from '../utils';\n\nconst DEFAULT_DETECTION_INTERVAL = 180_000; // 3 minutes\n\n/**\n * Minimal messenger interface for TokenDetector.\n */\nexport type TokenDetectorMessenger = {\n call: (action: 'TokenListController:getState') => TokenListState;\n};\n\nexport type TokenDetectorConfig = {\n /** Function returning whether token detection is enabled (avoids stale value) */\n tokenDetectionEnabled?: () => boolean;\n /** Function returning whether external services are allowed (avoids stale value; default: () => true) */\n useExternalService?: () => boolean;\n defaultBatchSize?: number;\n defaultTimeoutMs?: number;\n /** Polling interval in ms (default: 3 minutes) */\n pollingInterval?: number;\n};\n\n/**\n * Polling input for TokenDetector - identifies what to poll for.\n */\nexport type DetectionPollingInput = {\n /** Chain ID (hex format) */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address */\n accountAddress: Address;\n};\n\n/**\n * Callback type for token detection updates.\n */\nexport type OnDetectionUpdateCallback = (result: TokenDetectionResult) => void;\n\n/**\n * TokenDetector - Detects tokens with non-zero balances via multicall.\n * Extends StaticIntervalPollingControllerOnly for built-in polling support.\n */\nexport class TokenDetector extends StaticIntervalPollingControllerOnly<DetectionPollingInput>() {\n readonly #multicallClient: MulticallClient;\n\n readonly #messenger: TokenDetectorMessenger;\n\n readonly #config: Required<Omit<TokenDetectorConfig, 'pollingInterval'>>;\n\n #onDetectionUpdate: OnDetectionUpdateCallback | undefined;\n\n constructor(\n multicallClient: MulticallClient,\n messenger: TokenDetectorMessenger,\n config?: TokenDetectorConfig,\n ) {\n super();\n this.#multicallClient = multicallClient;\n this.#messenger = messenger;\n this.#config = {\n tokenDetectionEnabled:\n config?.tokenDetectionEnabled ?? ((): boolean => true),\n useExternalService: config?.useExternalService ?? ((): boolean => true),\n defaultBatchSize: config?.defaultBatchSize ?? 300,\n defaultTimeoutMs: config?.defaultTimeoutMs ?? 30000,\n };\n\n // Set the polling interval\n this.setIntervalLength(\n config?.pollingInterval ?? DEFAULT_DETECTION_INTERVAL,\n );\n }\n\n /**\n * Set the callback to receive detection updates during polling.\n *\n * @param callback - Function to call with detection results.\n */\n setOnDetectionUpdate(callback: OnDetectionUpdateCallback): void {\n this.#onDetectionUpdate = callback;\n }\n\n /**\n * Execute a poll cycle (required by base class).\n * Detects tokens and calls the update callback.\n *\n * @param input - The polling input.\n */\n async _executePoll(input: DetectionPollingInput): Promise<void> {\n // Check if token list is available for this chain\n const tokensToCheck = this.getTokensToCheck(input.chainId);\n\n if (tokensToCheck.length === 0) {\n // No tokens in list for chain, will retry on next poll\n return;\n }\n\n const result = await this.detectTokens(\n input.chainId,\n input.accountId,\n input.accountAddress,\n );\n\n if (this.#onDetectionUpdate && result.detectedAssets.length > 0) {\n this.#onDetectionUpdate(result);\n }\n }\n\n getTokensToCheck(chainId: ChainId): Address[] {\n const tokenListState = this.#messenger.call('TokenListController:getState');\n\n // Defensive check for tokensChainsCache\n if (!tokenListState?.tokensChainsCache) {\n return [];\n }\n\n // Try direct lookup first\n let chainCacheEntry = tokenListState.tokensChainsCache[chainId];\n\n // If not found, try normalizing the chain ID (e.g., 0x0a -> 0xa)\n if (!chainCacheEntry) {\n const normalizedChainId: ChainId = `0x${parseInt(chainId, 16).toString(\n 16,\n )}`;\n chainCacheEntry = tokenListState.tokensChainsCache[normalizedChainId];\n }\n\n const chainTokenList = chainCacheEntry?.data;\n\n if (!chainTokenList) {\n return [];\n }\n\n return Object.keys(chainTokenList) as Address[];\n }\n\n async detectTokens(\n chainId: ChainId,\n accountId: AccountId,\n accountAddress: Address,\n options?: TokenDetectionOptions,\n ): Promise<TokenDetectionResult> {\n const tokenDetectionEnabled =\n options?.tokenDetectionEnabled ?? this.#config.tokenDetectionEnabled();\n const useExternalService =\n options?.useExternalService ?? this.#config.useExternalService();\n if (!tokenDetectionEnabled || !useExternalService) {\n return {\n chainId,\n accountId,\n accountAddress,\n detectedAssets: [],\n detectedBalances: [],\n zeroBalanceAddresses: [],\n failedAddresses: [],\n timestamp: Date.now(),\n };\n }\n const batchSize = options?.batchSize ?? this.#config.defaultBatchSize;\n const timestamp = Date.now();\n\n const tokensToCheck = this.getTokensToCheck(chainId);\n\n if (tokensToCheck.length === 0) {\n return {\n chainId,\n accountId,\n accountAddress,\n detectedAssets: [],\n detectedBalances: [],\n zeroBalanceAddresses: [],\n failedAddresses: [],\n timestamp,\n };\n }\n\n const balanceRequests: BalanceOfRequest[] = tokensToCheck.map(\n (tokenAddress) => ({\n tokenAddress,\n accountAddress,\n }),\n );\n\n type DetectionAccumulator = {\n detectedAssets: Asset[];\n detectedBalances: AssetBalance[];\n zeroBalanceAddresses: Address[];\n failedAddresses: Address[];\n };\n\n const result = await reduceInBatchesSerially<\n BalanceOfRequest,\n DetectionAccumulator\n >({\n values: balanceRequests,\n batchSize,\n initialResult: {\n detectedAssets: [],\n detectedBalances: [],\n zeroBalanceAddresses: [],\n failedAddresses: [],\n },\n eachBatch: async (workingResult, batch) => {\n const responses = await this.#multicallClient.batchBalanceOf(\n chainId,\n batch,\n );\n\n return this.#processBalanceResponses(\n responses,\n workingResult as DetectionAccumulator,\n chainId,\n accountId,\n timestamp,\n );\n },\n });\n\n return {\n chainId,\n accountId,\n accountAddress,\n ...result,\n timestamp,\n };\n }\n\n #processBalanceResponses(\n responses: BalanceOfResponse[],\n accumulator: {\n detectedAssets: Asset[];\n detectedBalances: AssetBalance[];\n zeroBalanceAddresses: Address[];\n failedAddresses: Address[];\n },\n chainId: ChainId,\n accountId: AccountId,\n timestamp: number,\n ): {\n detectedAssets: Asset[];\n detectedBalances: AssetBalance[];\n zeroBalanceAddresses: Address[];\n failedAddresses: Address[];\n } {\n const {\n detectedAssets,\n detectedBalances,\n zeroBalanceAddresses,\n failedAddresses,\n } = accumulator;\n\n for (const response of responses) {\n if (!response.success) {\n failedAddresses.push(response.tokenAddress);\n continue;\n }\n\n const balance = response.balance ?? '0';\n\n if (balance === '0' || balance === '') {\n zeroBalanceAddresses.push(response.tokenAddress);\n continue;\n }\n\n const tokenMetadata = this.#getTokenMetadata(\n chainId,\n response.tokenAddress,\n );\n\n const asset = this.#createAsset(\n chainId,\n response.tokenAddress,\n tokenMetadata,\n );\n detectedAssets.push(asset);\n\n if (tokenMetadata?.decimals === undefined) {\n continue;\n }\n\n const { decimals } = tokenMetadata;\n const formattedBalance = this.#formatBalance(balance, decimals);\n\n detectedBalances.push({\n assetId: asset.assetId,\n accountId,\n chainId,\n balance,\n formattedBalance,\n decimals,\n timestamp,\n });\n }\n\n return {\n detectedAssets,\n detectedBalances,\n zeroBalanceAddresses,\n failedAddresses,\n };\n }\n\n #formatBalance(rawBalance: string, decimals: number): string {\n try {\n const balanceBigInt = BigInt(rawBalance);\n const divisor = BigInt(10 ** decimals);\n\n const integerPart = balanceBigInt / divisor;\n const remainder = balanceBigInt % divisor;\n const fractionalStr = remainder.toString().padStart(decimals, '0');\n const trimmedFractional = fractionalStr.replace(/0+$/u, '');\n\n if (trimmedFractional === '') {\n return integerPart.toString();\n }\n\n return `${integerPart}.${trimmedFractional}`;\n } catch {\n return rawBalance;\n }\n }\n\n #getTokenMetadata(\n chainId: ChainId,\n tokenAddress: Address,\n ): TokenListEntry | undefined {\n const tokenListState = this.#messenger.call('TokenListController:getState');\n if (!tokenListState?.tokensChainsCache) {\n return undefined;\n }\n\n const chainCacheEntry = tokenListState.tokensChainsCache[chainId];\n const chainTokenList = chainCacheEntry?.data;\n if (!chainTokenList) {\n return undefined;\n }\n\n if (chainTokenList[tokenAddress]) {\n return chainTokenList[tokenAddress];\n }\n\n const lowerAddress = tokenAddress.toLowerCase();\n for (const [address, metadata] of Object.entries(chainTokenList)) {\n if (address.toLowerCase() === lowerAddress) {\n return metadata;\n }\n }\n\n return undefined;\n }\n\n #createAsset(\n chainId: ChainId,\n tokenAddress: Address,\n metadata: TokenListEntry | undefined,\n ): Asset {\n const chainIdDecimal = parseInt(chainId, 16);\n\n const assetId =\n `eip155:${chainIdDecimal}/erc20:${tokenAddress.toLowerCase()}` as CaipAssetType;\n\n return {\n assetId,\n chainId,\n address: tokenAddress,\n type: 'erc20',\n symbol: metadata?.symbol,\n name: metadata?.name,\n decimals: metadata?.decimals,\n image: metadata?.iconUrl,\n isNative: false,\n aggregators: metadata?.aggregators,\n };\n }\n}\n"]}
1
+ {"version":3,"file":"TokenDetector.cjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/TokenDetector.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,qEAAmF;AAiBnF,8CAAmD;AAEnD,MAAM,0BAA0B,GAAG,MAAO,CAAC,CAAC,YAAY;AA8BxD;;;;GAIG;AACH,MAAa,aAAc,SAAQ,IAAA,wDAAmC,GAAyB;IAW7F,YACE,eAAgC,EAChC,eAAgC,EAChC,MAA4B;QAE5B,KAAK,EAAE,CAAC;;QAfD,iDAAkC;QAElC,iDAAkC;QAElC,wCAAgE;QAEhE,wCAAkD,IAAI,GAAG,EAAE,EAAC;QAErE,mDAA0D;QAQxD,uBAAA,IAAI,kCAAoB,eAAe,MAAA,CAAC;QACxC,uBAAA,IAAI,kCAAoB,eAAe,MAAA,CAAC;QACxC,uBAAA,IAAI,yBAAW;YACb,qBAAqB,EACnB,MAAM,EAAE,qBAAqB,IAAI,CAAC,GAAY,EAAE,CAAC,IAAI,CAAC;YACxD,kBAAkB,EAAE,MAAM,EAAE,kBAAkB,IAAI,CAAC,GAAY,EAAE,CAAC,IAAI,CAAC;YACvE,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,IAAI,GAAG;YACjD,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,IAAI,KAAK;SACpD,MAAA,CAAC;QAEF,IAAI,CAAC,iBAAiB,CACpB,MAAM,EAAE,eAAe,IAAI,0BAA0B,CACtD,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,oBAAoB,CAAC,QAAmC;QACtD,uBAAA,IAAI,oCAAsB,QAAQ,MAAA,CAAC;IACrC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,YAAY,CAAC,KAA4B;QAC7C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CACpC,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,cAAc,CACrB,CAAC;QAEF,IAAI,uBAAA,IAAI,wCAAmB,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChE,uBAAA,IAAI,wCAAmB,MAAvB,IAAI,EAAoB,MAAM,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,gBAAgB,CAAC,OAAgB;QACrC,MAAM,SAAS,GAAG,MAAM,uBAAA,IAAI,uEAAwB,MAA5B,IAAI,EAAyB,OAAO,CAAC,CAAC;QAC9D,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAkB,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,OAAgB,EAChB,SAAoB,EACpB,cAAuB,EACvB,OAA+B;QAE/B,MAAM,qBAAqB,GACzB,OAAO,EAAE,qBAAqB,IAAI,uBAAA,IAAI,6BAAQ,CAAC,qBAAqB,EAAE,CAAC;QACzE,MAAM,kBAAkB,GACtB,OAAO,EAAE,kBAAkB,IAAI,uBAAA,IAAI,6BAAQ,CAAC,kBAAkB,EAAE,CAAC;QACnE,IAAI,CAAC,qBAAqB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAClD,OAAO;gBACL,OAAO;gBACP,SAAS;gBACT,cAAc;gBACd,cAAc,EAAE,EAAE;gBAClB,gBAAgB,EAAE,EAAE;gBACpB,oBAAoB,EAAE,EAAE;gBACxB,eAAe,EAAE,EAAE;gBACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC;QACJ,CAAC;QACD,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,uBAAA,IAAI,6BAAQ,CAAC,gBAAgB,CAAC;QACtE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAE3D,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO;gBACL,OAAO;gBACP,SAAS;gBACT,cAAc;gBACd,cAAc,EAAE,EAAE;gBAClB,gBAAgB,EAAE,EAAE;gBACpB,oBAAoB,EAAE,EAAE;gBACxB,eAAe,EAAE,EAAE;gBACnB,SAAS;aACV,CAAC;QACJ,CAAC;QAED,MAAM,eAAe,GAAuB,aAAa,CAAC,GAAG,CAC3D,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YACjB,YAAY;YACZ,cAAc;SACf,CAAC,CACH,CAAC;QASF,MAAM,MAAM,GAAG,MAAM,IAAA,+BAAuB,EAG1C;YACA,MAAM,EAAE,eAAe;YACvB,SAAS;YACT,aAAa,EAAE;gBACb,cAAc,EAAE,EAAE;gBAClB,gBAAgB,EAAE,EAAE;gBACpB,oBAAoB,EAAE,EAAE;gBACxB,eAAe,EAAE,EAAE;aACpB;YACD,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE;gBACxC,MAAM,SAAS,GAAG,MAAM,uBAAA,IAAI,sCAAiB,CAAC,cAAc,CAC1D,OAAO,EACP,KAAK,CACN,CAAC;gBAEF,OAAO,uBAAA,IAAI,wEAAyB,MAA7B,IAAI,EACT,SAAS,EACT,aAAqC,EACrC,OAAO,EACP,SAAS,EACT,SAAS,CACV,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;QAEH,OAAO;YACL,OAAO;YACP,SAAS;YACT,cAAc;YACd,GAAG,MAAM;YACT,SAAS;SACV,CAAC;IACJ,CAAC;CA6IF;AA7SD,sCA6SC;0TA3IC,KAAK,gDAAyB,OAAgB;IAC5C,MAAM,IAAI,GAAG,MAAM,uBAAA,IAAI,sCAAiB,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IACjE,uBAAA,IAAI,qCAAgB,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC,2FAGC,SAA8B,EAC9B,WAKC,EACD,OAAgB,EAChB,SAAoB,EACpB,SAAiB;IAOjB,MAAM,EACJ,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,GAAG,WAAW,CAAC;IAEhB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtB,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;YAC5C,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,IAAI,GAAG,CAAC;QAExC,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;YACtC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;YACjD,SAAS;QACX,CAAC;QAED,MAAM,aAAa,GAAG,uBAAA,IAAI,iEAAkB,MAAtB,IAAI,EACxB,OAAO,EACP,QAAQ,CAAC,YAAY,CACtB,CAAC;QAEF,MAAM,KAAK,GAAG,uBAAA,IAAI,4DAAa,MAAjB,IAAI,EAChB,OAAO,EACP,QAAQ,CAAC,YAAY,EACrB,aAAa,CACd,CAAC;QACF,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE3B,IAAI,aAAa,EAAE,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC1C,SAAS;QACX,CAAC;QAED,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC;QACnC,MAAM,gBAAgB,GAAG,uBAAA,IAAI,8DAAe,MAAnB,IAAI,EAAgB,OAAO,EAAE,QAAQ,CAAC,CAAC;QAEhE,gBAAgB,CAAC,IAAI,CAAC;YACpB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS;YACT,OAAO;YACP,OAAO;YACP,gBAAgB;YAChB,QAAQ;YACR,SAAS;SACV,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,cAAc;QACd,gBAAgB;QAChB,oBAAoB;QACpB,eAAe;KAChB,CAAC;AACJ,CAAC,uEAEc,UAAkB,EAAE,QAAgB;IACjD,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,IAAI,QAAQ,CAAC,CAAC;QAEvC,MAAM,WAAW,GAAG,aAAa,GAAG,OAAO,CAAC;QAC5C,MAAM,SAAS,GAAG,aAAa,GAAG,OAAO,CAAC;QAC1C,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACnE,MAAM,iBAAiB,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAE5D,IAAI,iBAAiB,KAAK,EAAE,EAAE,CAAC;YAC7B,OAAO,WAAW,CAAC,QAAQ,EAAE,CAAC;QAChC,CAAC;QAED,OAAO,GAAG,WAAW,IAAI,iBAAiB,EAAE,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,UAAU,CAAC;IACpB,CAAC;AACH,CAAC,6EAGC,OAAgB,EAChB,YAAqB;IAErB,MAAM,IAAI,GAAG,uBAAA,IAAI,qCAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACrD,MAAM,YAAY,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;IAEhD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,KAAK,YAAY,CAAC,CAAC;IACnE,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,YAAY,CAAC,CAAC;AAC5E,CAAC,mEAGC,OAAgB,EAChB,YAAqB,EACrB,QAAoC;IAEpC,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAE7C,MAAM,OAAO,GACX,UAAU,cAAc,UAAU,YAAY,CAAC,WAAW,EAAE,EAAmB,CAAC;IAElF,OAAO;QACL,OAAO;QACP,OAAO;QACP,OAAO,EAAE,YAAY;QACrB,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,QAAQ,EAAE,MAAM;QACxB,IAAI,EAAE,QAAQ,EAAE,IAAI;QACpB,QAAQ,EAAE,QAAQ,EAAE,QAAQ;QAC5B,KAAK,EAAE,QAAQ,EAAE,OAAO;QACxB,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,QAAQ,EAAE,WAAW;KACnC,CAAC;AACJ,CAAC","sourcesContent":["import { StaticIntervalPollingControllerOnly } from '@metamask/polling-controller';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport type { MulticallClient } from '../clients';\nimport type { TokensApiClient } from '../clients/TokensApiClient';\nimport type {\n AccountId,\n Address,\n Asset,\n AssetBalance,\n BalanceOfRequest,\n BalanceOfResponse,\n ChainId,\n TokenDetectionOptions,\n TokenDetectionResult,\n TokenListEntry,\n} from '../types';\nimport { reduceInBatchesSerially } from '../utils';\n\nconst DEFAULT_DETECTION_INTERVAL = 180_000; // 3 minutes\n\nexport type TokenDetectorConfig = {\n /** Function returning whether token detection is enabled (avoids stale value) */\n tokenDetectionEnabled?: () => boolean;\n /** Function returning whether external services are allowed (avoids stale value; default: () => true) */\n useExternalService?: () => boolean;\n defaultBatchSize?: number;\n defaultTimeoutMs?: number;\n /** Polling interval in ms (default: 3 minutes) */\n pollingInterval?: number;\n};\n\n/**\n * Polling input for TokenDetector - identifies what to poll for.\n */\nexport type DetectionPollingInput = {\n /** Chain ID (hex format) */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address */\n accountAddress: Address;\n};\n\n/**\n * Callback type for token detection updates.\n */\nexport type OnDetectionUpdateCallback = (result: TokenDetectionResult) => void;\n\n/**\n * TokenDetector - Detects tokens with non-zero balances via multicall.\n * Fetches the token list from the Tokens API and uses multicall to check balances.\n * Extends StaticIntervalPollingControllerOnly for built-in polling support.\n */\nexport class TokenDetector extends StaticIntervalPollingControllerOnly<DetectionPollingInput>() {\n readonly #multicallClient: MulticallClient;\n\n readonly #tokensApiClient: TokensApiClient;\n\n readonly #config: Required<Omit<TokenDetectorConfig, 'pollingInterval'>>;\n\n readonly #tokenListCache: Map<ChainId, TokenListEntry[]> = new Map();\n\n #onDetectionUpdate: OnDetectionUpdateCallback | undefined;\n\n constructor(\n multicallClient: MulticallClient,\n tokensApiClient: TokensApiClient,\n config?: TokenDetectorConfig,\n ) {\n super();\n this.#multicallClient = multicallClient;\n this.#tokensApiClient = tokensApiClient;\n this.#config = {\n tokenDetectionEnabled:\n config?.tokenDetectionEnabled ?? ((): boolean => true),\n useExternalService: config?.useExternalService ?? ((): boolean => true),\n defaultBatchSize: config?.defaultBatchSize ?? 300,\n defaultTimeoutMs: config?.defaultTimeoutMs ?? 30000,\n };\n\n this.setIntervalLength(\n config?.pollingInterval ?? DEFAULT_DETECTION_INTERVAL,\n );\n }\n\n /**\n * Set the callback to receive detection updates during polling.\n *\n * @param callback - Function to call with detection results.\n */\n setOnDetectionUpdate(callback: OnDetectionUpdateCallback): void {\n this.#onDetectionUpdate = callback;\n }\n\n /**\n * Execute a poll cycle (required by base class).\n * Detects tokens and calls the update callback.\n *\n * @param input - The polling input.\n */\n async _executePoll(input: DetectionPollingInput): Promise<void> {\n const result = await this.detectTokens(\n input.chainId,\n input.accountId,\n input.accountAddress,\n );\n\n if (this.#onDetectionUpdate && result.detectedAssets.length > 0) {\n this.#onDetectionUpdate(result);\n }\n }\n\n /**\n * Fetch the list of token addresses to check for the given chain.\n * Calls the Tokens API and caches the result for metadata lookups.\n *\n * @param chainId - Chain ID in hex format.\n * @returns Array of token contract addresses.\n */\n async getTokensToCheck(chainId: ChainId): Promise<Address[]> {\n const tokenList = await this.#fetchAndCacheTokenList(chainId);\n return tokenList.map((entry) => entry.address as Address);\n }\n\n async detectTokens(\n chainId: ChainId,\n accountId: AccountId,\n accountAddress: Address,\n options?: TokenDetectionOptions,\n ): Promise<TokenDetectionResult> {\n const tokenDetectionEnabled =\n options?.tokenDetectionEnabled ?? this.#config.tokenDetectionEnabled();\n const useExternalService =\n options?.useExternalService ?? this.#config.useExternalService();\n if (!tokenDetectionEnabled || !useExternalService) {\n return {\n chainId,\n accountId,\n accountAddress,\n detectedAssets: [],\n detectedBalances: [],\n zeroBalanceAddresses: [],\n failedAddresses: [],\n timestamp: Date.now(),\n };\n }\n const batchSize = options?.batchSize ?? this.#config.defaultBatchSize;\n const timestamp = Date.now();\n\n const tokensToCheck = await this.getTokensToCheck(chainId);\n\n if (tokensToCheck.length === 0) {\n return {\n chainId,\n accountId,\n accountAddress,\n detectedAssets: [],\n detectedBalances: [],\n zeroBalanceAddresses: [],\n failedAddresses: [],\n timestamp,\n };\n }\n\n const balanceRequests: BalanceOfRequest[] = tokensToCheck.map(\n (tokenAddress) => ({\n tokenAddress,\n accountAddress,\n }),\n );\n\n type DetectionAccumulator = {\n detectedAssets: Asset[];\n detectedBalances: AssetBalance[];\n zeroBalanceAddresses: Address[];\n failedAddresses: Address[];\n };\n\n const result = await reduceInBatchesSerially<\n BalanceOfRequest,\n DetectionAccumulator\n >({\n values: balanceRequests,\n batchSize,\n initialResult: {\n detectedAssets: [],\n detectedBalances: [],\n zeroBalanceAddresses: [],\n failedAddresses: [],\n },\n eachBatch: async (workingResult, batch) => {\n const responses = await this.#multicallClient.batchBalanceOf(\n chainId,\n batch,\n );\n\n return this.#processBalanceResponses(\n responses,\n workingResult as DetectionAccumulator,\n chainId,\n accountId,\n timestamp,\n );\n },\n });\n\n return {\n chainId,\n accountId,\n accountAddress,\n ...result,\n timestamp,\n };\n }\n\n async #fetchAndCacheTokenList(chainId: ChainId): Promise<TokenListEntry[]> {\n const list = await this.#tokensApiClient.fetchTokenList(chainId);\n this.#tokenListCache.set(chainId, list);\n return list;\n }\n\n #processBalanceResponses(\n responses: BalanceOfResponse[],\n accumulator: {\n detectedAssets: Asset[];\n detectedBalances: AssetBalance[];\n zeroBalanceAddresses: Address[];\n failedAddresses: Address[];\n },\n chainId: ChainId,\n accountId: AccountId,\n timestamp: number,\n ): {\n detectedAssets: Asset[];\n detectedBalances: AssetBalance[];\n zeroBalanceAddresses: Address[];\n failedAddresses: Address[];\n } {\n const {\n detectedAssets,\n detectedBalances,\n zeroBalanceAddresses,\n failedAddresses,\n } = accumulator;\n\n for (const response of responses) {\n if (!response.success) {\n failedAddresses.push(response.tokenAddress);\n continue;\n }\n\n const balance = response.balance ?? '0';\n\n if (balance === '0' || balance === '') {\n zeroBalanceAddresses.push(response.tokenAddress);\n continue;\n }\n\n const tokenMetadata = this.#getTokenMetadata(\n chainId,\n response.tokenAddress,\n );\n\n const asset = this.#createAsset(\n chainId,\n response.tokenAddress,\n tokenMetadata,\n );\n detectedAssets.push(asset);\n\n if (tokenMetadata?.decimals === undefined) {\n continue;\n }\n\n const { decimals } = tokenMetadata;\n const formattedBalance = this.#formatBalance(balance, decimals);\n\n detectedBalances.push({\n assetId: asset.assetId,\n accountId,\n chainId,\n balance,\n formattedBalance,\n decimals,\n timestamp,\n });\n }\n\n return {\n detectedAssets,\n detectedBalances,\n zeroBalanceAddresses,\n failedAddresses,\n };\n }\n\n #formatBalance(rawBalance: string, decimals: number): string {\n try {\n const balanceBigInt = BigInt(rawBalance);\n const divisor = BigInt(10 ** decimals);\n\n const integerPart = balanceBigInt / divisor;\n const remainder = balanceBigInt % divisor;\n const fractionalStr = remainder.toString().padStart(decimals, '0');\n const trimmedFractional = fractionalStr.replace(/0+$/u, '');\n\n if (trimmedFractional === '') {\n return integerPart.toString();\n }\n\n return `${integerPart}.${trimmedFractional}`;\n } catch {\n return rawBalance;\n }\n }\n\n #getTokenMetadata(\n chainId: ChainId,\n tokenAddress: Address,\n ): TokenListEntry | undefined {\n const list = this.#tokenListCache.get(chainId) ?? [];\n const lowerAddress = tokenAddress.toLowerCase();\n\n const exact = list.find((entry) => entry.address === tokenAddress);\n if (exact) {\n return exact;\n }\n\n return list.find((entry) => entry.address.toLowerCase() === lowerAddress);\n }\n\n #createAsset(\n chainId: ChainId,\n tokenAddress: Address,\n metadata: TokenListEntry | undefined,\n ): Asset {\n const chainIdDecimal = parseInt(chainId, 16);\n\n const assetId =\n `eip155:${chainIdDecimal}/erc20:${tokenAddress.toLowerCase()}` as CaipAssetType;\n\n return {\n assetId,\n chainId,\n address: tokenAddress,\n type: 'erc20',\n symbol: metadata?.symbol,\n name: metadata?.name,\n decimals: metadata?.decimals,\n image: metadata?.iconUrl,\n isNative: false,\n aggregators: metadata?.aggregators,\n };\n }\n}\n"]}
@@ -1,11 +1,6 @@
1
1
  import type { MulticallClient } from "../clients/index.cjs";
2
- import type { AccountId, Address, ChainId, TokenDetectionOptions, TokenDetectionResult, TokenListState } from "../types/index.cjs";
3
- /**
4
- * Minimal messenger interface for TokenDetector.
5
- */
6
- export type TokenDetectorMessenger = {
7
- call: (action: 'TokenListController:getState') => TokenListState;
8
- };
2
+ import type { TokensApiClient } from "../clients/TokensApiClient.cjs";
3
+ import type { AccountId, Address, ChainId, TokenDetectionOptions, TokenDetectionResult } from "../types/index.cjs";
9
4
  export type TokenDetectorConfig = {
10
5
  /** Function returning whether token detection is enabled (avoids stale value) */
11
6
  tokenDetectionEnabled?: () => boolean;
@@ -50,11 +45,12 @@ declare const TokenDetector_base: (abstract new (...args: any[]) => {
50
45
  };
51
46
  /**
52
47
  * TokenDetector - Detects tokens with non-zero balances via multicall.
48
+ * Fetches the token list from the Tokens API and uses multicall to check balances.
53
49
  * Extends StaticIntervalPollingControllerOnly for built-in polling support.
54
50
  */
55
51
  export declare class TokenDetector extends TokenDetector_base {
56
52
  #private;
57
- constructor(multicallClient: MulticallClient, messenger: TokenDetectorMessenger, config?: TokenDetectorConfig);
53
+ constructor(multicallClient: MulticallClient, tokensApiClient: TokensApiClient, config?: TokenDetectorConfig);
58
54
  /**
59
55
  * Set the callback to receive detection updates during polling.
60
56
  *
@@ -68,7 +64,14 @@ export declare class TokenDetector extends TokenDetector_base {
68
64
  * @param input - The polling input.
69
65
  */
70
66
  _executePoll(input: DetectionPollingInput): Promise<void>;
71
- getTokensToCheck(chainId: ChainId): Address[];
67
+ /**
68
+ * Fetch the list of token addresses to check for the given chain.
69
+ * Calls the Tokens API and caches the result for metadata lookups.
70
+ *
71
+ * @param chainId - Chain ID in hex format.
72
+ * @returns Array of token contract addresses.
73
+ */
74
+ getTokensToCheck(chainId: ChainId): Promise<Address[]>;
72
75
  detectTokens(chainId: ChainId, accountId: AccountId, accountAddress: Address, options?: TokenDetectionOptions): Promise<TokenDetectionResult>;
73
76
  }
74
77
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"TokenDetector.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/TokenDetector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,6BAAmB;AAClD,OAAO,KAAK,EACV,SAAS,EACT,OAAO,EAKP,OAAO,EACP,qBAAqB,EACrB,oBAAoB,EAEpB,cAAc,EACf,2BAAiB;AAKlB;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,CAAC,MAAM,EAAE,8BAA8B,KAAK,cAAc,CAAC;CAClE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,iFAAiF;IACjF,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC;IACtC,yGAAyG;IACzG,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,sBAAsB;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;;;;;;;;;;;;;;;;;;AAE/E;;;GAGG;AACH,qBAAa,aAAc,SAAQ,kBAA4D;;gBAU3F,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,sBAAsB,EACjC,MAAM,CAAC,EAAE,mBAAmB;IAmB9B;;;;OAIG;IACH,oBAAoB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI;IAI/D;;;;;OAKG;IACG,YAAY,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB/D,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE;IA4BvC,YAAY,CAChB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,CAAC;CAyOjC"}
1
+ {"version":3,"file":"TokenDetector.d.cts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/TokenDetector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,6BAAmB;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAmC;AAClE,OAAO,KAAK,EACV,SAAS,EACT,OAAO,EAKP,OAAO,EACP,qBAAqB,EACrB,oBAAoB,EAErB,2BAAiB;AAKlB,MAAM,MAAM,mBAAmB,GAAG;IAChC,iFAAiF;IACjF,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC;IACtC,yGAAyG;IACzG,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,sBAAsB;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;;;;;;;;;;;;;;;;;;AAE/E;;;;GAIG;AACH,qBAAa,aAAc,SAAQ,kBAA4D;;gBAY3F,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,eAAe,EAChC,MAAM,CAAC,EAAE,mBAAmB;IAkB9B;;;;OAIG;IACH,oBAAoB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI;IAI/D;;;;;OAKG;IACG,YAAY,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/D;;;;;;OAMG;IACG,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAKtD,YAAY,CAChB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,CAAC;CAiOjC"}
@@ -1,11 +1,6 @@
1
1
  import type { MulticallClient } from "../clients/index.mjs";
2
- import type { AccountId, Address, ChainId, TokenDetectionOptions, TokenDetectionResult, TokenListState } from "../types/index.mjs";
3
- /**
4
- * Minimal messenger interface for TokenDetector.
5
- */
6
- export type TokenDetectorMessenger = {
7
- call: (action: 'TokenListController:getState') => TokenListState;
8
- };
2
+ import type { TokensApiClient } from "../clients/TokensApiClient.mjs";
3
+ import type { AccountId, Address, ChainId, TokenDetectionOptions, TokenDetectionResult } from "../types/index.mjs";
9
4
  export type TokenDetectorConfig = {
10
5
  /** Function returning whether token detection is enabled (avoids stale value) */
11
6
  tokenDetectionEnabled?: () => boolean;
@@ -50,11 +45,12 @@ declare const TokenDetector_base: (abstract new (...args: any[]) => {
50
45
  };
51
46
  /**
52
47
  * TokenDetector - Detects tokens with non-zero balances via multicall.
48
+ * Fetches the token list from the Tokens API and uses multicall to check balances.
53
49
  * Extends StaticIntervalPollingControllerOnly for built-in polling support.
54
50
  */
55
51
  export declare class TokenDetector extends TokenDetector_base {
56
52
  #private;
57
- constructor(multicallClient: MulticallClient, messenger: TokenDetectorMessenger, config?: TokenDetectorConfig);
53
+ constructor(multicallClient: MulticallClient, tokensApiClient: TokensApiClient, config?: TokenDetectorConfig);
58
54
  /**
59
55
  * Set the callback to receive detection updates during polling.
60
56
  *
@@ -68,7 +64,14 @@ export declare class TokenDetector extends TokenDetector_base {
68
64
  * @param input - The polling input.
69
65
  */
70
66
  _executePoll(input: DetectionPollingInput): Promise<void>;
71
- getTokensToCheck(chainId: ChainId): Address[];
67
+ /**
68
+ * Fetch the list of token addresses to check for the given chain.
69
+ * Calls the Tokens API and caches the result for metadata lookups.
70
+ *
71
+ * @param chainId - Chain ID in hex format.
72
+ * @returns Array of token contract addresses.
73
+ */
74
+ getTokensToCheck(chainId: ChainId): Promise<Address[]>;
72
75
  detectTokens(chainId: ChainId, accountId: AccountId, accountAddress: Address, options?: TokenDetectionOptions): Promise<TokenDetectionResult>;
73
76
  }
74
77
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"TokenDetector.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/TokenDetector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,6BAAmB;AAClD,OAAO,KAAK,EACV,SAAS,EACT,OAAO,EAKP,OAAO,EACP,qBAAqB,EACrB,oBAAoB,EAEpB,cAAc,EACf,2BAAiB;AAKlB;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,CAAC,MAAM,EAAE,8BAA8B,KAAK,cAAc,CAAC;CAClE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,iFAAiF;IACjF,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC;IACtC,yGAAyG;IACzG,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,sBAAsB;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;;;;;;;;;;;;;;;;;;AAE/E;;;GAGG;AACH,qBAAa,aAAc,SAAQ,kBAA4D;;gBAU3F,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,sBAAsB,EACjC,MAAM,CAAC,EAAE,mBAAmB;IAmB9B;;;;OAIG;IACH,oBAAoB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI;IAI/D;;;;;OAKG;IACG,YAAY,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB/D,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE;IA4BvC,YAAY,CAChB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,CAAC;CAyOjC"}
1
+ {"version":3,"file":"TokenDetector.d.mts","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/TokenDetector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,6BAAmB;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAmC;AAClE,OAAO,KAAK,EACV,SAAS,EACT,OAAO,EAKP,OAAO,EACP,qBAAqB,EACrB,oBAAoB,EAErB,2BAAiB;AAKlB,MAAM,MAAM,mBAAmB,GAAG;IAChC,iFAAiF;IACjF,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC;IACtC,yGAAyG;IACzG,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,4BAA4B;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,sBAAsB;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;;;;;;;;;;;;;;;;;;AAE/E;;;;GAIG;AACH,qBAAa,aAAc,SAAQ,kBAA4D;;gBAY3F,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,eAAe,EAChC,MAAM,CAAC,EAAE,mBAAmB;IAkB9B;;;;OAIG;IACH,oBAAoB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI;IAI/D;;;;;OAKG;IACG,YAAY,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/D;;;;;;OAMG;IACG,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAKtD,YAAY,CAChB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,CAAC;CAiOjC"}