eigen-skills 1.1.2 → 1.1.4
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/.env +5 -0
- package/index.js +3 -15
- package/package.json +5 -3
- package/skills/eigen-compute/SKILL.md +65 -1
- 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/.env
ADDED
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.4",
|
|
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
|
}
|
|
@@ -63,6 +63,7 @@ ecloud compute app create --name my-app --language typescript
|
|
|
63
63
|
|
|
64
64
|
### Deploy from Dockerfile (recommended)
|
|
65
65
|
|
|
66
|
+
**Interactive deploy:**
|
|
66
67
|
```bash
|
|
67
68
|
ecloud compute app deploy
|
|
68
69
|
```
|
|
@@ -70,8 +71,46 @@ ecloud compute app deploy
|
|
|
70
71
|
- Choose **Linux/AMD64** (standard TEE architecture)
|
|
71
72
|
- Estimated cost: ~0.008 ETH per deploy (Sepolia testnet)
|
|
72
73
|
|
|
74
|
+
**Non-interactive deploy (for scripting / CI):**
|
|
75
|
+
```bash
|
|
76
|
+
ecloud compute app deploy \
|
|
77
|
+
--name my-app \
|
|
78
|
+
--skip-profile \
|
|
79
|
+
--image-ref my-app:latest \
|
|
80
|
+
--build-caddyfile
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
| Flag | Purpose |
|
|
84
|
+
|------|---------|
|
|
85
|
+
| `--name <name>` | App name (skips interactive prompt) |
|
|
86
|
+
| `--skip-profile` | Skip machine profile selection (uses default) |
|
|
87
|
+
| `--image-ref <ref>` | Docker image reference tag |
|
|
88
|
+
| `--build-caddyfile` | **Auto-inject Caddy + TLS** — the CLI reads your `Caddyfile`, installs Caddy into the image, and wires up TLS certs automatically. You do NOT need to install Caddy in your Dockerfile or reference TLS cert paths. |
|
|
89
|
+
|
|
73
90
|
**IMPORTANT:** "Deploy from registry" method is unreliable — apps often end up in `Status: Unknown` with no error. Always use "Build from Dockerfile".
|
|
74
91
|
|
|
92
|
+
### TLS with `--build-caddyfile` (recommended)
|
|
93
|
+
|
|
94
|
+
When you pass `--build-caddyfile`, the ecloud CLI handles all TLS setup. Your project only needs a minimal `Caddyfile` that reverse-proxies to your app:
|
|
95
|
+
|
|
96
|
+
```caddyfile
|
|
97
|
+
:80 {
|
|
98
|
+
reverse_proxy 127.0.0.1:3000
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The CLI automatically:
|
|
103
|
+
- Installs Caddy into the Docker image
|
|
104
|
+
- Mounts TLS certs from the TEE's `/run/tls/` directory
|
|
105
|
+
- Sources sealed env vars via `compute-source-env.sh`
|
|
106
|
+
- Configures HTTPS on the deployed domain
|
|
107
|
+
|
|
108
|
+
**You do NOT need to:**
|
|
109
|
+
- Add `RUN apk add caddy` (or equivalent) in your Dockerfile
|
|
110
|
+
- Reference `/run/tls/fullchain.pem` or `/run/tls/privkey.pem` in your Caddyfile
|
|
111
|
+
- Source `compute-source-env.sh` manually in your entrypoint
|
|
112
|
+
- Expose ports 80 or 443 — only expose your app port (e.g., 3000)
|
|
113
|
+
|
|
75
114
|
### Check app status
|
|
76
115
|
|
|
77
116
|
```bash
|
|
@@ -125,6 +164,16 @@ Inside the TEE container, these are available:
|
|
|
125
164
|
|
|
126
165
|
### Entrypoint pattern for TEE
|
|
127
166
|
|
|
167
|
+
**With `--build-caddyfile` (recommended)** — no manual env sourcing needed:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
#!/bin/sh
|
|
171
|
+
set -e
|
|
172
|
+
node server.js
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Without `--build-caddyfile`** — you must source sealed secrets manually:
|
|
176
|
+
|
|
128
177
|
```bash
|
|
129
178
|
#!/bin/bash
|
|
130
179
|
# Source sealed secrets
|
|
@@ -138,13 +187,28 @@ node server.js
|
|
|
138
187
|
|
|
139
188
|
### Dockerfile pattern for TEE
|
|
140
189
|
|
|
190
|
+
**With `--build-caddyfile` (recommended)** — minimal Dockerfile, only expose your app port:
|
|
191
|
+
|
|
141
192
|
```dockerfile
|
|
142
|
-
FROM node:20-slim
|
|
193
|
+
FROM --platform=linux/amd64 node:20-slim
|
|
143
194
|
WORKDIR /app
|
|
144
195
|
COPY package*.json ./
|
|
145
196
|
RUN npm ci --production
|
|
146
197
|
COPY . .
|
|
147
198
|
EXPOSE 3000
|
|
199
|
+
CMD ["./start.sh"]
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Without `--build-caddyfile`** — you must install Caddy and expose TLS ports yourself:
|
|
203
|
+
|
|
204
|
+
```dockerfile
|
|
205
|
+
FROM --platform=linux/amd64 node:20-slim
|
|
206
|
+
WORKDIR /app
|
|
207
|
+
RUN apt-get update && apt-get install -y caddy
|
|
208
|
+
COPY package*.json ./
|
|
209
|
+
RUN npm ci --production
|
|
210
|
+
COPY . .
|
|
211
|
+
EXPOSE 80 443 3000
|
|
148
212
|
ENTRYPOINT ["bash", "entrypoint.sh"]
|
|
149
213
|
```
|
|
150
214
|
|
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
|
-
```
|