@metamask-previews/assets-controllers 83.1.0-preview-71feeb92 → 83.1.0-preview-2bb073da

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -9,15 +9,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Changed
11
11
 
12
- - **BREAKING:** Modify DeFi position fetching behaviour ([#6944](https://github.com/MetaMask/core/pull/6944))
13
-
14
- - The fetch request to the API times out after 8 seconds and attempts a single retry
15
- - Refresh only updates the selected evm address
16
- - `KeyringController:unlock` no longer starts polling
17
- - `AccountsController:accountAdded` no longer updates DeFi positions
18
- - `AccountTreeController:selectedAccountGroupChange` updates DeFi positions for the selected address
19
- - `TransactionController:transactionConfirmed` only updates DeFi positions if the transaction is for the selected address
20
-
21
12
  - Bump `@metamask/polling-controller` from `^14.0.1` to `^14.0.2` ([#6940](https://github.com/MetaMask/core/pull/6940))
22
13
 
23
14
  ## [83.1.0]
@@ -10,15 +10,16 @@ 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 _DeFiPositionsController_instances, _DeFiPositionsController_fetchPositions, _DeFiPositionsController_isEnabled, _DeFiPositionsController_trackEvent, _DeFiPositionsController_updateAccountPositions, _DeFiPositionsController_fetchAccountPositions, _DeFiPositionsController_updatePositionsCountMetrics, _DeFiPositionsController_getSelectedEvmAdress;
13
+ var _DeFiPositionsController_instances, _DeFiPositionsController_fetchPositions, _DeFiPositionsController_isEnabled, _DeFiPositionsController_trackEvent, _DeFiPositionsController_updateAccountPositions, _DeFiPositionsController_fetchAccountPositions, _DeFiPositionsController_updatePositionsCountMetrics;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.DeFiPositionsController = exports.getDefaultDefiPositionsControllerState = void 0;
16
- const keyring_api_1 = require("@metamask/keyring-api");
17
16
  const polling_controller_1 = require("@metamask/polling-controller");
18
17
  const calculate_defi_metrics_1 = require("./calculate-defi-metrics.cjs");
19
18
  const fetch_positions_1 = require("./fetch-positions.cjs");
20
19
  const group_defi_positions_1 = require("./group-defi-positions.cjs");
20
+ const assetsUtil_1 = require("../assetsUtil.cjs");
21
21
  const TEN_MINUTES_IN_MS = 600000;
22
+ const FETCH_POSITIONS_BATCH_SIZE = 10;
22
23
  const controllerName = 'DeFiPositionsController';
23
24
  const controllerMetadata = {
24
25
  allDeFiPositions: {
@@ -67,24 +68,23 @@ class DeFiPositionsController extends (0, polling_controller_1.StaticIntervalPol
67
68
  this.setIntervalLength(TEN_MINUTES_IN_MS);
68
69
  __classPrivateFieldSet(this, _DeFiPositionsController_fetchPositions, (0, fetch_positions_1.buildPositionFetcher)(), "f");
69
70
  __classPrivateFieldSet(this, _DeFiPositionsController_isEnabled, isEnabled, "f");
71
+ this.messagingSystem.subscribe('KeyringController:unlock', () => {
72
+ this.startPolling(null);
73
+ });
70
74
  this.messagingSystem.subscribe('KeyringController:lock', () => {
71
75
  this.stopAllPolling();
72
76
  });
73
77
  this.messagingSystem.subscribe('TransactionController:transactionConfirmed', async (transactionMeta) => {
74
- const selectedAddress = __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_getSelectedEvmAdress).call(this);
75
- if (!selectedAddress ||
76
- selectedAddress.toLowerCase() !==
77
- transactionMeta.txParams.from.toLowerCase()) {
78
+ if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this)) {
78
79
  return;
79
80
  }
80
- await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, selectedAddress);
81
+ await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, transactionMeta.txParams.from);
81
82
  });
82
- this.messagingSystem.subscribe('AccountTreeController:selectedAccountGroupChange', async () => {
83
- const selectedAddress = __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_getSelectedEvmAdress).call(this);
84
- if (!selectedAddress) {
83
+ this.messagingSystem.subscribe('AccountsController:accountAdded', async (account) => {
84
+ if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this) || !account.type.startsWith('eip155:')) {
85
85
  return;
86
86
  }
87
- await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, selectedAddress);
87
+ await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, account.address);
88
88
  });
89
89
  __classPrivateFieldSet(this, _DeFiPositionsController_trackEvent, trackEvent, "f");
90
90
  }
@@ -92,21 +92,37 @@ class DeFiPositionsController extends (0, polling_controller_1.StaticIntervalPol
92
92
  if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this)) {
93
93
  return;
94
94
  }
95
- const selectedAddress = __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_getSelectedEvmAdress).call(this);
96
- if (!selectedAddress) {
97
- return;
98
- }
99
- const accountPositions = await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_fetchAccountPositions).call(this, selectedAddress);
95
+ const accounts = this.messagingSystem.call('AccountsController:listAccounts');
96
+ const initialResult = [];
97
+ const results = await (0, assetsUtil_1.reduceInBatchesSerially)({
98
+ initialResult,
99
+ values: accounts,
100
+ batchSize: FETCH_POSITIONS_BATCH_SIZE,
101
+ eachBatch: async (workingResult, batch) => {
102
+ const batchResults = (await Promise.all(batch.map(async ({ address: accountAddress, type }) => {
103
+ if (type.startsWith('eip155:')) {
104
+ const positions = await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_fetchAccountPositions).call(this, accountAddress);
105
+ return {
106
+ accountAddress,
107
+ positions,
108
+ };
109
+ }
110
+ return undefined;
111
+ }))).filter(Boolean);
112
+ return [...workingResult, ...batchResults];
113
+ },
114
+ });
115
+ const allDefiPositions = results.reduce((acc, { accountAddress, positions }) => {
116
+ acc[accountAddress] = positions;
117
+ return acc;
118
+ }, {});
100
119
  this.update((state) => {
101
- state.allDeFiPositions[selectedAddress] = accountPositions;
120
+ state.allDeFiPositions = allDefiPositions;
102
121
  });
103
122
  }
104
123
  }
105
124
  exports.DeFiPositionsController = DeFiPositionsController;
106
125
  _DeFiPositionsController_fetchPositions = new WeakMap(), _DeFiPositionsController_isEnabled = new WeakMap(), _DeFiPositionsController_trackEvent = new WeakMap(), _DeFiPositionsController_instances = new WeakSet(), _DeFiPositionsController_updateAccountPositions = async function _DeFiPositionsController_updateAccountPositions(accountAddress) {
107
- if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this)) {
108
- return;
109
- }
110
126
  const accountPositionsPerChain = await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_fetchAccountPositions).call(this, accountAddress);
111
127
  this.update((state) => {
112
128
  state.allDeFiPositions[accountAddress] = accountPositionsPerChain;
@@ -139,10 +155,5 @@ _DeFiPositionsController_fetchPositions = new WeakMap(), _DeFiPositionsControlle
139
155
  });
140
156
  __classPrivateFieldGet(this, _DeFiPositionsController_trackEvent, "f")?.call(this, defiMetrics);
141
157
  }
142
- }, _DeFiPositionsController_getSelectedEvmAdress = function _DeFiPositionsController_getSelectedEvmAdress() {
143
- return this.messagingSystem
144
- .call('AccountTreeController:getAccountsFromSelectedAccountGroup')
145
- .find((account) => (0, keyring_api_1.isEvmAccountType)(account.type))
146
- ?.address;
147
158
  };
148
159
  //# sourceMappingURL=DeFiPositionsController.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeFiPositionsController.cjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n} from '@metamask/account-tree-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { KeyringControllerLockEvent } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { TransactionControllerTransactionConfirmedEvent } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport { calculateDeFiPositionMetrics } from './calculate-defi-metrics';\nimport type { DefiPositionResponse } from './fetch-positions';\nimport { buildPositionFetcher } from './fetch-positions';\nimport {\n groupDeFiPositions,\n type GroupedDeFiPositions,\n} from './group-defi-positions';\n\nconst TEN_MINUTES_IN_MS = 600_000;\n\nconst controllerName = 'DeFiPositionsController';\n\nexport type GroupedDeFiPositionsPerChain = {\n [chain: Hex]: GroupedDeFiPositions;\n};\n\nexport type TrackingEventPayload = {\n event: string;\n category: string;\n properties: {\n totalPositions: number;\n totalMarketValueUSD: number;\n breakdown?: {\n protocolId: string;\n marketValueUSD: number;\n chainId: Hex;\n count: number;\n }[];\n };\n};\n\ntype TrackEventHook = (event: TrackingEventPayload) => void;\n\nexport type DeFiPositionsControllerState = {\n /**\n * Object containing DeFi positions per account and network\n */\n allDeFiPositions: {\n [accountAddress: string]: GroupedDeFiPositionsPerChain | null;\n };\n\n /**\n * Object containing DeFi positions count per account\n */\n allDeFiPositionsCount: {\n [accountAddress: string]: number;\n };\n};\n\nconst controllerMetadata: StateMetadata<DeFiPositionsControllerState> = {\n allDeFiPositions: {\n includeInStateLogs: false,\n persist: false,\n anonymous: false,\n usedInUi: true,\n },\n allDeFiPositionsCount: {\n includeInStateLogs: false,\n persist: false,\n anonymous: false,\n usedInUi: false,\n },\n};\n\nexport const getDefaultDefiPositionsControllerState =\n (): DeFiPositionsControllerState => {\n return {\n allDeFiPositions: {},\n allDeFiPositionsCount: {},\n };\n };\n\nexport type DeFiPositionsControllerActions =\n DeFiPositionsControllerGetStateAction;\n\nexport type DeFiPositionsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n DeFiPositionsControllerState\n>;\n\nexport type DeFiPositionsControllerEvents =\n DeFiPositionsControllerStateChangeEvent;\n\nexport type DeFiPositionsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n DeFiPositionsControllerState\n >;\n\n/**\n * The external actions available to the {@link DeFiPositionsController}.\n */\nexport type AllowedActions =\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction;\n\n/**\n * The external events available to the {@link DeFiPositionsController}.\n */\nexport type AllowedEvents =\n | KeyringControllerLockEvent\n | TransactionControllerTransactionConfirmedEvent\n | AccountTreeControllerSelectedAccountGroupChangeEvent;\n\n/**\n * The messenger of the {@link DeFiPositionsController}.\n */\nexport type DeFiPositionsControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n DeFiPositionsControllerActions | AllowedActions,\n DeFiPositionsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Controller that stores assets and exposes convenience methods\n */\nexport class DeFiPositionsController extends StaticIntervalPollingController()<\n typeof controllerName,\n DeFiPositionsControllerState,\n DeFiPositionsControllerMessenger\n> {\n readonly #fetchPositions: (\n accountAddress: string,\n ) => Promise<DefiPositionResponse[]>;\n\n readonly #isEnabled: () => boolean;\n\n readonly #trackEvent?: TrackEventHook;\n\n /**\n * DeFiPositionsController constuctor\n *\n * @param options - Constructor options.\n * @param options.messenger - The controller messenger.\n * @param options.isEnabled - Function that returns whether the controller is enabled. (default: () => true)\n * @param options.trackEvent - Function to track events. (default: undefined)\n */\n constructor({\n messenger,\n isEnabled = () => true,\n trackEvent,\n }: {\n messenger: DeFiPositionsControllerMessenger;\n isEnabled?: () => boolean;\n trackEvent?: TrackEventHook;\n }) {\n super({\n name: controllerName,\n metadata: controllerMetadata,\n messenger,\n state: getDefaultDefiPositionsControllerState(),\n });\n\n this.setIntervalLength(TEN_MINUTES_IN_MS);\n\n this.#fetchPositions = buildPositionFetcher();\n this.#isEnabled = isEnabled;\n\n this.messagingSystem.subscribe('KeyringController:lock', () => {\n this.stopAllPolling();\n });\n\n this.messagingSystem.subscribe(\n 'TransactionController:transactionConfirmed',\n async (transactionMeta) => {\n const selectedAddress = this.#getSelectedEvmAdress();\n\n if (\n !selectedAddress ||\n selectedAddress.toLowerCase() !==\n transactionMeta.txParams.from.toLowerCase()\n ) {\n return;\n }\n\n await this.#updateAccountPositions(selectedAddress);\n },\n );\n\n this.messagingSystem.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n async () => {\n const selectedAddress = this.#getSelectedEvmAdress();\n\n if (!selectedAddress) {\n return;\n }\n\n await this.#updateAccountPositions(selectedAddress);\n },\n );\n\n this.#trackEvent = trackEvent;\n }\n\n async _executePoll(): Promise<void> {\n if (!this.#isEnabled()) {\n return;\n }\n\n const selectedAddress = this.#getSelectedEvmAdress();\n\n if (!selectedAddress) {\n return;\n }\n\n const accountPositions = await this.#fetchAccountPositions(selectedAddress);\n\n this.update((state) => {\n state.allDeFiPositions[selectedAddress] = accountPositions;\n });\n }\n\n async #updateAccountPositions(accountAddress: string): Promise<void> {\n if (!this.#isEnabled()) {\n return;\n }\n\n const accountPositionsPerChain =\n await this.#fetchAccountPositions(accountAddress);\n\n this.update((state) => {\n state.allDeFiPositions[accountAddress] = accountPositionsPerChain;\n });\n }\n\n async #fetchAccountPositions(\n accountAddress: string,\n ): Promise<GroupedDeFiPositionsPerChain | null> {\n try {\n const defiPositionsResponse = await this.#fetchPositions(accountAddress);\n\n const groupedDeFiPositions = groupDeFiPositions(defiPositionsResponse);\n\n try {\n this.#updatePositionsCountMetrics(groupedDeFiPositions, accountAddress);\n } catch (error) {\n console.error(\n `Failed to update positions count for account ${accountAddress}:`,\n error,\n );\n }\n\n return groupedDeFiPositions;\n } catch {\n return null;\n }\n }\n\n #updatePositionsCountMetrics(\n groupedDeFiPositions: GroupedDeFiPositionsPerChain,\n accountAddress: string,\n ) {\n // If no track event passed then skip the metrics update\n if (!this.#trackEvent) {\n return;\n }\n\n const defiMetrics = calculateDeFiPositionMetrics(groupedDeFiPositions);\n const { totalPositions } = defiMetrics.properties;\n\n if (totalPositions !== this.state.allDeFiPositionsCount[accountAddress]) {\n this.update((state) => {\n state.allDeFiPositionsCount[accountAddress] = totalPositions;\n });\n\n this.#trackEvent?.(defiMetrics);\n }\n }\n\n #getSelectedEvmAdress(): string | undefined {\n return this.messagingSystem\n .call('AccountTreeController:getAccountsFromSelectedAccountGroup')\n .find((account: InternalAccount) => isEvmAccountType(account.type))\n ?.address;\n }\n}\n"]}
