@metamask-previews/earn-controller 0.14.0-preview-d9a49231 → 0.14.0-preview-c4b7ea2e

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.
@@ -1,18 +1,18 @@
1
1
  "use strict";
2
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
- 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");
5
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
- };
7
2
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
8
3
  if (kind === "m") throw new TypeError("Private method is not writable");
9
4
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
10
5
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
11
6
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
12
7
  };
13
- var _EarnController_instances, _EarnController_stakeSDK, _EarnController_selectedNetworkClientId, _EarnController_stakingApiService, _EarnController_initializeSDK, _EarnController_getCurrentAccount, _EarnController_getCurrentChainId;
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
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
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _EarnController_instances, _EarnController_earnSDK, _EarnController_selectedNetworkClientId, _EarnController_earnApiService, _EarnController_addTransactionFn, _EarnController_supportedPooledStakingChains, _EarnController_env, _EarnController_initializeSDK, _EarnController_getCurrentAccount, _EarnController_getCurrentChainId;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.EarnController = exports.getDefaultEarnControllerState = exports.controllerName = void 0;
15
+ exports.EarnController = exports.getDefaultEarnControllerState = exports.DEFAULT_POOLED_STAKING_CHAIN_STATE = exports.DEFAULT_POOLED_STAKING_VAULT_APY_AVERAGES = exports.DEFAULT_LENDING_POSITION = exports.DEFAULT_LENDING_MARKET = exports.controllerName = void 0;
16
16
  const providers_1 = require("@ethersproject/providers");
17
17
  const base_controller_1 = require("@metamask/base-controller");
18
18
  const controller_utils_1 = require("@metamask/controller-utils");
@@ -24,6 +24,10 @@ const stakingTransactionTypes = new Set([
24
24
  transaction_controller_1.TransactionType.stakingUnstake,
25
25
  transaction_controller_1.TransactionType.stakingClaim,
26
26
  ]);
27
+ const lendingTransactionTypes = new Set([
28
+ transaction_controller_1.TransactionType.lendingDeposit,
29
+ 'lendingWithdraw',
30
+ ]);
27
31
  /**
28
32
  * Metadata for the EarnController.
29
33
  */
@@ -32,7 +36,7 @@ const earnControllerMetadata = {
32
36
  persist: true,
33
37
  anonymous: false,
34
38
  },
35
- stablecoin_lending: {
39
+ lending: {
36
40
  persist: true,
37
41
  anonymous: false,
38
42
  },
@@ -42,17 +46,42 @@ const earnControllerMetadata = {
42
46
  },
43
47
  };
44
48
  // === Default State ===
