@metamask/assets-controller 6.3.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +47 -1
  2. package/dist/AssetsController-method-action-types.cjs.map +1 -1
  3. package/dist/AssetsController-method-action-types.d.cts +10 -1
  4. package/dist/AssetsController-method-action-types.d.cts.map +1 -1
  5. package/dist/AssetsController-method-action-types.d.mts +10 -1
  6. package/dist/AssetsController-method-action-types.d.mts.map +1 -1
  7. package/dist/AssetsController-method-action-types.mjs.map +1 -1
  8. package/dist/AssetsController.cjs +35 -42
  9. package/dist/AssetsController.cjs.map +1 -1
  10. package/dist/AssetsController.d.cts +2 -2
  11. package/dist/AssetsController.d.cts.map +1 -1
  12. package/dist/AssetsController.d.mts +2 -2
  13. package/dist/AssetsController.d.mts.map +1 -1
  14. package/dist/AssetsController.mjs +35 -42
  15. package/dist/AssetsController.mjs.map +1 -1
  16. package/dist/data-sources/RpcDataSource.cjs +46 -25
  17. package/dist/data-sources/RpcDataSource.cjs.map +1 -1
  18. package/dist/data-sources/RpcDataSource.d.cts +12 -0
  19. package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
  20. package/dist/data-sources/RpcDataSource.d.mts +12 -0
  21. package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
  22. package/dist/data-sources/RpcDataSource.mjs +46 -25
  23. package/dist/data-sources/RpcDataSource.mjs.map +1 -1
  24. package/dist/data-sources/TokenDataSource.cjs +12 -5
  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 +12 -5
  29. package/dist/data-sources/TokenDataSource.mjs.map +1 -1
  30. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.cjs +124 -32
  31. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.cjs.map +1 -1
  32. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.cts +31 -3
  33. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.cts.map +1 -1
  34. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.mts +31 -3
  35. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.d.mts.map +1 -1
  36. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.mjs +124 -32
  37. package/dist/data-sources/evm-rpc-services/clients/TokensApiClient.mjs.map +1 -1
  38. package/dist/data-sources/evm-rpc-services/clients/index.cjs.map +1 -1
  39. package/dist/data-sources/evm-rpc-services/clients/index.d.cts +1 -1
  40. package/dist/data-sources/evm-rpc-services/clients/index.d.cts.map +1 -1
  41. package/dist/data-sources/evm-rpc-services/clients/index.d.mts +1 -1
  42. package/dist/data-sources/evm-rpc-services/clients/index.d.mts.map +1 -1
  43. package/dist/data-sources/evm-rpc-services/clients/index.mjs.map +1 -1
  44. package/dist/data-sources/evm-rpc-services/index.cjs.map +1 -1
  45. package/dist/data-sources/evm-rpc-services/index.d.cts +1 -1
  46. package/dist/data-sources/evm-rpc-services/index.d.cts.map +1 -1
  47. package/dist/data-sources/evm-rpc-services/index.d.mts +1 -1
  48. package/dist/data-sources/evm-rpc-services/index.d.mts.map +1 -1
  49. package/dist/data-sources/evm-rpc-services/index.mjs.map +1 -1
  50. package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs.map +1 -1
  51. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts.map +1 -1
  52. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts.map +1 -1
  53. package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs.map +1 -1
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.d.cts +1 -1
  56. package/dist/index.d.cts.map +1 -1
  57. package/dist/index.d.mts +1 -1
  58. package/dist/index.d.mts.map +1 -1
  59. package/dist/index.mjs.map +1 -1
  60. package/dist/middlewares/CustomAssetGraduationMiddleware.cjs +32 -4
  61. package/dist/middlewares/CustomAssetGraduationMiddleware.cjs.map +1 -1
  62. package/dist/middlewares/CustomAssetGraduationMiddleware.d.cts +11 -4
  63. package/dist/middlewares/CustomAssetGraduationMiddleware.d.cts.map +1 -1
  64. package/dist/middlewares/CustomAssetGraduationMiddleware.d.mts +11 -4
  65. package/dist/middlewares/CustomAssetGraduationMiddleware.d.mts.map +1 -1
  66. package/dist/middlewares/CustomAssetGraduationMiddleware.mjs +32 -4
  67. package/dist/middlewares/CustomAssetGraduationMiddleware.mjs.map +1 -1
  68. package/dist/utils/customAssetsRpcSupplement.cjs +72 -0
  69. package/dist/utils/customAssetsRpcSupplement.cjs.map +1 -0
  70. package/dist/utils/customAssetsRpcSupplement.d.cts +60 -0
  71. package/dist/utils/customAssetsRpcSupplement.d.cts.map +1 -0
  72. package/dist/utils/customAssetsRpcSupplement.d.mts +60 -0
  73. package/dist/utils/customAssetsRpcSupplement.d.mts.map +1 -0
  74. package/dist/utils/customAssetsRpcSupplement.mjs +68 -0
  75. package/dist/utils/customAssetsRpcSupplement.mjs.map +1 -0
  76. package/package.json +8 -8