1
+ {"version":3,"file":"DeFiPositionsController.cjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAYA,qEAA+E;AAI/E,yEAAwE;AAExE,2DAAyD;AACzD,qEAGgC;AAChC,kDAAwD;AAExD,MAAM,iBAAiB,GAAG,MAAO,CAAC;AAElC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAEtC,MAAM,cAAc,GAAG,yBAAyB,CAAC;AAuCjD,MAAM,kBAAkB,GAAgD;IACtE,gBAAgB,EAAE;QAChB,kBAAkB,EAAE,KAAK;QACzB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;QAChB,QAAQ,EAAE,IAAI;KACf;IACD,qBAAqB,EAAE;QACrB,kBAAkB,EAAE,KAAK;QACzB,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;QAChB,QAAQ,EAAE,KAAK;KAChB;CACF,CAAC;AAEK,MAAM,sCAAsC,GACjD,GAAiC,EAAE;IACjC,OAAO;QACL,gBAAgB,EAAE,EAAE;QACpB,qBAAqB,EAAE,EAAE;KAC1B,CAAC;AACJ,CAAC,CAAC;AANS,QAAA,sCAAsC,0CAM/C;AA4CJ;;GAEG;AACH,MAAa,uBAAwB,SAAQ,IAAA,oDAA+B,GAI3E;IASC;;;;;;;OAOG;IACH,YAAY,EACV,SAAS,EACT,SAAS,GAAG,GAAG,EAAE,CAAC,IAAI,EACtB,UAAU,GAKX;QACC,KAAK,CAAC;YACJ,IAAI,EAAE,cAAc;YACpB,QAAQ,EAAE,kBAAkB;YAC5B,SAAS;YACT,KAAK,EAAE,IAAA,8CAAsC,GAAE;SAChD,CAAC,CAAC;;QA9BI,0DAE4B;QAE5B,qDAA0B;QAE1B,sDAA6B;QA0BpC,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;QAE1C,uBAAA,IAAI,2CAAmB,IAAA,sCAAoB,GAAE,MAAA,CAAC;QAC9C,uBAAA,IAAI,sCAAc,SAAS,MAAA,CAAC;QAE5B,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAC9D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,wBAAwB,EAAE,GAAG,EAAE;YAC5D,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,4CAA4C,EAC5C,KAAK,EAAE,eAAe,EAAE,EAAE;YACxB,IAAI,CAAC,uBAAA,IAAI,0CAAW,MAAf,IAAI,CAAa,EAAE;gBACtB,OAAO;aACR;YAED,MAAM,uBAAA,IAAI,2FAAwB,MAA5B,IAAI,EAAyB,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpE,CAAC,CACF,CAAC;QAEF,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,iCAAiC,EACjC,KAAK,EAAE,OAAO,EAAE,EAAE;YAChB,IAAI,CAAC,uBAAA,IAAI,0CAAW,MAAf,IAAI,CAAa,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;gBAC7D,OAAO;aACR;YAED,MAAM,uBAAA,IAAI,2FAAwB,MAA5B,IAAI,EAAyB,OAAO,CAAC,OAAO,CAAC,CAAC;QACtD,CAAC,CACF,CAAC;QAEF,uBAAA,IAAI,uCAAe,UAAU,MAAA,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,uBAAA,IAAI,0CAAW,MAAf,IAAI,CAAa,EAAE;YACtB,OAAO;SACR;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CACxC,iCAAiC,CAClC,CAAC;QAEF,MAAM,aAAa,GAGb,EAAE,CAAC;QAET,MAAM,OAAO,GAAG,MAAM,IAAA,oCAAuB,EAAC;YAC5C,aAAa;YACb,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,0BAA0B;YACrC,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE;gBACxC,MAAM,YAAY,GAAG,CACnB,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,EAAE;oBACpD,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;wBAC9B,MAAM,SAAS,GACb,MAAM,uBAAA,IAAI,0FAAuB,MAA3B,IAAI,EAAwB,cAAc,CAAC,CAAC;wBAEpD,OAAO;4BACL,cAAc;4BACd,SAAS;yBACV,CAAC;qBACH;oBAED,OAAO,SAAS,CAAC;gBACnB,CAAC,CAAC,CACH,CACF,CAAC,MAAM,CAAC,OAAO,CAGb,CAAC;gBAEJ,OAAO,CAAC,GAAG,aAAa,EAAE,GAAG,YAAY,CAAC,CAAC;YAC7C,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CACrC,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,EAAE,EAAE;YACrC,GAAG,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC;YAChC,OAAO,GAAG,CAAC;QACb,CAAC,EACD,EAAsD,CACvD,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC;CAsDF;AAxLD,0DAwLC;wQApDC,KAAK,0DAAyB,cAAsB;IAClD,MAAM,wBAAwB,GAC5B,MAAM,uBAAA,IAAI,0FAAuB,MAA3B,IAAI,EAAwB,cAAc,CAAC,CAAC;IAEpD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QACpB,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,GAAG,wBAAwB,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC,mDAED,KAAK,yDACH,cAAsB;IAEtB,IAAI;QACF,MAAM,qBAAqB,GAAG,MAAM,uBAAA,IAAI,+CAAgB,MAApB,IAAI,EAAiB,cAAc,CAAC,CAAC;QAEzE,MAAM,oBAAoB,GAAG,IAAA,yCAAkB,EAAC,qBAAqB,CAAC,CAAC;QAEvE,IAAI;YACF,uBAAA,IAAI,gGAA6B,MAAjC,IAAI,EAA8B,oBAAoB,EAAE,cAAc,CAAC,CAAC;SACzE;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CACX,gDAAgD,cAAc,GAAG,EACjE,KAAK,CACN,CAAC;SACH;QAED,OAAO,oBAAoB,CAAC;KAC7B;IAAC,MAAM;QACN,OAAO,IAAI,CAAC;KACb;AACH,CAAC,uHAGC,oBAAkD,EAClD,cAAsB;IAEtB,wDAAwD;IACxD,IAAI,CAAC,uBAAA,IAAI,2CAAY,EAAE;QACrB,OAAO;KACR;IAED,MAAM,WAAW,GAAG,IAAA,qDAA4B,EAAC,oBAAoB,CAAC,CAAC;IACvE,MAAM,EAAE,cAAc,EAAE,GAAG,WAAW,CAAC,UAAU,CAAC;IAElD,IAAI,cAAc,KAAK,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,cAAc,CAAC,EAAE;QACvE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,qBAAqB,CAAC,cAAc,CAAC,GAAG,cAAc,CAAC;QAC/D,CAAC,CAAC,CAAC;QAEH,uBAAA,IAAI,2CAAY,EAAE,KAAlB,IAAI,EAAe,WAAW,CAAC,CAAC;KACjC;AACH,CAAC","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerListAccountsAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type { KeyringControllerUnlockEvent } from '@metamask/keyring-controller';\nimport type { KeyringControllerLockEvent } from '@metamask/keyring-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { TransactionControllerTransactionConfirmedEvent } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport { calculateDeFiPositionMetrics } from './calculate-defi-metrics';\nimport type { DefiPositionResponse } from './fetch-positions';\nimport { buildPositionFetcher } from './fetch-positions';\nimport {\n groupDeFiPositions,\n type GroupedDeFiPositions,\n} from './group-defi-positions';\nimport { reduceInBatchesSerially } from '../assetsUtil';\n\nconst TEN_MINUTES_IN_MS = 600_000;\n\nconst FETCH_POSITIONS_BATCH_SIZE = 10;\n\nconst controllerName = 'DeFiPositionsController';\n\nexport type GroupedDeFiPositionsPerChain = {\n [chain: Hex]: GroupedDeFiPositions;\n};\n\nexport type TrackingEventPayload = {\n event: string;\n category: string;\n properties: {\n totalPositions: number;\n totalMarketValueUSD: number;\n breakdown?: {\n protocolId: string;\n marketValueUSD: number;\n chainId: Hex;\n count: number;\n }[];\n };\n};\n\ntype TrackEventHook = (event: TrackingEventPayload) => void;\n\nexport type DeFiPositionsControllerState = {\n /**\n * Object containing DeFi positions per account and network\n */\n allDeFiPositions: {\n [accountAddress: string]: GroupedDeFiPositionsPerChain | null;\n };\n\n /**\n * Object containing DeFi positions count per account\n */\n allDeFiPositionsCount: {\n [accountAddress: string]: number;\n };\n};\n\nconst controllerMetadata: StateMetadata<DeFiPositionsControllerState> = {\n allDeFiPositions: {\n includeInStateLogs: false,\n persist: false,\n anonymous: false,\n usedInUi: true,\n },\n allDeFiPositionsCount: {\n includeInStateLogs: false,\n persist: false,\n anonymous: false,\n usedInUi: false,\n },\n};\n\nexport const getDefaultDefiPositionsControllerState =\n (): DeFiPositionsControllerState => {\n return {\n allDeFiPositions: {},\n allDeFiPositionsCount: {},\n };\n };\n\nexport type DeFiPositionsControllerActions =\n DeFiPositionsControllerGetStateAction;\n\nexport type DeFiPositionsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n DeFiPositionsControllerState\n>;\n\nexport type DeFiPositionsControllerEvents =\n DeFiPositionsControllerStateChangeEvent;\n\nexport type DeFiPositionsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n DeFiPositionsControllerState\n >;\n\n/**\n * The external actions available to the {@link DeFiPositionsController}.\n */\nexport type AllowedActions = AccountsControllerListAccountsAction;\n\n/**\n * The external events available to the {@link DeFiPositionsController}.\n */\nexport type AllowedEvents =\n | KeyringControllerUnlockEvent\n | KeyringControllerLockEvent\n | TransactionControllerTransactionConfirmedEvent\n | AccountsControllerAccountAddedEvent;\n\n/**\n * The messenger of the {@link DeFiPositionsController}.\n */\nexport type DeFiPositionsControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n DeFiPositionsControllerActions | AllowedActions,\n DeFiPositionsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Controller that stores assets and exposes convenience methods\n */\nexport class DeFiPositionsController extends StaticIntervalPollingController()<\n typeof controllerName,\n DeFiPositionsControllerState,\n DeFiPositionsControllerMessenger\n> {\n readonly #fetchPositions: (\n accountAddress: string,\n ) => Promise<DefiPositionResponse[]>;\n\n readonly #isEnabled: () => boolean;\n\n readonly #trackEvent?: TrackEventHook;\n\n /**\n * DeFiPositionsController constuctor\n *\n * @param options - Constructor options.\n * @param options.messenger - The controller messenger.\n * @param options.isEnabled - Function that returns whether the controller is enabled. (default: () => true)\n * @param options.trackEvent - Function to track events. (default: undefined)\n */\n constructor({\n messenger,\n isEnabled = () => true,\n trackEvent,\n }: {\n messenger: DeFiPositionsControllerMessenger;\n isEnabled?: () => boolean;\n trackEvent?: TrackEventHook;\n }) {\n super({\n name: controllerName,\n metadata: controllerMetadata,\n messenger,\n state: getDefaultDefiPositionsControllerState(),\n });\n\n this.setIntervalLength(TEN_MINUTES_IN_MS);\n\n this.#fetchPositions = buildPositionFetcher();\n this.#isEnabled = isEnabled;\n\n this.messagingSystem.subscribe('KeyringController:unlock', () => {\n this.startPolling(null);\n });\n\n this.messagingSystem.subscribe('KeyringController:lock', () => {\n this.stopAllPolling();\n });\n\n this.messagingSystem.subscribe(\n 'TransactionController:transactionConfirmed',\n async (transactionMeta) => {\n if (!this.#isEnabled()) {\n return;\n }\n\n await this.#updateAccountPositions(transactionMeta.txParams.from);\n },\n );\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountAdded',\n async (account) => {\n if (!this.#isEnabled() || !account.type.startsWith('eip155:')) {\n return;\n }\n\n await this.#updateAccountPositions(account.address);\n },\n );\n\n this.#trackEvent = trackEvent;\n }\n\n async _executePoll(): Promise<void> {\n if (!this.#isEnabled()) {\n return;\n }\n\n const accounts = this.messagingSystem.call(\n 'AccountsController:listAccounts',\n );\n\n const initialResult: {\n accountAddress: string;\n positions: GroupedDeFiPositionsPerChain | null;\n }[] = [];\n\n const results = await reduceInBatchesSerially({\n initialResult,\n values: accounts,\n batchSize: FETCH_POSITIONS_BATCH_SIZE,\n eachBatch: async (workingResult, batch) => {\n const batchResults = (\n await Promise.all(\n batch.map(async ({ address: accountAddress, type }) => {\n if (type.startsWith('eip155:')) {\n const positions =\n await this.#fetchAccountPositions(accountAddress);\n\n return {\n accountAddress,\n positions,\n };\n }\n\n return undefined;\n }),\n )\n ).filter(Boolean) as {\n accountAddress: string;\n positions: GroupedDeFiPositionsPerChain | null;\n }[];\n\n return [...workingResult, ...batchResults];\n },\n });\n\n const allDefiPositions = results.reduce(\n (acc, { accountAddress, positions }) => {\n acc[accountAddress] = positions;\n return acc;\n },\n {} as DeFiPositionsControllerState['allDeFiPositions'],\n );\n\n this.update((state) => {\n state.allDeFiPositions = allDefiPositions;\n });\n }\n\n async #updateAccountPositions(accountAddress: string): Promise<void> {\n const accountPositionsPerChain =\n await this.#fetchAccountPositions(accountAddress);\n\n this.update((state) => {\n state.allDeFiPositions[accountAddress] = accountPositionsPerChain;\n });\n }\n\n async #fetchAccountPositions(\n accountAddress: string,\n ): Promise<GroupedDeFiPositionsPerChain | null> {\n try {\n const defiPositionsResponse = await this.#fetchPositions(accountAddress);\n\n const groupedDeFiPositions = groupDeFiPositions(defiPositionsResponse);\n\n try {\n this.#updatePositionsCountMetrics(groupedDeFiPositions, accountAddress);\n } catch (error) {\n console.error(\n `Failed to update positions count for account ${accountAddress}:`,\n error,\n );\n }\n\n return groupedDeFiPositions;\n } catch {\n return null;\n }\n }\n\n #updatePositionsCountMetrics(\n groupedDeFiPositions: GroupedDeFiPositionsPerChain,\n accountAddress: string,\n ) {\n // If no track event passed then skip the metrics update\n if (!this.#trackEvent) {\n return;\n }\n\n const defiMetrics = calculateDeFiPositionMetrics(groupedDeFiPositions);\n const { totalPositions } = defiMetrics.properties;\n\n if (totalPositions !== this.state.allDeFiPositionsCount[accountAddress]) {\n this.update((state) => {\n state.allDeFiPositionsCount[accountAddress] = totalPositions;\n });\n\n this.#trackEvent?.(defiMetrics);\n }\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" />
2
- import type { AccountTreeControllerGetAccountsFromSelectedAccountGroupAction, AccountTreeControllerSelectedAccountGroupChangeEvent } from "@metamask/account-tree-controller";
2
+ import type { AccountsControllerAccountAddedEvent, AccountsControllerListAccountsAction } from "@metamask/accounts-controller";
3
3
  import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedMessenger } from "@metamask/base-controller";