45
- const DEFAULT_STABLECOIN_VAULT = {
46
- symbol: '',
49
+ exports.DEFAULT_LENDING_MARKET = {
50
+ id: '',
51
+ chainId: 0,
52
+ protocol: '',
47
53
  name: '',
54
+ address: '',
55
+ tvlUnderlying: '0',
56
+ netSupplyRate: 0,
57
+ totalSupplyRate: 0,
58
+ underlying: {
59
+ address: '',
60
+ chainId: 0,
61
+ },
62
+ outputToken: {
63
+ address: '',
64
+ chainId: 0,
65
+ },
66
+ rewards: [
67
+ {
68
+ token: {
69
+ address: '',
70
+ chainId: 0,
71
+ },
72
+ rate: 0,
73
+ },
74
+ ],
75
+ };
76
+ exports.DEFAULT_LENDING_POSITION = {
77
+ id: '',
48
78
  chainId: 0,
49
- tokenAddress: '',
50
- vaultAddress: '',
51
- currentAPY: '0',
52
- supply: '0',
53
- liquidity: '0',
79
+ assets: '0',
80
+ marketId: '',
81
+ marketAddress: '',
82
+ protocol: '',
54
83
  };
55
- const DEFAULT_POOLED_STAKING_VAULT_APY_AVERAGES = {
84
+ exports.DEFAULT_POOLED_STAKING_VAULT_APY_AVERAGES = {
56
85
  oneDay: '0',
57
86
  oneWeek: '0',
58
87
  oneMonth: '0',
@@ -60,6 +89,24 @@ const DEFAULT_POOLED_STAKING_VAULT_APY_AVERAGES = {
60
89
  sixMonths: '0',
61
90
  oneYear: '0',
62
91
  };
92
+ exports.DEFAULT_POOLED_STAKING_CHAIN_STATE = {
93
+ pooledStakes: {
94
+ account: '',
95
+ lifetimeRewards: '0',
96
+ assets: '0',
97
+ exitRequests: [],
98
+ },
99
+ exchangeRate: '1',
100
+ vaultMetadata: {
101
+ apy: '0',
102
+ capacity: '0',
103
+ feePercent: 0,
104
+ totalAssets: '0',
105
+ vaultAddress: '0x0000000000000000000000000000000000000000',
106
+ },
107
+ vaultDailyApys: [],
108
+ vaultApyAverages: exports.DEFAULT_POOLED_STAKING_VAULT_APY_AVERAGES,
109
+ };
63
110
  /**
64
111
  * Gets the default state for the EarnController.
65
112
  *
@@ -68,26 +115,12 @@ const DEFAULT_POOLED_STAKING_VAULT_APY_AVERAGES = {
68
115
  function getDefaultEarnControllerState() {
69
116
  return {
70
117
  pooled_staking: {
71
- pooledStakes: {
72
- account: '',
73
- lifetimeRewards: '0',
74
- assets: '0',
75
- exitRequests: [],
76
- },
77
- exchangeRate: '1',
78
- vaultMetadata: {
79
- apy: '0',
80
- capacity: '0',
81
- feePercent: 0,
82
- totalAssets: '0',
83
- vaultAddress: '0x0000000000000000000000000000000000000000',
84
- },
85
- vaultDailyApys: [],
86
- vaultApyAverages: DEFAULT_POOLED_STAKING_VAULT_APY_AVERAGES,
87
118
  isEligible: false,
88
119
  },
89
- stablecoin_lending: {
90
- vaults: [DEFAULT_STABLECOIN_VAULT],
120
+ lending: {
121
+ markets: [exports.DEFAULT_LENDING_MARKET],
122
+ positions: [exports.DEFAULT_LENDING_POSITION],
123
+ isEligible: false,
91
124
  },
92
125
  lastUpdated: 0,
93
126
  };
@@ -98,7 +131,7 @@ exports.getDefaultEarnControllerState = getDefaultEarnControllerState;
98
131
  * EarnController manages DeFi earning opportunities across different protocols and chains.
99
132
  */
100
133
  class EarnController extends base_controller_1.BaseController {
101
- constructor({ messenger, state = {}, }) {
134
+ constructor({ messenger, state = {}, addTransactionFn, env = stake_sdk_1.EarnEnvironments.PROD, }) {
102
135
  super({
103
136
  name: exports.controllerName,
104
137
  metadata: earnControllerMetadata,
@@ -109,22 +142,40 @@ class EarnController extends base_controller_1.BaseController {
109
142
  },
110
143
  });
111
144
  _EarnController_instances.add(this);
112
- _EarnController_stakeSDK.set(this, null);
145
+ _EarnController_earnSDK.set(this, null);
113
146
  _EarnController_selectedNetworkClientId.set(this, void 0);
114
- _EarnController_stakingApiService.set(this, new stake_sdk_1.StakingApiService());
115
- __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_initializeSDK).call(this);
147
+ _EarnController_earnApiService.set(this, void 0);
148
+ _EarnController_addTransactionFn.set(this, void 0);
149
+ _EarnController_supportedPooledStakingChains.set(this, void 0);
150
+ _EarnController_env.set(this, void 0);
151
+ __classPrivateFieldSet(this, _EarnController_env, env, "f");
152
+ __classPrivateFieldSet(this, _EarnController_earnApiService, new stake_sdk_1.EarnApiService(__classPrivateFieldGet(this, _EarnController_env, "f")), "f");
153
+ // temporary array of supported chains
154
+ // TODO: remove this once we export a supported chains list from the sdk
155
+ // from sdk or api to get lending and pooled staking chains
156
+ __classPrivateFieldSet(this, _EarnController_supportedPooledStakingChains, [1, 560048], "f");
157
+ __classPrivateFieldSet(this, _EarnController_addTransactionFn, addTransactionFn, "f");
158
+ __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_initializeSDK).call(this).catch(console.error);
116
159
  this.refreshPooledStakingData().catch(console.error);
160
+ this.refreshLendingData().catch(console.error);
117
161
  const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
118
162
  __classPrivateFieldSet(this, _EarnController_selectedNetworkClientId, selectedNetworkClientId, "f");
119
163
  // Listen for network changes
120
164
  this.messagingSystem.subscribe('NetworkController:stateChange', (networkControllerState) => {
121
165
  if (networkControllerState.selectedNetworkClientId !==
122
166
  __classPrivateFieldGet(this, _EarnController_selectedNetworkClientId, "f")) {
123
- __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_initializeSDK).call(this, networkControllerState.selectedNetworkClientId);
124
- this.refreshPooledStakingVaultMetadata().catch(console.error);
125
- this.refreshPooledStakingVaultDailyApys().catch(console.error);
126
- this.refreshPooledStakingVaultApyAverages().catch(console.error);
127
- this.refreshPooledStakes().catch(console.error);
167
+ const chainId = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this, networkControllerState.selectedNetworkClientId);
168
+ __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_initializeSDK).call(this, networkControllerState.selectedNetworkClientId).catch(console.error);
169
+ if ((0, stake_sdk_1.isSupportedPooledStakingChain)(chainId)) {
170
+ // only refresh pool staking data for the chain we are switching to
171
+ this.refreshPooledStakingVaultMetadata(chainId).catch(console.error);
172
+ this.refreshPooledStakingVaultDailyApys(chainId).catch(console.error);
173
+ this.refreshPooledStakingVaultApyAverages(chainId).catch(console.error);
174
+ this.refreshPooledStakes({ chainId }).catch(console.error);
175
+ }
176
+ // refresh lending data for all chains
177
+ this.refreshLendingMarkets().catch(console.error);
178
+ this.refreshLendingPositions().catch(console.error);
128
179
  }
129
180
  __classPrivateFieldSet(this, _EarnController_selectedNetworkClientId, networkControllerState.selectedNetworkClientId, "f");
130
181
  });
@@ -136,8 +187,11 @@ class EarnController extends base_controller_1.BaseController {
136
187
  * Until this has been fixed, we rely on the event payload for the latest account instead of #getCurrentAccount().
137
188
  * Issue: https://github.com/MetaMask/accounts-planning/issues/887
138
189
  */
190
+ // TODO: temp solution, this will refresh lending eligibility also
191
+ // we could have a more general check, as what is happening is a compliance address check
139
192
  this.refreshStakingEligibility({ address }).catch(console.error);
140
193
  this.refreshPooledStakes({ address }).catch(console.error);
194
+ this.refreshLendingPositions({ address }).catch(console.error);
141
195
  });