@@ -0,0 +1,68 @@
1
+ import { parseCaipAssetType } from "@metamask/utils";
2
+ /**
3
+ * Decide which chains require a supplemental `customAssetsOnly` RPC
4
+ * subscription so that user-imported customAssets are **always** polled by
5
+ * RPC — even when AccountsApi or the websocket data source has already
6
+ * claimed the chain in the regular handoff.
7
+ *
8
+ * RPC is the sole balance fetcher for customAssets:
9
+ * - AccountsApi indexes a curated token list and may return zero (or no
10
+ * entry at all) for a user-imported token, even on supported chains.
11
+ * - The websocket data source is push-only: it relays balance deltas from
12
+ * transactions, so a user who never transacts won't see balance updates.
13
+ *
14
+ * To guarantee freshness, we subscribe RPC in `customAssetsOnly` mode on
15
+ * any chain that:
16
+ * 1. has at least one selected account with a customAsset there;
17
+ * 2. is supported by the RPC data source;
18
+ * 3. is **not** already covered by the regular RPC subscription
19
+ * (`rpcAssignedChains`) — otherwise customAssets are picked up there;
20
+ * 4. is currently enabled (in `chainToAccounts`); polling a disabled
21
+ * chain wastes resources because the user can't see its balances.
22
+ *
23
+ * Malformed asset IDs are silently skipped — they can't be parsed into a
24
+ * chain anyway and shouldn't crash the subscription pipeline.
25
+ *
26
+ * @param input - Decision inputs.
27
+ * @returns Chains and account IDs that require supplemental subscription.
28
+ */
29
+ export function pickRpcCustomAssetsSupplement(input) {
30
+ const { accountIds, customAssetsByAccount, rpcAssignedChains, rpcAvailableChains, enabledChains, } = input;
31
+ const chains = new Set();
32
+ const supplementalAccountIds = new Set();
33
+ for (const accountId of accountIds) {
34
+ const customForAccount = customAssetsByAccount[accountId];
35
+ if (!customForAccount || customForAccount.length === 0) {
36
+ continue;
37
+ }
38
+ // Mirror the controller's prior behavior: an account with any customAsset
39
+ // (even if all are filtered out below) is added to the candidate set.
40
+ // The empty-chains early-return in the caller still prevents a useless
41
+ // subscription, so this preserves observable behavior.
42
+ supplementalAccountIds.add(accountId);
43
+ for (const assetId of customForAccount) {
44
+ let chainId;
45
+ try {
46
+ chainId = parseCaipAssetType(assetId).chainId;
47
+ }
48
+ catch {
49
+ continue;
50
+ }
51
+ if (rpcAssignedChains.has(chainId)) {
52
+ continue;
53
+ }
54
+ if (!rpcAvailableChains.has(chainId)) {
55
+ continue;
56
+ }
57
+ if (!enabledChains.has(chainId)) {
58
+ continue;
59
+ }
60
+ chains.add(chainId);
61
+ }
62
+ }
63
+ return {
64
+ chains: [...chains],
65
+ accountIds: supplementalAccountIds,
66
+ };
67
+ }
68
+ //# sourceMappingURL=customAssetsRpcSupplement.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customAssetsRpcSupplement.mjs","sourceRoot":"","sources":["../../src/utils/customAssetsRpcSupplement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AAoCrD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,6BAA6B,CAC3C,KAAqC;IAErC,MAAM,EACJ,UAAU,EACV,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,GACd,GAAG,KAAK,CAAC;IAEV,MAAM,MAAM,GAAG,IAAI,GAAG,EAAW,CAAC;IAClC,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAU,CAAC;IAEjD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvD,SAAS;QACX,CAAC;QACD,0EAA0E;QAC1E,sEAAsE;QACtE,uEAAuE;QACvE,uDAAuD;QACvD,sBAAsB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACtC,KAAK,MAAM,OAAO,IAAI,gBAAgB,EAAE,CAAC;YACvC,IAAI,OAAgB,CAAC;YACrB,IAAI,CAAC;gBACH,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnC,SAAS;YACX,CAAC;YACD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrC,SAAS;YACX,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChC,SAAS;YACX,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO;QACL,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC;QACnB,UAAU,EAAE,sBAAsB;KACnC,CAAC;AACJ,CAAC","sourcesContent":["import { parseCaipAssetType } from '@metamask/utils';\n\nimport type { Caip19AssetId, ChainId } from '../types';\n\n/**\n * Inputs needed to decide whether `RpcDataSource` should run a supplemental\n * `customAssetsOnly` subscription. All inputs are pre-computed by the caller\n * (controller) so this helper is fully pure and deterministic.\n */\nexport type RpcCustomAssetsSupplementInput = {\n /** Selected account IDs being considered for subscription. */\n accountIds: string[];\n /** `state.customAssets` slice — accountId → CAIP-19 asset IDs. */\n customAssetsByAccount: Record<string, Caip19AssetId[]>;\n /** Chains the regular RPC subscription already covers. */\n rpcAssignedChains: Set<ChainId>;\n /** Chains the RPC data source can serve (its current activeChains). */\n rpcAvailableChains: Set<ChainId>;\n /**\n * Chains that are currently enabled for at least one selected account\n * (i.e. keys of the controller's chainToAccounts map).\n */\n enabledChains: Set<ChainId>;\n};\n\n/**\n * The decision output: which chains and accounts need a supplemental\n * `customAssetsOnly` RPC subscription.\n */\nexport type RpcCustomAssetsSupplementResult = {\n /** Chains that need a supplemental customAssetsOnly RPC subscription. */\n chains: ChainId[];\n /** Accounts that own at least one customAsset on a supplemental chain. */\n accountIds: Set<string>;\n};\n\n/**\n * Decide which chains require a supplemental `customAssetsOnly` RPC\n * subscription so that user-imported customAssets are **always** polled by\n * RPC — even when AccountsApi or the websocket data source has already\n * claimed the chain in the regular handoff.\n *\n * RPC is the sole balance fetcher for customAssets:\n * - AccountsApi indexes a curated token list and may return zero (or no\n * entry at all) for a user-imported token, even on supported chains.\n * - The websocket data source is push-only: it relays balance deltas from\n * transactions, so a user who never transacts won't see balance updates.\n *\n * To guarantee freshness, we subscribe RPC in `customAssetsOnly` mode on\n * any chain that:\n * 1. has at least one selected account with a customAsset there;\n * 2. is supported by the RPC data source;\n * 3. is **not** already covered by the regular RPC subscription\n * (`rpcAssignedChains`) — otherwise customAssets are picked up there;\n * 4. is currently enabled (in `chainToAccounts`); polling a disabled\n * chain wastes resources because the user can't see its balances.\n *\n * Malformed asset IDs are silently skipped — they can't be parsed into a\n * chain anyway and shouldn't crash the subscription pipeline.\n *\n * @param input - Decision inputs.\n * @returns Chains and account IDs that require supplemental subscription.\n */\nexport function pickRpcCustomAssetsSupplement(\n input: RpcCustomAssetsSupplementInput,\n): RpcCustomAssetsSupplementResult {\n const {\n accountIds,\n customAssetsByAccount,\n rpcAssignedChains,\n rpcAvailableChains,\n enabledChains,\n } = input;\n\n const chains = new Set<ChainId>();\n const supplementalAccountIds = new Set<string>();\n\n for (const accountId of accountIds) {\n const customForAccount = customAssetsByAccount[accountId];\n if (!customForAccount || customForAccount.length === 0) {\n continue;\n }\n // Mirror the controller's prior behavior: an account with any customAsset\n // (even if all are filtered out below) is added to the candidate set.\n // The empty-chains early-return in the caller still prevents a useless\n // subscription, so this preserves observable behavior.\n supplementalAccountIds.add(accountId);\n for (const assetId of customForAccount) {\n let chainId: ChainId;\n try {\n chainId = parseCaipAssetType(assetId).chainId;\n } catch {\n continue;\n }\n if (rpcAssignedChains.has(chainId)) {\n continue;\n }\n if (!rpcAvailableChains.has(chainId)) {\n continue;\n }\n if (!enabledChains.has(chainId)) {\n continue;\n }\n chains.add(chainId);\n }\n }\n\n return {\n chains: [...chains],\n accountIds: supplementalAccountIds,\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/assets-controller",
3
- "version": "6.3.0",
3
+ "version": "7.0.0",
4
4
  "description": "Tracks assets balances/prices and handles token detection across all digital assets",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -56,27 +56,27 @@