4
+ import type { KeyringControllerUnlockEvent } from "@metamask/keyring-controller";
4
5
  import type { KeyringControllerLockEvent } from "@metamask/keyring-controller";
5
6
  import type { TransactionControllerTransactionConfirmedEvent } from "@metamask/transaction-controller";
6
7
  import type { Hex } from "@metamask/utils";
@@ -46,11 +47,11 @@ export type DeFiPositionsControllerStateChangeEvent = ControllerStateChangeEvent
46
47
  /**
47
48
  * The external actions available to the {@link DeFiPositionsController}.
48
49
  */
49
- export type AllowedActions = AccountTreeControllerGetAccountsFromSelectedAccountGroupAction;
50
+ export type AllowedActions = AccountsControllerListAccountsAction;
50
51
  /**
51
52
  * The external events available to the {@link DeFiPositionsController}.
52
53
  */
53
- export type AllowedEvents = KeyringControllerLockEvent | TransactionControllerTransactionConfirmedEvent | AccountTreeControllerSelectedAccountGroupChangeEvent;
54
+ export type AllowedEvents = KeyringControllerUnlockEvent | KeyringControllerLockEvent | TransactionControllerTransactionConfirmedEvent | AccountsControllerAccountAddedEvent;
54
55
  /**
55
56
  * The messenger of the {@link DeFiPositionsController}.
56
57
  */
@@ -1 +1 @@
1
- {"version":3,"file":"DeFiPositionsController.d.cts","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EACV,8DAA8D,EAC9D,oDAAoD,EACrD,0CAA0C;AAC3C,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EAEpB,kCAAkC;AAEnC,OAAO,KAAK,EAAE,0BAA0B,EAAE,qCAAqC;AAG/E,OAAO,KAAK,EAAE,8CAA8C,EAAE,yCAAyC;AACvG,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,EAEL,KAAK,oBAAoB,EAC1B,mCAA+B;AAIhC,QAAA,MAAM,cAAc,4BAA4B,CAAC;AAEjD,MAAM,MAAM,4BAA4B,GAAG;IACzC,CAAC,KAAK,EAAE,GAAG,GAAG,oBAAoB,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE;QACV,cAAc,EAAE,MAAM,CAAC;QACvB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,SAAS,CAAC,EAAE;YACV,UAAU,EAAE,MAAM,CAAC;YACnB,cAAc,EAAE,MAAM,CAAC;YACvB,OAAO,EAAE,GAAG,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;SACf,EAAE,CAAC;KACL,CAAC;CACH,CAAC;AAEF,KAAK,cAAc,GAAG,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;AAE5D,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,gBAAgB,EAAE;QAChB,CAAC,cAAc,EAAE,MAAM,GAAG,4BAA4B,GAAG,IAAI,CAAC;KAC/D,CAAC;IAEF;;OAEG;IACH,qBAAqB,EAAE;QACrB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC;KAClC,CAAC;CACH,CAAC;AAiBF,eAAO,MAAM,sCAAsC,QAC7C,4BAKH,CAAC;AAEJ,MAAM,MAAM,8BAA8B,GACxC,qCAAqC,CAAC;AAExC,MAAM,MAAM,qCAAqC,GAAG,wBAAwB,CAC1E,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GACvC,uCAAuC,CAAC;AAE1C,MAAM,MAAM,uCAAuC,GACjD,0BAA0B,CACxB,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,cAAc,GACxB,8DAA8D,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,0BAA0B,GAC1B,8CAA8C,GAC9C,oDAAoD,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,gCAAgC,GAAG,mBAAmB,CAChE,OAAO,cAAc,EACrB,8BAA8B,GAAG,cAAc,EAC/C,6BAA6B,GAAG,aAAa,EAC7C,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;;;;;;;;;;;;;;;;AAEF;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,6BAC3C,OAAO,cAAc,EACrB,4BAA4B,EAC5B,gCAAgC,CACjC;;IASC;;;;;;;OAOG;gBACS,EACV,SAAS,EACT,SAAsB,EACtB,UAAU,GACX,EAAE;QACD,SAAS,EAAE,gCAAgC,CAAC;QAC5C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;QAC1B,UAAU,CAAC,EAAE,cAAc,CAAC;KAC7B;IAkDK,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAiFpC"}
1
+ {"version":3,"file":"DeFiPositionsController.d.cts","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,oCAAoC,EACrC,sCAAsC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EAEpB,kCAAkC;AACnC,OAAO,KAAK,EAAE,4BAA4B,EAAE,qCAAqC;AACjF,OAAO,KAAK,EAAE,0BAA0B,EAAE,qCAAqC;AAE/E,OAAO,KAAK,EAAE,8CAA8C,EAAE,yCAAyC;AACvG,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,EAEL,KAAK,oBAAoB,EAC1B,mCAA+B;AAOhC,QAAA,MAAM,cAAc,4BAA4B,CAAC;AAEjD,MAAM,MAAM,4BAA4B,GAAG;IACzC,CAAC,KAAK,EAAE,GAAG,GAAG,oBAAoB,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE;QACV,cAAc,EAAE,MAAM,CAAC;QACvB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,SAAS,CAAC,EAAE;YACV,UAAU,EAAE,MAAM,CAAC;YACnB,cAAc,EAAE,MAAM,CAAC;YACvB,OAAO,EAAE,GAAG,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;SACf,EAAE,CAAC;KACL,CAAC;CACH,CAAC;AAEF,KAAK,cAAc,GAAG,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;AAE5D,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,gBAAgB,EAAE;QAChB,CAAC,cAAc,EAAE,MAAM,GAAG,4BAA4B,GAAG,IAAI,CAAC;KAC/D,CAAC;IAEF;;OAEG;IACH,qBAAqB,EAAE;QACrB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC;KAClC,CAAC;CACH,CAAC;AAiBF,eAAO,MAAM,sCAAsC,QAC7C,4BAKH,CAAC;AAEJ,MAAM,MAAM,8BAA8B,GACxC,qCAAqC,CAAC;AAExC,MAAM,MAAM,qCAAqC,GAAG,wBAAwB,CAC1E,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GACvC,uCAAuC,CAAC;AAE1C,MAAM,MAAM,uCAAuC,GACjD,0BAA0B,CACxB,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,oCAAoC,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,4BAA4B,GAC5B,0BAA0B,GAC1B,8CAA8C,GAC9C,mCAAmC,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,gCAAgC,GAAG,mBAAmB,CAChE,OAAO,cAAc,EACrB,8BAA8B,GAAG,cAAc,EAC/C,6BAA6B,GAAG,aAAa,EAC7C,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;;;;;;;;;;;;;;;;AAEF;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,6BAC3C,OAAO,cAAc,EACrB,4BAA4B,EAC5B,gCAAgC,CACjC;;IASC;;;;;;;OAOG;gBACS,EACV,SAAS,EACT,SAAsB,EACtB,UAAU,GACX,EAAE;QACD,SAAS,EAAE,gCAAgC,CAAC;QAC5C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;QAC1B,UAAU,CAAC,EAAE,cAAc,CAAC;KAC7B;IA8CK,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CA6GpC"}
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" />
2
- import type { AccountTreeControllerGetAccountsFromSelectedAccountGroupAction, AccountTreeControllerSelectedAccountGroupChangeEvent } from "@metamask/account-tree-controller";
2
+ import type { AccountsControllerAccountAddedEvent, AccountsControllerListAccountsAction } from "@metamask/accounts-controller";
3
3
  import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedMessenger } from "@metamask/base-controller";