142
196
  // Listen for confirmed staking transactions
143
197
  this.messagingSystem.subscribe('TransactionController:transactionConfirmed', (transactionMeta) => {
@@ -149,10 +203,15 @@ class EarnController extends base_controller_1.BaseController {
149
203
  const { type, originalType } = transactionMeta;
150
204
  const isStakingTransaction = stakingTransactionTypes.has(type) ||
151
205
  stakingTransactionTypes.has(originalType);
206
+ const isLendingTransaction = lendingTransactionTypes.has(type) ||
207
+ lendingTransactionTypes.has(originalType);
208
+ const sender = transactionMeta.txParams.from;
152
209
  if (isStakingTransaction) {
153
- const sender = transactionMeta.txParams.from;
154
210
  this.refreshPooledStakes({ resetCache: true, address: sender }).catch(console.error);
155
211
  }
212
+ if (isLendingTransaction) {
213
+ this.refreshLendingPositions({ address: sender }).catch(console.error);
214
+ }
156
215
  });
157
216
  }
158
217
  /**
@@ -163,18 +222,24 @@ class EarnController extends base_controller_1.BaseController {
163
222
  * @param options - Optional arguments
164
223
  * @param [options.resetCache] - Control whether the BE cache should be invalidated (optional).
165
224
  * @param [options.address] - The address to refresh pooled stakes for (optional).
225
+ * @param [options.chainId] - The chain id to refresh pooled stakes for (optional).
166
226
  * @returns A promise that resolves when the stakes data has been updated
167
227
  */
168
- async refreshPooledStakes({ resetCache = false, address, } = {}) {
228
+ async refreshPooledStakes({ resetCache = false, address, chainId, } = {}) {
169
229
  const addressToUse = address ?? __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this)?.address;
170
230
  if (!addressToUse) {
171
231
  return;
172
232
  }
173
- const chainId = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
174
- const { accounts, exchangeRate } = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getPooledStakes([addressToUse], chainId, resetCache);
233
+ const chainIdToUse = chainId ?? __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
234
+ const { accounts, exchangeRate } = await __classPrivateFieldGet(this, _EarnController_earnApiService, "f").pooledStaking.getPooledStakes([addressToUse], chainIdToUse, resetCache);
175
235
  this.update((state) => {
176
- state.pooled_staking.pooledStakes = accounts[0];
177
- state.pooled_staking.exchangeRate = exchangeRate;
236
+ const chainState = state.pooled_staking[chainIdToUse] ??
237
+ exports.DEFAULT_POOLED_STAKING_CHAIN_STATE;
238
+ state.pooled_staking[chainIdToUse] = {
239
+ ...chainState,
240
+ pooledStakes: accounts[0],
241
+ exchangeRate,
242
+ };
178
243
  });
179
244
  }
180
245
  /**
@@ -190,11 +255,12 @@ class EarnController extends base_controller_1.BaseController {
190
255
  if (!addressToCheck) {
191
256
  return;
192
257
  }
193
- const { eligible: isEligible } = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getPooledStakingEligibility([
258
+ const { eligible: isEligible } = await __classPrivateFieldGet(this, _EarnController_earnApiService, "f").pooledStaking.getPooledStakingEligibility([
194
259
  addressToCheck,
195
260
  ]);
196
261
  this.update((state) => {
197
262
  state.pooled_staking.isEligible = isEligible;
263
+ state.lending.isEligible = isEligible;
198
264
  });
199
265
  }
200
266
  /**
@@ -202,41 +268,59 @@ class EarnController extends base_controller_1.BaseController {
202
268
  * Updates the vault metadata in the controller state including APY, capacity,
203
269
  * fee percentage, total assets, and vault address.
204
270
  *
271
+ * @param chainId - The chain id to refresh pooled staking vault metadata for (optional).
205
272
  * @returns A promise that resolves when the vault metadata has been updated
206
273
  */