56
56
  "@ethereumjs/util": "^9.1.0",
57
57
  "@ethersproject/abi": "^5.7.0",
58
58
  "@ethersproject/providers": "^5.7.0",
59
- "@metamask/account-tree-controller": "^7.1.0",
60
- "@metamask/accounts-controller": "^37.2.0",
61
- "@metamask/assets-controllers": "^105.1.0",
59
+ "@metamask/account-tree-controller": "^7.3.0",
60
+ "@metamask/accounts-controller": "^38.0.0",
61
+ "@metamask/assets-controllers": "^106.0.0",
62
62
  "@metamask/base-controller": "^9.1.0",
63
63
  "@metamask/client-controller": "^1.0.1",
64
64
  "@metamask/controller-utils": "^11.20.0",
65
65
  "@metamask/core-backend": "^6.2.1",
66
66
  "@metamask/keyring-api": "^23.1.0",
67
- "@metamask/keyring-controller": "^25.3.0",
67
+ "@metamask/keyring-controller": "^25.5.0",
68
68
  "@metamask/keyring-internal-api": "^11.0.1",
69
69
  "@metamask/keyring-snap-client": "^9.0.2",
70
70
  "@metamask/messenger": "^1.2.0",
71
71
  "@metamask/network-controller": "^30.1.0",
72
- "@metamask/network-enablement-controller": "^5.0.2",
73
- "@metamask/permission-controller": "^13.0.0",
72
+ "@metamask/network-enablement-controller": "^5.1.0",
73
+ "@metamask/permission-controller": "^13.1.0",
74
74
  "@metamask/phishing-controller": "^17.1.1",
75
75
  "@metamask/polling-controller": "^16.0.4",
76
76
  "@metamask/preferences-controller": "^23.1.0",
77
77
  "@metamask/snaps-controllers": "^19.0.0",
78
78
  "@metamask/snaps-utils": "^12.1.2",
79
- "@metamask/transaction-controller": "^65.0.0",
79
+ "@metamask/transaction-controller": "^65.2.0",
80
80
  "@metamask/utils": "^11.9.0",
81
81
  "async-mutex": "^0.5.0",
82
82
  "bignumber.js": "^9.1.2",