4
+ import type { KeyringControllerUnlockEvent } from "@metamask/keyring-controller";
4
5
  import type { KeyringControllerLockEvent } from "@metamask/keyring-controller";
5
6
  import type { TransactionControllerTransactionConfirmedEvent } from "@metamask/transaction-controller";
6
7
  import type { Hex } from "@metamask/utils";
@@ -46,11 +47,11 @@ export type DeFiPositionsControllerStateChangeEvent = ControllerStateChangeEvent
46
47
  /**
47
48
  * The external actions available to the {@link DeFiPositionsController}.
48
49
  */
49
- export type AllowedActions = AccountTreeControllerGetAccountsFromSelectedAccountGroupAction;
50
+ export type AllowedActions = AccountsControllerListAccountsAction;
50
51
  /**
51
52
  * The external events available to the {@link DeFiPositionsController}.
52
53
  */
53
- export type AllowedEvents = KeyringControllerLockEvent | TransactionControllerTransactionConfirmedEvent | AccountTreeControllerSelectedAccountGroupChangeEvent;
54
+ export type AllowedEvents = KeyringControllerUnlockEvent | KeyringControllerLockEvent | TransactionControllerTransactionConfirmedEvent | AccountsControllerAccountAddedEvent;
54
55
  /**
55
56
  * The messenger of the {@link DeFiPositionsController}.
56
57
  */
@@ -1 +1 @@
1
- {"version":3,"file":"DeFiPositionsController.d.mts","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EACV,8DAA8D,EAC9D,oDAAoD,EACrD,0CAA0C;AAC3C,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EAEpB,kCAAkC;AAEnC,OAAO,KAAK,EAAE,0BAA0B,EAAE,qCAAqC;AAG/E,OAAO,KAAK,EAAE,8CAA8C,EAAE,yCAAyC;AACvG,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,EAEL,KAAK,oBAAoB,EAC1B,mCAA+B;AAIhC,QAAA,MAAM,cAAc,4BAA4B,CAAC;AAEjD,MAAM,MAAM,4BAA4B,GAAG;IACzC,CAAC,KAAK,EAAE,GAAG,GAAG,oBAAoB,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE;QACV,cAAc,EAAE,MAAM,CAAC;QACvB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,SAAS,CAAC,EAAE;YACV,UAAU,EAAE,MAAM,CAAC;YACnB,cAAc,EAAE,MAAM,CAAC;YACvB,OAAO,EAAE,GAAG,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;SACf,EAAE,CAAC;KACL,CAAC;CACH,CAAC;AAEF,KAAK,cAAc,GAAG,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;AAE5D,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,gBAAgB,EAAE;QAChB,CAAC,cAAc,EAAE,MAAM,GAAG,4BAA4B,GAAG,IAAI,CAAC;KAC/D,CAAC;IAEF;;OAEG;IACH,qBAAqB,EAAE;QACrB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC;KAClC,CAAC;CACH,CAAC;AAiBF,eAAO,MAAM,sCAAsC,QAC7C,4BAKH,CAAC;AAEJ,MAAM,MAAM,8BAA8B,GACxC,qCAAqC,CAAC;AAExC,MAAM,MAAM,qCAAqC,GAAG,wBAAwB,CAC1E,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GACvC,uCAAuC,CAAC;AAE1C,MAAM,MAAM,uCAAuC,GACjD,0BAA0B,CACxB,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,cAAc,GACxB,8DAA8D,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,0BAA0B,GAC1B,8CAA8C,GAC9C,oDAAoD,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,gCAAgC,GAAG,mBAAmB,CAChE,OAAO,cAAc,EACrB,8BAA8B,GAAG,cAAc,EAC/C,6BAA6B,GAAG,aAAa,EAC7C,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;;;;;;;;;;;;;;;;AAEF;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,6BAC3C,OAAO,cAAc,EACrB,4BAA4B,EAC5B,gCAAgC,CACjC;;IASC;;;;;;;OAOG;gBACS,EACV,SAAS,EACT,SAAsB,EACtB,UAAU,GACX,EAAE;QACD,SAAS,EAAE,gCAAgC,CAAC;QAC5C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;QAC1B,UAAU,CAAC,EAAE,cAAc,CAAC;KAC7B;IAkDK,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAiFpC"}
1
+ {"version":3,"file":"DeFiPositionsController.d.mts","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,oCAAoC,EACrC,sCAAsC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EAEpB,kCAAkC;AACnC,OAAO,KAAK,EAAE,4BAA4B,EAAE,qCAAqC;AACjF,OAAO,KAAK,EAAE,0BAA0B,EAAE,qCAAqC;AAE/E,OAAO,KAAK,EAAE,8CAA8C,EAAE,yCAAyC;AACvG,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAK3C,OAAO,EAEL,KAAK,oBAAoB,EAC1B,mCAA+B;AAOhC,QAAA,MAAM,cAAc,4BAA4B,CAAC;AAEjD,MAAM,MAAM,4BAA4B,GAAG;IACzC,CAAC,KAAK,EAAE,GAAG,GAAG,oBAAoB,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE;QACV,cAAc,EAAE,MAAM,CAAC;QACvB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,SAAS,CAAC,EAAE;YACV,UAAU,EAAE,MAAM,CAAC;YACnB,cAAc,EAAE,MAAM,CAAC;YACvB,OAAO,EAAE,GAAG,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;SACf,EAAE,CAAC;KACL,CAAC;CACH,CAAC;AAEF,KAAK,cAAc,GAAG,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;AAE5D,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,gBAAgB,EAAE;QAChB,CAAC,cAAc,EAAE,MAAM,GAAG,4BAA4B,GAAG,IAAI,CAAC;KAC/D,CAAC;IAEF;;OAEG;IACH,qBAAqB,EAAE;QACrB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC;KAClC,CAAC;CACH,CAAC;AAiBF,eAAO,MAAM,sCAAsC,QAC7C,4BAKH,CAAC;AAEJ,MAAM,MAAM,8BAA8B,GACxC,qCAAqC,CAAC;AAExC,MAAM,MAAM,qCAAqC,GAAG,wBAAwB,CAC1E,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GACvC,uCAAuC,CAAC;AAE1C,MAAM,MAAM,uCAAuC,GACjD,0BAA0B,CACxB,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,oCAAoC,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,4BAA4B,GAC5B,0BAA0B,GAC1B,8CAA8C,GAC9C,mCAAmC,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,gCAAgC,GAAG,mBAAmB,CAChE,OAAO,cAAc,EACrB,8BAA8B,GAAG,cAAc,EAC/C,6BAA6B,GAAG,aAAa,EAC7C,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;;;;;;;;;;;;;;;;AAEF;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,6BAC3C,OAAO,cAAc,EACrB,4BAA4B,EAC5B,gCAAgC,CACjC;;IASC;;;;;;;OAOG;gBACS,EACV,SAAS,EACT,SAAsB,EACtB,UAAU,GACX,EAAE;QACD,SAAS,EAAE,gCAAgC,CAAC;QAC5C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;QAC1B,UAAU,CAAC,EAAE,cAAc,CAAC;KAC7B;IA8CK,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CA6GpC"}
@@ -9,13 +9,14 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
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
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _DeFiPositionsController_instances, _DeFiPositionsController_fetchPositions, _DeFiPositionsController_isEnabled, _DeFiPositionsController_trackEvent, _DeFiPositionsController_updateAccountPositions, _DeFiPositionsController_fetchAccountPositions, _DeFiPositionsController_updatePositionsCountMetrics, _DeFiPositionsController_getSelectedEvmAdress;
13
- import { isEvmAccountType } from "@metamask/keyring-api";
12
+ var _DeFiPositionsController_instances, _DeFiPositionsController_fetchPositions, _DeFiPositionsController_isEnabled, _DeFiPositionsController_trackEvent, _DeFiPositionsController_updateAccountPositions, _DeFiPositionsController_fetchAccountPositions, _DeFiPositionsController_updatePositionsCountMetrics;
14
13
  import { StaticIntervalPollingController } from "@metamask/polling-controller";
15
14
  import { calculateDeFiPositionMetrics } from "./calculate-defi-metrics.mjs";
16
15
  import { buildPositionFetcher } from "./fetch-positions.mjs";
17
16
  import { groupDeFiPositions } from "./group-defi-positions.mjs";
17
+ import { reduceInBatchesSerially } from "../assetsUtil.mjs";
18
18
  const TEN_MINUTES_IN_MS = 600000;
19
+ const FETCH_POSITIONS_BATCH_SIZE = 10;
19
20
  const controllerName = 'DeFiPositionsController';