207
- async refreshPooledStakingVaultMetadata() {
208
- const chainId = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
209
- const vaultMetadata = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getVaultData(chainId);
274
+ async refreshPooledStakingVaultMetadata(chainId) {
275
+ const chainIdToUse = chainId ?? __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
276
+ const vaultMetadata = await __classPrivateFieldGet(this, _EarnController_earnApiService, "f").pooledStaking.getVaultData(chainIdToUse);
210
277
  this.update((state) => {
211
- state.pooled_staking.vaultMetadata = vaultMetadata;
278
+ const chainState = state.pooled_staking[chainIdToUse] ??
279
+ exports.DEFAULT_POOLED_STAKING_CHAIN_STATE;
280
+ state.pooled_staking[chainIdToUse] = {
281
+ ...chainState,
282
+ vaultMetadata,
283
+ };
212
284
  });
213
285
  }
214
286
  /**
215
287
  * Refreshes pooled staking vault daily apys for the current chain.
216
288
  * Updates the pooled staking vault daily apys controller state.
217
289
  *
290
+ * @param chainId - The chain id to refresh pooled staking vault daily apys for (optional).
218
291
  * @param days - The number of days to fetch pooled staking vault daily apys for (defaults to 365).
219
292
  * @param order - The order in which to fetch pooled staking vault daily apys. Descending order fetches the latest N days (latest working backwards). Ascending order fetches the oldest N days (oldest working forwards) (defaults to 'desc').
220
293
  * @returns A promise that resolves when the pooled staking vault daily apys have been updated.
221
294
  */
222
- async refreshPooledStakingVaultDailyApys(days = 365, order = 'desc') {
223
- const chainId = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
224
- const vaultDailyApys = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getVaultDailyApys(chainId, days, order);
295
+ async refreshPooledStakingVaultDailyApys(chainId, days = 365, order = 'desc') {
296
+ const chainIdToUse = chainId ?? __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
297
+ const vaultDailyApys = await __classPrivateFieldGet(this, _EarnController_earnApiService, "f").pooledStaking.getVaultDailyApys(chainIdToUse, days, order);
225
298
  this.update((state) => {
226
- state.pooled_staking.vaultDailyApys = vaultDailyApys;
299
+ const chainState = state.pooled_staking[chainIdToUse] ??
300
+ exports.DEFAULT_POOLED_STAKING_CHAIN_STATE;
301
+ state.pooled_staking[chainIdToUse] = {
302
+ ...chainState,
303
+ vaultDailyApys,
304
+ };
227
305
  });
228
306
  }
229
307
  /**
230
308
  * Refreshes pooled staking vault apy averages for the current chain.
231
309
  * Updates the pooled staking vault apy averages controller state.
232
310
  *
311
+ * @param chainId - The chain id to refresh pooled staking vault apy averages for (optional).
233
312
  * @returns A promise that resolves when the pooled staking vault apy averages have been updated.
234
313
  */
235
- async refreshPooledStakingVaultApyAverages() {
236
- const chainId = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
237
- const vaultApyAverages = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getVaultApyAverages(chainId);
314
+ async refreshPooledStakingVaultApyAverages(chainId) {
315
+ const chainIdToUse = chainId ?? __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
316
+ const vaultApyAverages = await __classPrivateFieldGet(this, _EarnController_earnApiService, "f").pooledStaking.getVaultApyAverages(chainIdToUse);
238
317
  this.update((state) => {
239
- state.pooled_staking.vaultApyAverages = vaultApyAverages;
318
+ const chainState = state.pooled_staking[chainIdToUse] ??
319
+ exports.DEFAULT_POOLED_STAKING_CHAIN_STATE;
320
+ state.pooled_staking[chainIdToUse] = {
321
+ ...chainState,
322
+ vaultApyAverages,
323
+ };
240
324
  });
241
325
  }
242
326
  /**
@@ -251,39 +335,309 @@ class EarnController extends base_controller_1.BaseController {
251
335
  * @throws {Error} If any of the refresh operations fail, with concatenated error messages
252
336
  */
253
337
  async refreshPooledStakingData({ resetCache, address, } = {}) {
338
+ const errors = [];
339
+ for (const chainId of __classPrivateFieldGet(this, _EarnController_supportedPooledStakingChains, "f")) {
340
+ await Promise.all([
341
+ this.refreshPooledStakes({ resetCache, address, chainId }).catch((error) => {
342
+ errors.push(error);
343
+ }),
344
+ this.refreshStakingEligibility({ address }).catch((error) => {
345
+ errors.push(error);
346
+ }),
347
+ this.refreshPooledStakingVaultMetadata(chainId).catch((error) => {
348
+ errors.push(error);
349
+ }),
350
+ this.refreshPooledStakingVaultDailyApys(chainId).catch((error) => {
351
+ errors.push(error);
352
+ }),
353
+ this.refreshPooledStakingVaultApyAverages(chainId).catch((error) => {
354
+ errors.push(error);
355
+ }),
356
+ ]);
357
+ }
358
+ if (errors.length > 0) {
359
+ throw new Error(`Failed to refresh some staking data: ${errors
360
+ .map((e) => e.message)
361
+ .join(', ')}`);
362
+ }
363
+ }
364
+ /**
365
+ * Refreshes the lending markets data for all chains.
366
+ * Updates the lending markets in the controller state.
367
+ *
368
+ * @returns A promise that resolves when the lending markets have been updated
369
+ */
370
+ async refreshLendingMarkets() {
371
+ const markets = await __classPrivateFieldGet(this, _EarnController_earnApiService, "f").lending.getMarkets();
372
+ this.update((state) => {
373
+ state.lending.markets = markets;
374
+ });
375
+ }
376
+ /**
377
+ * Refreshes the lending positions for the current account.
378
+ * Updates the lending positions in the controller state.
379
+ *
380
+ * @param options - Optional arguments
381
+ * @param [options.address] - The address to refresh lending positions for (optional).
382
+ * @returns A promise that resolves when the lending positions have been updated
383
+ */
384
+ async refreshLendingPositions({ address, } = {}) {
385
+ const addressToUse = address ?? __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this)?.address;
386
+ if (!addressToUse) {
387
+ return;
388
+ }
389
+ // linter complaining about this not being a promise, but it is
390
+ // TODO: figure out why this is not seen as a promise
391
+ const positions = await Promise.resolve(__classPrivateFieldGet(this, _EarnController_earnApiService, "f").lending.getPositions(addressToUse));
392
+ this.update((state) => {
393
+ state.lending.positions = positions.map((position) => ({
394
+ ...position,
395
+ marketId: position.market.id,
396
+ marketAddress: position.market.address,
397
+ protocol: position.market.protocol,
398
+ }));
399
+ });
400
+ }
401
+ /**
402
+ * Refreshes the lending eligibility status for the current account.
403
+ * Updates the eligibility status in the controller state based on the location and address blocklist for compliance.
404
+ *
405
+ * @param options - Optional arguments
406
+ * @param [options.address] - The address to refresh lending eligibility for (optional).
407
+ * @returns A promise that resolves when the eligibility status has been updated
408
+ */
409
+ async refreshLendingEligibility({ address, } = {}) {
410
+ const addressToUse = address ?? __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this)?.address;
411
+ // TODO: this is a temporary solution to refresh lending eligibility as
412
+ // the eligibility check is not yet implemented for lending
413
+ // this check will check the address against the same blocklist as the
414
+ // staking eligibility check
415
+ if (!addressToUse) {
416
+ return;
417
+ }
418
+ const { eligible: isEligible } = await __classPrivateFieldGet(this, _EarnController_earnApiService, "f").pooledStaking.getPooledStakingEligibility([
419
+ addressToUse,
420
+ ]);
421
+ this.update((state) => {
422
+ state.lending.isEligible = isEligible;
423
+ state.pooled_staking.isEligible = isEligible;
424
+ });
425
+ }
426
+ /**
427
+ * Refreshes all lending related data including markets, positions, and eligibility.
428
+ * This method allows partial success, meaning some data may update while other requests fail.
429
+ * All errors are collected and thrown as a single error message.
430
+ *
431
+ * @returns A promise that resolves when all possible data has been updated
432
+ * @throws {Error} If any of the refresh operations fail, with concatenated error messages
433
+ */
434
+ async refreshLendingData() {
254
435
  const errors = [];
255
436
  await Promise.all([
256
- this.refreshPooledStakes({ resetCache, address }).catch((error) => {
437
+ this.refreshLendingMarkets().catch((error) => {
257
438
  errors.push(error);
258
439
  }),
259
- this.refreshStakingEligibility({ address }).catch((error) => {
440
+ this.refreshLendingPositions().catch((error) => {
260
441
  errors.push(error);
261
442
  }),
262
- this.refreshPooledStakingVaultMetadata().catch((error) => {
263
- errors.push(error);
264
- }),
265
- this.refreshPooledStakingVaultDailyApys().catch((error) => {
266
- errors.push(error);
267
- }),
268
- this.refreshPooledStakingVaultApyAverages().catch((error) => {
443
+ this.refreshLendingEligibility().catch((error) => {
269
444
  errors.push(error);
270
445
  }),
271
446
  ]);
272
447
  if (errors.length > 0) {
273
- throw new Error(`Failed to refresh some staking data: ${errors
448
+ throw new Error(`Failed to refresh some lending data: ${errors
274
449
  .map((e) => e.message)
275
450
  .join(', ')}`);
276
451
  }
277
452
  }
453
+ /**
454
+ * Gets the lending position history for the current account.
455
+ *
456
+ * @param options - Optional arguments
457
+ * @param [options.address] - The address to get lending position history for (optional).
458
+ * @param [options.chainId] - The chain id to get lending position history for (optional).
459
+ * @param [options.positionId] - The position id to get lending position history for.
460
+ * @param [options.marketId] - The market id to get lending position history for.
461
+ * @param [options.marketAddress] - The market address to get lending position history for.
462
+ * @param [options.protocol] - The protocol to get lending position history for.
463
+ * @param [options.days] - The number of days to get lending position history for (optional).
464
+ * @returns A promise that resolves when the lending position history has been updated
465
+ */
466
+ getLendingPositionHistory({ address, chainId, positionId, marketId, marketAddress, protocol, days = 730, }) {
467
+ const addressToUse = address ?? __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this)?.address;
468
+ const chainIdToUse = chainId ?? __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
469
+ if (!addressToUse || !(0, stake_sdk_1.isSupportedLendingChain)(chainIdToUse)) {
470
+ return [];
471
+ }
472
+ return __classPrivateFieldGet(this, _EarnController_earnApiService, "f").lending.getPositionHistory(addressToUse, chainIdToUse, protocol, marketId, marketAddress, positionId, days);
473
+ }
474
+ /**
475
+ * Gets the lending market daily apys and averages for the current chain.
476
+ *
477
+ * @param options - Optional arguments
478
+ * @param [options.chainId] - The chain id to get lending market daily apys and averages for (optional).
479
+ * @param [options.protocol] - The protocol to get lending market daily apys and averages for.
480
+ * @param [options.marketId] - The market id to get lending market daily apys and averages for.
481
+ * @param [options.days] - The number of days to get lending market daily apys and averages for (optional).
482
+ * @returns A promise that resolves when the lending market daily apys and averages have been updated
483
+ */
484
+ getLendingMarketDailyApysAndAverages({ chainId, protocol, marketId, days = 365, }) {
485
+ const chainIdToUse = chainId ?? __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
486
+ if (!(0, stake_sdk_1.isSupportedLendingChain)(chainIdToUse)) {
487
+ return undefined;
488
+ }
489
+ return __classPrivateFieldGet(this, _EarnController_earnApiService, "f").lending.getHistoricMarketApys(chainIdToUse, protocol, marketId, days);
490
+ }
491
+ /**
492
+ * Executes a lending deposit transaction.
493
+ *
494
+ * @param options - The options for the lending deposit transaction.
495
+ * @param options.amount - The amount to deposit.
496
+ * @param options.protocol - The protocol of the lending market.
497
+ * @param options.underlyingTokenAddress - The address of the underlying token.
498
+ * @param options.gasOptions - The gas options for the transaction.
499
+ * @param options.gasOptions.gasLimit - The gas limit for the transaction.
500
+ * @param options.gasOptions.gasBufferPct - The gas buffer percentage for the transaction.
501
+ * @param options.txOptions - The transaction options for the transaction.
502
+ * @returns A promise that resolves to the transaction hash.
503
+ */
504
+ async executeLendingDeposit({ amount, protocol, underlyingTokenAddress, gasOptions, txOptions, }) {
505
+ const address = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this)?.address;
506
+ const transactionData = await __classPrivateFieldGet(this, _EarnController_earnSDK, "f")?.contracts?.lending?.[protocol]?.[underlyingTokenAddress]?.encodeDepositTransactionData(amount, address, gasOptions);
507
+ if (!transactionData) {
508
+ throw new Error('Transaction data not found');
509
+ }
510
+ if (!__classPrivateFieldGet(this, _EarnController_selectedNetworkClientId, "f")) {
511
+ throw new Error('Selected network client id not found');
512
+ }
513
+ const txHash = await __classPrivateFieldGet(this, _EarnController_addTransactionFn, "f").call(this, {
514
+ ...transactionData,
515
+ value: transactionData.value.toString(),
516
+ chainId: (0, controller_utils_1.toHex)(__classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this)),
517
+ gasLimit: String(transactionData.gasLimit),
518
+ }, {
519
+ ...txOptions,
520
+ networkClientId: __classPrivateFieldGet(this, _EarnController_selectedNetworkClientId, "f"),
521
+ });
522
+ return txHash;
523
+ }
524
+ /**
525
+ * Executes a lending withdraw transaction.
526
+ *
527
+ * @param options - The options for the lending withdraw transaction.
528
+ * @param options.amount - The amount to withdraw.
529
+ * @param options.protocol - The protocol of the lending market.
530
+ * @param options.underlyingTokenAddress - The address of the underlying token.
531
+ * @param options.gasOptions - The gas options for the transaction.
532
+ * @param options.gasOptions.gasLimit - The gas limit for the transaction.
533
+ * @param options.gasOptions.gasBufferPct - The gas buffer percentage for the transaction.
534
+ * @param options.txOptions - The transaction options for the transaction.
535
+ * @returns A promise that resolves to the transaction hash.
536
+ */
537
+ async executeLendingWithdraw({ amount, protocol, underlyingTokenAddress, gasOptions, txOptions, }) {
538
+ const address = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this)?.address;
539
+ const transactionData = await __classPrivateFieldGet(this, _EarnController_earnSDK, "f")?.contracts?.lending?.[protocol]?.[underlyingTokenAddress]?.encodeWithdrawTransactionData(amount, address, gasOptions);
540
+ if (!transactionData) {
541
+ throw new Error('Transaction data not found');
542
+ }
543
+ if (!__classPrivateFieldGet(this, _EarnController_selectedNetworkClientId, "f")) {
544
+ throw new Error('Selected network client id not found');
545
+ }
546
+ const txHash = await __classPrivateFieldGet(this, _EarnController_addTransactionFn, "f").call(this, {
547
+ ...transactionData,
548
+ value: transactionData.value.toString(),
549
+ chainId: (0, controller_utils_1.toHex)(__classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this)),
550
+ gasLimit: String(transactionData.gasLimit),
551
+ }, {
552
+ ...txOptions,
553
+ networkClientId: __classPrivateFieldGet(this, _EarnController_selectedNetworkClientId, "f"),
554
+ });
555
+ return txHash;
556
+ }
557
+ /**
558
+ * Executes a lending token approve transaction.
559
+ *
560
+ * @param options - The options for the lending token approve transaction.
561
+ * @param options.amount - The amount to approve.
562
+ * @param options.protocol - The protocol of the lending market.
563
+ * @param options.underlyingTokenAddress - The address of the underlying token.
564
+ * @param options.gasOptions - The gas options for the transaction.
565
+ * @param options.gasOptions.gasLimit - The gas limit for the transaction.
566
+ * @param options.gasOptions.gasBufferPct - The gas buffer percentage for the transaction.
567
+ * @param options.txOptions - The transaction options for the transaction.
568
+ * @returns A promise that resolves to the transaction hash.
569
+ */
570
+ async executeLendingTokenApprove({ protocol, amount, underlyingTokenAddress, gasOptions, txOptions, }) {
571
+ const address = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this)?.address;
572
+ const transactionData = await __classPrivateFieldGet(this, _EarnController_earnSDK, "f")?.contracts?.lending?.[protocol]?.[underlyingTokenAddress]?.encodeUnderlyingTokenApproveTransactionData(amount, address, gasOptions);
573
+ if (!transactionData) {
574
+ throw new Error('Transaction data not found');
575
+ }
576
+ if (!__classPrivateFieldGet(this, _EarnController_selectedNetworkClientId, "f")) {
577
+ throw new Error('Selected network client id not found');
578
+ }
579
+ const txHash = await __classPrivateFieldGet(this, _EarnController_addTransactionFn, "f").call(this, {
580
+ ...transactionData,
581
+ value: transactionData.value.toString(),
582
+ chainId: (0, controller_utils_1.toHex)(__classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this)),
583
+ gasLimit: String(transactionData.gasLimit),
584
+ }, {
585
+ ...txOptions,
586
+ networkClientId: __classPrivateFieldGet(this, _EarnController_selectedNetworkClientId, "f"),
587
+ });
588
+ return txHash;
589
+ }
590
+ /**
591
+ * Gets the allowance for a lending token.
592
+ *
593
+ * @param protocol - The protocol of the lending market.
594
+ * @param underlyingTokenAddress - The address of the underlying token.
595
+ * @returns A promise that resolves to the allowance.
596
+ */
597
+ async getLendingTokenAllowance(protocol, underlyingTokenAddress) {
598
+ const address = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this)?.address;
599
+ const allowance = await __classPrivateFieldGet(this, _EarnController_earnSDK, "f")?.contracts?.lending?.[protocol]?.[underlyingTokenAddress]?.underlyingTokenAllowance(address);
600
+ return allowance;
601
+ }
602
+ /**
603
+ * Gets the maximum withdraw amount for a lending token's output token or shares if no output token.
604
+ *
605
+ * @param protocol - The protocol of the lending market.
606
+ * @param underlyingTokenAddress - The address of the underlying token.
607
+ * @returns A promise that resolves to the maximum withdraw amount.
608
+ */
609
+ async getLendingTokenMaxWithdraw(protocol, underlyingTokenAddress) {
610
+ const address = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this)?.address;
611
+ const maxWithdraw = await __classPrivateFieldGet(this, _EarnController_earnSDK, "f")?.contracts?.lending?.[protocol]?.[underlyingTokenAddress]?.maxWithdraw(address);
612
+ return maxWithdraw;
613
+ }
614
+ /**
615
+ * Gets the maximum deposit amount for a lending token.
616
+ *
617
+ * @param protocol - The protocol of the lending market.
618
+ * @param underlyingTokenAddress - The address of the underlying token.
619
+ * @returns A promise that resolves to the maximum deposit amount.
620
+ */
621
+ async getLendingTokenMaxDeposit(protocol, underlyingTokenAddress) {
622
+ const address = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this)?.address;
623
+ const maxDeposit = await __classPrivateFieldGet(this, _EarnController_earnSDK, "f")?.contracts?.lending?.[protocol]?.[underlyingTokenAddress]?.maxDeposit(address);
624
+ return maxDeposit;
625
+ }
278
626
  }
279
627
  exports.EarnController = EarnController;
280
- _EarnController_stakeSDK = new WeakMap(), _EarnController_selectedNetworkClientId = new WeakMap(), _EarnController_stakingApiService = new WeakMap(), _EarnController_instances = new WeakSet(), _EarnController_initializeSDK = function _EarnController_initializeSDK(networkClientId) {
628
+ _EarnController_earnSDK = new WeakMap(), _EarnController_selectedNetworkClientId = new WeakMap(), _EarnController_earnApiService = new WeakMap(), _EarnController_addTransactionFn = new WeakMap(), _EarnController_supportedPooledStakingChains = new WeakMap(), _EarnController_env = new WeakMap(), _EarnController_instances = new WeakSet(), _EarnController_initializeSDK =
629
+ /**
630
+ * Initializes the Earn SDK.
631
+ *
632
+ * @param networkClientId - The network client id to initialize the Earn SDK for (optional).
633
+ */
634
+ async function _EarnController_initializeSDK(networkClientId) {
281
635
  const { selectedNetworkClientId } = networkClientId
282
636
  ? { selectedNetworkClientId: networkClientId }
283
637
  : this.messagingSystem.call('NetworkController:getState');
284
638
  const networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
285
639
  if (!networkClient?.provider) {
286
- __classPrivateFieldSet(this, _EarnController_stakeSDK, null, "f");
640
+ __classPrivateFieldSet(this, _EarnController_earnSDK, null, "f");
287
641
  return;
288
642
  }
289
643
  const provider = new providers_1.Web3Provider(networkClient.provider);
@@ -291,33 +645,26 @@ _EarnController_stakeSDK = new WeakMap(), _EarnController_selectedNetworkClientI
291
645
  // Initialize appropriate contracts based on chainId
292
646
  const config = {
293
647
  chainId: (0, controller_utils_1.convertHexToDecimal)(chainId),
648
+ env: __classPrivateFieldGet(this, _EarnController_env, "f"),
294
649
  };
295
650
  try {
296
- __classPrivateFieldSet(this, _EarnController_stakeSDK, stake_sdk_1.StakeSdk.create(config), "f");
297
- __classPrivateFieldGet(this, _EarnController_stakeSDK, "f").pooledStakingContract.connectSignerOrProvider(provider);
651
+ __classPrivateFieldSet(this, _EarnController_earnSDK, await stake_sdk_1.EarnSdk.create(provider, config), "f");
298
652
  }
299
653
  catch (error) {
300
- __classPrivateFieldSet(this, _EarnController_stakeSDK, null, "f");
654
+ __classPrivateFieldSet(this, _EarnController_earnSDK, null, "f");
301
655
  // Only log unexpected errors, not unsupported chain errors
302
656
  if (!(error instanceof Error &&
303
657
  error.message.includes('Unsupported chainId'))) {
304
- console.error('Stake SDK initialization failed:', error);
658
+ console.error('Earn SDK initialization failed:', error);
305
659
  }
306
660
  }
307
661
  }, _EarnController_getCurrentAccount = function _EarnController_getCurrentAccount() {
308
662
  return this.messagingSystem.call('AccountsController:getSelectedAccount');
309
- }, _EarnController_getCurrentChainId = function _EarnController_getCurrentChainId() {
310
- // const { selectedNetworkClientId } = this.messagingSystem.call(
311
- // 'NetworkController:getState',
312
- // );
313
- // const {
314
- // configuration: { chainId },
315
- // } = this.messagingSystem.call(
316
- // 'NetworkController:getNetworkClientById',
317
- // selectedNetworkClientId,
318
- // );
319
- // return convertHexToDecimal(chainId);
320
- // TEMP: Until we update our data-fetching and storage solution to not depend on single selected network.
321
- return stake_sdk_1.ChainId.ETHEREUM;
663
+ }, _EarnController_getCurrentChainId = function _EarnController_getCurrentChainId(networkClientId) {
664
+ const networkClientIdToUse = networkClientId ??
665
+ this.messagingSystem.call('NetworkController:getState')
666
+ .selectedNetworkClientId;
667
+ const { configuration: { chainId }, } = this.messagingSystem.call('NetworkController:getNetworkClientById', networkClientIdToUse);
668
+ return (0, controller_utils_1.convertHexToDecimal)(chainId);
322
669
  };
323
670
  //# sourceMappingURL=EarnController.cjs.map