eigen-skills 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -654
- package/bin/eigen-mcp.js +3 -0
- package/index.js +5 -14
- package/package.json +16 -8
- package/src/mcp-server.js +321 -0
- package/skills/eigen-avs/SKILL.md +0 -92
- package/skills/eigen-avs/scripts/avs-api.js +0 -117
- package/skills/eigen-da/SKILL.md +0 -148
- package/skills/eigen-da/scripts/da-api.js +0 -128
- package/skills/eigen-delegation/SKILL.md +0 -98
- package/skills/eigen-delegation/scripts/delegation-api.js +0 -102
- package/skills/eigen-restaking/SKILL.md +0 -92
- package/skills/eigen-restaking/scripts/eigen-api.js +0 -196
- package/skills/eigen-rewards/SKILL.md +0 -83
- package/skills/eigen-rewards/scripts/rewards-api.js +0 -73
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* EigenLayer Restaking API Client
|
|
3
|
-
*
|
|
4
|
-
* Data source: EigenExplorer REST API (https://api.eigenexplorer.com)
|
|
5
|
-
* Auth: x-api-token header (free tier available at https://developer.eigenexplorer.com)
|
|
6
|
-
*
|
|
7
|
-
* Covers: operators, stakers, TVL, deposits, withdrawals
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const axios = require('axios');
|
|
11
|
-
|
|
12
|
-
const MAINNET = 'https://api.eigenexplorer.com';
|
|
13
|
-
const HOLESKY = 'https://api-holesky.eigenexplorer.com';
|
|
14
|
-
|
|
15
|
-
class EigenAPI {
|
|
16
|
-
constructor(apiKey, { network = 'mainnet' } = {}) {
|
|
17
|
-
if (!apiKey) throw new Error('EigenExplorer API key required. Get one free at https://developer.eigenexplorer.com');
|
|
18
|
-
this.apiKey = apiKey;
|
|
19
|
-
this.baseUrl = network === 'holesky' ? HOLESKY : MAINNET;
|
|
20
|
-
this.client = axios.create({
|
|
21
|
-
baseURL: this.baseUrl,
|
|
22
|
-
headers: {
|
|
23
|
-
'x-api-token': this.apiKey,
|
|
24
|
-
'Content-Type': 'application/json',
|
|
25
|
-
},
|
|
26
|
-
timeout: 30000,
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// ─── Operators ────────────────────────────────────────
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Get all operators with optional filtering and sorting.
|
|
34
|
-
* @param {object} opts
|
|
35
|
-
* @param {boolean} [opts.withTvl=true] - include TVL calculations
|
|
36
|
-
* @param {string} [opts.searchByText] - case-insensitive name search
|
|
37
|
-
* @param {'asc'|'desc'} [opts.sortByTvl] - sort by TVL
|
|
38
|
-
* @param {'asc'|'desc'} [opts.sortByApy] - sort by APY
|
|
39
|
-
* @param {'asc'|'desc'} [opts.sortByTotalStakers] - sort by staker count
|
|
40
|
-
* @param {number} [opts.skip=0]
|
|
41
|
-
* @param {number} [opts.take=12]
|
|
42
|
-
*/
|
|
43
|
-
async getOperators(opts = {}) {
|
|
44
|
-
const params = {
|
|
45
|
-
withTvl: opts.withTvl !== false ? 'true' : 'false',
|
|
46
|
-
skip: opts.skip || 0,
|
|
47
|
-
take: opts.take || 12,
|
|
48
|
-
};
|
|
49
|
-
if (opts.searchByText) params.searchByText = opts.searchByText;
|
|
50
|
-
if (opts.sortByTvl) params.sortByTvl = opts.sortByTvl;
|
|
51
|
-
if (opts.sortByApy) params.sortByApy = opts.sortByApy;
|
|
52
|
-
if (opts.sortByTotalStakers) params.sortByTotalStakers = opts.sortByTotalStakers;
|
|
53
|
-
if (opts.sortByTotalAvs) params.sortByTotalAvs = opts.sortByTotalAvs;
|
|
54
|
-
|
|
55
|
-
const { data } = await this.client.get('/operators', { params });
|
|
56
|
-
return data;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Get a single operator by address.
|
|
61
|
-
* @param {string} address - operator ETH address
|
|
62
|
-
* @param {boolean} [withTvl=true]
|
|
63
|
-
*/
|
|
64
|
-
async getOperator(address, withTvl = true) {
|
|
65
|
-
const { data } = await this.client.get(`/operators/${address}`, {
|
|
66
|
-
params: { withTvl: withTvl ? 'true' : 'false' },
|
|
67
|
-
});
|
|
68
|
-
return data;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Get all operator addresses (lightweight, no metadata).
|
|
73
|
-
*/
|
|
74
|
-
async getOperatorAddresses() {
|
|
75
|
-
const { data } = await this.client.get('/operators/addresses');
|
|
76
|
-
return data;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// ─── Stakers ──────────────────────────────────────────
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Get staker info by address.
|
|
83
|
-
* @param {string} address - staker wallet address
|
|
84
|
-
*/
|
|
85
|
-
async getStaker(address) {
|
|
86
|
-
const { data } = await this.client.get(`/stakers/${address}`);
|
|
87
|
-
return data;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Get withdrawals for a staker.
|
|
92
|
-
* @param {string} address
|
|
93
|
-
* @param {object} opts
|
|
94
|
-
*/
|
|
95
|
-
async getStakerWithdrawals(address, opts = {}) {
|
|
96
|
-
const { data } = await this.client.get(`/stakers/${address}/withdrawals`, {
|
|
97
|
-
params: { skip: opts.skip || 0, take: opts.take || 12 },
|
|
98
|
-
});
|
|
99
|
-
return data;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Get deposits for a staker.
|
|
104
|
-
* @param {string} address
|
|
105
|
-
* @param {object} opts
|
|
106
|
-
*/
|
|
107
|
-
async getStakerDeposits(address, opts = {}) {
|
|
108
|
-
const { data } = await this.client.get(`/stakers/${address}/deposits`, {
|
|
109
|
-
params: { skip: opts.skip || 0, take: opts.take || 12 },
|
|
110
|
-
});
|
|
111
|
-
return data;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// ─── Deposits & Withdrawals (global) ──────────────────
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Get all deposits.
|
|
118
|
-
*/
|
|
119
|
-
async getDeposits(opts = {}) {
|
|
120
|
-
const { data } = await this.client.get('/deposits', {
|
|
121
|
-
params: { skip: opts.skip || 0, take: opts.take || 12 },
|
|
122
|
-
});
|
|
123
|
-
return data;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Get all withdrawals.
|
|
128
|
-
*/
|
|
129
|
-
async getWithdrawals(opts = {}) {
|
|
130
|
-
const { data } = await this.client.get('/withdrawals', {
|
|
131
|
-
params: { skip: opts.skip || 0, take: opts.take || 12 },
|
|
132
|
-
});
|
|
133
|
-
return data;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ─── Ecosystem Metrics ────────────────────────────────
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Get ecosystem-wide metrics (total TVL, staker count, operator count, etc.)
|
|
140
|
-
*/
|
|
141
|
-
async getMetrics() {
|
|
142
|
-
const { data } = await this.client.get('/metrics');
|
|
143
|
-
return data;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Get historical TVL metrics.
|
|
148
|
-
* @param {object} opts
|
|
149
|
-
*/
|
|
150
|
-
async getHistoricalMetrics(opts = {}) {
|
|
151
|
-
const { data } = await this.client.get('/metrics/historical/tvl', {
|
|
152
|
-
params: opts,
|
|
153
|
-
});
|
|
154
|
-
return data;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// ─── Events ───────────────────────────────────────────
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Get delegation events (shares increased/decreased, staker delegated/undelegated).
|
|
161
|
-
* @param {object} opts
|
|
162
|
-
*/
|
|
163
|
-
async getDelegationEvents(opts = {}) {
|
|
164
|
-
const { data } = await this.client.get('/events/delegation', {
|
|
165
|
-
params: { skip: opts.skip || 0, take: opts.take || 12 },
|
|
166
|
-
});
|
|
167
|
-
return data;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Get operator registration/deregistration events.
|
|
172
|
-
* @param {object} opts
|
|
173
|
-
*/
|
|
174
|
-
async getRegistrationEvents(opts = {}) {
|
|
175
|
-
const { data } = await this.client.get('/events/registration-status', {
|
|
176
|
-
params: { skip: opts.skip || 0, take: opts.take || 12 },
|
|
177
|
-
});
|
|
178
|
-
return data;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// ─── Health ───────────────────────────────────────────
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Health check — hit the metrics endpoint as a lightweight ping.
|
|
185
|
-
*/
|
|
186
|
-
async healthCheck() {
|
|
187
|
-
try {
|
|
188
|
-
const { data } = await this.client.get('/metrics');
|
|
189
|
-
return { ok: true, tvl: data?.tvl?.tvl || data?.tvl };
|
|
190
|
-
} catch (err) {
|
|
191
|
-
return { ok: false, error: err.message };
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
module.exports = EigenAPI;
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: eigen-rewards
|
|
3
|
-
description: "Query EigenLayer rewards — operator rewards, staker rewards, AVS reward distributions, top yield operators and AVS"
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
metadata:
|
|
6
|
-
emoji: "💰"
|
|
7
|
-
tags: ["eigenlayer", "rewards", "yield", "apy", "staking"]
|
|
8
|
-
user-invocable: true
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# EigenLayer Rewards Skill
|
|
12
|
-
|
|
13
|
-
Query live rewards data from EigenLayer: operator rewards, staker rewards, AVS reward distributions, and find the best yield opportunities.
|
|
14
|
-
|
|
15
|
-
## Data Source
|
|
16
|
-
|
|
17
|
-
**EigenExplorer API** — `https://api.eigenexplorer.com`
|
|
18
|
-
- Auth: `x-api-token` header (free key at https://developer.eigenexplorer.com)
|
|
19
|
-
|
|
20
|
-
## When to use this skill
|
|
21
|
-
|
|
22
|
-
Use when the user asks about:
|
|
23
|
-
- EigenLayer rewards (operator or staker rewards)
|
|
24
|
-
- Best yield / highest APY operators
|
|
25
|
-
- Best yield / highest APY AVS
|
|
26
|
-
- Reward tokens and strategies for an operator
|
|
27
|
-
- How much a staker is earning
|
|
28
|
-
- AVS reward distributions
|
|
29
|
-
- Comparing restaking yields
|
|
30
|
-
|
|
31
|
-
## How to query
|
|
32
|
-
|
|
33
|
-
### Get top operators by APY
|
|
34
|
-
```bash
|
|
35
|
-
curl -s "https://api.eigenexplorer.com/operators?withTvl=true&sortByApy=desc&take=10" -H "x-api-token: $EIGEN_API_KEY"
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Get top AVS by APY
|
|
39
|
-
```bash
|
|
40
|
-
curl -s "https://api.eigenexplorer.com/avs?withTvl=true&sortByApy=desc&take=10" -H "x-api-token: $EIGEN_API_KEY"
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### Get rewards for a specific operator
|
|
44
|
-
```bash
|
|
45
|
-
curl -s "https://api.eigenexplorer.com/operators/0xOPERATOR_ADDRESS/rewards" -H "x-api-token: $EIGEN_API_KEY"
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Get rewards for a specific staker
|
|
49
|
-
```bash
|
|
50
|
-
curl -s "https://api.eigenexplorer.com/stakers/0xSTAKER_ADDRESS/rewards" -H "x-api-token: $EIGEN_API_KEY"
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Get rewards distributed by a specific AVS
|
|
54
|
-
```bash
|
|
55
|
-
curl -s "https://api.eigenexplorer.com/avs/0xAVS_ADDRESS/rewards" -H "x-api-token: $EIGEN_API_KEY"
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Get all rewards data
|
|
59
|
-
```bash
|
|
60
|
-
curl -s "https://api.eigenexplorer.com/rewards?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Response Format
|
|
64
|
-
|
|
65
|
-
Format results for the user with:
|
|
66
|
-
- **Bold operator/AVS names**
|
|
67
|
-
- APY as a percentage (e.g., "4.2% APY")
|
|
68
|
-
- Reward token names and amounts
|
|
69
|
-
- TVL alongside APY for context (high APY + low TVL = be cautious)
|
|
70
|
-
- Rank operators/AVS by APY when comparing yield
|
|
71
|
-
- Use bullet points, never tables in chat
|
|
72
|
-
|
|
73
|
-
## Programmatic Usage
|
|
74
|
-
|
|
75
|
-
```javascript
|
|
76
|
-
const RewardsAPI = require('eigen-agent-skills/skills/eigen-rewards/scripts/rewards-api');
|
|
77
|
-
const api = new RewardsAPI('YOUR_API_KEY');
|
|
78
|
-
|
|
79
|
-
const topOps = await api.getTopOperatorsByAPY(10);
|
|
80
|
-
const topAVS = await api.getTopAVSByAPY(10);
|
|
81
|
-
const opRewards = await api.getOperatorRewards('0x...');
|
|
82
|
-
const stakerRewards = await api.getStakerRewards('0x...');
|
|
83
|
-
```
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* EigenLayer Rewards API Client
|
|
3
|
-
*
|
|
4
|
-
* Data source: EigenExplorer REST API
|
|
5
|
-
* Covers: rewards per operator, rewards per staker, reward strategies
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const axios = require('axios');
|
|
9
|
-
|
|
10
|
-
const MAINNET = 'https://api.eigenexplorer.com';
|
|
11
|
-
const HOLESKY = 'https://api-holesky.eigenexplorer.com';
|
|
12
|
-
|
|
13
|
-
class RewardsAPI {
|
|
14
|
-
constructor(apiKey, { network = 'mainnet' } = {}) {
|
|
15
|
-
if (!apiKey) throw new Error('EigenExplorer API key required. Get one free at https://developer.eigenexplorer.com');
|
|
16
|
-
this.client = axios.create({
|
|
17
|
-
baseURL: network === 'holesky' ? HOLESKY : MAINNET,
|
|
18
|
-
headers: {
|
|
19
|
-
'x-api-token': apiKey,
|
|
20
|
-
'Content-Type': 'application/json',
|
|
21
|
-
},
|
|
22
|
-
timeout: 30000,
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// ─── AVS Rewards (only verified working rewards endpoint) ─────
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Get rewards distributed by a specific AVS.
|
|
30
|
-
* Returns reward submission hashes, durations, tokens, and amounts.
|
|
31
|
-
* @param {string} avsAddress
|
|
32
|
-
*/
|
|
33
|
-
async getAVSRewards(avsAddress) {
|
|
34
|
-
const { data } = await this.client.get(`/avs/${avsAddress}/rewards`);
|
|
35
|
-
return data;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// ─── Convenience Queries ──────────────────────────────
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Get the top operators sorted by APY (best yield first).
|
|
42
|
-
* @param {number} [limit=10]
|
|
43
|
-
*/
|
|
44
|
-
async getTopOperatorsByAPY(limit = 10) {
|
|
45
|
-
const { data } = await this.client.get('/operators', {
|
|
46
|
-
params: {
|
|
47
|
-
withTvl: 'true',
|
|
48
|
-
sortByApy: 'desc',
|
|
49
|
-
take: limit,
|
|
50
|
-
skip: 0,
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
return data;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Get top AVS sorted by APY.
|
|
58
|
-
* @param {number} [limit=10]
|
|
59
|
-
*/
|
|
60
|
-
async getTopAVSByAPY(limit = 10) {
|
|
61
|
-
const { data } = await this.client.get('/avs', {
|
|
62
|
-
params: {
|
|
63
|
-
withTvl: 'true',
|
|
64
|
-
sortByApy: 'desc',
|
|
65
|
-
take: limit,
|
|
66
|
-
skip: 0,
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
return data;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
module.exports = RewardsAPI;
|