20
21
  const controllerMetadata = {
21
22
  allDeFiPositions: {
@@ -63,24 +64,23 @@ export class DeFiPositionsController extends StaticIntervalPollingController() {
63
64
  this.setIntervalLength(TEN_MINUTES_IN_MS);
64
65
  __classPrivateFieldSet(this, _DeFiPositionsController_fetchPositions, buildPositionFetcher(), "f");
65
66
  __classPrivateFieldSet(this, _DeFiPositionsController_isEnabled, isEnabled, "f");
67
+ this.messagingSystem.subscribe('KeyringController:unlock', () => {
68
+ this.startPolling(null);
69
+ });
66
70
  this.messagingSystem.subscribe('KeyringController:lock', () => {
67
71
  this.stopAllPolling();
68
72
  });
69
73
  this.messagingSystem.subscribe('TransactionController:transactionConfirmed', async (transactionMeta) => {
70
- const selectedAddress = __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_getSelectedEvmAdress).call(this);
71
- if (!selectedAddress ||
72
- selectedAddress.toLowerCase() !==
73
- transactionMeta.txParams.from.toLowerCase()) {
74
+ if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this)) {
74
75
  return;
75
76
  }
76
- await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, selectedAddress);
77
+ await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, transactionMeta.txParams.from);
77
78
  });
78
- this.messagingSystem.subscribe('AccountTreeController:selectedAccountGroupChange', async () => {
79
- const selectedAddress = __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_getSelectedEvmAdress).call(this);
80
- if (!selectedAddress) {
79
+ this.messagingSystem.subscribe('AccountsController:accountAdded', async (account) => {
80
+ if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this) || !account.type.startsWith('eip155:')) {
81
81
  return;
82
82
  }
83
- await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, selectedAddress);
83
+ await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_updateAccountPositions).call(this, account.address);
84
84
  });
85
85
  __classPrivateFieldSet(this, _DeFiPositionsController_trackEvent, trackEvent, "f");
86
86
  }
@@ -88,20 +88,36 @@ export class DeFiPositionsController extends StaticIntervalPollingController() {
88
88
  if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this)) {
89
89
  return;
90
90
  }
91
- const selectedAddress = __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_getSelectedEvmAdress).call(this);
92
- if (!selectedAddress) {
93
- return;
94
- }
95
- const accountPositions = await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_fetchAccountPositions).call(this, selectedAddress);
91
+ const accounts = this.messagingSystem.call('AccountsController:listAccounts');
92
+ const initialResult = [];
93
+ const results = await reduceInBatchesSerially({
94
+ initialResult,
95
+ values: accounts,
96
+ batchSize: FETCH_POSITIONS_BATCH_SIZE,
97
+ eachBatch: async (workingResult, batch) => {
98
+ const batchResults = (await Promise.all(batch.map(async ({ address: accountAddress, type }) => {
99
+ if (type.startsWith('eip155:')) {
100
+ const positions = await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_fetchAccountPositions).call(this, accountAddress);
101
+ return {
102
+ accountAddress,
103
+ positions,
104
+ };
105
+ }
106
+ return undefined;
107
+ }))).filter(Boolean);
108
+ return [...workingResult, ...batchResults];
109
+ },
110
+ });
111
+ const allDefiPositions = results.reduce((acc, { accountAddress, positions }) => {
112
+ acc[accountAddress] = positions;
113
+ return acc;
114
+ }, {});
96
115
  this.update((state) => {
97
- state.allDeFiPositions[selectedAddress] = accountPositions;
116
+ state.allDeFiPositions = allDefiPositions;
98
117
  });
99
118
  }
100
119
  }
101
120
  _DeFiPositionsController_fetchPositions = new WeakMap(), _DeFiPositionsController_isEnabled = new WeakMap(), _DeFiPositionsController_trackEvent = new WeakMap(), _DeFiPositionsController_instances = new WeakSet(), _DeFiPositionsController_updateAccountPositions = async function _DeFiPositionsController_updateAccountPositions(accountAddress) {
102
- if (!__classPrivateFieldGet(this, _DeFiPositionsController_isEnabled, "f").call(this)) {
103
- return;
104
- }
105
121
  const accountPositionsPerChain = await __classPrivateFieldGet(this, _DeFiPositionsController_instances, "m", _DeFiPositionsController_fetchAccountPositions).call(this, accountAddress);
106
122
  this.update((state) => {
107
123
  state.allDeFiPositions[accountAddress] = accountPositionsPerChain;
@@ -134,10 +150,5 @@ _DeFiPositionsController_fetchPositions = new WeakMap(), _DeFiPositionsControlle
134
150
  });
135
151
  __classPrivateFieldGet(this, _DeFiPositionsController_trackEvent, "f")?.call(this, defiMetrics);
136
152
  }
137
- }, _DeFiPositionsController_getSelectedEvmAdress = function _DeFiPositionsController_getSelectedEvmAdress() {
138
- return this.messagingSystem
139
- .call('AccountTreeController:getAccountsFromSelectedAccountGroup')
140
- .find((account) => isEvmAccountType(account.type))
141
- ?.address;
142
153
  };
143
154
  //# sourceMappingURL=DeFiPositionsController.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeFiPositionsController.mjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n} from '@metamask/account-tree-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { KeyringControllerLockEvent } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { TransactionControllerTransactionConfirmedEvent } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport { calculateDeFiPositionMetrics } from './calculate-defi-metrics';\nimport type { DefiPositionResponse } from './fetch-positions';\nimport { buildPositionFetcher } from './fetch-positions';\nimport {\n groupDeFiPositions,\n type GroupedDeFiPositions,\n} from './group-defi-positions';\n\nconst TEN_MINUTES_IN_MS = 600_000;\n\nconst controllerName = 'DeFiPositionsController';\n\nexport type GroupedDeFiPositionsPerChain = {\n [chain: Hex]: GroupedDeFiPositions;\n};\n\nexport type TrackingEventPayload = {\n event: string;\n category: string;\n properties: {\n totalPositions: number;\n totalMarketValueUSD: number;\n breakdown?: {\n protocolId: string;\n marketValueUSD: number;\n chainId: Hex;\n count: number;\n }[];\n };\n};\n\ntype TrackEventHook = (event: TrackingEventPayload) => void;\n\nexport type DeFiPositionsControllerState = {\n /**\n * Object containing DeFi positions per account and network\n */\n allDeFiPositions: {\n [accountAddress: string]: GroupedDeFiPositionsPerChain | null;\n };\n\n /**\n * Object containing DeFi positions count per account\n */\n allDeFiPositionsCount: {\n [accountAddress: string]: number;\n };\n};\n\nconst controllerMetadata: StateMetadata<DeFiPositionsControllerState> = {\n allDeFiPositions: {\n includeInStateLogs: false,\n persist: false,\n anonymous: false,\n usedInUi: true,\n },\n allDeFiPositionsCount: {\n includeInStateLogs: false,\n persist: false,\n anonymous: false,\n usedInUi: false,\n },\n};\n\nexport const getDefaultDefiPositionsControllerState =\n (): DeFiPositionsControllerState => {\n return {\n allDeFiPositions: {},\n allDeFiPositionsCount: {},\n };\n };\n\nexport type DeFiPositionsControllerActions =\n DeFiPositionsControllerGetStateAction;\n\nexport type DeFiPositionsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n DeFiPositionsControllerState\n>;\n\nexport type DeFiPositionsControllerEvents =\n DeFiPositionsControllerStateChangeEvent;\n\nexport type DeFiPositionsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n DeFiPositionsControllerState\n >;\n\n/**\n * The external actions available to the {@link DeFiPositionsController}.\n */\nexport type AllowedActions =\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction;\n\n/**\n * The external events available to the {@link DeFiPositionsController}.\n */\nexport type AllowedEvents =\n | KeyringControllerLockEvent\n | TransactionControllerTransactionConfirmedEvent\n | AccountTreeControllerSelectedAccountGroupChangeEvent;\n\n/**\n * The messenger of the {@link DeFiPositionsController}.\n */\nexport type DeFiPositionsControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n DeFiPositionsControllerActions | AllowedActions,\n DeFiPositionsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Controller that stores assets and exposes convenience methods\n */\nexport class DeFiPositionsController extends StaticIntervalPollingController()<\n typeof controllerName,\n DeFiPositionsControllerState,\n DeFiPositionsControllerMessenger\n> {\n readonly #fetchPositions: (\n accountAddress: string,\n ) => Promise<DefiPositionResponse[]>;\n\n readonly #isEnabled: () => boolean;\n\n readonly #trackEvent?: TrackEventHook;\n\n /**\n * DeFiPositionsController constuctor\n *\n * @param options - Constructor options.\n * @param options.messenger - The controller messenger.\n * @param options.isEnabled - Function that returns whether the controller is enabled. (default: () => true)\n * @param options.trackEvent - Function to track events. (default: undefined)\n */\n constructor({\n messenger,\n isEnabled = () => true,\n trackEvent,\n }: {\n messenger: DeFiPositionsControllerMessenger;\n isEnabled?: () => boolean;\n trackEvent?: TrackEventHook;\n }) {\n super({\n name: controllerName,\n metadata: controllerMetadata,\n messenger,\n state: getDefaultDefiPositionsControllerState(),\n });\n\n this.setIntervalLength(TEN_MINUTES_IN_MS);\n\n this.#fetchPositions = buildPositionFetcher();\n this.#isEnabled = isEnabled;\n\n this.messagingSystem.subscribe('KeyringController:lock', () => {\n this.stopAllPolling();\n });\n\n this.messagingSystem.subscribe(\n 'TransactionController:transactionConfirmed',\n async (transactionMeta) => {\n const selectedAddress = this.#getSelectedEvmAdress();\n\n if (\n !selectedAddress ||\n selectedAddress.toLowerCase() !==\n transactionMeta.txParams.from.toLowerCase()\n ) {\n return;\n }\n\n await this.#updateAccountPositions(selectedAddress);\n },\n );\n\n this.messagingSystem.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n async () => {\n const selectedAddress = this.#getSelectedEvmAdress();\n\n if (!selectedAddress) {\n return;\n }\n\n await this.#updateAccountPositions(selectedAddress);\n },\n );\n\n this.#trackEvent = trackEvent;\n }\n\n async _executePoll(): Promise<void> {\n if (!this.#isEnabled()) {\n return;\n }\n\n const selectedAddress = this.#getSelectedEvmAdress();\n\n if (!selectedAddress) {\n return;\n }\n\n const accountPositions = await this.#fetchAccountPositions(selectedAddress);\n\n this.update((state) => {\n state.allDeFiPositions[selectedAddress] = accountPositions;\n });\n }\n\n async #updateAccountPositions(accountAddress: string): Promise<void> {\n if (!this.#isEnabled()) {\n return;\n }\n\n const accountPositionsPerChain =\n await this.#fetchAccountPositions(accountAddress);\n\n this.update((state) => {\n state.allDeFiPositions[accountAddress] = accountPositionsPerChain;\n });\n }\n\n async #fetchAccountPositions(\n accountAddress: string,\n ): Promise<GroupedDeFiPositionsPerChain | null> {\n try {\n const defiPositionsResponse = await this.#fetchPositions(accountAddress);\n\n const groupedDeFiPositions = groupDeFiPositions(defiPositionsResponse);\n\n try {\n this.#updatePositionsCountMetrics(groupedDeFiPositions, accountAddress);\n } catch (error) {\n console.error(\n `Failed to update positions count for account ${accountAddress}:`,\n error,\n );\n }\n\n return groupedDeFiPositions;\n } catch {\n return null;\n }\n }\n\n #updatePositionsCountMetrics(\n groupedDeFiPositions: GroupedDeFiPositionsPerChain,\n accountAddress: string,\n ) {\n // If no track event passed then skip the metrics update\n if (!this.#trackEvent) {\n return;\n }\n\n const defiMetrics = calculateDeFiPositionMetrics(groupedDeFiPositions);\n const { totalPositions } = defiMetrics.properties;\n\n if (totalPositions !== this.state.allDeFiPositionsCount[accountAddress]) {\n this.update((state) => {\n state.allDeFiPositionsCount[accountAddress] = totalPositions;\n });\n\n this.#trackEvent?.(defiMetrics);\n }\n }\n\n #getSelectedEvmAdress(): string | undefined {\n return this.messagingSystem\n .call('AccountTreeController:getAccountsFromSelectedAccountGroup')\n .find((account: InternalAccount) => isEvmAccountType(account.type))\n ?.address;\n }\n}\n"]}
