@metamask-previews/assets-controller 2.0.2-preview-980f677 → 2.0.2-preview-567bc78af
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -1
- package/dist/AssetsController-method-action-types.cjs.map +1 -1
- package/dist/AssetsController-method-action-types.d.cts +5 -0
- package/dist/AssetsController-method-action-types.d.cts.map +1 -1
- package/dist/AssetsController-method-action-types.d.mts +5 -0
- package/dist/AssetsController-method-action-types.d.mts.map +1 -1
- package/dist/AssetsController-method-action-types.mjs.map +1 -1
- package/dist/AssetsController.cjs +30 -2
- package/dist/AssetsController.cjs.map +1 -1
- package/dist/AssetsController.d.cts +21 -1
- package/dist/AssetsController.d.cts.map +1 -1
- package/dist/AssetsController.d.mts +21 -1
- package/dist/AssetsController.d.mts.map +1 -1
- package/dist/AssetsController.mjs +30 -2
- package/dist/AssetsController.mjs.map +1 -1
- package/dist/data-sources/TokenDataSource.cjs +1 -0
- package/dist/data-sources/TokenDataSource.cjs.map +1 -1
- package/dist/data-sources/TokenDataSource.d.cts.map +1 -1
- package/dist/data-sources/TokenDataSource.d.mts.map +1 -1
- package/dist/data-sources/TokenDataSource.mjs +1 -0
- package/dist/data-sources/TokenDataSource.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.cjs +44 -27
- package/dist/middlewares/DetectionMiddleware.cjs.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.cts +15 -9
- package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.d.mts +15 -9
- package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -1
- package/dist/middlewares/DetectionMiddleware.mjs +44 -27
- package/dist/middlewares/DetectionMiddleware.mjs.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenDataSource.cjs","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import type { V3AssetResponse } from '@metamask/core-backend';\nimport { ApiPlatformClient } from '@metamask/core-backend';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport { isStakingContractAssetId } from './evm-rpc-services';\nimport { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type {\n Caip19AssetId,\n AssetMetadata,\n Middleware,\n FungibleAssetMetadata,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'TokenDataSource';\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n/**\n * TokenDataSource does not call external messenger actions.\n * It uses ApiPlatformClient directly.\n */\nexport type TokenDataSourceAllowedActions = never;\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type TokenDataSourceOptions = {\n /** ApiPlatformClient for API calls with caching */\n queryApiClient: ApiPlatformClient;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Transform V3 API response to FungibleAssetMetadata for state storage.\n *\n * Mapping:\n * - assetId → used to derive `type` (native/erc20/spl)\n * - iconUrl → image\n * - All other fields map directly\n *\n * @param assetId - CAIP-19 asset ID used to derive token type.\n * @param assetData - V3 API response data.\n * @returns FungibleAssetMetadata for state storage.\n */\nfunction transformV3AssetResponseToMetadata(\n assetId: string,\n assetData: V3AssetResponse,\n): AssetMetadata {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n let tokenType: 'native' | 'erc20' | 'spl' = 'erc20';\n\n if (parsed.assetNamespace === 'slip44') {\n tokenType = 'native';\n } else if (parsed.assetNamespace === 'spl') {\n tokenType = 'spl';\n }\n\n const metadata: FungibleAssetMetadata = {\n // Type derived from assetId\n type: tokenType,\n // BaseAssetMetadata fields\n name: assetData.name,\n symbol: assetData.symbol,\n decimals: assetData.decimals,\n image: assetData.iconUrl,\n // Direct mapping fields\n coingeckoId: assetData.coingeckoId,\n occurrences: assetData.occurrences,\n aggregators: assetData.aggregators,\n labels: assetData.labels,\n erc20Permit: assetData.erc20Permit,\n fees: assetData.fees,\n honeypotStatus: assetData.honeypotStatus,\n storage: assetData.storage,\n isContractVerified: assetData.isContractVerified,\n description: assetData.description,\n };\n\n return metadata;\n}\n\n// ============================================================================\n// TOKEN DATA SOURCE\n// ============================================================================\n\n/**\n * TokenDataSource enriches responses with token metadata from the Tokens API.\n *\n * This middleware-based data source:\n * - Checks detected assets for missing metadata/images\n * - Fetches metadata from Tokens API v3 for assets needing enrichment\n * - Merges fetched metadata into the response\n *\n * Usage: Create with queryApiClient and use assetsMiddleware; no messenger required.\n */\nexport class TokenDataSource {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /** ApiPlatformClient for cached API calls */\n readonly #apiClient: ApiPlatformClient;\n\n constructor(options: TokenDataSourceOptions) {\n this.#apiClient = options.queryApiClient;\n }\n\n /**\n * Gets the supported networks from the API.\n * Caching is handled by ApiPlatformClient.\n *\n * @returns Set of supported chain IDs in CAIP format\n */\n async #getSupportedNetworks(): Promise<Set<string>> {\n try {\n // Use v2/supportedNetworks which returns CAIP chain IDs\n // ApiPlatformClient handles caching\n const response =\n await this.#apiClient.tokens.fetchTokenV2SupportedNetworks();\n\n // Combine full and partial support networks\n const allNetworks = [...response.fullSupport, ...response.partialSupport];\n\n return new Set(allNetworks);\n } catch (error) {\n log('Failed to fetch supported networks', { error });\n return new Set();\n }\n }\n\n /**\n * Filters asset IDs to only include those from supported networks.\n *\n * @param assetIds - Array of CAIP-19 asset IDs\n * @param supportedNetworks - Set of supported chain IDs\n * @returns Array of asset IDs from supported networks\n */\n #filterAssetsByNetwork(\n assetIds: string[],\n supportedNetworks: Set<string>,\n ): string[] {\n return assetIds.filter((assetId) => {\n try {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n // chainId is in format \"eip155:1\" or \"tron:728126428\"\n // parsed.chain has namespace and reference properties\n const chainId = `${parsed.chain.namespace}:${parsed.chain.reference}`;\n return supportedNetworks.has(chainId);\n } catch {\n // If we can't parse the asset ID, filter it out\n return false;\n }\n });\n }\n\n /**\n * Get the middleware for enriching responses with token metadata.\n *\n * This middleware:\n * 1. Extracts the response from context\n * 2. Fetches metadata for detected assets (assets without metadata)\n * 3. Enriches the response with fetched metadata\n * 4. Calls next() at the end to continue the middleware chain\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['metadata'], async (ctx, next) => {\n // Extract response from context\n const { response } = ctx;\n\n // Only fetch metadata for detected assets (assets without metadata)\n if (!response.detectedAssets) {\n return next(ctx);\n }\n\n const { assetsInfo: stateMetadata } = ctx.getAssetsState();\n const assetIdsNeedingMetadata = new Set<string>();\n\n for (const detectedIds of Object.values(response.detectedAssets)) {\n for (const assetId of detectedIds) {\n // Skip if response already has metadata with image\n const responseMetadata = response.assetsInfo?.[assetId];\n if (responseMetadata?.image) {\n continue;\n }\n\n // Skip if state already has metadata with image\n const existingMetadata = stateMetadata[assetId];\n if (existingMetadata?.image) {\n continue;\n }\n\n // Skip staking contracts; we use built-in metadata and do not fetch from the tokens API\n if (isStakingContractAssetId(assetId)) {\n continue;\n }\n\n assetIdsNeedingMetadata.add(assetId);\n }\n }\n\n if (assetIdsNeedingMetadata.size === 0) {\n return next(ctx);\n }\n\n // Filter asset IDs to only include supported networks\n const supportedNetworks = await this.#getSupportedNetworks();\n const supportedAssetIds = this.#filterAssetsByNetwork(\n [...assetIdsNeedingMetadata],\n supportedNetworks,\n );\n\n if (supportedAssetIds.length === 0) {\n return next(ctx);\n }\n\n try {\n // Use ApiPlatformClient for fetching asset metadata\n // API returns an array with assetId as a property on each item\n const metadataResponse = await this.#apiClient.tokens.fetchV3Assets(\n supportedAssetIds,\n {\n includeIconUrl: true,\n includeMarketData: true,\n includeMetadata: true,\n includeLabels: true,\n includeRwaData: true,\n },\n );\n\n response.assetsInfo ??= {};\n\n for (const assetData of metadataResponse) {\n const caipAssetId = assetData.assetId as Caip19AssetId;\n response.assetsInfo[caipAssetId] = transformV3AssetResponseToMetadata(\n assetData.assetId,\n assetData,\n );\n }\n } catch (error) {\n log('Failed to fetch metadata', { error });\n }\n\n // Call next() at the end to continue the middleware chain\n return next(ctx);\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TokenDataSource.cjs","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import type { V3AssetResponse } from '@metamask/core-backend';\nimport { ApiPlatformClient } from '@metamask/core-backend';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport { isStakingContractAssetId } from './evm-rpc-services';\nimport { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type {\n Caip19AssetId,\n AssetMetadata,\n Middleware,\n FungibleAssetMetadata,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'TokenDataSource';\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n/**\n * TokenDataSource does not call external messenger actions.\n * It uses ApiPlatformClient directly.\n */\nexport type TokenDataSourceAllowedActions = never;\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type TokenDataSourceOptions = {\n /** ApiPlatformClient for API calls with caching */\n queryApiClient: ApiPlatformClient;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Transform V3 API response to FungibleAssetMetadata for state storage.\n *\n * Mapping:\n * - assetId → used to derive `type` (native/erc20/spl)\n * - iconUrl → image\n * - All other fields map directly\n *\n * @param assetId - CAIP-19 asset ID used to derive token type.\n * @param assetData - V3 API response data.\n * @returns FungibleAssetMetadata for state storage.\n */\nfunction transformV3AssetResponseToMetadata(\n assetId: string,\n assetData: V3AssetResponse,\n): AssetMetadata {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n let tokenType: 'native' | 'erc20' | 'spl' = 'erc20';\n\n if (parsed.assetNamespace === 'slip44') {\n tokenType = 'native';\n } else if (parsed.assetNamespace === 'spl') {\n tokenType = 'spl';\n }\n\n const metadata: FungibleAssetMetadata = {\n // Type derived from assetId\n type: tokenType,\n // BaseAssetMetadata fields\n name: assetData.name,\n symbol: assetData.symbol,\n decimals: assetData.decimals,\n image: assetData.iconUrl,\n // Direct mapping fields\n coingeckoId: assetData.coingeckoId,\n occurrences: assetData.occurrences,\n aggregators: assetData.aggregators,\n labels: assetData.labels,\n erc20Permit: assetData.erc20Permit,\n fees: assetData.fees,\n honeypotStatus: assetData.honeypotStatus,\n storage: assetData.storage,\n isContractVerified: assetData.isContractVerified,\n description: assetData.description,\n };\n\n return metadata;\n}\n\n// ============================================================================\n// TOKEN DATA SOURCE\n// ============================================================================\n\n/**\n * TokenDataSource enriches responses with token metadata from the Tokens API.\n *\n * This middleware-based data source:\n * - Checks detected assets for missing metadata/images\n * - Fetches metadata from Tokens API v3 for assets needing enrichment\n * - Merges fetched metadata into the response\n *\n * Usage: Create with queryApiClient and use assetsMiddleware; no messenger required.\n */\nexport class TokenDataSource {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /** ApiPlatformClient for cached API calls */\n readonly #apiClient: ApiPlatformClient;\n\n constructor(options: TokenDataSourceOptions) {\n this.#apiClient = options.queryApiClient;\n }\n\n /**\n * Gets the supported networks from the API.\n * Caching is handled by ApiPlatformClient.\n *\n * @returns Set of supported chain IDs in CAIP format\n */\n async #getSupportedNetworks(): Promise<Set<string>> {\n try {\n // Use v2/supportedNetworks which returns CAIP chain IDs\n // ApiPlatformClient handles caching\n const response =\n await this.#apiClient.tokens.fetchTokenV2SupportedNetworks();\n\n // Combine full and partial support networks\n const allNetworks = [...response.fullSupport, ...response.partialSupport];\n\n return new Set(allNetworks);\n } catch (error) {\n log('Failed to fetch supported networks', { error });\n return new Set();\n }\n }\n\n /**\n * Filters asset IDs to only include those from supported networks.\n *\n * @param assetIds - Array of CAIP-19 asset IDs\n * @param supportedNetworks - Set of supported chain IDs\n * @returns Array of asset IDs from supported networks\n */\n #filterAssetsByNetwork(\n assetIds: string[],\n supportedNetworks: Set<string>,\n ): string[] {\n return assetIds.filter((assetId) => {\n try {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n // chainId is in format \"eip155:1\" or \"tron:728126428\"\n // parsed.chain has namespace and reference properties\n const chainId = `${parsed.chain.namespace}:${parsed.chain.reference}`;\n return supportedNetworks.has(chainId);\n } catch {\n // If we can't parse the asset ID, filter it out\n return false;\n }\n });\n }\n\n /**\n * Get the middleware for enriching responses with token metadata.\n *\n * This middleware:\n * 1. Extracts the response from context\n * 2. Fetches metadata for detected assets (assets without metadata)\n * 3. Enriches the response with fetched metadata\n * 4. Calls next() at the end to continue the middleware chain\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['metadata'], async (ctx, next) => {\n // Extract response from context\n const { response } = ctx;\n\n // Only fetch metadata for detected assets (assets without metadata)\n if (!response.detectedAssets) {\n return next(ctx);\n }\n\n const { assetsInfo: stateMetadata } = ctx.getAssetsState();\n const assetIdsNeedingMetadata = new Set<string>();\n\n for (const detectedIds of Object.values(response.detectedAssets)) {\n for (const assetId of detectedIds) {\n // Skip if response already has metadata with image\n const responseMetadata = response.assetsInfo?.[assetId];\n if (responseMetadata?.image) {\n continue;\n }\n\n // Skip if state already has metadata with image\n const existingMetadata = stateMetadata[assetId];\n if (existingMetadata?.image) {\n continue;\n }\n\n // Skip staking contracts; we use built-in metadata and do not fetch from the tokens API\n if (isStakingContractAssetId(assetId)) {\n continue;\n }\n\n assetIdsNeedingMetadata.add(assetId);\n }\n }\n\n if (assetIdsNeedingMetadata.size === 0) {\n return next(ctx);\n }\n\n // Filter asset IDs to only include supported networks\n const supportedNetworks = await this.#getSupportedNetworks();\n const supportedAssetIds = this.#filterAssetsByNetwork(\n [...assetIdsNeedingMetadata],\n supportedNetworks,\n );\n\n if (supportedAssetIds.length === 0) {\n return next(ctx);\n }\n\n try {\n // Use ApiPlatformClient for fetching asset metadata\n // API returns an array with assetId as a property on each item\n const metadataResponse = await this.#apiClient.tokens.fetchV3Assets(\n supportedAssetIds,\n {\n includeIconUrl: true,\n includeMarketData: true,\n includeMetadata: true,\n includeLabels: true,\n includeRwaData: true,\n includeAggregators: true,\n },\n );\n\n response.assetsInfo ??= {};\n\n for (const assetData of metadataResponse) {\n const caipAssetId = assetData.assetId as Caip19AssetId;\n response.assetsInfo[caipAssetId] = transformV3AssetResponseToMetadata(\n assetData.assetId,\n assetData,\n );\n }\n } catch (error) {\n log('Failed to fetch metadata', { error });\n }\n\n // Call next() at the end to continue the middleware chain\n return next(ctx);\n });\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenDataSource.d.cts","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,+BAA+B;AAO3D,OAAO,KAAK,EAGV,UAAU,EAEX,qBAAiB;AAclB;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAMlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,mDAAmD;IACnD,cAAc,EAAE,iBAAiB,CAAC;CACnC,CAAC;AA2DF;;;;;;;;;GASG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,IAAI,qBAAmB;IAEhC,OAAO,IAAI,MAAM;gBAOL,OAAO,EAAE,sBAAsB;IAoD3C;;;;;;;;;;OAUG;IACH,IAAI,gBAAgB,IAAI,UAAU,
|
|
1
|
+
{"version":3,"file":"TokenDataSource.d.cts","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,+BAA+B;AAO3D,OAAO,KAAK,EAGV,UAAU,EAEX,qBAAiB;AAclB;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAMlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,mDAAmD;IACnD,cAAc,EAAE,iBAAiB,CAAC;CACnC,CAAC;AA2DF;;;;;;;;;GASG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,IAAI,qBAAmB;IAEhC,OAAO,IAAI,MAAM;gBAOL,OAAO,EAAE,sBAAsB;IAoD3C;;;;;;;;;;OAUG;IACH,IAAI,gBAAgB,IAAI,UAAU,CAkFjC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenDataSource.d.mts","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,+BAA+B;AAO3D,OAAO,KAAK,EAGV,UAAU,EAEX,qBAAiB;AAclB;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAMlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,mDAAmD;IACnD,cAAc,EAAE,iBAAiB,CAAC;CACnC,CAAC;AA2DF;;;;;;;;;GASG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,IAAI,qBAAmB;IAEhC,OAAO,IAAI,MAAM;gBAOL,OAAO,EAAE,sBAAsB;IAoD3C;;;;;;;;;;OAUG;IACH,IAAI,gBAAgB,IAAI,UAAU,
|
|
1
|
+
{"version":3,"file":"TokenDataSource.d.mts","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,+BAA+B;AAO3D,OAAO,KAAK,EAGV,UAAU,EAEX,qBAAiB;AAclB;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAMlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,mDAAmD;IACnD,cAAc,EAAE,iBAAiB,CAAC;CACnC,CAAC;AA2DF;;;;;;;;;GASG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,IAAI,qBAAmB;IAEhC,OAAO,IAAI,MAAM;gBAOL,OAAO,EAAE,sBAAsB;IAoD3C;;;;;;;;;;OAUG;IACH,IAAI,gBAAgB,IAAI,UAAU,CAkFjC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenDataSource.mjs","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import type { V3AssetResponse } from '@metamask/core-backend';\nimport { ApiPlatformClient } from '@metamask/core-backend';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport { isStakingContractAssetId } from './evm-rpc-services';\nimport { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type {\n Caip19AssetId,\n AssetMetadata,\n Middleware,\n FungibleAssetMetadata,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'TokenDataSource';\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n/**\n * TokenDataSource does not call external messenger actions.\n * It uses ApiPlatformClient directly.\n */\nexport type TokenDataSourceAllowedActions = never;\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type TokenDataSourceOptions = {\n /** ApiPlatformClient for API calls with caching */\n queryApiClient: ApiPlatformClient;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Transform V3 API response to FungibleAssetMetadata for state storage.\n *\n * Mapping:\n * - assetId → used to derive `type` (native/erc20/spl)\n * - iconUrl → image\n * - All other fields map directly\n *\n * @param assetId - CAIP-19 asset ID used to derive token type.\n * @param assetData - V3 API response data.\n * @returns FungibleAssetMetadata for state storage.\n */\nfunction transformV3AssetResponseToMetadata(\n assetId: string,\n assetData: V3AssetResponse,\n): AssetMetadata {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n let tokenType: 'native' | 'erc20' | 'spl' = 'erc20';\n\n if (parsed.assetNamespace === 'slip44') {\n tokenType = 'native';\n } else if (parsed.assetNamespace === 'spl') {\n tokenType = 'spl';\n }\n\n const metadata: FungibleAssetMetadata = {\n // Type derived from assetId\n type: tokenType,\n // BaseAssetMetadata fields\n name: assetData.name,\n symbol: assetData.symbol,\n decimals: assetData.decimals,\n image: assetData.iconUrl,\n // Direct mapping fields\n coingeckoId: assetData.coingeckoId,\n occurrences: assetData.occurrences,\n aggregators: assetData.aggregators,\n labels: assetData.labels,\n erc20Permit: assetData.erc20Permit,\n fees: assetData.fees,\n honeypotStatus: assetData.honeypotStatus,\n storage: assetData.storage,\n isContractVerified: assetData.isContractVerified,\n description: assetData.description,\n };\n\n return metadata;\n}\n\n// ============================================================================\n// TOKEN DATA SOURCE\n// ============================================================================\n\n/**\n * TokenDataSource enriches responses with token metadata from the Tokens API.\n *\n * This middleware-based data source:\n * - Checks detected assets for missing metadata/images\n * - Fetches metadata from Tokens API v3 for assets needing enrichment\n * - Merges fetched metadata into the response\n *\n * Usage: Create with queryApiClient and use assetsMiddleware; no messenger required.\n */\nexport class TokenDataSource {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /** ApiPlatformClient for cached API calls */\n readonly #apiClient: ApiPlatformClient;\n\n constructor(options: TokenDataSourceOptions) {\n this.#apiClient = options.queryApiClient;\n }\n\n /**\n * Gets the supported networks from the API.\n * Caching is handled by ApiPlatformClient.\n *\n * @returns Set of supported chain IDs in CAIP format\n */\n async #getSupportedNetworks(): Promise<Set<string>> {\n try {\n // Use v2/supportedNetworks which returns CAIP chain IDs\n // ApiPlatformClient handles caching\n const response =\n await this.#apiClient.tokens.fetchTokenV2SupportedNetworks();\n\n // Combine full and partial support networks\n const allNetworks = [...response.fullSupport, ...response.partialSupport];\n\n return new Set(allNetworks);\n } catch (error) {\n log('Failed to fetch supported networks', { error });\n return new Set();\n }\n }\n\n /**\n * Filters asset IDs to only include those from supported networks.\n *\n * @param assetIds - Array of CAIP-19 asset IDs\n * @param supportedNetworks - Set of supported chain IDs\n * @returns Array of asset IDs from supported networks\n */\n #filterAssetsByNetwork(\n assetIds: string[],\n supportedNetworks: Set<string>,\n ): string[] {\n return assetIds.filter((assetId) => {\n try {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n // chainId is in format \"eip155:1\" or \"tron:728126428\"\n // parsed.chain has namespace and reference properties\n const chainId = `${parsed.chain.namespace}:${parsed.chain.reference}`;\n return supportedNetworks.has(chainId);\n } catch {\n // If we can't parse the asset ID, filter it out\n return false;\n }\n });\n }\n\n /**\n * Get the middleware for enriching responses with token metadata.\n *\n * This middleware:\n * 1. Extracts the response from context\n * 2. Fetches metadata for detected assets (assets without metadata)\n * 3. Enriches the response with fetched metadata\n * 4. Calls next() at the end to continue the middleware chain\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['metadata'], async (ctx, next) => {\n // Extract response from context\n const { response } = ctx;\n\n // Only fetch metadata for detected assets (assets without metadata)\n if (!response.detectedAssets) {\n return next(ctx);\n }\n\n const { assetsInfo: stateMetadata } = ctx.getAssetsState();\n const assetIdsNeedingMetadata = new Set<string>();\n\n for (const detectedIds of Object.values(response.detectedAssets)) {\n for (const assetId of detectedIds) {\n // Skip if response already has metadata with image\n const responseMetadata = response.assetsInfo?.[assetId];\n if (responseMetadata?.image) {\n continue;\n }\n\n // Skip if state already has metadata with image\n const existingMetadata = stateMetadata[assetId];\n if (existingMetadata?.image) {\n continue;\n }\n\n // Skip staking contracts; we use built-in metadata and do not fetch from the tokens API\n if (isStakingContractAssetId(assetId)) {\n continue;\n }\n\n assetIdsNeedingMetadata.add(assetId);\n }\n }\n\n if (assetIdsNeedingMetadata.size === 0) {\n return next(ctx);\n }\n\n // Filter asset IDs to only include supported networks\n const supportedNetworks = await this.#getSupportedNetworks();\n const supportedAssetIds = this.#filterAssetsByNetwork(\n [...assetIdsNeedingMetadata],\n supportedNetworks,\n );\n\n if (supportedAssetIds.length === 0) {\n return next(ctx);\n }\n\n try {\n // Use ApiPlatformClient for fetching asset metadata\n // API returns an array with assetId as a property on each item\n const metadataResponse = await this.#apiClient.tokens.fetchV3Assets(\n supportedAssetIds,\n {\n includeIconUrl: true,\n includeMarketData: true,\n includeMetadata: true,\n includeLabels: true,\n includeRwaData: true,\n },\n );\n\n response.assetsInfo ??= {};\n\n for (const assetData of metadataResponse) {\n const caipAssetId = assetData.assetId as Caip19AssetId;\n response.assetsInfo[caipAssetId] = transformV3AssetResponseToMetadata(\n assetData.assetId,\n assetData,\n );\n }\n } catch (error) {\n log('Failed to fetch metadata', { error });\n }\n\n // Call next() at the end to continue the middleware chain\n return next(ctx);\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TokenDataSource.mjs","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import type { V3AssetResponse } from '@metamask/core-backend';\nimport { ApiPlatformClient } from '@metamask/core-backend';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport { isStakingContractAssetId } from './evm-rpc-services';\nimport { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type {\n Caip19AssetId,\n AssetMetadata,\n Middleware,\n FungibleAssetMetadata,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'TokenDataSource';\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n/**\n * TokenDataSource does not call external messenger actions.\n * It uses ApiPlatformClient directly.\n */\nexport type TokenDataSourceAllowedActions = never;\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type TokenDataSourceOptions = {\n /** ApiPlatformClient for API calls with caching */\n queryApiClient: ApiPlatformClient;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Transform V3 API response to FungibleAssetMetadata for state storage.\n *\n * Mapping:\n * - assetId → used to derive `type` (native/erc20/spl)\n * - iconUrl → image\n * - All other fields map directly\n *\n * @param assetId - CAIP-19 asset ID used to derive token type.\n * @param assetData - V3 API response data.\n * @returns FungibleAssetMetadata for state storage.\n */\nfunction transformV3AssetResponseToMetadata(\n assetId: string,\n assetData: V3AssetResponse,\n): AssetMetadata {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n let tokenType: 'native' | 'erc20' | 'spl' = 'erc20';\n\n if (parsed.assetNamespace === 'slip44') {\n tokenType = 'native';\n } else if (parsed.assetNamespace === 'spl') {\n tokenType = 'spl';\n }\n\n const metadata: FungibleAssetMetadata = {\n // Type derived from assetId\n type: tokenType,\n // BaseAssetMetadata fields\n name: assetData.name,\n symbol: assetData.symbol,\n decimals: assetData.decimals,\n image: assetData.iconUrl,\n // Direct mapping fields\n coingeckoId: assetData.coingeckoId,\n occurrences: assetData.occurrences,\n aggregators: assetData.aggregators,\n labels: assetData.labels,\n erc20Permit: assetData.erc20Permit,\n fees: assetData.fees,\n honeypotStatus: assetData.honeypotStatus,\n storage: assetData.storage,\n isContractVerified: assetData.isContractVerified,\n description: assetData.description,\n };\n\n return metadata;\n}\n\n// ============================================================================\n// TOKEN DATA SOURCE\n// ============================================================================\n\n/**\n * TokenDataSource enriches responses with token metadata from the Tokens API.\n *\n * This middleware-based data source:\n * - Checks detected assets for missing metadata/images\n * - Fetches metadata from Tokens API v3 for assets needing enrichment\n * - Merges fetched metadata into the response\n *\n * Usage: Create with queryApiClient and use assetsMiddleware; no messenger required.\n */\nexport class TokenDataSource {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /** ApiPlatformClient for cached API calls */\n readonly #apiClient: ApiPlatformClient;\n\n constructor(options: TokenDataSourceOptions) {\n this.#apiClient = options.queryApiClient;\n }\n\n /**\n * Gets the supported networks from the API.\n * Caching is handled by ApiPlatformClient.\n *\n * @returns Set of supported chain IDs in CAIP format\n */\n async #getSupportedNetworks(): Promise<Set<string>> {\n try {\n // Use v2/supportedNetworks which returns CAIP chain IDs\n // ApiPlatformClient handles caching\n const response =\n await this.#apiClient.tokens.fetchTokenV2SupportedNetworks();\n\n // Combine full and partial support networks\n const allNetworks = [...response.fullSupport, ...response.partialSupport];\n\n return new Set(allNetworks);\n } catch (error) {\n log('Failed to fetch supported networks', { error });\n return new Set();\n }\n }\n\n /**\n * Filters asset IDs to only include those from supported networks.\n *\n * @param assetIds - Array of CAIP-19 asset IDs\n * @param supportedNetworks - Set of supported chain IDs\n * @returns Array of asset IDs from supported networks\n */\n #filterAssetsByNetwork(\n assetIds: string[],\n supportedNetworks: Set<string>,\n ): string[] {\n return assetIds.filter((assetId) => {\n try {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n // chainId is in format \"eip155:1\" or \"tron:728126428\"\n // parsed.chain has namespace and reference properties\n const chainId = `${parsed.chain.namespace}:${parsed.chain.reference}`;\n return supportedNetworks.has(chainId);\n } catch {\n // If we can't parse the asset ID, filter it out\n return false;\n }\n });\n }\n\n /**\n * Get the middleware for enriching responses with token metadata.\n *\n * This middleware:\n * 1. Extracts the response from context\n * 2. Fetches metadata for detected assets (assets without metadata)\n * 3. Enriches the response with fetched metadata\n * 4. Calls next() at the end to continue the middleware chain\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['metadata'], async (ctx, next) => {\n // Extract response from context\n const { response } = ctx;\n\n // Only fetch metadata for detected assets (assets without metadata)\n if (!response.detectedAssets) {\n return next(ctx);\n }\n\n const { assetsInfo: stateMetadata } = ctx.getAssetsState();\n const assetIdsNeedingMetadata = new Set<string>();\n\n for (const detectedIds of Object.values(response.detectedAssets)) {\n for (const assetId of detectedIds) {\n // Skip if response already has metadata with image\n const responseMetadata = response.assetsInfo?.[assetId];\n if (responseMetadata?.image) {\n continue;\n }\n\n // Skip if state already has metadata with image\n const existingMetadata = stateMetadata[assetId];\n if (existingMetadata?.image) {\n continue;\n }\n\n // Skip staking contracts; we use built-in metadata and do not fetch from the tokens API\n if (isStakingContractAssetId(assetId)) {\n continue;\n }\n\n assetIdsNeedingMetadata.add(assetId);\n }\n }\n\n if (assetIdsNeedingMetadata.size === 0) {\n return next(ctx);\n }\n\n // Filter asset IDs to only include supported networks\n const supportedNetworks = await this.#getSupportedNetworks();\n const supportedAssetIds = this.#filterAssetsByNetwork(\n [...assetIdsNeedingMetadata],\n supportedNetworks,\n );\n\n if (supportedAssetIds.length === 0) {\n return next(ctx);\n }\n\n try {\n // Use ApiPlatformClient for fetching asset metadata\n // API returns an array with assetId as a property on each item\n const metadataResponse = await this.#apiClient.tokens.fetchV3Assets(\n supportedAssetIds,\n {\n includeIconUrl: true,\n includeMarketData: true,\n includeMetadata: true,\n includeLabels: true,\n includeRwaData: true,\n includeAggregators: true,\n },\n );\n\n response.assetsInfo ??= {};\n\n for (const assetData of metadataResponse) {\n const caipAssetId = assetData.assetId as Caip19AssetId;\n response.assetsInfo[caipAssetId] = transformV3AssetResponseToMetadata(\n assetData.assetId,\n assetData,\n );\n }\n } catch (error) {\n log('Failed to fetch metadata', { error });\n }\n\n // Call next() at the end to continue the middleware chain\n return next(ctx);\n });\n }\n}\n"]}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AACzB,2DAG4B;AAF1B,oHAAA,gBAAgB,OAAA;AAChB,mIAAA,+BAA+B,OAAA;
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yBAAyB;AACzB,2DAG4B;AAF1B,oHAAA,gBAAgB,OAAA;AAChB,mIAAA,+BAA+B,OAAA;AAoFjC,sCAAsC;AACtC,yDAAoD;AAA3C,kHAAA,kBAAkB,OAAA;AAI3B,6BAA6B;AAC7B,yDAAuD;AAA9C,qHAAA,qBAAqB,OAAA;AAS9B,kCAAkC;AAClC,yDAGwB;AAFtB,0HAAA,0BAA0B,OAAA;AAC1B,gIAAA,gCAAgC,OAAA;AAUlC,qBAAqB;AACrB,yDAAoE;AAA3D,6GAAA,aAAa,OAAA;AAAE,mHAAA,mBAAmB,OAAA;AAW3C,gFAAgF;AAChF,yDASwB;AARtB,8GAAA,cAAc,OAAA;AACd,oHAAA,oBAAoB,OAAA;AACpB,qHAAA,qBAAqB,OAAA;AACrB,YAAY;AACZ,kHAAA,kBAAkB,OAAA;AAClB,oBAAoB;AACpB,iHAAA,iBAAiB,OAAA;AACjB,uHAAA,uBAAuB,OAAA;AAUzB,0BAA0B;AAC1B,yDAAkE;AAAzD,+GAAA,eAAe,OAAA;AAAE,+GAAA,eAAe,OAAA;AASzC,cAAc;AACd,uDAAoD;AAA3C,kHAAA,mBAAmB,OAAA;AAE5B,YAAY;AACZ,qCAA2C;AAAlC,yGAAA,gBAAgB,OAAA;AAEzB,YAAY;AACZ,mDAI6B;AAH3B,yHAAA,8BAA8B,OAAA;AAC9B,+GAAA,oBAAoB,OAAA;AACpB,sHAAA,2BAA2B,OAAA","sourcesContent":["// Main controller export\nexport {\n AssetsController,\n getDefaultAssetsControllerState,\n} from './AssetsController';\nexport type { PendingTokenMetadata } from './AssetsController';\n\n// State and messenger types\nexport type {\n AssetsControllerState,\n AssetsControllerMessenger,\n AssetsControllerOptions,\n AssetsControllerFirstInitFetchMetaMetricsPayload,\n AssetsControllerGetStateAction,\n AssetsControllerActions,\n AssetsControllerStateChangeEvent,\n AssetsControllerBalanceChangedEvent,\n AssetsControllerPriceChangedEvent,\n AssetsControllerAssetsDetectedEvent,\n AssetsControllerEvents,\n} from './AssetsController';\nexport type {\n AssetsControllerGetAssetsAction,\n AssetsControllerGetAssetsBalanceAction,\n AssetsControllerGetAssetMetadataAction,\n AssetsControllerGetAssetsPriceAction,\n AssetsControllerAddCustomAssetAction,\n AssetsControllerRemoveCustomAssetAction,\n AssetsControllerGetCustomAssetsAction,\n AssetsControllerHideAssetAction,\n AssetsControllerUnhideAssetAction,\n AssetsControllerMethodActions,\n} from './AssetsController-method-action-types';\n\n// Core types\nexport type {\n // CAIP types\n Caip19AssetId,\n AccountId,\n ChainId,\n // Asset types\n AssetType,\n TokenStandard,\n // Contract data types\n TokenFees,\n HoneypotStatus,\n StorageSlots,\n LocalizedDescription,\n // Metadata types\n BaseAssetMetadata,\n FungibleAssetMetadata,\n ERC721AssetMetadata,\n ERC1155AssetMetadata,\n AssetMetadata,\n // Price types\n BaseAssetPrice,\n FungibleAssetPrice,\n NFTAssetPrice,\n AssetPrice,\n // Balance types\n FungibleAssetBalance,\n ERC721AssetBalance,\n ERC1155AssetBalance,\n AssetBalance,\n // Data source types\n AccountWithSupportedChains,\n DataType,\n DataRequest,\n DataResponse,\n AssetsUpdateMode,\n // Middleware types\n Context,\n NextFunction,\n Middleware,\n FetchContext,\n FetchNextFunction,\n FetchMiddleware,\n SubscriptionResponse,\n // Combined asset type\n Asset,\n // Event types\n BalanceChangeEvent,\n PriceChangeEvent,\n MetadataChangeEvent,\n AssetsDetectedEvent,\n} from './types';\n\n// Data sources - base class and types\nexport { AbstractDataSource } from './data-sources';\n\nexport type { DataSourceState, SubscriptionRequest } from './data-sources';\n\n// Data sources - AccountsApi\nexport { AccountsApiDataSource } from './data-sources';\n\nexport type {\n AccountsApiDataSourceConfig,\n AccountsApiDataSourceOptions,\n AccountsApiDataSourceState,\n AccountsApiDataSourceAllowedActions,\n} from './data-sources';\n\n// Data sources - BackendWebsocket\nexport {\n BackendWebsocketDataSource,\n createBackendWebsocketDataSource,\n} from './data-sources';\n\nexport type {\n BackendWebsocketDataSourceOptions,\n BackendWebsocketDataSourceState,\n BackendWebsocketDataSourceAllowedActions,\n BackendWebsocketDataSourceAllowedEvents,\n} from './data-sources';\n\n// Data sources - RPC\nexport { RpcDataSource, createRpcDataSource } from './data-sources';\n\nexport type {\n RpcDataSourceConfig,\n RpcDataSourceOptions,\n RpcDataSourceState,\n RpcDataSourceAllowedActions,\n RpcDataSourceAllowedEvents,\n ChainStatus,\n} from './data-sources';\n\n// Data sources - Unified Snap Data Source (dynamically discovers keyring snaps)\nexport {\n SnapDataSource,\n createSnapDataSource,\n SNAP_DATA_SOURCE_NAME,\n // Constants\n KEYRING_PERMISSION,\n // Utility functions\n getChainIdsCaveat,\n extractChainFromAssetId,\n} from './data-sources';\n\nexport type {\n SnapDataSourceState,\n SnapDataSourceOptions,\n SnapDataSourceAllowedActions,\n SnapDataSourceAllowedEvents,\n} from './data-sources';\n\n// Enrichment data sources\nexport { TokenDataSource, PriceDataSource } from './data-sources';\n\nexport type {\n TokenDataSourceOptions,\n TokenDataSourceAllowedActions,\n PriceDataSourceConfig,\n PriceDataSourceOptions,\n} from './data-sources';\n\n// Middlewares\nexport { DetectionMiddleware } from './middlewares';\n\n// Utilities\nexport { normalizeAssetId } from './utils';\n\n// Selectors\nexport {\n getAggregatedBalanceForAccount,\n getGroupIdForAccount,\n getInternalAccountsForGroup,\n} from './selectors/balance';\n\nexport type {\n AccountsById,\n AggregatedBalanceEntry,\n AggregatedBalanceForAccount,\n EnabledNetworkMap,\n} from './selectors/balance';\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { AssetsController, getDefaultAssetsControllerState, } from "./AssetsController.cjs";
|
|
2
|
+
export type { PendingTokenMetadata } from "./AssetsController.cjs";
|
|
2
3
|
export type { AssetsControllerState, AssetsControllerMessenger, AssetsControllerOptions, AssetsControllerFirstInitFetchMetaMetricsPayload, AssetsControllerGetStateAction, AssetsControllerActions, AssetsControllerStateChangeEvent, AssetsControllerBalanceChangedEvent, AssetsControllerPriceChangedEvent, AssetsControllerAssetsDetectedEvent, AssetsControllerEvents, } from "./AssetsController.cjs";
|
|
3
4
|
export type { AssetsControllerGetAssetsAction, AssetsControllerGetAssetsBalanceAction, AssetsControllerGetAssetMetadataAction, AssetsControllerGetAssetsPriceAction, AssetsControllerAddCustomAssetAction, AssetsControllerRemoveCustomAssetAction, AssetsControllerGetCustomAssetsAction, AssetsControllerHideAssetAction, AssetsControllerUnhideAssetAction, AssetsControllerMethodActions, } from "./AssetsController-method-action-types.cjs";
|
|
4
5
|
export type { Caip19AssetId, AccountId, ChainId, AssetType, TokenStandard, TokenFees, HoneypotStatus, StorageSlots, LocalizedDescription, BaseAssetMetadata, FungibleAssetMetadata, ERC721AssetMetadata, ERC1155AssetMetadata, AssetMetadata, BaseAssetPrice, FungibleAssetPrice, NFTAssetPrice, AssetPrice, FungibleAssetBalance, ERC721AssetBalance, ERC1155AssetBalance, AssetBalance, AccountWithSupportedChains, DataType, DataRequest, DataResponse, AssetsUpdateMode, Context, NextFunction, Middleware, FetchContext, FetchNextFunction, FetchMiddleware, SubscriptionResponse, Asset, BalanceChangeEvent, PriceChangeEvent, MetadataChangeEvent, AssetsDetectedEvent, } from "./types.cjs";
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,+BAA+B,GAChC,+BAA2B;
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,+BAA+B,GAChC,+BAA2B;AAC5B,YAAY,EAAE,oBAAoB,EAAE,+BAA2B;AAG/D,YAAY,EACV,qBAAqB,EACrB,yBAAyB,EACzB,uBAAuB,EACvB,gDAAgD,EAChD,8BAA8B,EAC9B,uBAAuB,EACvB,gCAAgC,EAChC,mCAAmC,EACnC,iCAAiC,EACjC,mCAAmC,EACnC,sBAAsB,GACvB,+BAA2B;AAC5B,YAAY,EACV,+BAA+B,EAC/B,sCAAsC,EACtC,sCAAsC,EACtC,oCAAoC,EACpC,oCAAoC,EACpC,uCAAuC,EACvC,qCAAqC,EACrC,+BAA+B,EAC/B,iCAAiC,EACjC,6BAA6B,GAC9B,mDAA+C;AAGhD,YAAY,EAEV,aAAa,EACb,SAAS,EACT,OAAO,EAEP,SAAS,EACT,aAAa,EAEb,SAAS,EACT,cAAc,EACd,YAAY,EACZ,oBAAoB,EAEpB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EAEb,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,UAAU,EAEV,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EAEZ,0BAA0B,EAC1B,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,gBAAgB,EAEhB,OAAO,EACP,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EAEpB,KAAK,EAEL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,GACpB,oBAAgB;AAGjB,OAAO,EAAE,kBAAkB,EAAE,iCAAuB;AAEpD,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,iCAAuB;AAG3E,OAAO,EAAE,qBAAqB,EAAE,iCAAuB;AAEvD,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC1B,mCAAmC,GACpC,iCAAuB;AAGxB,OAAO,EACL,0BAA0B,EAC1B,gCAAgC,GACjC,iCAAuB;AAExB,YAAY,EACV,iCAAiC,EACjC,+BAA+B,EAC/B,wCAAwC,EACxC,uCAAuC,GACxC,iCAAuB;AAGxB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,iCAAuB;AAEpE,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,2BAA2B,EAC3B,0BAA0B,EAC1B,WAAW,GACZ,iCAAuB;AAGxB,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EAErB,kBAAkB,EAElB,iBAAiB,EACjB,uBAAuB,GACxB,iCAAuB;AAExB,YAAY,EACV,mBAAmB,EACnB,qBAAqB,EACrB,4BAA4B,EAC5B,2BAA2B,GAC5B,iCAAuB;AAGxB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iCAAuB;AAElE,YAAY,EACV,sBAAsB,EACtB,6BAA6B,EAC7B,qBAAqB,EACrB,sBAAsB,GACvB,iCAAuB;AAGxB,OAAO,EAAE,mBAAmB,EAAE,gCAAsB;AAGpD,OAAO,EAAE,gBAAgB,EAAE,oBAAgB;AAG3C,OAAO,EACL,8BAA8B,EAC9B,oBAAoB,EACpB,2BAA2B,GAC5B,gCAA4B;AAE7B,YAAY,EACV,YAAY,EACZ,sBAAsB,EACtB,2BAA2B,EAC3B,iBAAiB,GAClB,gCAA4B"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { AssetsController, getDefaultAssetsControllerState, } from "./AssetsController.mjs";
|
|
2
|
+
export type { PendingTokenMetadata } from "./AssetsController.mjs";
|
|
2
3
|
export type { AssetsControllerState, AssetsControllerMessenger, AssetsControllerOptions, AssetsControllerFirstInitFetchMetaMetricsPayload, AssetsControllerGetStateAction, AssetsControllerActions, AssetsControllerStateChangeEvent, AssetsControllerBalanceChangedEvent, AssetsControllerPriceChangedEvent, AssetsControllerAssetsDetectedEvent, AssetsControllerEvents, } from "./AssetsController.mjs";
|
|
3
4
|
export type { AssetsControllerGetAssetsAction, AssetsControllerGetAssetsBalanceAction, AssetsControllerGetAssetMetadataAction, AssetsControllerGetAssetsPriceAction, AssetsControllerAddCustomAssetAction, AssetsControllerRemoveCustomAssetAction, AssetsControllerGetCustomAssetsAction, AssetsControllerHideAssetAction, AssetsControllerUnhideAssetAction, AssetsControllerMethodActions, } from "./AssetsController-method-action-types.mjs";
|
|
4
5
|
export type { Caip19AssetId, AccountId, ChainId, AssetType, TokenStandard, TokenFees, HoneypotStatus, StorageSlots, LocalizedDescription, BaseAssetMetadata, FungibleAssetMetadata, ERC721AssetMetadata, ERC1155AssetMetadata, AssetMetadata, BaseAssetPrice, FungibleAssetPrice, NFTAssetPrice, AssetPrice, FungibleAssetBalance, ERC721AssetBalance, ERC1155AssetBalance, AssetBalance, AccountWithSupportedChains, DataType, DataRequest, DataResponse, AssetsUpdateMode, Context, NextFunction, Middleware, FetchContext, FetchNextFunction, FetchMiddleware, SubscriptionResponse, Asset, BalanceChangeEvent, PriceChangeEvent, MetadataChangeEvent, AssetsDetectedEvent, } from "./types.mjs";
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,+BAA+B,GAChC,+BAA2B;
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,+BAA+B,GAChC,+BAA2B;AAC5B,YAAY,EAAE,oBAAoB,EAAE,+BAA2B;AAG/D,YAAY,EACV,qBAAqB,EACrB,yBAAyB,EACzB,uBAAuB,EACvB,gDAAgD,EAChD,8BAA8B,EAC9B,uBAAuB,EACvB,gCAAgC,EAChC,mCAAmC,EACnC,iCAAiC,EACjC,mCAAmC,EACnC,sBAAsB,GACvB,+BAA2B;AAC5B,YAAY,EACV,+BAA+B,EAC/B,sCAAsC,EACtC,sCAAsC,EACtC,oCAAoC,EACpC,oCAAoC,EACpC,uCAAuC,EACvC,qCAAqC,EACrC,+BAA+B,EAC/B,iCAAiC,EACjC,6BAA6B,GAC9B,mDAA+C;AAGhD,YAAY,EAEV,aAAa,EACb,SAAS,EACT,OAAO,EAEP,SAAS,EACT,aAAa,EAEb,SAAS,EACT,cAAc,EACd,YAAY,EACZ,oBAAoB,EAEpB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EAEb,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,UAAU,EAEV,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EAEZ,0BAA0B,EAC1B,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,gBAAgB,EAEhB,OAAO,EACP,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EAEpB,KAAK,EAEL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,GACpB,oBAAgB;AAGjB,OAAO,EAAE,kBAAkB,EAAE,iCAAuB;AAEpD,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,iCAAuB;AAG3E,OAAO,EAAE,qBAAqB,EAAE,iCAAuB;AAEvD,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC1B,mCAAmC,GACpC,iCAAuB;AAGxB,OAAO,EACL,0BAA0B,EAC1B,gCAAgC,GACjC,iCAAuB;AAExB,YAAY,EACV,iCAAiC,EACjC,+BAA+B,EAC/B,wCAAwC,EACxC,uCAAuC,GACxC,iCAAuB;AAGxB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,iCAAuB;AAEpE,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,2BAA2B,EAC3B,0BAA0B,EAC1B,WAAW,GACZ,iCAAuB;AAGxB,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EAErB,kBAAkB,EAElB,iBAAiB,EACjB,uBAAuB,GACxB,iCAAuB;AAExB,YAAY,EACV,mBAAmB,EACnB,qBAAqB,EACrB,4BAA4B,EAC5B,2BAA2B,GAC5B,iCAAuB;AAGxB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iCAAuB;AAElE,YAAY,EACV,sBAAsB,EACtB,6BAA6B,EAC7B,qBAAqB,EACrB,sBAAsB,GACvB,iCAAuB;AAGxB,OAAO,EAAE,mBAAmB,EAAE,gCAAsB;AAGpD,OAAO,EAAE,gBAAgB,EAAE,oBAAgB;AAG3C,OAAO,EACL,8BAA8B,EAC9B,oBAAoB,EACpB,2BAA2B,GAC5B,gCAA4B;AAE7B,YAAY,EACV,YAAY,EACZ,sBAAsB,EACtB,2BAA2B,EAC3B,iBAAiB,GAClB,gCAA4B"}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,OAAO,EACL,gBAAgB,EAChB,+BAA+B,EAChC,+BAA2B;
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,OAAO,EACL,gBAAgB,EAChB,+BAA+B,EAChC,+BAA2B;AAmF5B,sCAAsC;AACtC,OAAO,EAAE,kBAAkB,EAAE,iCAAuB;AAIpD,6BAA6B;AAC7B,OAAO,EAAE,qBAAqB,EAAE,iCAAuB;AASvD,kCAAkC;AAClC,OAAO,EACL,0BAA0B,EAC1B,gCAAgC,EACjC,iCAAuB;AASxB,qBAAqB;AACrB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,iCAAuB;AAWpE,gFAAgF;AAChF,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,qBAAqB;AACrB,YAAY;AACZ,kBAAkB;AAClB,oBAAoB;AACpB,iBAAiB,EACjB,uBAAuB,EACxB,iCAAuB;AASxB,0BAA0B;AAC1B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iCAAuB;AASlE,cAAc;AACd,OAAO,EAAE,mBAAmB,EAAE,gCAAsB;AAEpD,YAAY;AACZ,OAAO,EAAE,gBAAgB,EAAE,oBAAgB;AAE3C,YAAY;AACZ,OAAO,EACL,8BAA8B,EAC9B,oBAAoB,EACpB,2BAA2B,EAC5B,gCAA4B","sourcesContent":["// Main controller export\nexport {\n AssetsController,\n getDefaultAssetsControllerState,\n} from './AssetsController';\nexport type { PendingTokenMetadata } from './AssetsController';\n\n// State and messenger types\nexport type {\n AssetsControllerState,\n AssetsControllerMessenger,\n AssetsControllerOptions,\n AssetsControllerFirstInitFetchMetaMetricsPayload,\n AssetsControllerGetStateAction,\n AssetsControllerActions,\n AssetsControllerStateChangeEvent,\n AssetsControllerBalanceChangedEvent,\n AssetsControllerPriceChangedEvent,\n AssetsControllerAssetsDetectedEvent,\n AssetsControllerEvents,\n} from './AssetsController';\nexport type {\n AssetsControllerGetAssetsAction,\n AssetsControllerGetAssetsBalanceAction,\n AssetsControllerGetAssetMetadataAction,\n AssetsControllerGetAssetsPriceAction,\n AssetsControllerAddCustomAssetAction,\n AssetsControllerRemoveCustomAssetAction,\n AssetsControllerGetCustomAssetsAction,\n AssetsControllerHideAssetAction,\n AssetsControllerUnhideAssetAction,\n AssetsControllerMethodActions,\n} from './AssetsController-method-action-types';\n\n// Core types\nexport type {\n // CAIP types\n Caip19AssetId,\n AccountId,\n ChainId,\n // Asset types\n AssetType,\n TokenStandard,\n // Contract data types\n TokenFees,\n HoneypotStatus,\n StorageSlots,\n LocalizedDescription,\n // Metadata types\n BaseAssetMetadata,\n FungibleAssetMetadata,\n ERC721AssetMetadata,\n ERC1155AssetMetadata,\n AssetMetadata,\n // Price types\n BaseAssetPrice,\n FungibleAssetPrice,\n NFTAssetPrice,\n AssetPrice,\n // Balance types\n FungibleAssetBalance,\n ERC721AssetBalance,\n ERC1155AssetBalance,\n AssetBalance,\n // Data source types\n AccountWithSupportedChains,\n DataType,\n DataRequest,\n DataResponse,\n AssetsUpdateMode,\n // Middleware types\n Context,\n NextFunction,\n Middleware,\n FetchContext,\n FetchNextFunction,\n FetchMiddleware,\n SubscriptionResponse,\n // Combined asset type\n Asset,\n // Event types\n BalanceChangeEvent,\n PriceChangeEvent,\n MetadataChangeEvent,\n AssetsDetectedEvent,\n} from './types';\n\n// Data sources - base class and types\nexport { AbstractDataSource } from './data-sources';\n\nexport type { DataSourceState, SubscriptionRequest } from './data-sources';\n\n// Data sources - AccountsApi\nexport { AccountsApiDataSource } from './data-sources';\n\nexport type {\n AccountsApiDataSourceConfig,\n AccountsApiDataSourceOptions,\n AccountsApiDataSourceState,\n AccountsApiDataSourceAllowedActions,\n} from './data-sources';\n\n// Data sources - BackendWebsocket\nexport {\n BackendWebsocketDataSource,\n createBackendWebsocketDataSource,\n} from './data-sources';\n\nexport type {\n BackendWebsocketDataSourceOptions,\n BackendWebsocketDataSourceState,\n BackendWebsocketDataSourceAllowedActions,\n BackendWebsocketDataSourceAllowedEvents,\n} from './data-sources';\n\n// Data sources - RPC\nexport { RpcDataSource, createRpcDataSource } from './data-sources';\n\nexport type {\n RpcDataSourceConfig,\n RpcDataSourceOptions,\n RpcDataSourceState,\n RpcDataSourceAllowedActions,\n RpcDataSourceAllowedEvents,\n ChainStatus,\n} from './data-sources';\n\n// Data sources - Unified Snap Data Source (dynamically discovers keyring snaps)\nexport {\n SnapDataSource,\n createSnapDataSource,\n SNAP_DATA_SOURCE_NAME,\n // Constants\n KEYRING_PERMISSION,\n // Utility functions\n getChainIdsCaveat,\n extractChainFromAssetId,\n} from './data-sources';\n\nexport type {\n SnapDataSourceState,\n SnapDataSourceOptions,\n SnapDataSourceAllowedActions,\n SnapDataSourceAllowedEvents,\n} from './data-sources';\n\n// Enrichment data sources\nexport { TokenDataSource, PriceDataSource } from './data-sources';\n\nexport type {\n TokenDataSourceOptions,\n TokenDataSourceAllowedActions,\n PriceDataSourceConfig,\n PriceDataSourceOptions,\n} from './data-sources';\n\n// Middlewares\nexport { DetectionMiddleware } from './middlewares';\n\n// Utilities\nexport { normalizeAssetId } from './utils';\n\n// Selectors\nexport {\n getAggregatedBalanceForAccount,\n getGroupIdForAccount,\n getInternalAccountsForGroup,\n} from './selectors/balance';\n\nexport type {\n AccountsById,\n AggregatedBalanceEntry,\n AggregatedBalanceForAccount,\n EnabledNetworkMap,\n} from './selectors/balance';\n"]}
|
|
@@ -13,12 +13,19 @@ const CONTROLLER_NAME = 'DetectionMiddleware';
|
|
|
13
13
|
// DETECTION MIDDLEWARE
|
|
14
14
|
// ============================================================================
|
|
15
15
|
/**
|
|
16
|
-
* DetectionMiddleware
|
|
16
|
+
* DetectionMiddleware builds the set of assets that downstream sources use for
|
|
17
|
+
* metadata and price fetching.
|
|
17
18
|
*
|
|
18
19
|
* This middleware:
|
|
19
|
-
* -
|
|
20
|
-
*
|
|
21
|
-
* -
|
|
20
|
+
* - Includes every asset that appears in response.assetsBalance (so prices and
|
|
21
|
+
* metadata are fetched for existing assets as well as new ones)
|
|
22
|
+
* - Includes each account's custom assets from state (so custom tokens get
|
|
23
|
+
* metadata and prices even when they have no balance yet)
|
|
24
|
+
* - Fills response.detectedAssets with these asset IDs per account
|
|
25
|
+
*
|
|
26
|
+
* TokenDataSource and PriceDataSource both key off detectedAssets. TokenDataSource
|
|
27
|
+
* then filters to only fetch metadata for assets that lack it; PriceDataSource
|
|
28
|
+
* fetches prices for all detected assets.
|
|
22
29
|
*
|
|
23
30
|
* Usage:
|
|
24
31
|
* ```typescript
|
|
@@ -34,45 +41,55 @@ class DetectionMiddleware {
|
|
|
34
41
|
return this.name;
|
|
35
42
|
}
|
|
36
43
|
/**
|
|
37
|
-
* Get the middleware for
|
|
44
|
+
* Get the middleware that builds detectedAssets for metadata and price fetching.
|
|
38
45
|
*
|
|
39
46
|
* This middleware:
|
|
40
|
-
* 1.
|
|
41
|
-
* 2.
|
|
42
|
-
* 3. Fills response.detectedAssets with
|
|
43
|
-
* 4. Calls next() to continue the middleware chain
|
|
47
|
+
* 1. Includes all assets from response.assetsBalance (so prices are fetched for existing assets too)
|
|
48
|
+
* 2. Merges each account's custom assets from state
|
|
49
|
+
* 3. Fills response.detectedAssets with these asset IDs per account
|
|
44
50
|
*
|
|
45
51
|
* @returns The middleware function for the assets pipeline.
|
|
46
52
|
*/
|
|
47
53
|
get assetsMiddleware() {
|
|
48
54
|
return (0, types_1.forDataTypes)(['balance'], async (ctx, next) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return next(ctx);
|
|
54
|
-
}
|
|
55
|
-
// Get metadata from state
|
|
56
|
-
const { assetsInfo: stateMetadata } = ctx.getAssetsState();
|
|
55
|
+
const { request, response } = ctx;
|
|
56
|
+
// Get state for custom assets
|
|
57
|
+
const state = ctx.getAssetsState();
|
|
58
|
+
const { customAssets: stateCustomAssets } = state;
|
|
57
59
|
const detectedAssets = {};
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (!stateMetadata[assetId]) {
|
|
60
|
+
// 1. From balance response: include every asset with balance (so prices + metadata path include existing assets)
|
|
61
|
+
if (response.assetsBalance) {
|
|
62
|
+
for (const [accountId, accountBalances] of Object.entries(response.assetsBalance)) {
|
|
63
|
+
const detected = [];
|
|
64
|
+
for (const assetId of Object.keys(accountBalances)) {
|
|
64
65
|
detected.push(assetId);
|
|
65
66
|
}
|
|
67
|
+
// Merge this account's custom assets from state
|
|
68
|
+
const customForAccount = stateCustomAssets?.[accountId] ?? [];
|
|
69
|
+
for (const assetId of customForAccount) {
|
|
70
|
+
if (!detected.includes(assetId)) {
|
|
71
|
+
detected.push(assetId);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (detected.length > 0) {
|
|
75
|
+
detectedAssets[accountId] = detected;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// 2. Accounts in request that weren't in balance response: include their custom assets
|
|
80
|
+
for (const { account } of request.accountsWithSupportedChains) {
|
|
81
|
+
const accountId = account.id;
|
|
82
|
+
if (detectedAssets[accountId]) {
|
|
83
|
+
continue;
|
|
66
84
|
}
|
|
67
|
-
|
|
68
|
-
|
|
85
|
+
const customForAccount = stateCustomAssets?.[accountId] ?? [];
|
|
86
|
+
if (customForAccount.length > 0) {
|
|
87
|
+
detectedAssets[accountId] = customForAccount;
|
|
69
88
|
}
|
|
70
89
|
}
|
|
71
|
-
// Fill detectedAssets in the response
|
|
72
90
|
if (Object.keys(detectedAssets).length > 0) {
|
|
73
91
|
response.detectedAssets = detectedAssets;
|
|
74
92
|
}
|
|
75
|
-
// Call next() to continue the middleware chain
|
|
76
93
|
return next(ctx);
|
|
77
94
|
});
|
|
78
95
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DetectionMiddleware.cjs","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":";;;AAAA,0CAA8D;AAC9D,wCAAwC;AAGxC,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,uBAAuB;AACvB,IAAA,2BAAkB,EAAC,sBAAa,EAAE,eAAe,CAAC,CAAC;AAEnD,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E
|
|
1
|
+
{"version":3,"file":"DetectionMiddleware.cjs","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":";;;AAAA,0CAA8D;AAC9D,wCAAwC;AAGxC,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,uBAAuB;AACvB,IAAA,2BAAkB,EAAC,sBAAa,EAAE,eAAe,CAAC,CAAC;AAEnD,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAa,mBAAmB;IAAhC;QACW,SAAI,GAAG,eAAe,CAAC;IAwElC,CAAC;IAtEC,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,gBAAgB;QAClB,OAAO,IAAA,oBAAY,EAAC,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YACnD,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;YAElC,8BAA8B;YAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACnC,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,GAAG,KAAK,CAAC;YAElD,MAAM,cAAc,GAAuC,EAAE,CAAC;YAE9D,iHAAiH;YACjH,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;gBAC3B,KAAK,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CACvD,QAAQ,CAAC,aAAa,CACvB,EAAE,CAAC;oBACF,MAAM,QAAQ,GAAoB,EAAE,CAAC;oBAErC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,CAC/B,eAA0C,CAC3C,EAAE,CAAC;wBACF,QAAQ,CAAC,IAAI,CAAC,OAAwB,CAAC,CAAC;oBAC1C,CAAC;oBAED,gDAAgD;oBAChD,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;oBAC9D,KAAK,MAAM,OAAO,IAAI,gBAAgB,EAAE,CAAC;wBACvC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;4BAChC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;wBACzB,CAAC;oBACH,CAAC;oBAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACxB,cAAc,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC;oBACvC,CAAC;gBACH,CAAC;YACH,CAAC;YAED,uFAAuF;YACvF,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,OAAO,CAAC,2BAA2B,EAAE,CAAC;gBAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC;gBAC7B,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC9B,SAAS;gBACX,CAAC;gBACD,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;gBAC9D,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAChC,cAAc,CAAC,SAAS,CAAC,GAAG,gBAAgB,CAAC;gBAC/C,CAAC;YACH,CAAC;YAED,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3C,QAAQ,CAAC,cAAc,GAAG,cAAc,CAAC;YAC3C,CAAC;YAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAzED,kDAyEC","sourcesContent":["import { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type { AccountId, Caip19AssetId, Middleware } from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'DetectionMiddleware';\n\n// Logger for debugging\ncreateModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// DETECTION MIDDLEWARE\n// ============================================================================\n\n/**\n * DetectionMiddleware builds the set of assets that downstream sources use for\n * metadata and price fetching.\n *\n * This middleware:\n * - Includes every asset that appears in response.assetsBalance (so prices and\n * metadata are fetched for existing assets as well as new ones)\n * - Includes each account's custom assets from state (so custom tokens get\n * metadata and prices even when they have no balance yet)\n * - Fills response.detectedAssets with these asset IDs per account\n *\n * TokenDataSource and PriceDataSource both key off detectedAssets. TokenDataSource\n * then filters to only fetch metadata for assets that lack it; PriceDataSource\n * fetches prices for all detected assets.\n *\n * Usage:\n * ```typescript\n * const detectionMiddleware = new DetectionMiddleware();\n * const middleware = detectionMiddleware.assetsMiddleware;\n * ```\n */\nexport class DetectionMiddleware {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /**\n * Get the middleware that builds detectedAssets for metadata and price fetching.\n *\n * This middleware:\n * 1. Includes all assets from response.assetsBalance (so prices are fetched for existing assets too)\n * 2. Merges each account's custom assets from state\n * 3. Fills response.detectedAssets with these asset IDs per account\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['balance'], async (ctx, next) => {\n const { request, response } = ctx;\n\n // Get state for custom assets\n const state = ctx.getAssetsState();\n const { customAssets: stateCustomAssets } = state;\n\n const detectedAssets: Record<AccountId, Caip19AssetId[]> = {};\n\n // 1. From balance response: include every asset with balance (so prices + metadata path include existing assets)\n if (response.assetsBalance) {\n for (const [accountId, accountBalances] of Object.entries(\n response.assetsBalance,\n )) {\n const detected: Caip19AssetId[] = [];\n\n for (const assetId of Object.keys(\n accountBalances as Record<string, unknown>,\n )) {\n detected.push(assetId as Caip19AssetId);\n }\n\n // Merge this account's custom assets from state\n const customForAccount = stateCustomAssets?.[accountId] ?? [];\n for (const assetId of customForAccount) {\n if (!detected.includes(assetId)) {\n detected.push(assetId);\n }\n }\n\n if (detected.length > 0) {\n detectedAssets[accountId] = detected;\n }\n }\n }\n\n // 2. Accounts in request that weren't in balance response: include their custom assets\n for (const { account } of request.accountsWithSupportedChains) {\n const accountId = account.id;\n if (detectedAssets[accountId]) {\n continue;\n }\n const customForAccount = stateCustomAssets?.[accountId] ?? [];\n if (customForAccount.length > 0) {\n detectedAssets[accountId] = customForAccount;\n }\n }\n\n if (Object.keys(detectedAssets).length > 0) {\n response.detectedAssets = detectedAssets;\n }\n\n return next(ctx);\n });\n }\n}\n"]}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import type { Middleware } from "../types.cjs";
|
|
2
2
|
/**
|
|
3
|
-
* DetectionMiddleware
|
|
3
|
+
* DetectionMiddleware builds the set of assets that downstream sources use for
|
|
4
|
+
* metadata and price fetching.
|
|
4
5
|
*
|
|
5
6
|
* This middleware:
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
7
|
+
* - Includes every asset that appears in response.assetsBalance (so prices and
|
|
8
|
+
* metadata are fetched for existing assets as well as new ones)
|
|
9
|
+
* - Includes each account's custom assets from state (so custom tokens get
|
|
10
|
+
* metadata and prices even when they have no balance yet)
|
|
11
|
+
* - Fills response.detectedAssets with these asset IDs per account
|
|
12
|
+
*
|
|
13
|
+
* TokenDataSource and PriceDataSource both key off detectedAssets. TokenDataSource
|
|
14
|
+
* then filters to only fetch metadata for assets that lack it; PriceDataSource
|
|
15
|
+
* fetches prices for all detected assets.
|
|
9
16
|
*
|
|
10
17
|
* Usage:
|
|
11
18
|
* ```typescript
|
|
@@ -17,13 +24,12 @@ export declare class DetectionMiddleware {
|
|
|
17
24
|
readonly name = "DetectionMiddleware";
|
|
18
25
|
getName(): string;
|
|
19
26
|
/**
|
|
20
|
-
* Get the middleware for
|
|
27
|
+
* Get the middleware that builds detectedAssets for metadata and price fetching.
|
|
21
28
|
*
|
|
22
29
|
* This middleware:
|
|
23
|
-
* 1.
|
|
24
|
-
* 2.
|
|
25
|
-
* 3. Fills response.detectedAssets with
|
|
26
|
-
* 4. Calls next() to continue the middleware chain
|
|
30
|
+
* 1. Includes all assets from response.assetsBalance (so prices are fetched for existing assets too)
|
|
31
|
+
* 2. Merges each account's custom assets from state
|
|
32
|
+
* 3. Fills response.detectedAssets with these asset IDs per account
|
|
27
33
|
*
|
|
28
34
|
* @returns The middleware function for the assets pipeline.
|
|
29
35
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DetectionMiddleware.d.cts","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA4B,UAAU,EAAE,qBAAiB;AAerE
|
|
1
|
+
{"version":3,"file":"DetectionMiddleware.d.cts","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA4B,UAAU,EAAE,qBAAiB;AAerE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,mBAAmB;IAC9B,QAAQ,CAAC,IAAI,yBAAmB;IAEhC,OAAO,IAAI,MAAM;IAIjB;;;;;;;;;OASG;IACH,IAAI,gBAAgB,IAAI,UAAU,CAuDjC;CACF"}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import type { Middleware } from "../types.mjs";
|
|
2
2
|
/**
|
|
3
|
-
* DetectionMiddleware
|
|
3
|
+
* DetectionMiddleware builds the set of assets that downstream sources use for
|
|
4
|
+
* metadata and price fetching.
|
|
4
5
|
*
|
|
5
6
|
* This middleware:
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
7
|
+
* - Includes every asset that appears in response.assetsBalance (so prices and
|
|
8
|
+
* metadata are fetched for existing assets as well as new ones)
|
|
9
|
+
* - Includes each account's custom assets from state (so custom tokens get
|
|
10
|
+
* metadata and prices even when they have no balance yet)
|
|
11
|
+
* - Fills response.detectedAssets with these asset IDs per account
|
|
12
|
+
*
|
|
13
|
+
* TokenDataSource and PriceDataSource both key off detectedAssets. TokenDataSource
|
|
14
|
+
* then filters to only fetch metadata for assets that lack it; PriceDataSource
|
|
15
|
+
* fetches prices for all detected assets.
|
|
9
16
|
*
|
|
10
17
|
* Usage:
|
|
11
18
|
* ```typescript
|
|
@@ -17,13 +24,12 @@ export declare class DetectionMiddleware {
|
|
|
17
24
|
readonly name = "DetectionMiddleware";
|
|
18
25
|
getName(): string;
|
|
19
26
|
/**
|
|
20
|
-
* Get the middleware for
|
|
27
|
+
* Get the middleware that builds detectedAssets for metadata and price fetching.
|
|
21
28
|
*
|
|
22
29
|
* This middleware:
|
|
23
|
-
* 1.
|
|
24
|
-
* 2.
|
|
25
|
-
* 3. Fills response.detectedAssets with
|
|
26
|
-
* 4. Calls next() to continue the middleware chain
|
|
30
|
+
* 1. Includes all assets from response.assetsBalance (so prices are fetched for existing assets too)
|
|
31
|
+
* 2. Merges each account's custom assets from state
|
|
32
|
+
* 3. Fills response.detectedAssets with these asset IDs per account
|
|
27
33
|
*
|
|
28
34
|
* @returns The middleware function for the assets pipeline.
|
|
29
35
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DetectionMiddleware.d.mts","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA4B,UAAU,EAAE,qBAAiB;AAerE
|
|
1
|
+
{"version":3,"file":"DetectionMiddleware.d.mts","sourceRoot":"","sources":["../../src/middlewares/DetectionMiddleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA4B,UAAU,EAAE,qBAAiB;AAerE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,mBAAmB;IAC9B,QAAQ,CAAC,IAAI,yBAAmB;IAEhC,OAAO,IAAI,MAAM;IAIjB;;;;;;;;;OASG;IACH,IAAI,gBAAgB,IAAI,UAAU,CAuDjC;CACF"}
|