@metamask-previews/earn-controller 0.0.0-preview-43593c4e
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 +10 -0
- package/LICENSE +20 -0
- package/README.md +15 -0
- package/dist/EarnController.cjs +230 -0
- package/dist/EarnController.cjs.map +1 -0
- package/dist/EarnController.d.cts +109 -0
- package/dist/EarnController.d.cts.map +1 -0
- package/dist/EarnController.d.mts +109 -0
- package/dist/EarnController.d.mts.map +1 -0
- package/dist/EarnController.mjs +225 -0
- package/dist/EarnController.mjs.map +1 -0
- package/dist/index.cjs +8 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +78 -0
package/CHANGELOG.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [Unreleased]
|
9
|
+
|
10
|
+
[Unreleased]: https://github.com/MetaMask/core/
|
package/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 MetaMask
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
package/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# `@metamask/earn-controller`
|
2
|
+
|
3
|
+
Manages state for earning features and coordinates interactions between staking services, SDK integrations, and other controllers to enable users to participate in various earning opportunities.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
`yarn add @metamask/earn-controller`
|
8
|
+
|
9
|
+
or
|
10
|
+
|
11
|
+
`npm install @metamask/earn-controller`
|
12
|
+
|
13
|
+
## Contributing
|
14
|
+
|
15
|
+
This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/core#readme).
|
@@ -0,0 +1,230 @@
|
|
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
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
8
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
10
|
+
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
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
12
|
+
};
|
13
|
+
var _EarnController_instances, _EarnController_stakeSDK, _EarnController_selectedNetworkClientId, _EarnController_stakingApiService, _EarnController_initializeSDK, _EarnController_getCurrentAccount, _EarnController_getCurrentChainId;
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
15
|
+
exports.EarnController = exports.getDefaultEarnControllerState = exports.controllerName = void 0;
|
16
|
+
const providers_1 = require("@ethersproject/providers");
|
17
|
+
const base_controller_1 = require("@metamask/base-controller");
|
18
|
+
const controller_utils_1 = require("@metamask/controller-utils");
|
19
|
+
const stake_sdk_1 = require("@metamask/stake-sdk");
|
20
|
+
exports.controllerName = 'EarnController';
|
21
|
+
/**
|
22
|
+
* Metadata for the EarnController.
|
23
|
+
*/
|
24
|
+
const earnControllerMetadata = {
|
25
|
+
pooled_staking: {
|
26
|
+
persist: true,
|
27
|
+
anonymous: false,
|
28
|
+
},
|
29
|
+
stablecoin_lending: {
|
30
|
+
persist: true,
|
31
|
+
anonymous: false,
|
32
|
+
},
|
33
|
+
lastUpdated: {
|
34
|
+
persist: false,
|
35
|
+
anonymous: true,
|
36
|
+
},
|
37
|
+
};
|
38
|
+
// === Default State ===
|
39
|
+
const DEFAULT_STABLECOIN_VAULT = {
|
40
|
+
symbol: '',
|
41
|
+
name: '',
|
42
|
+
chainId: 0,
|
43
|
+
tokenAddress: '',
|
44
|
+
vaultAddress: '',
|
45
|
+
currentAPY: '0',
|
46
|
+
supply: '0',
|
47
|
+
liquidity: '0',
|
48
|
+
};
|
49
|
+
/**
|
50
|
+
* Gets the default state for the EarnController.
|
51
|
+
*
|
52
|
+
* @returns The default EarnController state.
|
53
|
+
*/
|
54
|
+
function getDefaultEarnControllerState() {
|
55
|
+
return {
|
56
|
+
pooled_staking: {
|
57
|
+
pooledStakes: {
|
58
|
+
account: '',
|
59
|
+
lifetimeRewards: '0',
|
60
|
+
assets: '0',
|
61
|
+
exitRequests: [],
|
62
|
+
},
|
63
|
+
exchangeRate: '1',
|
64
|
+
vaultData: {
|
65
|
+
apy: '0',
|
66
|
+
capacity: '0',
|
67
|
+
feePercent: 0,
|
68
|
+
totalAssets: '0',
|
69
|
+
vaultAddress: '0x0000000000000000000000000000000000000000',
|
70
|
+
},
|
71
|
+
isEligible: false,
|
72
|
+
},
|
73
|
+
stablecoin_lending: {
|
74
|
+
vaults: [DEFAULT_STABLECOIN_VAULT],
|
75
|
+
},
|
76
|
+
lastUpdated: 0,
|
77
|
+
};
|
78
|
+
}
|
79
|
+
exports.getDefaultEarnControllerState = getDefaultEarnControllerState;
|
80
|
+
// === CONTROLLER DEFINITION ===
|
81
|
+
/**
|
82
|
+
* EarnController manages DeFi earning opportunities across different protocols and chains.
|
83
|
+
*/
|
84
|
+
class EarnController extends base_controller_1.BaseController {
|
85
|
+
constructor({ messenger, state = {}, }) {
|
86
|
+
super({
|
87
|
+
name: exports.controllerName,
|
88
|
+
metadata: earnControllerMetadata,
|
89
|
+
messenger,
|
90
|
+
state: {
|
91
|
+
...getDefaultEarnControllerState(),
|
92
|
+
...state,
|
93
|
+
},
|
94
|
+
});
|
95
|
+
_EarnController_instances.add(this);
|
96
|
+
_EarnController_stakeSDK.set(this, null);
|
97
|
+
_EarnController_selectedNetworkClientId.set(this, void 0);
|
98
|
+
_EarnController_stakingApiService.set(this, new stake_sdk_1.StakingApiService());
|
99
|
+
__classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_initializeSDK).call(this);
|
100
|
+
this.refreshPooledStakingData().catch(console.error);
|
101
|
+
const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
|
102
|
+
__classPrivateFieldSet(this, _EarnController_selectedNetworkClientId, selectedNetworkClientId, "f");
|
103
|
+
this.messagingSystem.subscribe('NetworkController:stateChange', (networkControllerState) => {
|
104
|
+
if (networkControllerState.selectedNetworkClientId !==
|
105
|
+
__classPrivateFieldGet(this, _EarnController_selectedNetworkClientId, "f")) {
|
106
|
+
__classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_initializeSDK).call(this, networkControllerState.selectedNetworkClientId);
|
107
|
+
this.refreshPooledStakingData().catch(console.error);
|
108
|
+
}
|
109
|
+
__classPrivateFieldSet(this, _EarnController_selectedNetworkClientId, networkControllerState.selectedNetworkClientId, "f");
|
110
|
+
});
|
111
|
+
// Listen for account changes
|
112
|
+
this.messagingSystem.subscribe('AccountsController:selectedAccountChange', () => {
|
113
|
+
this.refreshPooledStakingData().catch(console.error);
|
114
|
+
});
|
115
|
+
}
|
116
|
+
/**
|
117
|
+
* Refreshes the pooled stakes data for the current account.
|
118
|
+
* Fetches updated stake information including lifetime rewards, assets, and exit requests
|
119
|
+
* from the staking API service and updates the state.
|
120
|
+
*
|
121
|
+
* @returns A promise that resolves when the stakes data has been updated
|
122
|
+
*/
|
123
|
+
async refreshPooledStakes() {
|
124
|
+
const currentAccount = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this);
|
125
|
+
if (!currentAccount?.address) {
|
126
|
+
return;
|
127
|
+
}
|
128
|
+
const chainId = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
|
129
|
+
const { accounts, exchangeRate } = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getPooledStakes([currentAccount.address], chainId);
|
130
|
+
this.update((state) => {
|
131
|
+
state.pooled_staking.pooledStakes = accounts[0];
|
132
|
+
state.pooled_staking.exchangeRate = exchangeRate;
|
133
|
+
});
|
134
|
+
}
|
135
|
+
/**
|
136
|
+
* Refreshes the staking eligibility status for the current account.
|
137
|
+
* Updates the eligibility status in the controller state based on the location and address blocklist for compliance.
|
138
|
+
*
|
139
|
+
* @returns A promise that resolves when the eligibility status has been updated
|
140
|
+
*/
|
141
|
+
async refreshStakingEligibility() {
|
142
|
+
const currentAccount = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this);
|
143
|
+
if (!currentAccount?.address) {
|
144
|
+
return;
|
145
|
+
}
|
146
|
+
const { eligible: isEligible } = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getPooledStakingEligibility([
|
147
|
+
currentAccount.address,
|
148
|
+
]);
|
149
|
+
this.update((state) => {
|
150
|
+
state.pooled_staking.isEligible = isEligible;
|
151
|
+
});
|
152
|
+
}
|
153
|
+
/**
|
154
|
+
* Refreshes vault data for the current chain.
|
155
|
+
* Updates the vault data in the controller state including APY, capacity,
|
156
|
+
* fee percentage, total assets, and vault address.
|
157
|
+
*
|
158
|
+
* @returns A promise that resolves when the vault data has been updated
|
159
|
+
*/
|
160
|
+
async refreshVaultData() {
|
161
|
+
const chainId = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
|
162
|
+
const vaultData = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getVaultData(chainId);
|
163
|
+
this.update((state) => {
|
164
|
+
state.pooled_staking.vaultData = vaultData;
|
165
|
+
});
|
166
|
+
}
|
167
|
+
/**
|
168
|
+
* Refreshes all pooled staking related data including stakes, eligibility, and vault data.
|
169
|
+
* This method allows partial success, meaning some data may update while other requests fail.
|
170
|
+
* All errors are collected and thrown as a single error message.
|
171
|
+
*
|
172
|
+
* @returns A promise that resolves when all possible data has been updated
|
173
|
+
* @throws {Error} If any of the refresh operations fail, with concatenated error messages
|
174
|
+
*/
|
175
|
+
async refreshPooledStakingData() {
|
176
|
+
const errors = [];
|
177
|
+
await Promise.all([
|
178
|
+
this.refreshPooledStakes().catch((error) => {
|
179
|
+
errors.push(error);
|
180
|
+
}),
|
181
|
+
this.refreshStakingEligibility().catch((error) => {
|
182
|
+
errors.push(error);
|
183
|
+
}),
|
184
|
+
this.refreshVaultData().catch((error) => {
|
185
|
+
errors.push(error);
|
186
|
+
}),
|
187
|
+
]);
|
188
|
+
if (errors.length > 0) {
|
189
|
+
throw new Error(`Failed to refresh some staking data: ${errors
|
190
|
+
.map((e) => e.message)
|
191
|
+
.join(', ')}`);
|
192
|
+
}
|
193
|
+
}
|
194
|
+
}
|
195
|
+
exports.EarnController = EarnController;
|
196
|
+
_EarnController_stakeSDK = new WeakMap(), _EarnController_selectedNetworkClientId = new WeakMap(), _EarnController_stakingApiService = new WeakMap(), _EarnController_instances = new WeakSet(), _EarnController_initializeSDK = function _EarnController_initializeSDK(networkClientId) {
|
197
|
+
const { selectedNetworkClientId } = networkClientId
|
198
|
+
? { selectedNetworkClientId: networkClientId }
|
199
|
+
: this.messagingSystem.call('NetworkController:getState');
|
200
|
+
const networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
|
201
|
+
if (!networkClient?.provider) {
|
202
|
+
__classPrivateFieldSet(this, _EarnController_stakeSDK, null, "f");
|
203
|
+
return;
|
204
|
+
}
|
205
|
+
const provider = new providers_1.Web3Provider(networkClient.provider);
|
206
|
+
const { chainId } = networkClient.configuration;
|
207
|
+
// Initialize appropriate contracts based on chainId
|
208
|
+
const config = {
|
209
|
+
chainId: (0, controller_utils_1.convertHexToDecimal)(chainId),
|
210
|
+
};
|
211
|
+
try {
|
212
|
+
__classPrivateFieldSet(this, _EarnController_stakeSDK, stake_sdk_1.StakeSdk.create(config), "f");
|
213
|
+
__classPrivateFieldGet(this, _EarnController_stakeSDK, "f").pooledStakingContract.connectSignerOrProvider(provider);
|
214
|
+
}
|
215
|
+
catch (error) {
|
216
|
+
__classPrivateFieldSet(this, _EarnController_stakeSDK, null, "f");
|
217
|
+
// Only log unexpected errors, not unsupported chain errors
|
218
|
+
if (!(error instanceof Error &&
|
219
|
+
error.message.includes('Unsupported chainId'))) {
|
220
|
+
console.error('Stake SDK initialization failed:', error);
|
221
|
+
}
|
222
|
+
}
|
223
|
+
}, _EarnController_getCurrentAccount = function _EarnController_getCurrentAccount() {
|
224
|
+
return this.messagingSystem.call('AccountsController:getSelectedAccount');
|
225
|
+
}, _EarnController_getCurrentChainId = function _EarnController_getCurrentChainId() {
|
226
|
+
const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
|
227
|
+
const { configuration: { chainId }, } = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
|
228
|
+
return (0, controller_utils_1.convertHexToDecimal)(chainId);
|
229
|
+
};
|
230
|
+
//# sourceMappingURL=EarnController.cjs.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"EarnController.cjs","sourceRoot":"","sources":["../src/EarnController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Web3Provider } from '@ethersproject/providers';\nimport type {\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerSelectedAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { convertHexToDecimal } from '@metamask/controller-utils';\nimport type { NetworkControllerStateChangeEvent } from '@metamask/network-controller';\nimport type {\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n} from '@metamask/network-controller';\nimport {\n StakeSdk,\n StakingApiService,\n type PooledStake,\n type StakeSdkConfig,\n type VaultData,\n} from '@metamask/stake-sdk';\n\nexport const controllerName = 'EarnController';\n\nexport type PooledStakingState = {\n pooledStakes: PooledStake;\n exchangeRate: string;\n vaultData: VaultData;\n isEligible: boolean;\n};\n\nexport type StablecoinLendingState = {\n vaults: StablecoinVault[];\n};\n\nexport type StablecoinVault = {\n symbol: string;\n name: string;\n chainId: number;\n tokenAddress: string;\n vaultAddress: string;\n currentAPY: string;\n supply: string;\n liquidity: string;\n};\n\n/**\n * Metadata for the EarnController.\n */\nconst earnControllerMetadata: StateMetadata<EarnControllerState> = {\n pooled_staking: {\n persist: true,\n anonymous: false,\n },\n stablecoin_lending: {\n persist: true,\n anonymous: false,\n },\n lastUpdated: {\n persist: false,\n anonymous: true,\n },\n};\n\n// === State Types ===\nexport type EarnControllerState = {\n pooled_staking: PooledStakingState;\n stablecoin_lending?: StablecoinLendingState;\n lastUpdated: number;\n};\n\n// === Default State ===\nconst DEFAULT_STABLECOIN_VAULT: StablecoinVault = {\n symbol: '',\n name: '',\n chainId: 0,\n tokenAddress: '',\n vaultAddress: '',\n currentAPY: '0',\n supply: '0',\n liquidity: '0',\n};\n\n/**\n * Gets the default state for the EarnController.\n *\n * @returns The default EarnController state.\n */\nexport function getDefaultEarnControllerState(): EarnControllerState {\n return {\n pooled_staking: {\n pooledStakes: {\n account: '',\n lifetimeRewards: '0',\n assets: '0',\n exitRequests: [],\n },\n exchangeRate: '1',\n vaultData: {\n apy: '0',\n capacity: '0',\n feePercent: 0,\n totalAssets: '0',\n vaultAddress: '0x0000000000000000000000000000000000000000',\n },\n isEligible: false,\n },\n stablecoin_lending: {\n vaults: [DEFAULT_STABLECOIN_VAULT],\n },\n lastUpdated: 0,\n };\n}\n\n// === MESSENGER ===\n\n/**\n * The action which can be used to retrieve the state of the EarnController.\n */\nexport type EarnControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n EarnControllerState\n>;\n\n/**\n * All actions that EarnController registers, to be called externally.\n */\nexport type EarnControllerActions = EarnControllerGetStateAction;\n\n/**\n * All actions that EarnController calls internally.\n */\nexport type AllowedActions =\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction;\n\n/**\n * The event that EarnController publishes when updating state.\n */\nexport type EarnControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n EarnControllerState\n>;\n\n/**\n * All events that EarnController publishes, to be subscribed to externally.\n */\nexport type EarnControllerEvents = EarnControllerStateChangeEvent;\n\n/**\n * All events that EarnController subscribes to internally.\n */\nexport type AllowedEvents =\n | AccountsControllerSelectedAccountChangeEvent\n | NetworkControllerStateChangeEvent;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * EarnController.\n */\nexport type EarnControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n EarnControllerActions | AllowedActions,\n EarnControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n// === CONTROLLER DEFINITION ===\n\n/**\n * EarnController manages DeFi earning opportunities across different protocols and chains.\n */\nexport class EarnController extends BaseController<\n typeof controllerName,\n EarnControllerState,\n EarnControllerMessenger\n> {\n #stakeSDK: StakeSdk | null = null;\n\n #selectedNetworkClientId?: string;\n\n readonly #stakingApiService: StakingApiService = new StakingApiService();\n\n constructor({\n messenger,\n state = {},\n }: {\n messenger: EarnControllerMessenger;\n state?: Partial<EarnControllerState>;\n }) {\n super({\n name: controllerName,\n metadata: earnControllerMetadata,\n messenger,\n state: {\n ...getDefaultEarnControllerState(),\n ...state,\n },\n });\n\n this.#initializeSDK();\n this.refreshPooledStakingData().catch(console.error);\n\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n this.#selectedNetworkClientId = selectedNetworkClientId;\n\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n (networkControllerState) => {\n if (\n networkControllerState.selectedNetworkClientId !==\n this.#selectedNetworkClientId\n ) {\n this.#initializeSDK(networkControllerState.selectedNetworkClientId);\n this.refreshPooledStakingData().catch(console.error);\n }\n this.#selectedNetworkClientId =\n networkControllerState.selectedNetworkClientId;\n },\n );\n\n // Listen for account changes\n this.messagingSystem.subscribe(\n 'AccountsController:selectedAccountChange',\n () => {\n this.refreshPooledStakingData().catch(console.error);\n },\n );\n }\n\n #initializeSDK(networkClientId?: string) {\n const { selectedNetworkClientId } = networkClientId\n ? { selectedNetworkClientId: networkClientId }\n : this.messagingSystem.call('NetworkController:getState');\n\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n if (!networkClient?.provider) {\n this.#stakeSDK = null;\n return;\n }\n\n const provider = new Web3Provider(networkClient.provider);\n const { chainId } = networkClient.configuration;\n\n // Initialize appropriate contracts based on chainId\n const config: StakeSdkConfig = {\n chainId: convertHexToDecimal(chainId),\n };\n\n try {\n this.#stakeSDK = StakeSdk.create(config);\n this.#stakeSDK.pooledStakingContract.connectSignerOrProvider(provider);\n } catch (error) {\n this.#stakeSDK = null;\n // Only log unexpected errors, not unsupported chain errors\n if (\n !(\n error instanceof Error &&\n error.message.includes('Unsupported chainId')\n )\n ) {\n console.error('Stake SDK initialization failed:', error);\n }\n }\n }\n\n #getCurrentAccount() {\n return this.messagingSystem.call('AccountsController:getSelectedAccount');\n }\n\n #getCurrentChainId(): number {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const {\n configuration: { chainId },\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return convertHexToDecimal(chainId);\n }\n\n /**\n * Refreshes the pooled stakes data for the current account.\n * Fetches updated stake information including lifetime rewards, assets, and exit requests\n * from the staking API service and updates the state.\n *\n * @returns A promise that resolves when the stakes data has been updated\n */\n async refreshPooledStakes(): Promise<void> {\n const currentAccount = this.#getCurrentAccount();\n if (!currentAccount?.address) {\n return;\n }\n\n const chainId = this.#getCurrentChainId();\n\n const { accounts, exchangeRate } =\n await this.#stakingApiService.getPooledStakes(\n [currentAccount.address],\n chainId,\n );\n\n this.update((state) => {\n state.pooled_staking.pooledStakes = accounts[0];\n state.pooled_staking.exchangeRate = exchangeRate;\n });\n }\n\n /**\n * Refreshes the staking eligibility status for the current account.\n * Updates the eligibility status in the controller state based on the location and address blocklist for compliance.\n *\n * @returns A promise that resolves when the eligibility status has been updated\n */\n async refreshStakingEligibility(): Promise<void> {\n const currentAccount = this.#getCurrentAccount();\n if (!currentAccount?.address) {\n return;\n }\n\n const { eligible: isEligible } =\n await this.#stakingApiService.getPooledStakingEligibility([\n currentAccount.address,\n ]);\n\n this.update((state) => {\n state.pooled_staking.isEligible = isEligible;\n });\n }\n\n /**\n * Refreshes vault data for the current chain.\n * Updates the vault data in the controller state including APY, capacity,\n * fee percentage, total assets, and vault address.\n *\n * @returns A promise that resolves when the vault data has been updated\n */\n async refreshVaultData(): Promise<void> {\n const chainId = this.#getCurrentChainId();\n const vaultData = await this.#stakingApiService.getVaultData(chainId);\n\n this.update((state) => {\n state.pooled_staking.vaultData = vaultData;\n });\n }\n\n /**\n * Refreshes all pooled staking related data including stakes, eligibility, and vault data.\n * This method allows partial success, meaning some data may update while other requests fail.\n * All errors are collected and thrown as a single error message.\n *\n * @returns A promise that resolves when all possible data has been updated\n * @throws {Error} If any of the refresh operations fail, with concatenated error messages\n */\n async refreshPooledStakingData(): Promise<void> {\n const errors: Error[] = [];\n\n await Promise.all([\n this.refreshPooledStakes().catch((error) => {\n errors.push(error);\n }),\n this.refreshStakingEligibility().catch((error) => {\n errors.push(error);\n }),\n this.refreshVaultData().catch((error) => {\n errors.push(error);\n }),\n ]);\n\n if (errors.length > 0) {\n throw new Error(\n `Failed to refresh some staking data: ${errors\n .map((e) => e.message)\n .join(', ')}`,\n );\n }\n }\n}\n"]}
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import type { AccountsControllerGetSelectedAccountAction, AccountsControllerSelectedAccountChangeEvent } from "@metamask/accounts-controller";
|
2
|
+
import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedControllerMessenger } from "@metamask/base-controller";
|
3
|
+
import { BaseController } from "@metamask/base-controller";
|
4
|
+
import type { NetworkControllerStateChangeEvent } from "@metamask/network-controller";
|
5
|
+
import type { NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction } from "@metamask/network-controller";
|
6
|
+
import { type PooledStake, type VaultData } from "@metamask/stake-sdk";
|
7
|
+
export declare const controllerName = "EarnController";
|
8
|
+
export type PooledStakingState = {
|
9
|
+
pooledStakes: PooledStake;
|
10
|
+
exchangeRate: string;
|
11
|
+
vaultData: VaultData;
|
12
|
+
isEligible: boolean;
|
13
|
+
};
|
14
|
+
export type StablecoinLendingState = {
|
15
|
+
vaults: StablecoinVault[];
|
16
|
+
};
|
17
|
+
export type StablecoinVault = {
|
18
|
+
symbol: string;
|
19
|
+
name: string;
|
20
|
+
chainId: number;
|
21
|
+
tokenAddress: string;
|
22
|
+
vaultAddress: string;
|
23
|
+
currentAPY: string;
|
24
|
+
supply: string;
|
25
|
+
liquidity: string;
|
26
|
+
};
|
27
|
+
export type EarnControllerState = {
|
28
|
+
pooled_staking: PooledStakingState;
|
29
|
+
stablecoin_lending?: StablecoinLendingState;
|
30
|
+
lastUpdated: number;
|
31
|
+
};
|
32
|
+
/**
|
33
|
+
* Gets the default state for the EarnController.
|
34
|
+
*
|
35
|
+
* @returns The default EarnController state.
|
36
|
+
*/
|
37
|
+
export declare function getDefaultEarnControllerState(): EarnControllerState;
|
38
|
+
/**
|
39
|
+
* The action which can be used to retrieve the state of the EarnController.
|
40
|
+
*/
|
41
|
+
export type EarnControllerGetStateAction = ControllerGetStateAction<typeof controllerName, EarnControllerState>;
|
42
|
+
/**
|
43
|
+
* All actions that EarnController registers, to be called externally.
|
44
|
+
*/
|
45
|
+
export type EarnControllerActions = EarnControllerGetStateAction;
|
46
|
+
/**
|
47
|
+
* All actions that EarnController calls internally.
|
48
|
+
*/
|
49
|
+
export type AllowedActions = NetworkControllerGetNetworkClientByIdAction | NetworkControllerGetStateAction | AccountsControllerGetSelectedAccountAction;
|
50
|
+
/**
|
51
|
+
* The event that EarnController publishes when updating state.
|
52
|
+
*/
|
53
|
+
export type EarnControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, EarnControllerState>;
|
54
|
+
/**
|
55
|
+
* All events that EarnController publishes, to be subscribed to externally.
|
56
|
+
*/
|
57
|
+
export type EarnControllerEvents = EarnControllerStateChangeEvent;
|
58
|
+
/**
|
59
|
+
* All events that EarnController subscribes to internally.
|
60
|
+
*/
|
61
|
+
export type AllowedEvents = AccountsControllerSelectedAccountChangeEvent | NetworkControllerStateChangeEvent;
|
62
|
+
/**
|
63
|
+
* The messenger which is restricted to actions and events accessed by
|
64
|
+
* EarnController.
|
65
|
+
*/
|
66
|
+
export type EarnControllerMessenger = RestrictedControllerMessenger<typeof controllerName, EarnControllerActions | AllowedActions, EarnControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
|
67
|
+
/**
|
68
|
+
* EarnController manages DeFi earning opportunities across different protocols and chains.
|
69
|
+
*/
|
70
|
+
export declare class EarnController extends BaseController<typeof controllerName, EarnControllerState, EarnControllerMessenger> {
|
71
|
+
#private;
|
72
|
+
constructor({ messenger, state, }: {
|
73
|
+
messenger: EarnControllerMessenger;
|
74
|
+
state?: Partial<EarnControllerState>;
|
75
|
+
});
|
76
|
+
/**
|
77
|
+
* Refreshes the pooled stakes data for the current account.
|
78
|
+
* Fetches updated stake information including lifetime rewards, assets, and exit requests
|
79
|
+
* from the staking API service and updates the state.
|
80
|
+
*
|
81
|
+
* @returns A promise that resolves when the stakes data has been updated
|
82
|
+
*/
|
83
|
+
refreshPooledStakes(): Promise<void>;
|
84
|
+
/**
|
85
|
+
* Refreshes the staking eligibility status for the current account.
|
86
|
+
* Updates the eligibility status in the controller state based on the location and address blocklist for compliance.
|
87
|
+
*
|
88
|
+
* @returns A promise that resolves when the eligibility status has been updated
|
89
|
+
*/
|
90
|
+
refreshStakingEligibility(): Promise<void>;
|
91
|
+
/**
|
92
|
+
* Refreshes vault data for the current chain.
|
93
|
+
* Updates the vault data in the controller state including APY, capacity,
|
94
|
+
* fee percentage, total assets, and vault address.
|
95
|
+
*
|
96
|
+
* @returns A promise that resolves when the vault data has been updated
|
97
|
+
*/
|
98
|
+
refreshVaultData(): Promise<void>;
|
99
|
+
/**
|
100
|
+
* Refreshes all pooled staking related data including stakes, eligibility, and vault data.
|
101
|
+
* This method allows partial success, meaning some data may update while other requests fail.
|
102
|
+
* All errors are collected and thrown as a single error message.
|
103
|
+
*
|
104
|
+
* @returns A promise that resolves when all possible data has been updated
|
105
|
+
* @throws {Error} If any of the refresh operations fail, with concatenated error messages
|
106
|
+
*/
|
107
|
+
refreshPooledStakingData(): Promise<void>;
|
108
|
+
}
|
109
|
+
//# sourceMappingURL=EarnController.d.cts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"EarnController.d.cts","sourceRoot":"","sources":["../src/EarnController.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,0CAA0C,EAC1C,4CAA4C,EAC7C,sCAAsC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,6BAA6B,EAE9B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAE3D,OAAO,KAAK,EAAE,iCAAiC,EAAE,qCAAqC;AACtF,OAAO,KAAK,EACV,2CAA2C,EAC3C,+BAA+B,EAChC,qCAAqC;AACtC,OAAO,EAGL,KAAK,WAAW,EAEhB,KAAK,SAAS,EACf,4BAA4B;AAE7B,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE,WAAW,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAqBF,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,EAAE,kBAAkB,CAAC;IACnC,kBAAkB,CAAC,EAAE,sBAAsB,CAAC;IAC5C,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAcF;;;;GAIG;AACH,wBAAgB,6BAA6B,IAAI,mBAAmB,CAwBnE;AAID;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,wBAAwB,CACjE,OAAO,cAAc,EACrB,mBAAmB,CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,2CAA2C,GAC3C,+BAA+B,GAC/B,0CAA0C,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG,0BAA0B,CACrE,OAAO,cAAc,EACrB,mBAAmB,CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,8BAA8B,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,4CAA4C,GAC5C,iCAAiC,CAAC;AAEtC;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,6BAA6B,CACjE,OAAO,cAAc,EACrB,qBAAqB,GAAG,cAAc,EACtC,oBAAoB,GAAG,aAAa,EACpC,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;AAIF;;GAEG;AACH,qBAAa,cAAe,SAAQ,cAAc,CAChD,OAAO,cAAc,EACrB,mBAAmB,EACnB,uBAAuB,CACxB;;gBAOa,EACV,SAAS,EACT,KAAU,GACX,EAAE;QACD,SAAS,EAAE,uBAAuB,CAAC;QACnC,KAAK,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;KACtC;IAoGD;;;;;;OAMG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB1C;;;;;OAKG;IACG,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBhD;;;;;;OAMG;IACG,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IASvC;;;;;;;OAOG;IACG,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;CAuBhD"}
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import type { AccountsControllerGetSelectedAccountAction, AccountsControllerSelectedAccountChangeEvent } from "@metamask/accounts-controller";
|
2
|
+
import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedControllerMessenger } from "@metamask/base-controller";
|
3
|
+
import { BaseController } from "@metamask/base-controller";
|
4
|
+
import type { NetworkControllerStateChangeEvent } from "@metamask/network-controller";
|
5
|
+
import type { NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction } from "@metamask/network-controller";
|
6
|
+
import { type PooledStake, type VaultData } from "@metamask/stake-sdk";
|
7
|
+
export declare const controllerName = "EarnController";
|
8
|
+
export type PooledStakingState = {
|
9
|
+
pooledStakes: PooledStake;
|
10
|
+
exchangeRate: string;
|
11
|
+
vaultData: VaultData;
|
12
|
+
isEligible: boolean;
|
13
|
+
};
|
14
|
+
export type StablecoinLendingState = {
|
15
|
+
vaults: StablecoinVault[];
|
16
|
+
};
|
17
|
+
export type StablecoinVault = {
|
18
|
+
symbol: string;
|
19
|
+
name: string;
|
20
|
+
chainId: number;
|
21
|
+
tokenAddress: string;
|
22
|
+
vaultAddress: string;
|
23
|
+
currentAPY: string;
|
24
|
+
supply: string;
|
25
|
+
liquidity: string;
|
26
|
+
};
|
27
|
+
export type EarnControllerState = {
|
28
|
+
pooled_staking: PooledStakingState;
|
29
|
+
stablecoin_lending?: StablecoinLendingState;
|
30
|
+
lastUpdated: number;
|
31
|
+
};
|
32
|
+
/**
|
33
|
+
* Gets the default state for the EarnController.
|
34
|
+
*
|
35
|
+
* @returns The default EarnController state.
|
36
|
+
*/
|
37
|
+
export declare function getDefaultEarnControllerState(): EarnControllerState;
|
38
|
+
/**
|
39
|
+
* The action which can be used to retrieve the state of the EarnController.
|
40
|
+
*/
|
41
|
+
export type EarnControllerGetStateAction = ControllerGetStateAction<typeof controllerName, EarnControllerState>;
|
42
|
+
/**
|
43
|
+
* All actions that EarnController registers, to be called externally.
|
44
|
+
*/
|
45
|
+
export type EarnControllerActions = EarnControllerGetStateAction;
|
46
|
+
/**
|
47
|
+
* All actions that EarnController calls internally.
|
48
|
+
*/
|
49
|
+
export type AllowedActions = NetworkControllerGetNetworkClientByIdAction | NetworkControllerGetStateAction | AccountsControllerGetSelectedAccountAction;
|
50
|
+
/**
|
51
|
+
* The event that EarnController publishes when updating state.
|
52
|
+
*/
|
53
|
+
export type EarnControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, EarnControllerState>;
|
54
|
+
/**
|
55
|
+
* All events that EarnController publishes, to be subscribed to externally.
|
56
|
+
*/
|
57
|
+
export type EarnControllerEvents = EarnControllerStateChangeEvent;
|
58
|
+
/**
|
59
|
+
* All events that EarnController subscribes to internally.
|
60
|
+
*/
|
61
|
+
export type AllowedEvents = AccountsControllerSelectedAccountChangeEvent | NetworkControllerStateChangeEvent;
|
62
|
+
/**
|
63
|
+
* The messenger which is restricted to actions and events accessed by
|
64
|
+
* EarnController.
|
65
|
+
*/
|
66
|
+
export type EarnControllerMessenger = RestrictedControllerMessenger<typeof controllerName, EarnControllerActions | AllowedActions, EarnControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
|
67
|
+
/**
|
68
|
+
* EarnController manages DeFi earning opportunities across different protocols and chains.
|
69
|
+
*/
|
70
|
+
export declare class EarnController extends BaseController<typeof controllerName, EarnControllerState, EarnControllerMessenger> {
|
71
|
+
#private;
|
72
|
+
constructor({ messenger, state, }: {
|
73
|
+
messenger: EarnControllerMessenger;
|
74
|
+
state?: Partial<EarnControllerState>;
|
75
|
+
});
|
76
|
+
/**
|
77
|
+
* Refreshes the pooled stakes data for the current account.
|
78
|
+
* Fetches updated stake information including lifetime rewards, assets, and exit requests
|
79
|
+
* from the staking API service and updates the state.
|
80
|
+
*
|
81
|
+
* @returns A promise that resolves when the stakes data has been updated
|
82
|
+
*/
|
83
|
+
refreshPooledStakes(): Promise<void>;
|
84
|
+
/**
|
85
|
+
* Refreshes the staking eligibility status for the current account.
|
86
|
+
* Updates the eligibility status in the controller state based on the location and address blocklist for compliance.
|
87
|
+
*
|
88
|
+
* @returns A promise that resolves when the eligibility status has been updated
|
89
|
+
*/
|
90
|
+
refreshStakingEligibility(): Promise<void>;
|
91
|
+
/**
|
92
|
+
* Refreshes vault data for the current chain.
|
93
|
+
* Updates the vault data in the controller state including APY, capacity,
|
94
|
+
* fee percentage, total assets, and vault address.
|
95
|
+
*
|
96
|
+
* @returns A promise that resolves when the vault data has been updated
|
97
|
+
*/
|
98
|
+
refreshVaultData(): Promise<void>;
|
99
|
+
/**
|
100
|
+
* Refreshes all pooled staking related data including stakes, eligibility, and vault data.
|
101
|
+
* This method allows partial success, meaning some data may update while other requests fail.
|
102
|
+
* All errors are collected and thrown as a single error message.
|
103
|
+
*
|
104
|
+
* @returns A promise that resolves when all possible data has been updated
|
105
|
+
* @throws {Error} If any of the refresh operations fail, with concatenated error messages
|
106
|
+
*/
|
107
|
+
refreshPooledStakingData(): Promise<void>;
|
108
|
+
}
|
109
|
+
//# sourceMappingURL=EarnController.d.mts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"EarnController.d.mts","sourceRoot":"","sources":["../src/EarnController.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,0CAA0C,EAC1C,4CAA4C,EAC7C,sCAAsC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,6BAA6B,EAE9B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAE3D,OAAO,KAAK,EAAE,iCAAiC,EAAE,qCAAqC;AACtF,OAAO,KAAK,EACV,2CAA2C,EAC3C,+BAA+B,EAChC,qCAAqC;AACtC,OAAO,EAGL,KAAK,WAAW,EAEhB,KAAK,SAAS,EACf,4BAA4B;AAE7B,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE,WAAW,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAqBF,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,EAAE,kBAAkB,CAAC;IACnC,kBAAkB,CAAC,EAAE,sBAAsB,CAAC;IAC5C,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAcF;;;;GAIG;AACH,wBAAgB,6BAA6B,IAAI,mBAAmB,CAwBnE;AAID;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,wBAAwB,CACjE,OAAO,cAAc,EACrB,mBAAmB,CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,2CAA2C,GAC3C,+BAA+B,GAC/B,0CAA0C,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG,0BAA0B,CACrE,OAAO,cAAc,EACrB,mBAAmB,CACpB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,8BAA8B,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,4CAA4C,GAC5C,iCAAiC,CAAC;AAEtC;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,6BAA6B,CACjE,OAAO,cAAc,EACrB,qBAAqB,GAAG,cAAc,EACtC,oBAAoB,GAAG,aAAa,EACpC,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;AAIF;;GAEG;AACH,qBAAa,cAAe,SAAQ,cAAc,CAChD,OAAO,cAAc,EACrB,mBAAmB,EACnB,uBAAuB,CACxB;;gBAOa,EACV,SAAS,EACT,KAAU,GACX,EAAE;QACD,SAAS,EAAE,uBAAuB,CAAC;QACnC,KAAK,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;KACtC;IAoGD;;;;;;OAMG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB1C;;;;;OAKG;IACG,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBhD;;;;;;OAMG;IACG,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IASvC;;;;;;;OAOG;IACG,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;CAuBhD"}
|
@@ -0,0 +1,225 @@
|
|
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
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
7
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
9
|
+
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
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
11
|
+
};
|
12
|
+
var _EarnController_instances, _EarnController_stakeSDK, _EarnController_selectedNetworkClientId, _EarnController_stakingApiService, _EarnController_initializeSDK, _EarnController_getCurrentAccount, _EarnController_getCurrentChainId;
|
13
|
+
import { Web3Provider } from "@ethersproject/providers";
|
14
|
+
import { BaseController } from "@metamask/base-controller";
|
15
|
+
import { convertHexToDecimal } from "@metamask/controller-utils";
|
16
|
+
import { StakeSdk, StakingApiService } from "@metamask/stake-sdk";
|
17
|
+
export const controllerName = 'EarnController';
|
18
|
+
/**
|
19
|
+
* Metadata for the EarnController.
|
20
|
+
*/
|
21
|
+
const earnControllerMetadata = {
|
22
|
+
pooled_staking: {
|
23
|
+
persist: true,
|
24
|
+
anonymous: false,
|
25
|
+
},
|
26
|
+
stablecoin_lending: {
|
27
|
+
persist: true,
|
28
|
+
anonymous: false,
|
29
|
+
},
|
30
|
+
lastUpdated: {
|
31
|
+
persist: false,
|
32
|
+
anonymous: true,
|
33
|
+
},
|
34
|
+
};
|
35
|
+
// === Default State ===
|
36
|
+
const DEFAULT_STABLECOIN_VAULT = {
|
37
|
+
symbol: '',
|
38
|
+
name: '',
|
39
|
+
chainId: 0,
|
40
|
+
tokenAddress: '',
|
41
|
+
vaultAddress: '',
|
42
|
+
currentAPY: '0',
|
43
|
+
supply: '0',
|
44
|
+
liquidity: '0',
|
45
|
+
};
|
46
|
+
/**
|
47
|
+
* Gets the default state for the EarnController.
|
48
|
+
*
|
49
|
+
* @returns The default EarnController state.
|
50
|
+
*/
|
51
|
+
export function getDefaultEarnControllerState() {
|
52
|
+
return {
|
53
|
+
pooled_staking: {
|
54
|
+
pooledStakes: {
|
55
|
+
account: '',
|
56
|
+
lifetimeRewards: '0',
|
57
|
+
assets: '0',
|
58
|
+
exitRequests: [],
|
59
|
+
},
|
60
|
+
exchangeRate: '1',
|
61
|
+
vaultData: {
|
62
|
+
apy: '0',
|
63
|
+
capacity: '0',
|
64
|
+
feePercent: 0,
|
65
|
+
totalAssets: '0',
|
66
|
+
vaultAddress: '0x0000000000000000000000000000000000000000',
|
67
|
+
},
|
68
|
+
isEligible: false,
|
69
|
+
},
|
70
|
+
stablecoin_lending: {
|
71
|
+
vaults: [DEFAULT_STABLECOIN_VAULT],
|
72
|
+
},
|
73
|
+
lastUpdated: 0,
|
74
|
+
};
|
75
|
+
}
|
76
|
+
// === CONTROLLER DEFINITION ===
|
77
|
+
/**
|
78
|
+
* EarnController manages DeFi earning opportunities across different protocols and chains.
|
79
|
+
*/
|
80
|
+
export class EarnController extends BaseController {
|
81
|
+
constructor({ messenger, state = {}, }) {
|
82
|
+
super({
|
83
|
+
name: controllerName,
|
84
|
+
metadata: earnControllerMetadata,
|
85
|
+
messenger,
|
86
|
+
state: {
|
87
|
+
...getDefaultEarnControllerState(),
|
88
|
+
...state,
|
89
|
+
},
|
90
|
+
});
|
91
|
+
_EarnController_instances.add(this);
|
92
|
+
_EarnController_stakeSDK.set(this, null);
|
93
|
+
_EarnController_selectedNetworkClientId.set(this, void 0);
|
94
|
+
_EarnController_stakingApiService.set(this, new StakingApiService());
|
95
|
+
__classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_initializeSDK).call(this);
|
96
|
+
this.refreshPooledStakingData().catch(console.error);
|
97
|
+
const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
|
98
|
+
__classPrivateFieldSet(this, _EarnController_selectedNetworkClientId, selectedNetworkClientId, "f");
|
99
|
+
this.messagingSystem.subscribe('NetworkController:stateChange', (networkControllerState) => {
|
100
|
+
if (networkControllerState.selectedNetworkClientId !==
|
101
|
+
__classPrivateFieldGet(this, _EarnController_selectedNetworkClientId, "f")) {
|
102
|
+
__classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_initializeSDK).call(this, networkControllerState.selectedNetworkClientId);
|
103
|
+
this.refreshPooledStakingData().catch(console.error);
|
104
|
+
}
|
105
|
+
__classPrivateFieldSet(this, _EarnController_selectedNetworkClientId, networkControllerState.selectedNetworkClientId, "f");
|
106
|
+
});
|
107
|
+
// Listen for account changes
|
108
|
+
this.messagingSystem.subscribe('AccountsController:selectedAccountChange', () => {
|
109
|
+
this.refreshPooledStakingData().catch(console.error);
|
110
|
+
});
|
111
|
+
}
|
112
|
+
/**
|
113
|
+
* Refreshes the pooled stakes data for the current account.
|
114
|
+
* Fetches updated stake information including lifetime rewards, assets, and exit requests
|
115
|
+
* from the staking API service and updates the state.
|
116
|
+
*
|
117
|
+
* @returns A promise that resolves when the stakes data has been updated
|
118
|
+
*/
|
119
|
+
async refreshPooledStakes() {
|
120
|
+
const currentAccount = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this);
|
121
|
+
if (!currentAccount?.address) {
|
122
|
+
return;
|
123
|
+
}
|
124
|
+
const chainId = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
|
125
|
+
const { accounts, exchangeRate } = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getPooledStakes([currentAccount.address], chainId);
|
126
|
+
this.update((state) => {
|
127
|
+
state.pooled_staking.pooledStakes = accounts[0];
|
128
|
+
state.pooled_staking.exchangeRate = exchangeRate;
|
129
|
+
});
|
130
|
+
}
|
131
|
+
/**
|
132
|
+
* Refreshes the staking eligibility status for the current account.
|
133
|
+
* Updates the eligibility status in the controller state based on the location and address blocklist for compliance.
|
134
|
+
*
|
135
|
+
* @returns A promise that resolves when the eligibility status has been updated
|
136
|
+
*/
|
137
|
+
async refreshStakingEligibility() {
|
138
|
+
const currentAccount = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentAccount).call(this);
|
139
|
+
if (!currentAccount?.address) {
|
140
|
+
return;
|
141
|
+
}
|
142
|
+
const { eligible: isEligible } = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getPooledStakingEligibility([
|
143
|
+
currentAccount.address,
|
144
|
+
]);
|
145
|
+
this.update((state) => {
|
146
|
+
state.pooled_staking.isEligible = isEligible;
|
147
|
+
});
|
148
|
+
}
|
149
|
+
/**
|
150
|
+
* Refreshes vault data for the current chain.
|
151
|
+
* Updates the vault data in the controller state including APY, capacity,
|
152
|
+
* fee percentage, total assets, and vault address.
|
153
|
+
*
|
154
|
+
* @returns A promise that resolves when the vault data has been updated
|
155
|
+
*/
|
156
|
+
async refreshVaultData() {
|
157
|
+
const chainId = __classPrivateFieldGet(this, _EarnController_instances, "m", _EarnController_getCurrentChainId).call(this);
|
158
|
+
const vaultData = await __classPrivateFieldGet(this, _EarnController_stakingApiService, "f").getVaultData(chainId);
|
159
|
+
this.update((state) => {
|
160
|
+
state.pooled_staking.vaultData = vaultData;
|
161
|
+
});
|
162
|
+
}
|
163
|
+
/**
|
164
|
+
* Refreshes all pooled staking related data including stakes, eligibility, and vault data.
|
165
|
+
* This method allows partial success, meaning some data may update while other requests fail.
|
166
|
+
* All errors are collected and thrown as a single error message.
|
167
|
+
*
|
168
|
+
* @returns A promise that resolves when all possible data has been updated
|
169
|
+
* @throws {Error} If any of the refresh operations fail, with concatenated error messages
|
170
|
+
*/
|
171
|
+
async refreshPooledStakingData() {
|
172
|
+
const errors = [];
|
173
|
+
await Promise.all([
|
174
|
+
this.refreshPooledStakes().catch((error) => {
|
175
|
+
errors.push(error);
|
176
|
+
}),
|
177
|
+
this.refreshStakingEligibility().catch((error) => {
|
178
|
+
errors.push(error);
|
179
|
+
}),
|
180
|
+
this.refreshVaultData().catch((error) => {
|
181
|
+
errors.push(error);
|
182
|
+
}),
|
183
|
+
]);
|
184
|
+
if (errors.length > 0) {
|
185
|
+
throw new Error(`Failed to refresh some staking data: ${errors
|
186
|
+
.map((e) => e.message)
|
187
|
+
.join(', ')}`);
|
188
|
+
}
|
189
|
+
}
|
190
|
+
}
|
191
|
+
_EarnController_stakeSDK = new WeakMap(), _EarnController_selectedNetworkClientId = new WeakMap(), _EarnController_stakingApiService = new WeakMap(), _EarnController_instances = new WeakSet(), _EarnController_initializeSDK = function _EarnController_initializeSDK(networkClientId) {
|
192
|
+
const { selectedNetworkClientId } = networkClientId
|
193
|
+
? { selectedNetworkClientId: networkClientId }
|
194
|
+
: this.messagingSystem.call('NetworkController:getState');
|
195
|
+
const networkClient = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
|
196
|
+
if (!networkClient?.provider) {
|
197
|
+
__classPrivateFieldSet(this, _EarnController_stakeSDK, null, "f");
|
198
|
+
return;
|
199
|
+
}
|
200
|
+
const provider = new Web3Provider(networkClient.provider);
|
201
|
+
const { chainId } = networkClient.configuration;
|
202
|
+
// Initialize appropriate contracts based on chainId
|
203
|
+
const config = {
|
204
|
+
chainId: convertHexToDecimal(chainId),
|
205
|
+
};
|
206
|
+
try {
|
207
|
+
__classPrivateFieldSet(this, _EarnController_stakeSDK, StakeSdk.create(config), "f");
|
208
|
+
__classPrivateFieldGet(this, _EarnController_stakeSDK, "f").pooledStakingContract.connectSignerOrProvider(provider);
|
209
|
+
}
|
210
|
+
catch (error) {
|
211
|
+
__classPrivateFieldSet(this, _EarnController_stakeSDK, null, "f");
|
212
|
+
// Only log unexpected errors, not unsupported chain errors
|
213
|
+
if (!(error instanceof Error &&
|
214
|
+
error.message.includes('Unsupported chainId'))) {
|
215
|
+
console.error('Stake SDK initialization failed:', error);
|
216
|
+
}
|
217
|
+
}
|
218
|
+
}, _EarnController_getCurrentAccount = function _EarnController_getCurrentAccount() {
|
219
|
+
return this.messagingSystem.call('AccountsController:getSelectedAccount');
|
220
|
+
}, _EarnController_getCurrentChainId = function _EarnController_getCurrentChainId() {
|
221
|
+
const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
|
222
|
+
const { configuration: { chainId }, } = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
|
223
|
+
return convertHexToDecimal(chainId);
|
224
|
+
};
|
225
|
+
//# sourceMappingURL=EarnController.mjs.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"EarnController.mjs","sourceRoot":"","sources":["../src/EarnController.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,iCAAiC;AAWxD,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,mCAAmC;AAMjE,OAAO,EACL,QAAQ,EACR,iBAAiB,EAIlB,4BAA4B;AAE7B,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAwB/C;;GAEG;AACH,MAAM,sBAAsB,GAAuC;IACjE,cAAc,EAAE;QACd,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;KACjB;IACD,kBAAkB,EAAE;QAClB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;KACjB;IACD,WAAW,EAAE;QACX,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,IAAI;KAChB;CACF,CAAC;AASF,wBAAwB;AACxB,MAAM,wBAAwB,GAAoB;IAChD,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,CAAC;IACV,YAAY,EAAE,EAAE;IAChB,YAAY,EAAE,EAAE;IAChB,UAAU,EAAE,GAAG;IACf,MAAM,EAAE,GAAG;IACX,SAAS,EAAE,GAAG;CACf,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,6BAA6B;IAC3C,OAAO;QACL,cAAc,EAAE;YACd,YAAY,EAAE;gBACZ,OAAO,EAAE,EAAE;gBACX,eAAe,EAAE,GAAG;gBACpB,MAAM,EAAE,GAAG;gBACX,YAAY,EAAE,EAAE;aACjB;YACD,YAAY,EAAE,GAAG;YACjB,SAAS,EAAE;gBACT,GAAG,EAAE,GAAG;gBACR,QAAQ,EAAE,GAAG;gBACb,UAAU,EAAE,CAAC;gBACb,WAAW,EAAE,GAAG;gBAChB,YAAY,EAAE,4CAA4C;aAC3D;YACD,UAAU,EAAE,KAAK;SAClB;QACD,kBAAkB,EAAE;YAClB,MAAM,EAAE,CAAC,wBAAwB,CAAC;SACnC;QACD,WAAW,EAAE,CAAC;KACf,CAAC;AACJ,CAAC;AAyDD,gCAAgC;AAEhC;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,cAInC;IAOC,YAAY,EACV,SAAS,EACT,KAAK,GAAG,EAAE,GAIX;QACC,KAAK,CAAC;YACJ,IAAI,EAAE,cAAc;YACpB,QAAQ,EAAE,sBAAsB;YAChC,SAAS;YACT,KAAK,EAAE;gBACL,GAAG,6BAA6B,EAAE;gBAClC,GAAG,KAAK;aACT;SACF,CAAC,CAAC;;QArBL,mCAA6B,IAAI,EAAC;QAElC,0DAAkC;QAEzB,4CAAwC,IAAI,iBAAiB,EAAE,EAAC;QAmBvE,uBAAA,IAAI,gEAAe,MAAnB,IAAI,CAAiB,CAAC;QACtB,IAAI,CAAC,wBAAwB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAErD,MAAM,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3D,4BAA4B,CAC7B,CAAC;QACF,uBAAA,IAAI,2CAA4B,uBAAuB,MAAA,CAAC;QAExD,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,+BAA+B,EAC/B,CAAC,sBAAsB,EAAE,EAAE;YACzB,IACE,sBAAsB,CAAC,uBAAuB;gBAC9C,uBAAA,IAAI,+CAAyB,EAC7B;gBACA,uBAAA,IAAI,gEAAe,MAAnB,IAAI,EAAgB,sBAAsB,CAAC,uBAAuB,CAAC,CAAC;gBACpE,IAAI,CAAC,wBAAwB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;aACtD;YACD,uBAAA,IAAI,2CACF,sBAAsB,CAAC,uBAAuB,MAAA,CAAC;QACnD,CAAC,CACF,CAAC;QAEF,6BAA6B;QAC7B,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,0CAA0C,EAC1C,GAAG,EAAE;YACH,IAAI,CAAC,wBAAwB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACvD,CAAC,CACF,CAAC;IACJ,CAAC;IA2DD;;;;;;OAMG;IACH,KAAK,CAAC,mBAAmB;QACvB,MAAM,cAAc,GAAG,uBAAA,IAAI,oEAAmB,MAAvB,IAAI,CAAqB,CAAC;QACjD,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE;YAC5B,OAAO;SACR;QAED,MAAM,OAAO,GAAG,uBAAA,IAAI,oEAAmB,MAAvB,IAAI,CAAqB,CAAC;QAE1C,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAC9B,MAAM,uBAAA,IAAI,yCAAmB,CAAC,eAAe,CAC3C,CAAC,cAAc,CAAC,OAAO,CAAC,EACxB,OAAO,CACR,CAAC;QAEJ,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,cAAc,CAAC,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAChD,KAAK,CAAC,cAAc,CAAC,YAAY,GAAG,YAAY,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,yBAAyB;QAC7B,MAAM,cAAc,GAAG,uBAAA,IAAI,oEAAmB,MAAvB,IAAI,CAAqB,CAAC;QACjD,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE;YAC5B,OAAO;SACR;QAED,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAC5B,MAAM,uBAAA,IAAI,yCAAmB,CAAC,2BAA2B,CAAC;YACxD,cAAc,CAAC,OAAO;SACvB,CAAC,CAAC;QAEL,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,UAAU,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,gBAAgB;QACpB,MAAM,OAAO,GAAG,uBAAA,IAAI,oEAAmB,MAAvB,IAAI,CAAqB,CAAC;QAC1C,MAAM,SAAS,GAAG,MAAM,uBAAA,IAAI,yCAAmB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAEtE,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,cAAc,CAAC,SAAS,GAAG,SAAS,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,wBAAwB;QAC5B,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,IAAI,CAAC,mBAAmB,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACzC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC,CAAC;YACF,IAAI,CAAC,yBAAyB,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC/C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC,CAAC;YACF,IAAI,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;YACrB,MAAM,IAAI,KAAK,CACb,wCAAwC,MAAM;iBAC3C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;iBACrB,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;SACH;IACH,CAAC;CACF;wQAzJgB,eAAwB;IACrC,MAAM,EAAE,uBAAuB,EAAE,GAAG,eAAe;QACjD,CAAC,CAAC,EAAE,uBAAuB,EAAE,eAAe,EAAE;QAC9C,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAE5D,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC7C,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;IAEF,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE;QAC5B,uBAAA,IAAI,4BAAa,IAAI,MAAA,CAAC;QACtB,OAAO;KACR;IAED,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC1D,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,aAAa,CAAC;IAEhD,oDAAoD;IACpD,MAAM,MAAM,GAAmB;QAC7B,OAAO,EAAE,mBAAmB,CAAC,OAAO,CAAC;KACtC,CAAC;IAEF,IAAI;QACF,uBAAA,IAAI,4BAAa,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,MAAA,CAAC;QACzC,uBAAA,IAAI,gCAAU,CAAC,qBAAqB,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;KACxE;IAAC,OAAO,KAAK,EAAE;QACd,uBAAA,IAAI,4BAAa,IAAI,MAAA,CAAC;QACtB,2DAA2D;QAC3D,IACE,CAAC,CACC,KAAK,YAAY,KAAK;YACtB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAC9C,EACD;YACA,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;SAC1D;KACF;AACH,CAAC;IAGC,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;AAC5E,CAAC;IAGC,MAAM,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3D,4BAA4B,CAC7B,CAAC;IACF,MAAM,EACJ,aAAa,EAAE,EAAE,OAAO,EAAE,GAC3B,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3B,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;IACF,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAC;AACtC,CAAC","sourcesContent":["import { Web3Provider } from '@ethersproject/providers';\nimport type {\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerSelectedAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { convertHexToDecimal } from '@metamask/controller-utils';\nimport type { NetworkControllerStateChangeEvent } from '@metamask/network-controller';\nimport type {\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n} from '@metamask/network-controller';\nimport {\n StakeSdk,\n StakingApiService,\n type PooledStake,\n type StakeSdkConfig,\n type VaultData,\n} from '@metamask/stake-sdk';\n\nexport const controllerName = 'EarnController';\n\nexport type PooledStakingState = {\n pooledStakes: PooledStake;\n exchangeRate: string;\n vaultData: VaultData;\n isEligible: boolean;\n};\n\nexport type StablecoinLendingState = {\n vaults: StablecoinVault[];\n};\n\nexport type StablecoinVault = {\n symbol: string;\n name: string;\n chainId: number;\n tokenAddress: string;\n vaultAddress: string;\n currentAPY: string;\n supply: string;\n liquidity: string;\n};\n\n/**\n * Metadata for the EarnController.\n */\nconst earnControllerMetadata: StateMetadata<EarnControllerState> = {\n pooled_staking: {\n persist: true,\n anonymous: false,\n },\n stablecoin_lending: {\n persist: true,\n anonymous: false,\n },\n lastUpdated: {\n persist: false,\n anonymous: true,\n },\n};\n\n// === State Types ===\nexport type EarnControllerState = {\n pooled_staking: PooledStakingState;\n stablecoin_lending?: StablecoinLendingState;\n lastUpdated: number;\n};\n\n// === Default State ===\nconst DEFAULT_STABLECOIN_VAULT: StablecoinVault = {\n symbol: '',\n name: '',\n chainId: 0,\n tokenAddress: '',\n vaultAddress: '',\n currentAPY: '0',\n supply: '0',\n liquidity: '0',\n};\n\n/**\n * Gets the default state for the EarnController.\n *\n * @returns The default EarnController state.\n */\nexport function getDefaultEarnControllerState(): EarnControllerState {\n return {\n pooled_staking: {\n pooledStakes: {\n account: '',\n lifetimeRewards: '0',\n assets: '0',\n exitRequests: [],\n },\n exchangeRate: '1',\n vaultData: {\n apy: '0',\n capacity: '0',\n feePercent: 0,\n totalAssets: '0',\n vaultAddress: '0x0000000000000000000000000000000000000000',\n },\n isEligible: false,\n },\n stablecoin_lending: {\n vaults: [DEFAULT_STABLECOIN_VAULT],\n },\n lastUpdated: 0,\n };\n}\n\n// === MESSENGER ===\n\n/**\n * The action which can be used to retrieve the state of the EarnController.\n */\nexport type EarnControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n EarnControllerState\n>;\n\n/**\n * All actions that EarnController registers, to be called externally.\n */\nexport type EarnControllerActions = EarnControllerGetStateAction;\n\n/**\n * All actions that EarnController calls internally.\n */\nexport type AllowedActions =\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction;\n\n/**\n * The event that EarnController publishes when updating state.\n */\nexport type EarnControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n EarnControllerState\n>;\n\n/**\n * All events that EarnController publishes, to be subscribed to externally.\n */\nexport type EarnControllerEvents = EarnControllerStateChangeEvent;\n\n/**\n * All events that EarnController subscribes to internally.\n */\nexport type AllowedEvents =\n | AccountsControllerSelectedAccountChangeEvent\n | NetworkControllerStateChangeEvent;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * EarnController.\n */\nexport type EarnControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n EarnControllerActions | AllowedActions,\n EarnControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n// === CONTROLLER DEFINITION ===\n\n/**\n * EarnController manages DeFi earning opportunities across different protocols and chains.\n */\nexport class EarnController extends BaseController<\n typeof controllerName,\n EarnControllerState,\n EarnControllerMessenger\n> {\n #stakeSDK: StakeSdk | null = null;\n\n #selectedNetworkClientId?: string;\n\n readonly #stakingApiService: StakingApiService = new StakingApiService();\n\n constructor({\n messenger,\n state = {},\n }: {\n messenger: EarnControllerMessenger;\n state?: Partial<EarnControllerState>;\n }) {\n super({\n name: controllerName,\n metadata: earnControllerMetadata,\n messenger,\n state: {\n ...getDefaultEarnControllerState(),\n ...state,\n },\n });\n\n this.#initializeSDK();\n this.refreshPooledStakingData().catch(console.error);\n\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n this.#selectedNetworkClientId = selectedNetworkClientId;\n\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n (networkControllerState) => {\n if (\n networkControllerState.selectedNetworkClientId !==\n this.#selectedNetworkClientId\n ) {\n this.#initializeSDK(networkControllerState.selectedNetworkClientId);\n this.refreshPooledStakingData().catch(console.error);\n }\n this.#selectedNetworkClientId =\n networkControllerState.selectedNetworkClientId;\n },\n );\n\n // Listen for account changes\n this.messagingSystem.subscribe(\n 'AccountsController:selectedAccountChange',\n () => {\n this.refreshPooledStakingData().catch(console.error);\n },\n );\n }\n\n #initializeSDK(networkClientId?: string) {\n const { selectedNetworkClientId } = networkClientId\n ? { selectedNetworkClientId: networkClientId }\n : this.messagingSystem.call('NetworkController:getState');\n\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n if (!networkClient?.provider) {\n this.#stakeSDK = null;\n return;\n }\n\n const provider = new Web3Provider(networkClient.provider);\n const { chainId } = networkClient.configuration;\n\n // Initialize appropriate contracts based on chainId\n const config: StakeSdkConfig = {\n chainId: convertHexToDecimal(chainId),\n };\n\n try {\n this.#stakeSDK = StakeSdk.create(config);\n this.#stakeSDK.pooledStakingContract.connectSignerOrProvider(provider);\n } catch (error) {\n this.#stakeSDK = null;\n // Only log unexpected errors, not unsupported chain errors\n if (\n !(\n error instanceof Error &&\n error.message.includes('Unsupported chainId')\n )\n ) {\n console.error('Stake SDK initialization failed:', error);\n }\n }\n }\n\n #getCurrentAccount() {\n return this.messagingSystem.call('AccountsController:getSelectedAccount');\n }\n\n #getCurrentChainId(): number {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const {\n configuration: { chainId },\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return convertHexToDecimal(chainId);\n }\n\n /**\n * Refreshes the pooled stakes data for the current account.\n * Fetches updated stake information including lifetime rewards, assets, and exit requests\n * from the staking API service and updates the state.\n *\n * @returns A promise that resolves when the stakes data has been updated\n */\n async refreshPooledStakes(): Promise<void> {\n const currentAccount = this.#getCurrentAccount();\n if (!currentAccount?.address) {\n return;\n }\n\n const chainId = this.#getCurrentChainId();\n\n const { accounts, exchangeRate } =\n await this.#stakingApiService.getPooledStakes(\n [currentAccount.address],\n chainId,\n );\n\n this.update((state) => {\n state.pooled_staking.pooledStakes = accounts[0];\n state.pooled_staking.exchangeRate = exchangeRate;\n });\n }\n\n /**\n * Refreshes the staking eligibility status for the current account.\n * Updates the eligibility status in the controller state based on the location and address blocklist for compliance.\n *\n * @returns A promise that resolves when the eligibility status has been updated\n */\n async refreshStakingEligibility(): Promise<void> {\n const currentAccount = this.#getCurrentAccount();\n if (!currentAccount?.address) {\n return;\n }\n\n const { eligible: isEligible } =\n await this.#stakingApiService.getPooledStakingEligibility([\n currentAccount.address,\n ]);\n\n this.update((state) => {\n state.pooled_staking.isEligible = isEligible;\n });\n }\n\n /**\n * Refreshes vault data for the current chain.\n * Updates the vault data in the controller state including APY, capacity,\n * fee percentage, total assets, and vault address.\n *\n * @returns A promise that resolves when the vault data has been updated\n */\n async refreshVaultData(): Promise<void> {\n const chainId = this.#getCurrentChainId();\n const vaultData = await this.#stakingApiService.getVaultData(chainId);\n\n this.update((state) => {\n state.pooled_staking.vaultData = vaultData;\n });\n }\n\n /**\n * Refreshes all pooled staking related data including stakes, eligibility, and vault data.\n * This method allows partial success, meaning some data may update while other requests fail.\n * All errors are collected and thrown as a single error message.\n *\n * @returns A promise that resolves when all possible data has been updated\n * @throws {Error} If any of the refresh operations fail, with concatenated error messages\n */\n async refreshPooledStakingData(): Promise<void> {\n const errors: Error[] = [];\n\n await Promise.all([\n this.refreshPooledStakes().catch((error) => {\n errors.push(error);\n }),\n this.refreshStakingEligibility().catch((error) => {\n errors.push(error);\n }),\n this.refreshVaultData().catch((error) => {\n errors.push(error);\n }),\n ]);\n\n if (errors.length > 0) {\n throw new Error(\n `Failed to refresh some staking data: ${errors\n .map((e) => e.message)\n .join(', ')}`,\n );\n }\n }\n}\n"]}
|
package/dist/index.cjs
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.EarnController = exports.getDefaultEarnControllerState = exports.controllerName = void 0;
|
4
|
+
var EarnController_1 = require("./EarnController.cjs");
|
5
|
+
Object.defineProperty(exports, "controllerName", { enumerable: true, get: function () { return EarnController_1.controllerName; } });
|
6
|
+
Object.defineProperty(exports, "getDefaultEarnControllerState", { enumerable: true, get: function () { return EarnController_1.getDefaultEarnControllerState; } });
|
7
|
+
Object.defineProperty(exports, "EarnController", { enumerable: true, get: function () { return EarnController_1.EarnController; } });
|
8
|
+
//# sourceMappingURL=index.cjs.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAYA,uDAI0B;AAHxB,gHAAA,cAAc,OAAA;AACd,+HAAA,6BAA6B,OAAA;AAC7B,gHAAA,cAAc,OAAA","sourcesContent":["export type {\n PooledStakingState,\n StablecoinLendingState,\n StablecoinVault,\n EarnControllerState,\n EarnControllerGetStateAction,\n EarnControllerStateChangeEvent,\n EarnControllerActions,\n EarnControllerEvents,\n EarnControllerMessenger,\n} from './EarnController';\n\nexport {\n controllerName,\n getDefaultEarnControllerState,\n EarnController,\n} from './EarnController';\n"]}
|
package/dist/index.d.cts
ADDED
@@ -0,0 +1,3 @@
|
|
1
|
+
export type { PooledStakingState, StablecoinLendingState, StablecoinVault, EarnControllerState, EarnControllerGetStateAction, EarnControllerStateChangeEvent, EarnControllerActions, EarnControllerEvents, EarnControllerMessenger, } from "./EarnController.cjs";
|
2
|
+
export { controllerName, getDefaultEarnControllerState, EarnController, } from "./EarnController.cjs";
|
3
|
+
//# sourceMappingURL=index.d.cts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,4BAA4B,EAC5B,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,GACxB,6BAAyB;AAE1B,OAAO,EACL,cAAc,EACd,6BAA6B,EAC7B,cAAc,GACf,6BAAyB"}
|
package/dist/index.d.mts
ADDED
@@ -0,0 +1,3 @@
|
|
1
|
+
export type { PooledStakingState, StablecoinLendingState, StablecoinVault, EarnControllerState, EarnControllerGetStateAction, EarnControllerStateChangeEvent, EarnControllerActions, EarnControllerEvents, EarnControllerMessenger, } from "./EarnController.mjs";
|
2
|
+
export { controllerName, getDefaultEarnControllerState, EarnController, } from "./EarnController.mjs";
|
3
|
+
//# sourceMappingURL=index.d.mts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,4BAA4B,EAC5B,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,GACxB,6BAAyB;AAE1B,OAAO,EACL,cAAc,EACd,6BAA6B,EAC7B,cAAc,GACf,6BAAyB"}
|
package/dist/index.mjs
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,cAAc,EACd,6BAA6B,EAC7B,cAAc,EACf,6BAAyB","sourcesContent":["export type {\n PooledStakingState,\n StablecoinLendingState,\n StablecoinVault,\n EarnControllerState,\n EarnControllerGetStateAction,\n EarnControllerStateChangeEvent,\n EarnControllerActions,\n EarnControllerEvents,\n EarnControllerMessenger,\n} from './EarnController';\n\nexport {\n controllerName,\n getDefaultEarnControllerState,\n EarnController,\n} from './EarnController';\n"]}
|
package/package.json
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
{
|
2
|
+
"name": "@metamask-previews/earn-controller",
|
3
|
+
"version": "0.0.0-preview-43593c4e",
|
4
|
+
"description": "Manages state for earning features and coordinates interactions between staking services, SDK integrations, and other controllers to enable users to participate in various earning opportunities",
|
5
|
+
"keywords": [
|
6
|
+
"MetaMask",
|
7
|
+
"Ethereum"
|
8
|
+
],
|
9
|
+
"homepage": "https://github.com/MetaMask/core/tree/main/packages/earn-controller#readme",
|
10
|
+
"bugs": {
|
11
|
+
"url": "https://github.com/MetaMask/core/issues"
|
12
|
+
},
|
13
|
+
"repository": {
|
14
|
+
"type": "git",
|
15
|
+
"url": "https://github.com/MetaMask/core.git"
|
16
|
+
},
|
17
|
+
"license": "MIT",
|
18
|
+
"sideEffects": false,
|
19
|
+
"exports": {
|
20
|
+
".": {
|
21
|
+
"import": {
|
22
|
+
"types": "./dist/index.d.mts",
|
23
|
+
"default": "./dist/index.mjs"
|
24
|
+
},
|
25
|
+
"require": {
|
26
|
+
"types": "./dist/index.d.cts",
|
27
|
+
"default": "./dist/index.cjs"
|
28
|
+
}
|
29
|
+
},
|
30
|
+
"./package.json": "./package.json"
|
31
|
+
},
|
32
|
+
"main": "./dist/index.cjs",
|
33
|
+
"types": "./dist/index.d.cts",
|
34
|
+
"files": [
|
35
|
+
"dist/"
|
36
|
+
],
|
37
|
+
"scripts": {
|
38
|
+
"build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
|
39
|
+
"build:docs": "typedoc",
|
40
|
+
"changelog:validate": "../../scripts/validate-changelog.sh @metamask/earn-controller",
|
41
|
+
"changelog:update": "../../scripts/update-changelog.sh @metamask/earn-controller",
|
42
|
+
"publish:preview": "yarn npm publish --tag preview",
|
43
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter",
|
44
|
+
"test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache",
|
45
|
+
"test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
|
46
|
+
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch",
|
47
|
+
"since-latest-release": "../../scripts/since-latest-release.sh"
|
48
|
+
},
|
49
|
+
"dependencies": {
|
50
|
+
"@ethersproject/providers": "^5.7.0",
|
51
|
+
"@metamask/base-controller": "^7.1.1",
|
52
|
+
"@metamask/controller-utils": "^11.4.5",
|
53
|
+
"@metamask/stake-sdk": "^1.0.0"
|
54
|
+
},
|
55
|
+
"devDependencies": {
|
56
|
+
"@metamask/accounts-controller": "^22.0.0",
|
57
|
+
"@metamask/auto-changelog": "^3.4.4",
|
58
|
+
"@metamask/network-controller": "^22.1.1",
|
59
|
+
"@types/jest": "^27.4.1",
|
60
|
+
"deepmerge": "^4.2.2",
|
61
|
+
"jest": "^27.5.1",
|
62
|
+
"ts-jest": "^27.1.4",
|
63
|
+
"typedoc": "^0.24.8",
|
64
|
+
"typedoc-plugin-missing-exports": "^2.0.0",
|
65
|
+
"typescript": "~5.2.2"
|
66
|
+
},
|
67
|
+
"peerDependencies": {
|
68
|
+
"@metamask/accounts-controller": "^22.0.0",
|
69
|
+
"@metamask/network-controller": "^22.1.1"
|
70
|
+
},
|
71
|
+
"engines": {
|
72
|
+
"node": "^18.18 || >=20"
|
73
|
+
},
|
74
|
+
"publishConfig": {
|
75
|
+
"access": "public",
|
76
|
+
"registry": "https://registry.npmjs.org/"
|
77
|
+
}
|
78
|
+
}
|