1
+ {"version":3,"file":"DeFiPositionsController.mjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/DeFiPositionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerListAccountsAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type { KeyringControllerUnlockEvent } from '@metamask/keyring-controller';\nimport type { KeyringControllerLockEvent } from '@metamask/keyring-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { TransactionControllerTransactionConfirmedEvent } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\n\nimport { calculateDeFiPositionMetrics } from './calculate-defi-metrics';\nimport type { DefiPositionResponse } from './fetch-positions';\nimport { buildPositionFetcher } from './fetch-positions';\nimport {\n groupDeFiPositions,\n type GroupedDeFiPositions,\n} from './group-defi-positions';\nimport { reduceInBatchesSerially } from '../assetsUtil';\n\nconst TEN_MINUTES_IN_MS = 600_000;\n\nconst FETCH_POSITIONS_BATCH_SIZE = 10;\n\nconst controllerName = 'DeFiPositionsController';\n\nexport type GroupedDeFiPositionsPerChain = {\n [chain: Hex]: GroupedDeFiPositions;\n};\n\nexport type TrackingEventPayload = {\n event: string;\n category: string;\n properties: {\n totalPositions: number;\n totalMarketValueUSD: number;\n breakdown?: {\n protocolId: string;\n marketValueUSD: number;\n chainId: Hex;\n count: number;\n }[];\n };\n};\n\ntype TrackEventHook = (event: TrackingEventPayload) => void;\n\nexport type DeFiPositionsControllerState = {\n /**\n * Object containing DeFi positions per account and network\n */\n allDeFiPositions: {\n [accountAddress: string]: GroupedDeFiPositionsPerChain | null;\n };\n\n /**\n * Object containing DeFi positions count per account\n */\n allDeFiPositionsCount: {\n [accountAddress: string]: number;\n };\n};\n\nconst controllerMetadata: StateMetadata<DeFiPositionsControllerState> = {\n allDeFiPositions: {\n includeInStateLogs: false,\n persist: false,\n anonymous: false,\n usedInUi: true,\n },\n allDeFiPositionsCount: {\n includeInStateLogs: false,\n persist: false,\n anonymous: false,\n usedInUi: false,\n },\n};\n\nexport const getDefaultDefiPositionsControllerState =\n (): DeFiPositionsControllerState => {\n return {\n allDeFiPositions: {},\n allDeFiPositionsCount: {},\n };\n };\n\nexport type DeFiPositionsControllerActions =\n DeFiPositionsControllerGetStateAction;\n\nexport type DeFiPositionsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n DeFiPositionsControllerState\n>;\n\nexport type DeFiPositionsControllerEvents =\n DeFiPositionsControllerStateChangeEvent;\n\nexport type DeFiPositionsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n DeFiPositionsControllerState\n >;\n\n/**\n * The external actions available to the {@link DeFiPositionsController}.\n */\nexport type AllowedActions = AccountsControllerListAccountsAction;\n\n/**\n * The external events available to the {@link DeFiPositionsController}.\n */\nexport type AllowedEvents =\n | KeyringControllerUnlockEvent\n | KeyringControllerLockEvent\n | TransactionControllerTransactionConfirmedEvent\n | AccountsControllerAccountAddedEvent;\n\n/**\n * The messenger of the {@link DeFiPositionsController}.\n */\nexport type DeFiPositionsControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n DeFiPositionsControllerActions | AllowedActions,\n DeFiPositionsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Controller that stores assets and exposes convenience methods\n */\nexport class DeFiPositionsController extends StaticIntervalPollingController()<\n typeof controllerName,\n DeFiPositionsControllerState,\n DeFiPositionsControllerMessenger\n> {\n readonly #fetchPositions: (\n accountAddress: string,\n ) => Promise<DefiPositionResponse[]>;\n\n readonly #isEnabled: () => boolean;\n\n readonly #trackEvent?: TrackEventHook;\n\n /**\n * DeFiPositionsController constuctor\n *\n * @param options - Constructor options.\n * @param options.messenger - The controller messenger.\n * @param options.isEnabled - Function that returns whether the controller is enabled. (default: () => true)\n * @param options.trackEvent - Function to track events. (default: undefined)\n */\n constructor({\n messenger,\n isEnabled = () => true,\n trackEvent,\n }: {\n messenger: DeFiPositionsControllerMessenger;\n isEnabled?: () => boolean;\n trackEvent?: TrackEventHook;\n }) {\n super({\n name: controllerName,\n metadata: controllerMetadata,\n messenger,\n state: getDefaultDefiPositionsControllerState(),\n });\n\n this.setIntervalLength(TEN_MINUTES_IN_MS);\n\n this.#fetchPositions = buildPositionFetcher();\n this.#isEnabled = isEnabled;\n\n this.messagingSystem.subscribe('KeyringController:unlock', () => {\n this.startPolling(null);\n });\n\n this.messagingSystem.subscribe('KeyringController:lock', () => {\n this.stopAllPolling();\n });\n\n this.messagingSystem.subscribe(\n 'TransactionController:transactionConfirmed',\n async (transactionMeta) => {\n if (!this.#isEnabled()) {\n return;\n }\n\n await this.#updateAccountPositions(transactionMeta.txParams.from);\n },\n );\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountAdded',\n async (account) => {\n if (!this.#isEnabled() || !account.type.startsWith('eip155:')) {\n return;\n }\n\n await this.#updateAccountPositions(account.address);\n },\n );\n\n this.#trackEvent = trackEvent;\n }\n\n async _executePoll(): Promise<void> {\n if (!this.#isEnabled()) {\n return;\n }\n\n const accounts = this.messagingSystem.call(\n 'AccountsController:listAccounts',\n );\n\n const initialResult: {\n accountAddress: string;\n positions: GroupedDeFiPositionsPerChain | null;\n }[] = [];\n\n const results = await reduceInBatchesSerially({\n initialResult,\n values: accounts,\n batchSize: FETCH_POSITIONS_BATCH_SIZE,\n eachBatch: async (workingResult, batch) => {\n const batchResults = (\n await Promise.all(\n batch.map(async ({ address: accountAddress, type }) => {\n if (type.startsWith('eip155:')) {\n const positions =\n await this.#fetchAccountPositions(accountAddress);\n\n return {\n accountAddress,\n positions,\n };\n }\n\n return undefined;\n }),\n )\n ).filter(Boolean) as {\n accountAddress: string;\n positions: GroupedDeFiPositionsPerChain | null;\n }[];\n\n return [...workingResult, ...batchResults];\n },\n });\n\n const allDefiPositions = results.reduce(\n (acc, { accountAddress, positions }) => {\n acc[accountAddress] = positions;\n return acc;\n },\n {} as DeFiPositionsControllerState['allDeFiPositions'],\n );\n\n this.update((state) => {\n state.allDeFiPositions = allDefiPositions;\n });\n }\n\n async #updateAccountPositions(accountAddress: string): Promise<void> {\n const accountPositionsPerChain =\n await this.#fetchAccountPositions(accountAddress);\n\n this.update((state) => {\n state.allDeFiPositions[accountAddress] = accountPositionsPerChain;\n });\n }\n\n async #fetchAccountPositions(\n accountAddress: string,\n ): Promise<GroupedDeFiPositionsPerChain | null> {\n try {\n const defiPositionsResponse = await this.#fetchPositions(accountAddress);\n\n const groupedDeFiPositions = groupDeFiPositions(defiPositionsResponse);\n\n try {\n this.#updatePositionsCountMetrics(groupedDeFiPositions, accountAddress);\n } catch (error) {\n console.error(\n `Failed to update positions count for account ${accountAddress}:`,\n error,\n );\n }\n\n return groupedDeFiPositions;\n } catch {\n return null;\n }\n }\n\n #updatePositionsCountMetrics(\n groupedDeFiPositions: GroupedDeFiPositionsPerChain,\n accountAddress: string,\n ) {\n // If no track event passed then skip the metrics update\n if (!this.#trackEvent) {\n return;\n }\n\n const defiMetrics = calculateDeFiPositionMetrics(groupedDeFiPositions);\n const { totalPositions } = defiMetrics.properties;\n\n if (totalPositions !== this.state.allDeFiPositionsCount[accountAddress]) {\n this.update((state) => {\n state.allDeFiPositionsCount[accountAddress] = totalPositions;\n });\n\n this.#trackEvent?.(defiMetrics);\n }\n }\n}\n"]}
@@ -1,11 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildPositionFetcher = exports.DEFI_POSITIONS_API_URL = void 0;
4
- const timeout_with_retry_1 = require("../utils/timeout-with-retry.cjs");
5
4
  // TODO: Update with prod API URL when available
6
5
  exports.DEFI_POSITIONS_API_URL = 'https://defiadapters.api.cx.metamask.io';
7
- const EIGHT_SECONDS_IN_MS = 8000;
8
- const MAX_RETRIES = 1;
9
6
  /**
10
7
  * Builds a function that fetches DeFi positions for a given account address
11
8
  *
@@ -13,7 +10,7 @@ const MAX_RETRIES = 1;
13
10
  */
