eigen-skills 1.1.1 → 1.1.3
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/index.js +3 -15
- package/package.json +5 -3
- package/scripts/demo.js +0 -93
- 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
package/index.js
CHANGED
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* eigencloud-skills — EigenCompute TEE deployment skills for AI agents
|
|
3
3
|
*
|
|
4
|
-
* Install:
|
|
4
|
+
* Install: npm install eigen-skills
|
|
5
5
|
* Usage: Agents discover SKILL.md files in skills/ automatically.
|
|
6
6
|
* For programmatic use, require this module.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
const EigenAPI = require('./skills/eigen-restaking/scripts/eigen-api');
|
|
10
|
-
const AVSAPI = require('./skills/eigen-avs/scripts/avs-api');
|
|
11
|
-
const RewardsAPI = require('./skills/eigen-rewards/scripts/rewards-api');
|
|
12
|
-
const DelegationAPI = require('./skills/eigen-delegation/scripts/delegation-api');
|
|
13
9
|
const EigenCompute = require('./skills/eigen-compute/scripts/compute-api');
|
|
14
|
-
const EigenDA = require('./skills/eigen-da/scripts/da-api');
|
|
15
10
|
|
|
16
|
-
module.exports = {
|
|
17
|
-
EigenAPI,
|
|
18
|
-
AVSAPI,
|
|
19
|
-
RewardsAPI,
|
|
20
|
-
DelegationAPI,
|
|
21
|
-
EigenCompute,
|
|
22
|
-
EigenDA,
|
|
23
|
-
};
|
|
11
|
+
module.exports = { EigenCompute };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eigen-skills",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.3",
|
|
4
|
+
"description": "EigenCompute TEE deployment skills for AI agents — encrypted memory, sealed secrets, cryptographic attestation",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"agents": {
|
|
7
7
|
"skills": "skills/"
|
|
@@ -27,7 +27,9 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"axios": "^1.7.0",
|
|
30
|
-
"dotenv": "^17.3.1"
|
|
30
|
+
"dotenv": "^17.3.1"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
31
33
|
"express": "^5.2.1",
|
|
32
34
|
"socket.io": "^4.8.3"
|
|
33
35
|
}
|
package/scripts/demo.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Demo — run all eigen-agent-skills to verify they work.
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* EIGEN_API_KEY=your_key node scripts/demo.js
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const EigenAPI = require('../skills/eigen-restaking/scripts/eigen-api');
|
|
11
|
-
const AVSAPI = require('../skills/eigen-avs/scripts/avs-api');
|
|
12
|
-
const RewardsAPI = require('../skills/eigen-rewards/scripts/rewards-api');
|
|
13
|
-
const DelegationAPI = require('../skills/eigen-delegation/scripts/delegation-api');
|
|
14
|
-
|
|
15
|
-
const API_KEY = process.env.EIGEN_API_KEY;
|
|
16
|
-
|
|
17
|
-
if (!API_KEY) {
|
|
18
|
-
console.error('❌ Set EIGEN_API_KEY env var. Get a free key at https://developer.eigenexplorer.com');
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async function run() {
|
|
23
|
-
console.log('\n🔄 ═════════════════════════════════════');
|
|
24
|
-
console.log(' Eigen Agent Skills — Demo');
|
|
25
|
-
console.log('═══════════════════════════════════════\n');
|
|
26
|
-
|
|
27
|
-
const eigen = new EigenAPI(API_KEY);
|
|
28
|
-
const avs = new AVSAPI(API_KEY);
|
|
29
|
-
const rewards = new RewardsAPI(API_KEY);
|
|
30
|
-
const delegation = new DelegationAPI(API_KEY);
|
|
31
|
-
|
|
32
|
-
// 1. Health check
|
|
33
|
-
console.log('📡 Health check...');
|
|
34
|
-
const health = await eigen.healthCheck();
|
|
35
|
-
console.log(` Status: ${health.ok ? '✅ Healthy' : '❌ Failed'}`);
|
|
36
|
-
if (health.tvl) console.log(` EigenLayer TVL: ${JSON.stringify(health.tvl)}`);
|
|
37
|
-
console.log('');
|
|
38
|
-
|
|
39
|
-
// 2. Ecosystem metrics
|
|
40
|
-
console.log('📊 Ecosystem Metrics...');
|
|
41
|
-
const metrics = await eigen.getMetrics();
|
|
42
|
-
console.log(` ${JSON.stringify(metrics, null, 2).substring(0, 500)}`);
|
|
43
|
-
console.log('');
|
|
44
|
-
|
|
45
|
-
// 3. Top 5 operators by TVL
|
|
46
|
-
console.log('👥 Top 5 Operators by TVL...');
|
|
47
|
-
const ops = await eigen.getOperators({ sortByTvl: 'desc', take: 5 });
|
|
48
|
-
if (ops.data) {
|
|
49
|
-
ops.data.forEach((op, i) => {
|
|
50
|
-
console.log(` ${i + 1}. ${op.metadataName || op.address} — TVL: ${JSON.stringify(op.tvl?.tvl || 'N/A')} — Stakers: ${op.totalStakers}`);
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
console.log('');
|
|
54
|
-
|
|
55
|
-
// 4. Top 5 AVS by TVL
|
|
56
|
-
console.log('🛡️ Top 5 AVS by TVL...');
|
|
57
|
-
const avsList = await avs.getAllAVS({ sortByTvl: 'desc', take: 5 });
|
|
58
|
-
if (avsList.data) {
|
|
59
|
-
avsList.data.forEach((a, i) => {
|
|
60
|
-
console.log(` ${i + 1}. ${a.metadataName || a.address} — TVL: ${JSON.stringify(a.tvl?.tvl || 'N/A')}`);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
console.log('');
|
|
64
|
-
|
|
65
|
-
// 5. Top 5 operators by APY
|
|
66
|
-
console.log('💰 Top 5 Operators by APY...');
|
|
67
|
-
const topApy = await rewards.getTopOperatorsByAPY(5);
|
|
68
|
-
if (topApy.data) {
|
|
69
|
-
topApy.data.forEach((op, i) => {
|
|
70
|
-
console.log(` ${i + 1}. ${op.metadataName || op.address} — APY: ${op.maxApy || 'N/A'}`);
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
console.log('');
|
|
74
|
-
|
|
75
|
-
// 6. Top 5 operators by delegation
|
|
76
|
-
console.log('🤝 Top 5 Operators by Delegation (staker count)...');
|
|
77
|
-
const topDel = await delegation.getTopDelegatedOperators(5);
|
|
78
|
-
if (topDel.data) {
|
|
79
|
-
topDel.data.forEach((op, i) => {
|
|
80
|
-
console.log(` ${i + 1}. ${op.metadataName || op.address} — Stakers: ${op.totalStakers} — AVS: ${op.totalAvs}`);
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
console.log('');
|
|
84
|
-
|
|
85
|
-
console.log('═══════════════════════════════════════');
|
|
86
|
-
console.log(' ✅ Demo complete');
|
|
87
|
-
console.log('═══════════════════════════════════════\n');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
run().catch(err => {
|
|
91
|
-
console.error('Demo failed:', err.message);
|
|
92
|
-
process.exit(1);
|
|
93
|
-
});
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: eigen-avs
|
|
3
|
-
description: "Query EigenLayer AVS (Actively Validated Services) — list services, operators per AVS, stakers per AVS, registration events, and operator-sets"
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
metadata:
|
|
6
|
-
emoji: "🛡️"
|
|
7
|
-
tags: ["eigenlayer", "avs", "services", "operators", "security"]
|
|
8
|
-
user-invocable: true
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# EigenLayer AVS Skill
|
|
12
|
-
|
|
13
|
-
Query live data about Actively Validated Services (AVS) on EigenLayer: service listings, operators securing each AVS, staker delegations, registration events, and operator-sets.
|
|
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
|
-
- AVS (Actively Validated Services) on EigenLayer
|
|
24
|
-
- Which operators are securing a specific AVS
|
|
25
|
-
- Stakers delegated to a specific AVS
|
|
26
|
-
- AVS registration/deregistration events
|
|
27
|
-
- Operator-sets for an AVS
|
|
28
|
-
- Comparing AVS by TVL, staker count, or APY
|
|
29
|
-
|
|
30
|
-
## How to query
|
|
31
|
-
|
|
32
|
-
### Get all AVS (sorted by TVL)
|
|
33
|
-
```bash
|
|
34
|
-
curl -s "https://api.eigenexplorer.com/avs?withTvl=true&sortByTvl=desc&take=10" -H "x-api-token: $EIGEN_API_KEY"
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Search AVS by name
|
|
38
|
-
```bash
|
|
39
|
-
curl -s "https://api.eigenexplorer.com/avs?searchByText=eigenda&withTvl=true" -H "x-api-token: $EIGEN_API_KEY"
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Get a specific AVS
|
|
43
|
-
```bash
|
|
44
|
-
curl -s "https://api.eigenexplorer.com/avs/0xAVS_ADDRESS?withTvl=true" -H "x-api-token: $EIGEN_API_KEY"
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Get operators registered to an AVS
|
|
48
|
-
```bash
|
|
49
|
-
curl -s "https://api.eigenexplorer.com/avs/0xAVS_ADDRESS/operators?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Get stakers for an AVS
|
|
53
|
-
```bash
|
|
54
|
-
curl -s "https://api.eigenexplorer.com/avs/0xAVS_ADDRESS/stakers?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Get registration events for an AVS
|
|
58
|
-
```bash
|
|
59
|
-
curl -s "https://api.eigenexplorer.com/avs/0xAVS_ADDRESS/events/registration?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### Get operator-sets for an AVS
|
|
63
|
-
```bash
|
|
64
|
-
curl -s "https://api.eigenexplorer.com/avs/0xAVS_ADDRESS/operator-sets?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### Get all AVS addresses (lightweight)
|
|
68
|
-
```bash
|
|
69
|
-
curl -s "https://api.eigenexplorer.com/avs/addresses" -H "x-api-token: $EIGEN_API_KEY"
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Response Format
|
|
73
|
-
|
|
74
|
-
Format results for the user with:
|
|
75
|
-
- **Bold AVS names** and abbreviated addresses
|
|
76
|
-
- TVL in human-readable form (e.g., "$500M")
|
|
77
|
-
- Number of operators securing the AVS
|
|
78
|
-
- Number of stakers
|
|
79
|
-
- APY if available
|
|
80
|
-
- Active/inactive status for operator registrations
|
|
81
|
-
- Use bullet points, never tables in chat
|
|
82
|
-
|
|
83
|
-
## Programmatic Usage
|
|
84
|
-
|
|
85
|
-
```javascript
|
|
86
|
-
const AVSAPI = require('eigen-agent-skills/skills/eigen-avs/scripts/avs-api');
|
|
87
|
-
const api = new AVSAPI('YOUR_API_KEY');
|
|
88
|
-
|
|
89
|
-
const allAVS = await api.getAllAVS({ sortByTvl: 'desc', take: 10 });
|
|
90
|
-
const operators = await api.getAVSOperators('0xAVS_ADDRESS');
|
|
91
|
-
const stakers = await api.getAVSStakers('0xAVS_ADDRESS');
|
|
92
|
-
```
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* EigenLayer AVS (Actively Validated Services) API Client
|
|
3
|
-
*
|
|
4
|
-
* Data source: EigenExplorer REST API
|
|
5
|
-
* Covers: AVS listing, detail, operators per AVS, stakers per AVS, registration events
|
|
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 AVSAPI {
|
|
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 Listing ──────────────────────────────────────
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Get all AVS with optional filtering and sorting.
|
|
30
|
-
* @param {object} opts
|
|
31
|
-
* @param {boolean} [opts.withTvl=true]
|
|
32
|
-
* @param {string} [opts.searchByText] - search AVS by name
|
|
33
|
-
* @param {'asc'|'desc'} [opts.sortByTvl]
|
|
34
|
-
* @param {'asc'|'desc'} [opts.sortByApy]
|
|
35
|
-
* @param {'asc'|'desc'} [opts.sortByTotalStakers]
|
|
36
|
-
* @param {number} [opts.skip=0]
|
|
37
|
-
* @param {number} [opts.take=12]
|
|
38
|
-
*/
|
|
39
|
-
async getAllAVS(opts = {}) {
|
|
40
|
-
const params = {
|
|
41
|
-
withTvl: opts.withTvl !== false ? 'true' : 'false',
|
|
42
|
-
skip: opts.skip || 0,
|
|
43
|
-
take: opts.take || 12,
|
|
44
|
-
};
|
|
45
|
-
if (opts.searchByText) params.searchByText = opts.searchByText;
|
|
46
|
-
if (opts.sortByTvl) params.sortByTvl = opts.sortByTvl;
|
|
47
|
-
if (opts.sortByApy) params.sortByApy = opts.sortByApy;
|
|
48
|
-
if (opts.sortByTotalStakers) params.sortByTotalStakers = opts.sortByTotalStakers;
|
|
49
|
-
|
|
50
|
-
const { data } = await this.client.get('/avs', { params });
|
|
51
|
-
return data;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Get AVS addresses only (lightweight).
|
|
56
|
-
*/
|
|
57
|
-
async getAVSAddresses() {
|
|
58
|
-
const { data } = await this.client.get('/avs/addresses');
|
|
59
|
-
return data;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Get detailed info for a single AVS.
|
|
64
|
-
* @param {string} address - AVS contract address
|
|
65
|
-
* @param {boolean} [withTvl=true]
|
|
66
|
-
*/
|
|
67
|
-
async getAVS(address, withTvl = true) {
|
|
68
|
-
const { data } = await this.client.get(`/avs/${address}`, {
|
|
69
|
-
params: { withTvl: withTvl ? 'true' : 'false' },
|
|
70
|
-
});
|
|
71
|
-
return data;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// ─── AVS ↔ Operators ─────────────────────────────────
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Get operators registered to a specific AVS.
|
|
78
|
-
* @param {string} avsAddress
|
|
79
|
-
* @param {object} opts
|
|
80
|
-
*/
|
|
81
|
-
async getAVSOperators(avsAddress, opts = {}) {
|
|
82
|
-
const { data } = await this.client.get(`/avs/${avsAddress}/operators`, {
|
|
83
|
-
params: { skip: opts.skip || 0, take: opts.take || 12 },
|
|
84
|
-
});
|
|
85
|
-
return data;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// ─── AVS ↔ Stakers ───────────────────────────────────
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Get stakers delegated to a specific AVS.
|
|
92
|
-
* @param {string} avsAddress
|
|
93
|
-
* @param {object} opts
|
|
94
|
-
*/
|
|
95
|
-
async getAVSStakers(avsAddress, opts = {}) {
|
|
96
|
-
const { data } = await this.client.get(`/avs/${avsAddress}/stakers`, {
|
|
97
|
-
params: { skip: opts.skip || 0, take: opts.take || 12 },
|
|
98
|
-
});
|
|
99
|
-
return data;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ─── AVS Registration Events ──────────────────────────
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Get registration/deregistration events for a specific AVS.
|
|
106
|
-
* @param {string} avsAddress
|
|
107
|
-
* @param {object} opts
|
|
108
|
-
*/
|
|
109
|
-
async getAVSRegistrationEvents(avsAddress, opts = {}) {
|
|
110
|
-
const { data } = await this.client.get(`/avs/${avsAddress}/events/registration-status`, {
|
|
111
|
-
params: { skip: opts.skip || 0, take: opts.take || 12 },
|
|
112
|
-
});
|
|
113
|
-
return data;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
module.exports = AVSAPI;
|
package/skills/eigen-da/SKILL.md
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: eigen-da
|
|
3
|
-
description: "Store and retrieve data blobs on EigenDA (Data Availability layer) — disperse blobs, retrieve by commitment, check status via proxy or direct API"
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
metadata:
|
|
6
|
-
emoji: "📦"
|
|
7
|
-
tags: ["eigenlayer", "eigenda", "data-availability", "blobs", "storage"]
|
|
8
|
-
user-invocable: true
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# EigenDA Skill
|
|
12
|
-
|
|
13
|
-
Store and retrieve data blobs on EigenDA — EigenLayer's Data Availability layer. EigenDA provides high-throughput, low-cost data availability for rollups and applications.
|
|
14
|
-
|
|
15
|
-
## What is EigenDA?
|
|
16
|
-
|
|
17
|
-
EigenDA is a **data availability (DA) service** built on EigenLayer. It lets you:
|
|
18
|
-
- **Store blobs** — submit arbitrary data, get back a cryptographic commitment
|
|
19
|
-
- **Retrieve blobs** — fetch data using the commitment hash
|
|
20
|
-
- **Verify** — KZG commitments prove data integrity
|
|
21
|
-
|
|
22
|
-
## Architecture
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
Your App → EigenDA Proxy (localhost:3100) → EigenDA Disperser → EigenDA Operators
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
The **EigenDA Proxy** is a local REST server that handles encoding, KZG verification, and communication with the EigenDA disperser network.
|
|
29
|
-
|
|
30
|
-
## Prerequisites
|
|
31
|
-
|
|
32
|
-
Run the EigenDA Proxy locally via Docker:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
docker run -d \
|
|
36
|
-
--name eigenda-proxy \
|
|
37
|
-
-p 3100:3100 \
|
|
38
|
-
ghcr.io/layr-labs/eigenda-proxy:latest \
|
|
39
|
-
--eigenda.disperser-rpc=disperser-sepolia.eigenda.xyz:443 \
|
|
40
|
-
--eigenda.service-manager-addr=0xD4A7E1Bd8015057293f0D0A557088c286942e84b \
|
|
41
|
-
--eigenda.eth-rpc=YOUR_SEPOLIA_RPC_URL \
|
|
42
|
-
--eigenda.status-query-timeout=45s \
|
|
43
|
-
--eigenda.signer-private-key-hex=YOUR_PRIVATE_KEY \
|
|
44
|
-
--memstore.enabled=false \
|
|
45
|
-
--eigenda.disable-tls=false
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## When to use this skill
|
|
49
|
-
|
|
50
|
-
Use when the user asks about:
|
|
51
|
-
- Storing data on EigenDA
|
|
52
|
-
- Retrieving data from EigenDA by commitment
|
|
53
|
-
- Data availability for rollups
|
|
54
|
-
- Blob storage and retrieval
|
|
55
|
-
- EigenDA proxy setup
|
|
56
|
-
- Verifying data commitments
|
|
57
|
-
- EigenDA health/status checks
|
|
58
|
-
|
|
59
|
-
## How to use
|
|
60
|
-
|
|
61
|
-
### Store a blob via proxy
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
curl -s -X POST "http://127.0.0.1:3100/put?commitment_mode=standard" \
|
|
65
|
-
-H "Content-Type: application/json" \
|
|
66
|
-
-d '{"key": "value", "timestamp": "2025-01-01T00:00:00Z"}'
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Returns: a hex commitment string (the blob's address on EigenDA).
|
|
70
|
-
|
|
71
|
-
### Retrieve a blob via proxy
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
curl -s "http://127.0.0.1:3100/get/COMMITMENT_HASH?commitment_mode=standard"
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Returns: the original JSON data.
|
|
78
|
-
|
|
79
|
-
### Health check
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
curl -s "http://127.0.0.1:3100/health"
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### View blob on explorer
|
|
86
|
-
|
|
87
|
-
After storing, view the blob at:
|
|
88
|
-
```
|
|
89
|
-
https://blobs-sepolia.eigenda.xyz/blobs/COMMITMENT_HASH
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## EigenDA v2 Disperser API (Direct)
|
|
93
|
-
|
|
94
|
-
For direct access without the proxy (advanced):
|
|
95
|
-
|
|
96
|
-
### Disperse a blob
|
|
97
|
-
The v2 disperser uses gRPC at `disperser-sepolia.eigenda.xyz:443`:
|
|
98
|
-
- `DisperseBlob()` — enqueue a blob for dispersal
|
|
99
|
-
- `GetBlobStatus()` — poll dispersal status
|
|
100
|
-
- `GetBlobCommitment()` — get the KZG commitment
|
|
101
|
-
|
|
102
|
-
### Retrieve from relay
|
|
103
|
-
The v2 Relay API provides:
|
|
104
|
-
- `GetBlob(blob_key)` — retrieve blob from relay nodes
|
|
105
|
-
|
|
106
|
-
## Configuration
|
|
107
|
-
|
|
108
|
-
| Env Var | Default | Description |
|
|
109
|
-
|---------|---------|-------------|
|
|
110
|
-
| `EIGENDA_PROXY_URL` | `http://127.0.0.1:3100` | Proxy address |
|
|
111
|
-
| `EIGENDA_COMMITMENT_MODE` | `standard` | `standard` or `optimistic` |
|
|
112
|
-
| `EIGENDA_TIMEOUT` | `60000` | Timeout in ms |
|
|
113
|
-
|
|
114
|
-
### Commitment modes
|
|
115
|
-
|
|
116
|
-
- **standard** — full KZG commitment, highest security
|
|
117
|
-
- **optimistic** — faster but with weaker guarantees
|
|
118
|
-
|
|
119
|
-
## Networks
|
|
120
|
-
|
|
121
|
-
| Network | Disperser RPC | Service Manager |
|
|
122
|
-
|---------|---------------|-----------------|
|
|
123
|
-
| Sepolia | `disperser-sepolia.eigenda.xyz:443` | `0xD4A7E1Bd8015057293f0D0A557088c286942e84b` |
|
|
124
|
-
| Mainnet | `disperser.eigenda.xyz:443` | Check EigenLayer docs |
|
|
125
|
-
|
|
126
|
-
## Programmatic Usage
|
|
127
|
-
|
|
128
|
-
```javascript
|
|
129
|
-
const EigenDA = require('eigen-skills/skills/eigen-da/scripts/da-api');
|
|
130
|
-
|
|
131
|
-
const da = new EigenDA({
|
|
132
|
-
proxyUrl: 'http://127.0.0.1:3100', // default
|
|
133
|
-
commitmentMode: 'standard', // default
|
|
134
|
-
timeout: 60000, // default
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// Store data
|
|
138
|
-
const commitment = await da.store({ key: 'value', timestamp: new Date() });
|
|
139
|
-
console.log('Commitment:', commitment);
|
|
140
|
-
console.log('Explorer:', da.getExplorerUrl(commitment));
|
|
141
|
-
|
|
142
|
-
// Retrieve data
|
|
143
|
-
const data = await da.retrieve(commitment);
|
|
144
|
-
console.log('Retrieved:', data);
|
|
145
|
-
|
|
146
|
-
// Health check
|
|
147
|
-
const healthy = await da.healthCheck();
|
|
148
|
-
```
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* EigenDA API Client — Blob Storage via Local Proxy
|
|
3
|
-
*
|
|
4
|
-
* Stores and retrieves data blobs on EigenDA through the local proxy.
|
|
5
|
-
* Proxy handles KZG commitments, encoding, and disperser communication.
|
|
6
|
-
*
|
|
7
|
-
* Proxy endpoints:
|
|
8
|
-
* POST /put?commitment_mode=standard → store blob, get commitment hash
|
|
9
|
-
* GET /get/<commitment>?commitment_mode=standard → retrieve stored blob
|
|
10
|
-
* GET /health → proxy health check
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const axios = require('axios');
|
|
14
|
-
|
|
15
|
-
class EigenDA {
|
|
16
|
-
/**
|
|
17
|
-
* @param {object} opts
|
|
18
|
-
* @param {string} [opts.proxyUrl='http://127.0.0.1:3100']
|
|
19
|
-
* @param {string} [opts.commitmentMode='standard'] - 'standard' | 'optimistic'
|
|
20
|
-
* @param {number} [opts.timeout=60000]
|
|
21
|
-
*/
|
|
22
|
-
constructor(opts = {}) {
|
|
23
|
-
this.proxyUrl = opts.proxyUrl || process.env.EIGENDA_PROXY_URL || 'http://127.0.0.1:3100';
|
|
24
|
-
this.commitmentMode = opts.commitmentMode || process.env.EIGENDA_COMMITMENT_MODE || 'standard';
|
|
25
|
-
this.timeout = opts.timeout || parseInt(process.env.EIGENDA_TIMEOUT || '60000', 10);
|
|
26
|
-
|
|
27
|
-
this.client = axios.create({
|
|
28
|
-
baseURL: this.proxyUrl,
|
|
29
|
-
timeout: this.timeout,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Store a JSON payload on EigenDA.
|
|
35
|
-
* @param {object} data - the data to store
|
|
36
|
-
* @returns {Promise<string>} commitment hash
|
|
37
|
-
*/
|
|
38
|
-
async store(data) {
|
|
39
|
-
const payload = JSON.stringify(data);
|
|
40
|
-
console.log(`[EigenDA] Storing blob (${payload.length} bytes)...`);
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const response = await this.client.post(
|
|
44
|
-
`/put?commitment_mode=${this.commitmentMode}`,
|
|
45
|
-
payload,
|
|
46
|
-
{ headers: { 'Content-Type': 'application/json' } }
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const commitment = response.data;
|
|
50
|
-
if (!commitment || typeof commitment !== 'string') {
|
|
51
|
-
throw new Error(`Invalid commitment: ${JSON.stringify(response.data)}`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
console.log(`[EigenDA] ✅ Stored. Commitment: ${commitment.substring(0, 40)}...`);
|
|
55
|
-
return commitment;
|
|
56
|
-
} catch (error) {
|
|
57
|
-
const msg = this._formatError(error);
|
|
58
|
-
console.error(`[EigenDA] ❌ Store failed: ${msg}`);
|
|
59
|
-
throw new Error(`EigenDA store failed: ${msg}`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Retrieve a blob from EigenDA by commitment.
|
|
65
|
-
* @param {string} commitment
|
|
66
|
-
* @returns {Promise<object>} parsed JSON
|
|
67
|
-
*/
|
|
68
|
-
async retrieve(commitment) {
|
|
69
|
-
console.log(`[EigenDA] Retrieving blob: ${commitment.substring(0, 40)}...`);
|
|
70
|
-
|
|
71
|
-
try {
|
|
72
|
-
const response = await this.client.get(
|
|
73
|
-
`/get/${commitment}?commitment_mode=${this.commitmentMode}`
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
const payload = response.data;
|
|
77
|
-
if (typeof payload === 'string') {
|
|
78
|
-
return JSON.parse(payload);
|
|
79
|
-
}
|
|
80
|
-
return payload;
|
|
81
|
-
} catch (error) {
|
|
82
|
-
const msg = this._formatError(error);
|
|
83
|
-
console.error(`[EigenDA] ❌ Retrieve failed: ${msg}`);
|
|
84
|
-
throw new Error(`EigenDA retrieve failed: ${msg}`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Get the EigenDA blob explorer URL for a commitment.
|
|
90
|
-
* @param {string} commitment
|
|
91
|
-
* @param {string} [network='sepolia']
|
|
92
|
-
* @returns {string}
|
|
93
|
-
*/
|
|
94
|
-
getExplorerUrl(commitment, network = 'sepolia') {
|
|
95
|
-
const base = network === 'mainnet'
|
|
96
|
-
? 'https://blobs.eigenda.xyz/blobs'
|
|
97
|
-
: 'https://blobs-sepolia.eigenda.xyz/blobs';
|
|
98
|
-
return `${base}/${commitment}`;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Health check — ping the proxy.
|
|
103
|
-
* @returns {Promise<boolean>}
|
|
104
|
-
*/
|
|
105
|
-
async healthCheck() {
|
|
106
|
-
try {
|
|
107
|
-
const response = await this.client.get('/health', {
|
|
108
|
-
validateStatus: () => true,
|
|
109
|
-
timeout: 5000,
|
|
110
|
-
});
|
|
111
|
-
return response.status === 200 || response.status === 404;
|
|
112
|
-
} catch {
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
_formatError(error) {
|
|
118
|
-
if (axios.isAxiosError(error) && error.response) {
|
|
119
|
-
return `HTTP ${error.response.status}: ${typeof error.response.data === 'string'
|
|
120
|
-
? error.response.data
|
|
121
|
-
: JSON.stringify(error.response.data)
|
|
122
|
-
}`;
|
|
123
|
-
}
|
|
124
|
-
return error.message || String(error);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
module.exports = EigenDA;
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: eigen-delegation
|
|
3
|
-
description: "Query EigenLayer delegation data — delegation events, operator delegations, staker positions, operator-sets, and top delegated operators"
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
metadata:
|
|
6
|
-
emoji: "🤝"
|
|
7
|
-
tags: ["eigenlayer", "delegation", "operators", "stakers", "operator-sets"]
|
|
8
|
-
user-invocable: true
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# EigenLayer Delegation Skill
|
|
12
|
-
|
|
13
|
-
Query live delegation data from EigenLayer: delegation/undelegation events, operator delegation profiles, staker delegation positions, operator-sets, and find the most delegated operators.
|
|
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
|
-
- Who is delegating to whom
|
|
24
|
-
- Delegation/undelegation events
|
|
25
|
-
- Top operators by delegation (most stakers, most TVL)
|
|
26
|
-
- A specific staker's delegation position
|
|
27
|
-
- Which operator a staker is delegated to
|
|
28
|
-
- Operator-sets
|
|
29
|
-
- Withdrawal queue or pending undelegations
|
|
30
|
-
|
|
31
|
-
## How to query
|
|
32
|
-
|
|
33
|
-
### Get top operators by total stakers (most delegated)
|
|
34
|
-
```bash
|
|
35
|
-
curl -s "https://api.eigenexplorer.com/operators?withTvl=true&sortByTotalStakers=desc&take=10" -H "x-api-token: $EIGEN_API_KEY"
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Get top operators by TVL (most capital delegated)
|
|
39
|
-
```bash
|
|
40
|
-
curl -s "https://api.eigenexplorer.com/operators?withTvl=true&sortByTvl=desc&take=10" -H "x-api-token: $EIGEN_API_KEY"
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### Get a specific operator's delegation profile
|
|
44
|
-
```bash
|
|
45
|
-
curl -s "https://api.eigenexplorer.com/operators/0xOPERATOR_ADDRESS?withTvl=true" -H "x-api-token: $EIGEN_API_KEY"
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Get stakers delegating to an operator
|
|
49
|
-
```bash
|
|
50
|
-
curl -s "https://api.eigenexplorer.com/operators/0xOPERATOR_ADDRESS/stakers?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Get which operator a staker has delegated to
|
|
54
|
-
```bash
|
|
55
|
-
curl -s "https://api.eigenexplorer.com/stakers/0xSTAKER_ADDRESS" -H "x-api-token: $EIGEN_API_KEY"
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Get staker withdrawals (undelegations)
|
|
59
|
-
```bash
|
|
60
|
-
curl -s "https://api.eigenexplorer.com/stakers/0xSTAKER_ADDRESS/withdrawals?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Get delegation events
|
|
64
|
-
```bash
|
|
65
|
-
curl -s "https://api.eigenexplorer.com/events?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Get all operator-sets
|
|
69
|
-
```bash
|
|
70
|
-
curl -s "https://api.eigenexplorer.com/operator-sets?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Get operator-sets for a specific AVS
|
|
74
|
-
```bash
|
|
75
|
-
curl -s "https://api.eigenexplorer.com/avs/0xAVS_ADDRESS/operator-sets?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## Response Format
|
|
79
|
-
|
|
80
|
-
Format results for the user with:
|
|
81
|
-
- **Bold operator names** and abbreviated addresses
|
|
82
|
-
- Total stakers count
|
|
83
|
-
- TVL in human-readable form
|
|
84
|
-
- Shares breakdown by strategy where relevant
|
|
85
|
-
- Active vs inactive AVS registrations
|
|
86
|
-
- Use bullet points, never tables in chat
|
|
87
|
-
|
|
88
|
-
## Programmatic Usage
|
|
89
|
-
|
|
90
|
-
```javascript
|
|
91
|
-
const DelegationAPI = require('eigen-agent-skills/skills/eigen-delegation/scripts/delegation-api');
|
|
92
|
-
const api = new DelegationAPI('YOUR_API_KEY');
|
|
93
|
-
|
|
94
|
-
const topDelegated = await api.getTopDelegatedOperators(10);
|
|
95
|
-
const topByTVL = await api.getTopOperatorsByTVL(10);
|
|
96
|
-
const opProfile = await api.getOperatorDelegation('0x...');
|
|
97
|
-
const stakerPos = await api.getStakerDelegation('0x...');
|
|
98
|
-
```
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* EigenLayer Delegation API Client
|
|
3
|
-
*
|
|
4
|
-
* Data source: EigenExplorer REST API
|
|
5
|
-
* Covers: delegation events, operator-sets, staker ↔ operator delegation tracking
|
|
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 DelegationAPI {
|
|
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
|
-
// ─── Delegation Events ────────────────────────────────
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Get recent delegation/undelegation events across the protocol.
|
|
30
|
-
* @param {object} opts
|
|
31
|
-
* @param {string} [opts.type] - 'DELEGATION' | 'UNDELEGATION'
|
|
32
|
-
* @param {number} [opts.skip=0]
|
|
33
|
-
* @param {number} [opts.take=12]
|
|
34
|
-
*/
|
|
35
|
-
async getDelegationEvents(opts = {}) {
|
|
36
|
-
const params = {
|
|
37
|
-
skip: opts.skip || 0,
|
|
38
|
-
take: opts.take || 12,
|
|
39
|
-
};
|
|
40
|
-
if (opts.type) params.type = opts.type;
|
|
41
|
-
|
|
42
|
-
const { data } = await this.client.get('/events/delegation', { params });
|
|
43
|
-
return data;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// ─── Operator Delegation Details ──────────────────────
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Get an operator's full delegation profile (stakers, shares, strategies, TVL).
|
|
50
|
-
* @param {string} operatorAddress
|
|
51
|
-
*/
|
|
52
|
-
async getOperatorDelegation(operatorAddress) {
|
|
53
|
-
const { data } = await this.client.get(`/operators/${operatorAddress}`, {
|
|
54
|
-
params: { withTvl: 'true' },
|
|
55
|
-
});
|
|
56
|
-
return {
|
|
57
|
-
address: data.address,
|
|
58
|
-
name: data.metadataName,
|
|
59
|
-
totalStakers: data.totalStakers,
|
|
60
|
-
totalAvs: data.totalAvs,
|
|
61
|
-
shares: data.shares,
|
|
62
|
-
tvl: data.tvl,
|
|
63
|
-
avsRegistrations: data.avsRegistrations,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// ─── Top Delegated Operators ──────────────────────────
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Get operators sorted by total stakers (most delegated first).
|
|
71
|
-
* @param {number} [limit=10]
|
|
72
|
-
*/
|
|
73
|
-
async getTopDelegatedOperators(limit = 10) {
|
|
74
|
-
const { data } = await this.client.get('/operators', {
|
|
75
|
-
params: {
|
|
76
|
-
withTvl: 'true',
|
|
77
|
-
sortByTotalStakers: 'desc',
|
|
78
|
-
take: limit,
|
|
79
|
-
skip: 0,
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
return data;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Get operators sorted by TVL (most capital delegated first).
|
|
87
|
-
* @param {number} [limit=10]
|
|
88
|
-
*/
|
|
89
|
-
async getTopOperatorsByTVL(limit = 10) {
|
|
90
|
-
const { data } = await this.client.get('/operators', {
|
|
91
|
-
params: {
|
|
92
|
-
withTvl: 'true',
|
|
93
|
-
sortByTvl: 'desc',
|
|
94
|
-
take: limit,
|
|
95
|
-
skip: 0,
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
return data;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
module.exports = DelegationAPI;
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: eigen-restaking
|
|
3
|
-
description: "Query EigenLayer restaking data — operators, stakers, TVL, deposits, withdrawals, and ecosystem metrics via EigenExplorer API"
|
|
4
|
-
version: 1.0.0
|
|
5
|
-
metadata:
|
|
6
|
-
emoji: "🔄"
|
|
7
|
-
tags: ["eigenlayer", "restaking", "operators", "tvl", "stakers"]
|
|
8
|
-
user-invocable: true
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# EigenLayer Restaking Skill
|
|
12
|
-
|
|
13
|
-
Query live EigenLayer restaking data: operators, stakers, TVL, deposits, withdrawals, and ecosystem metrics.
|
|
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
|
-
- Holesky testnet: `https://api-holesky.eigenexplorer.com`
|
|
20
|
-
|
|
21
|
-
## When to use this skill
|
|
22
|
-
|
|
23
|
-
Use when the user asks about:
|
|
24
|
-
- EigenLayer operators (who they are, how much TVL, how many stakers)
|
|
25
|
-
- Restaking stats or metrics (total TVL, total stakers, total operators)
|
|
26
|
-
- Individual staker positions (deposits, withdrawals, delegations)
|
|
27
|
-
- Historical EigenLayer metrics
|
|
28
|
-
- EigenLayer ecosystem overview
|
|
29
|
-
|
|
30
|
-
## How to query
|
|
31
|
-
|
|
32
|
-
Use the `exec` tool to curl the EigenExplorer API. **Always include your API key.**
|
|
33
|
-
|
|
34
|
-
### Get ecosystem metrics
|
|
35
|
-
```bash
|
|
36
|
-
curl -s "https://api.eigenexplorer.com/metrics" -H "x-api-token: $EIGEN_API_KEY"
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Get top operators by TVL
|
|
40
|
-
```bash
|
|
41
|
-
curl -s "https://api.eigenexplorer.com/operators?withTvl=true&sortByTvl=desc&take=10" -H "x-api-token: $EIGEN_API_KEY"
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Search operators by name
|
|
45
|
-
```bash
|
|
46
|
-
curl -s "https://api.eigenexplorer.com/operators?searchByText=p2p&withTvl=true" -H "x-api-token: $EIGEN_API_KEY"
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### Get a specific operator
|
|
50
|
-
```bash
|
|
51
|
-
curl -s "https://api.eigenexplorer.com/operators/0x09e6eb09213bdd3698bd8afb43ec3cb0ecff683a?withTvl=true" -H "x-api-token: $EIGEN_API_KEY"
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### Get staker info
|
|
55
|
-
```bash
|
|
56
|
-
curl -s "https://api.eigenexplorer.com/stakers/0xYOUR_STAKER_ADDRESS" -H "x-api-token: $EIGEN_API_KEY"
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Get recent deposits
|
|
60
|
-
```bash
|
|
61
|
-
curl -s "https://api.eigenexplorer.com/deposits?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Get recent withdrawals
|
|
65
|
-
```bash
|
|
66
|
-
curl -s "https://api.eigenexplorer.com/withdrawals?take=20" -H "x-api-token: $EIGEN_API_KEY"
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### Get historical metrics
|
|
70
|
-
```bash
|
|
71
|
-
curl -s "https://api.eigenexplorer.com/metrics/historical" -H "x-api-token: $EIGEN_API_KEY"
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Response Format
|
|
75
|
-
|
|
76
|
-
Format results for the user with:
|
|
77
|
-
- **Bold operator names** and addresses (abbreviated)
|
|
78
|
-
- TVL in human-readable form (e.g., "$1.2B" not "1200000000")
|
|
79
|
-
- Staker counts
|
|
80
|
-
- APY where available
|
|
81
|
-
- Use bullet points, never tables in chat
|
|
82
|
-
|
|
83
|
-
## Programmatic Usage
|
|
84
|
-
|
|
85
|
-
```javascript
|
|
86
|
-
const EigenAPI = require('eigen-agent-skills/skills/eigen-restaking/scripts/eigen-api');
|
|
87
|
-
const api = new EigenAPI('YOUR_API_KEY');
|
|
88
|
-
|
|
89
|
-
const metrics = await api.getMetrics();
|
|
90
|
-
const topOps = await api.getOperators({ sortByTvl: 'desc', take: 10 });
|
|
91
|
-
const operator = await api.getOperator('0x...');
|
|
92
|
-
```
|
|
@@ -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;
|