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