14
11
  function buildPositionFetcher() {
15
12
  return async (accountAddress) => {
16
- const defiPositionsResponse = await (0, timeout_with_retry_1.timeoutWithRetry)(() => fetch(`${exports.DEFI_POSITIONS_API_URL}/positions/${accountAddress}`), EIGHT_SECONDS_IN_MS, MAX_RETRIES);
13
+ const defiPositionsResponse = await fetch(`${exports.DEFI_POSITIONS_API_URL}/positions/${accountAddress}`);
17
14
  if (defiPositionsResponse.status !== 200) {
18
15
  throw new Error(`Unable to fetch defi positions - HTTP ${defiPositionsResponse.status}`);
19
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-positions.cjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":";;;AAAA,wEAA+D;AA2D/D,gDAAgD;AACnC,QAAA,sBAAsB,GAAG,yCAAyC,CAAC;AAEhF,MAAM,mBAAmB,GAAG,IAAK,CAAC;AAClC,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB;;;;GAIG;AACH,SAAgB,oBAAoB;IAClC,OAAO,KAAK,EAAE,cAAsB,EAAmC,EAAE;QACvE,MAAM,qBAAqB,GAAG,MAAM,IAAA,qCAAgB,EAClD,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,8BAAsB,cAAc,cAAc,EAAE,CAAC,EACpE,mBAAmB,EACnB,WAAW,CACZ,CAAC;QAEF,IAAI,qBAAqB,CAAC,MAAM,KAAK,GAAG,EAAE;YACxC,MAAM,IAAI,KAAK,CACb,yCAAyC,qBAAqB,CAAC,MAAM,EAAE,CACxE,CAAC;SACH;QAED,OAAO,CAAC,MAAM,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACnD,CAAC,CAAC;AACJ,CAAC;AAhBD,oDAgBC","sourcesContent":["import { timeoutWithRetry } from '../utils/timeout-with-retry';\n\nexport type DefiPositionResponse = AdapterResponse<{\n tokens: ProtocolToken[];\n}>;\n\ntype ProtocolDetails = {\n chainId: number;\n protocolId: string;\n productId: string;\n protocolDisplayName: string;\n name: string;\n description: string;\n iconUrl: string;\n siteUrl: string;\n positionType: PositionType;\n metadata?: {\n groupPositions?: boolean;\n };\n};\n\ntype AdapterResponse<ProtocolResponse> =\n | (ProtocolDetails & {\n chainName: string;\n } & (\n | (ProtocolResponse & { success: true })\n | (AdapterErrorResponse & { success: false })\n ))\n | (AdapterErrorResponse & { success: false });\n\ntype AdapterErrorResponse = {\n error: {\n message: string;\n };\n};\n\nexport type PositionType = 'supply' | 'borrow' | 'stake' | 'reward';\n\nexport type ProtocolToken = Balance & {\n type: 'protocol';\n tokenId?: string;\n};\n\nexport type Underlying = Balance & {\n type: 'underlying' | 'underlying-claimable';\n iconUrl: string;\n};\n\nexport type Balance = {\n address: string;\n name: string;\n symbol: string;\n decimals: number;\n balanceRaw: string;\n balance: number;\n price?: number;\n tokens?: Underlying[];\n};\n\n// TODO: Update with prod API URL when available\nexport const DEFI_POSITIONS_API_URL = 'https://defiadapters.api.cx.metamask.io';\n\nconst EIGHT_SECONDS_IN_MS = 8_000;\nconst MAX_RETRIES = 1;\n\n/**\n * Builds a function that fetches DeFi positions for a given account address\n *\n * @returns A function that fetches DeFi positions for a given account address\n */\nexport function buildPositionFetcher() {\n return async (accountAddress: string): Promise<DefiPositionResponse[]> => {\n const defiPositionsResponse = await timeoutWithRetry(\n () => fetch(`${DEFI_POSITIONS_API_URL}/positions/${accountAddress}`),\n EIGHT_SECONDS_IN_MS,\n MAX_RETRIES,\n );\n\n if (defiPositionsResponse.status !== 200) {\n throw new Error(\n `Unable to fetch defi positions - HTTP ${defiPositionsResponse.status}`,\n );\n }\n\n return (await defiPositionsResponse.json()).data;\n };\n}\n"]}
1
+ {"version":3,"file":"fetch-positions.cjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":";;;AAyDA,gDAAgD;AACnC,QAAA,sBAAsB,GAAG,yCAAyC,CAAC;AAEhF;;;;GAIG;AACH,SAAgB,oBAAoB;IAClC,OAAO,KAAK,EAAE,cAAsB,EAAmC,EAAE;QACvE,MAAM,qBAAqB,GAAG,MAAM,KAAK,CACvC,GAAG,8BAAsB,cAAc,cAAc,EAAE,CACxD,CAAC;QAEF,IAAI,qBAAqB,CAAC,MAAM,KAAK,GAAG,EAAE;YACxC,MAAM,IAAI,KAAK,CACb,yCAAyC,qBAAqB,CAAC,MAAM,EAAE,CACxE,CAAC;SACH;QAED,OAAO,CAAC,MAAM,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACnD,CAAC,CAAC;AACJ,CAAC;AAdD,oDAcC","sourcesContent":["export type DefiPositionResponse = AdapterResponse<{\n tokens: ProtocolToken[];\n}>;\n\ntype ProtocolDetails = {\n chainId: number;\n protocolId: string;\n productId: string;\n protocolDisplayName: string;\n name: string;\n description: string;\n iconUrl: string;\n siteUrl: string;\n positionType: PositionType;\n metadata?: {\n groupPositions?: boolean;\n };\n};\n\ntype AdapterResponse<ProtocolResponse> =\n | (ProtocolDetails & {\n chainName: string;\n } & (\n | (ProtocolResponse & { success: true })\n | (AdapterErrorResponse & { success: false })\n ))\n | (AdapterErrorResponse & { success: false });\n\ntype AdapterErrorResponse = {\n error: {\n message: string;\n };\n};\n\nexport type PositionType = 'supply' | 'borrow' | 'stake' | 'reward';\n\nexport type ProtocolToken = Balance & {\n type: 'protocol';\n tokenId?: string;\n};\n\nexport type Underlying = Balance & {\n type: 'underlying' | 'underlying-claimable';\n iconUrl: string;\n};\n\nexport type Balance = {\n address: string;\n name: string;\n symbol: string;\n decimals: number;\n balanceRaw: string;\n balance: number;\n price?: number;\n tokens?: Underlying[];\n};\n\n// TODO: Update with prod API URL when available\nexport const DEFI_POSITIONS_API_URL = 'https://defiadapters.api.cx.metamask.io';\n\n/**\n * Builds a function that fetches DeFi positions for a given account address\n *\n * @returns A function that fetches DeFi positions for a given account address\n */\nexport function buildPositionFetcher() {\n return async (accountAddress: string): Promise<DefiPositionResponse[]> => {\n const defiPositionsResponse = await fetch(\n `${DEFI_POSITIONS_API_URL}/positions/${accountAddress}`,\n );\n\n if (defiPositionsResponse.status !== 200) {\n throw new Error(\n `Unable to fetch defi positions - HTTP ${defiPositionsResponse.status}`,\n );\n }\n\n return (await defiPositionsResponse.json()).data;\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-positions.d.cts","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,oBAAoB,GAAG,eAAe,CAAC;IACjD,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,CAAC,gBAAgB,IACjC,CAAC,eAAe,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,CACE,CAAC,gBAAgB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC,GACtC,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAC9C,CAAC,GACJ,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAEhD,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG;IACjC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB,CAAC;AAGF,eAAO,MAAM,sBAAsB,4CAA4C,CAAC;AAKhF;;;;GAIG;AACH,wBAAgB,oBAAoB,qBACJ,MAAM,KAAG,QAAQ,oBAAoB,EAAE,CAAC,CAevE"}
1
+ {"version":3,"file":"fetch-positions.d.cts","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG,eAAe,CAAC;IACjD,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,CAAC,gBAAgB,IACjC,CAAC,eAAe,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,CACE,CAAC,gBAAgB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC,GACtC,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAC9C,CAAC,GACJ,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAEhD,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG;IACjC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB,CAAC;AAGF,eAAO,MAAM,sBAAsB,4CAA4C,CAAC;AAEhF;;;;GAIG;AACH,wBAAgB,oBAAoB,qBACJ,MAAM,KAAG,QAAQ,oBAAoB,EAAE,CAAC,CAavE"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-positions.d.mts","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,oBAAoB,GAAG,eAAe,CAAC;IACjD,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,CAAC,gBAAgB,IACjC,CAAC,eAAe,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,CACE,CAAC,gBAAgB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC,GACtC,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAC9C,CAAC,GACJ,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAEhD,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG;IACjC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB,CAAC;AAGF,eAAO,MAAM,sBAAsB,4CAA4C,CAAC;AAKhF;;;;GAIG;AACH,wBAAgB,oBAAoB,qBACJ,MAAM,KAAG,QAAQ,oBAAoB,EAAE,CAAC,CAevE"}
1
+ {"version":3,"file":"fetch-positions.d.mts","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG,eAAe,CAAC;IACjD,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB,CAAC,CAAC;AAEH,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,KAAK,eAAe,CAAC,gBAAgB,IACjC,CAAC,eAAe,GAAG;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,CACE,CAAC,gBAAgB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC,GACtC,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAC9C,CAAC,GACJ,CAAC,oBAAoB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAEhD,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG;IACjC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB,CAAC;AAGF,eAAO,MAAM,sBAAsB,4CAA4C,CAAC;AAEhF;;;;GAIG;AACH,wBAAgB,oBAAoB,qBACJ,MAAM,KAAG,QAAQ,oBAAoB,EAAE,CAAC,CAavE"}
@@ -1,8 +1,5 @@
1
- import { timeoutWithRetry } from "../utils/timeout-with-retry.mjs";
2
1
  // TODO: Update with prod API URL when available
3
2
  export const DEFI_POSITIONS_API_URL = 'https://defiadapters.api.cx.metamask.io';
4
- const EIGHT_SECONDS_IN_MS = 8000;
5
- const MAX_RETRIES = 1;
6
3
  /**
7
4
  * Builds a function that fetches DeFi positions for a given account address
8
5
  *
@@ -10,7 +7,7 @@ const MAX_RETRIES = 1;
10
7
  */
11
8
  export function buildPositionFetcher() {
12
9
  return async (accountAddress) => {
13
- const defiPositionsResponse = await timeoutWithRetry(() => fetch(`${DEFI_POSITIONS_API_URL}/positions/${accountAddress}`), EIGHT_SECONDS_IN_MS, MAX_RETRIES);
10
+ const defiPositionsResponse = await fetch(`${DEFI_POSITIONS_API_URL}/positions/${accountAddress}`);
14
11
  if (defiPositionsResponse.status !== 200) {
15
12
  throw new Error(`Unable to fetch defi positions - HTTP ${defiPositionsResponse.status}`);
16
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-positions.mjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,wCAAoC;AA2D/D,gDAAgD;AAChD,MAAM,CAAC,MAAM,sBAAsB,GAAG,yCAAyC,CAAC;AAEhF,MAAM,mBAAmB,GAAG,IAAK,CAAC;AAClC,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB;;;;GAIG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,KAAK,EAAE,cAAsB,EAAmC,EAAE;QACvE,MAAM,qBAAqB,GAAG,MAAM,gBAAgB,CAClD,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,sBAAsB,cAAc,cAAc,EAAE,CAAC,EACpE,mBAAmB,EACnB,WAAW,CACZ,CAAC;QAEF,IAAI,qBAAqB,CAAC,MAAM,KAAK,GAAG,EAAE;YACxC,MAAM,IAAI,KAAK,CACb,yCAAyC,qBAAqB,CAAC,MAAM,EAAE,CACxE,CAAC;SACH;QAED,OAAO,CAAC,MAAM,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACnD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { timeoutWithRetry } from '../utils/timeout-with-retry';\n\nexport type DefiPositionResponse = AdapterResponse<{\n tokens: ProtocolToken[];\n}>;\n\ntype ProtocolDetails = {\n chainId: number;\n protocolId: string;\n productId: string;\n protocolDisplayName: string;\n name: string;\n description: string;\n iconUrl: string;\n siteUrl: string;\n positionType: PositionType;\n metadata?: {\n groupPositions?: boolean;\n };\n};\n\ntype AdapterResponse<ProtocolResponse> =\n | (ProtocolDetails & {\n chainName: string;\n } & (\n | (ProtocolResponse & { success: true })\n | (AdapterErrorResponse & { success: false })\n ))\n | (AdapterErrorResponse & { success: false });\n\ntype AdapterErrorResponse = {\n error: {\n message: string;\n };\n};\n\nexport type PositionType = 'supply' | 'borrow' | 'stake' | 'reward';\n\nexport type ProtocolToken = Balance & {\n type: 'protocol';\n tokenId?: string;\n};\n\nexport type Underlying = Balance & {\n type: 'underlying' | 'underlying-claimable';\n iconUrl: string;\n};\n\nexport type Balance = {\n address: string;\n name: string;\n symbol: string;\n decimals: number;\n balanceRaw: string;\n balance: number;\n price?: number;\n tokens?: Underlying[];\n};\n\n// TODO: Update with prod API URL when available\nexport const DEFI_POSITIONS_API_URL = 'https://defiadapters.api.cx.metamask.io';\n\nconst EIGHT_SECONDS_IN_MS = 8_000;\nconst MAX_RETRIES = 1;\n\n/**\n * Builds a function that fetches DeFi positions for a given account address\n *\n * @returns A function that fetches DeFi positions for a given account address\n */\nexport function buildPositionFetcher() {\n return async (accountAddress: string): Promise<DefiPositionResponse[]> => {\n const defiPositionsResponse = await timeoutWithRetry(\n () => fetch(`${DEFI_POSITIONS_API_URL}/positions/${accountAddress}`),\n EIGHT_SECONDS_IN_MS,\n MAX_RETRIES,\n );\n\n if (defiPositionsResponse.status !== 200) {\n throw new Error(\n `Unable to fetch defi positions - HTTP ${defiPositionsResponse.status}`,\n );\n }\n\n return (await defiPositionsResponse.json()).data;\n };\n}\n"]}
1
+ {"version":3,"file":"fetch-positions.mjs","sourceRoot":"","sources":["../../src/DeFiPositionsController/fetch-positions.ts"],"names":[],"mappings":"AAyDA,gDAAgD;AAChD,MAAM,CAAC,MAAM,sBAAsB,GAAG,yCAAyC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,KAAK,EAAE,cAAsB,EAAmC,EAAE;QACvE,MAAM,qBAAqB,GAAG,MAAM,KAAK,CACvC,GAAG,sBAAsB,cAAc,cAAc,EAAE,CACxD,CAAC;QAEF,IAAI,qBAAqB,CAAC,MAAM,KAAK,GAAG,EAAE;YACxC,MAAM,IAAI,KAAK,CACb,yCAAyC,qBAAqB,CAAC,MAAM,EAAE,CACxE,CAAC;SACH;QAED,OAAO,CAAC,MAAM,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACnD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["export type DefiPositionResponse = AdapterResponse<{\n tokens: ProtocolToken[];\n}>;\n\ntype ProtocolDetails = {\n chainId: number;\n protocolId: string;\n productId: string;\n protocolDisplayName: string;\n name: string;\n description: string;\n iconUrl: string;\n siteUrl: string;\n positionType: PositionType;\n metadata?: {\n groupPositions?: boolean;\n };\n};\n\ntype AdapterResponse<ProtocolResponse> =\n | (ProtocolDetails & {\n chainName: string;\n } & (\n | (ProtocolResponse & { success: true })\n | (AdapterErrorResponse & { success: false })\n ))\n | (AdapterErrorResponse & { success: false });\n\ntype AdapterErrorResponse = {\n error: {\n message: string;\n };\n};\n\nexport type PositionType = 'supply' | 'borrow' | 'stake' | 'reward';\n\nexport type ProtocolToken = Balance & {\n type: 'protocol';\n tokenId?: string;\n};\n\nexport type Underlying = Balance & {\n type: 'underlying' | 'underlying-claimable';\n iconUrl: string;\n};\n\nexport type Balance = {\n address: string;\n name: string;\n symbol: string;\n decimals: number;\n balanceRaw: string;\n balance: number;\n price?: number;\n tokens?: Underlying[];\n};\n\n// TODO: Update with prod API URL when available\nexport const DEFI_POSITIONS_API_URL = 'https://defiadapters.api.cx.metamask.io';\n\n/**\n * Builds a function that fetches DeFi positions for a given account address\n *\n * @returns A function that fetches DeFi positions for a given account address\n */\nexport function buildPositionFetcher() {\n return async (accountAddress: string): Promise<DefiPositionResponse[]> => {\n const defiPositionsResponse = await fetch(\n `${DEFI_POSITIONS_API_URL}/positions/${accountAddress}`,\n );\n\n if (defiPositionsResponse.status !== 200) {\n throw new Error(\n `Unable to fetch defi positions - HTTP ${defiPositionsResponse.status}`,\n );\n }\n\n return (await defiPositionsResponse.json()).data;\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/assets-controllers",
3
- "version": "83.1.0-preview-71feeb92",
3
+ "version": "83.1.0-preview-2bb073da",
4
4
  "description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -1,34 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.timeoutWithRetry = void 0;
4
- const utils_1 = require("@metamask/utils");
5
- const TIMEOUT_ERROR = new Error('timeout');
6
- /**
7
- *
8
- * @param call - The async function to call.
9
- * @param timeout - Timeout in milliseconds for each call attempt.
10
- * @param maxRetries - Maximum number of retries on timeout.
11
- * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.
12
- */
13
- // eslint-disable-next-line consistent-return
14
- async function timeoutWithRetry(call, timeout, maxRetries) {
15
- (0, utils_1.assert)(maxRetries > 0, 'maxRetries must be greater than 0');
16
- let attempt = 0;
17
- while (attempt <= maxRetries) {
18
- try {
19
- return (await Promise.race([
20
- call(),
21
- new Promise((_resolve, reject) => setTimeout(() => reject(TIMEOUT_ERROR), timeout)),
22
- ]));
23
- }
24
- catch (err) {
25
- if (err === TIMEOUT_ERROR && attempt < maxRetries) {
26
- attempt += 1;
27
- continue;
28
- }
29
- throw err;
30
- }
31
- }
32
- }
33
- exports.timeoutWithRetry = timeoutWithRetry;
34
- //# sourceMappingURL=timeout-with-retry.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"timeout-with-retry.cjs","sourceRoot":"","sources":["../../src/utils/timeout-with-retry.ts"],"names":[],"mappings":";;;AAAA,2CAAyC;AAEzC,MAAM,aAAa,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;AAE3C;;;;;;GAMG;AACH,6CAA6C;AACtC,KAAK,UAAU,gBAAgB,CACpC,IAAO,EACP,OAAe,EACf,UAAkB;IAGlB,IAAA,cAAM,EAAC,UAAU,GAAG,CAAC,EAAE,mCAAmC,CAAC,CAAC;IAE5D,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,OAAO,OAAO,IAAI,UAAU,EAAE;QAC5B,IAAI;YACF,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC;gBACzB,IAAI,EAAE;gBACN,IAAI,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,CACjD;aACF,CAAC,CAA2B,CAAC;SAC/B;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,GAAG,KAAK,aAAa,IAAI,OAAO,GAAG,UAAU,EAAE;gBACjD,OAAO,IAAI,CAAC,CAAC;gBACb,SAAS;aACV;YACD,MAAM,GAAG,CAAC;SACX;KACF;AACH,CAAC;AA1BD,4CA0BC","sourcesContent":["import { assert } from '@metamask/utils';\n\nconst TIMEOUT_ERROR = new Error('timeout');\n\n/**\n *\n * @param call - The async function to call.\n * @param timeout - Timeout in milliseconds for each call attempt.\n * @param maxRetries - Maximum number of retries on timeout.\n * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.\n */\n// eslint-disable-next-line consistent-return\nexport async function timeoutWithRetry<T extends () => Promise<unknown>>(\n call: T,\n timeout: number,\n maxRetries: number,\n // @ts-expect-error TS2366: Assertion guarantees loop executes\n): Promise<Awaited<ReturnType<T>>> {\n assert(maxRetries > 0, 'maxRetries must be greater than 0');\n\n let attempt = 0;\n\n while (attempt <= maxRetries) {\n try {\n return (await Promise.race([\n call(),\n new Promise((_resolve, reject) =>\n setTimeout(() => reject(TIMEOUT_ERROR), timeout),\n ),\n ])) as Awaited<ReturnType<T>>;\n } catch (err) {\n if (err === TIMEOUT_ERROR && attempt < maxRetries) {\n attempt += 1;\n continue;\n }\n throw err;\n }\n }\n}\n"]}
@@ -1,9 +0,0 @@
1
- /**
2
- *
3
- * @param call - The async function to call.
4
- * @param timeout - Timeout in milliseconds for each call attempt.
5
- * @param maxRetries - Maximum number of retries on timeout.
6
- * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.
7
- */
8
- export declare function timeoutWithRetry<T extends () => Promise<unknown>>(call: T, timeout: number, maxRetries: number): Promise<Awaited<ReturnType<T>>>;
9
- //# sourceMappingURL=timeout-with-retry.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"timeout-with-retry.d.cts","sourceRoot":"","sources":["../../src/utils/timeout-with-retry.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,MAAM,OAAO,CAAC,OAAO,CAAC,EACrE,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GAEjB,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAqBjC"}
@@ -1,9 +0,0 @@
1
- /**
2
- *
3
- * @param call - The async function to call.
4
- * @param timeout - Timeout in milliseconds for each call attempt.
5
- * @param maxRetries - Maximum number of retries on timeout.
6
- * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.
7
- */
8
- export declare function timeoutWithRetry<T extends () => Promise<unknown>>(call: T, timeout: number, maxRetries: number): Promise<Awaited<ReturnType<T>>>;
9
- //# sourceMappingURL=timeout-with-retry.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"timeout-with-retry.d.mts","sourceRoot":"","sources":["../../src/utils/timeout-with-retry.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,MAAM,OAAO,CAAC,OAAO,CAAC,EACrE,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GAEjB,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAqBjC"}
@@ -1,30 +0,0 @@
1
- import { assert } from "@metamask/utils";
2
- const TIMEOUT_ERROR = new Error('timeout');
3
- /**
4
- *
5
- * @param call - The async function to call.
6
- * @param timeout - Timeout in milliseconds for each call attempt.
7
- * @param maxRetries - Maximum number of retries on timeout.
8
- * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.
9
- */
10
- // eslint-disable-next-line consistent-return
11
- export async function timeoutWithRetry(call, timeout, maxRetries) {
12
- assert(maxRetries > 0, 'maxRetries must be greater than 0');
13
- let attempt = 0;
14
- while (attempt <= maxRetries) {
15
- try {
16
- return (await Promise.race([
17
- call(),
18
- new Promise((_resolve, reject) => setTimeout(() => reject(TIMEOUT_ERROR), timeout)),
19
- ]));
20
- }
21
- catch (err) {
22
- if (err === TIMEOUT_ERROR && attempt < maxRetries) {
23
- attempt += 1;
24
- continue;
25
- }
26
- throw err;
27
- }
28
- }
29
- }
30
- //# sourceMappingURL=timeout-with-retry.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"timeout-with-retry.mjs","sourceRoot":"","sources":["../../src/utils/timeout-with-retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,wBAAwB;AAEzC,MAAM,aAAa,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;AAE3C;;;;;;GAMG;AACH,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAO,EACP,OAAe,EACf,UAAkB;IAGlB,MAAM,CAAC,UAAU,GAAG,CAAC,EAAE,mCAAmC,CAAC,CAAC;IAE5D,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,OAAO,OAAO,IAAI,UAAU,EAAE;QAC5B,IAAI;YACF,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC;gBACzB,IAAI,EAAE;gBACN,IAAI,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC,CACjD;aACF,CAAC,CAA2B,CAAC;SAC/B;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,GAAG,KAAK,aAAa,IAAI,OAAO,GAAG,UAAU,EAAE;gBACjD,OAAO,IAAI,CAAC,CAAC;gBACb,SAAS;aACV;YACD,MAAM,GAAG,CAAC;SACX;KACF;AACH,CAAC","sourcesContent":["import { assert } from '@metamask/utils';\n\nconst TIMEOUT_ERROR = new Error('timeout');\n\n/**\n *\n * @param call - The async function to call.\n * @param timeout - Timeout in milliseconds for each call attempt.\n * @param maxRetries - Maximum number of retries on timeout.\n * @returns The resolved value of the call, or throws the last error if not a timeout or retries exhausted.\n */\n// eslint-disable-next-line consistent-return\nexport async function timeoutWithRetry<T extends () => Promise<unknown>>(\n call: T,\n timeout: number,\n maxRetries: number,\n // @ts-expect-error TS2366: Assertion guarantees loop executes\n): Promise<Awaited<ReturnType<T>>> {\n assert(maxRetries > 0, 'maxRetries must be greater than 0');\n\n let attempt = 0;\n\n while (attempt <= maxRetries) {\n try {\n return (await Promise.race([\n call(),\n new Promise((_resolve, reject) =>\n setTimeout(() => reject(TIMEOUT_ERROR), timeout),\n ),\n ])) as Awaited<ReturnType<T>>;\n } catch (err) {\n if (err === TIMEOUT_ERROR && attempt < maxRetries) {\n attempt += 1;\n continue;\n }\n throw err;\n }\n }\n}\n"]}