@layr-labs/hourglass-performer
Version:
TypeScript SDK for building Hourglass AVS performers
622 lines (455 loc) • 11.7 kB
Markdown
# Hourglass TypeScript Performer SDK
Build EigenLayer AVS performers in TypeScript with minimal setup and maximum type safety.
## 🚀 Quick Start
### 1. Create a New Performer
```bash
# Create a new performer project
npx @hourglass/create-performer my-avs
# Navigate to the project
cd my-avs
# Install dependencies
npm install
# Start development server
npm run dev
```
### 2. Basic Performer
```typescript
// performer.ts
import { BaseWorker } from '@hourglass/performer';
class MyBasicPerformer extends BaseWorker {
async handleSimpleTask(input: any) {
// Your AVS logic here
return input * input; // Example: square the input
}
}
// One-line server startup
new MyBasicPerformer().start();
```
### 3. Solidity Contract Integration
```typescript
// performer.ts
import { SolidityWorker } from '@hourglass/performer';
class MySolidityPerformer extends SolidityWorker<any, 'processTask'> {
async handleSolidityTask(params: { amount: bigint; user: string }) {
// Fully typed based on your contract ABI
const result = params.amount * 2n;
return { result };
}
}
new MySolidityPerformer().start();
```
### 4. Deploy with Docker
```bash
# Build your performer
npm run build
# Build Docker image
npm run docker:build
# Run container
npm run docker:run
```
## 📋 Table of Contents
- [Installation](#installation)
- [Core Concepts](#core-concepts)
- [API Reference](#api-reference)
- [TypeChain Integration](#typechain-integration)
- [Environment Configuration](#environment-configuration)
- [Docker Deployment](#docker-deployment)
- [Examples](#examples)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
## 📦 Installation
### Using the CLI (Recommended)
```bash
# Create a new project with interactive setup
npx @hourglass/create-performer my-avs
# Options:
# - Basic performer (no contracts)
# - Solidity performer (TypeChain integration)
# - Advanced performer (monitoring + TypeChain)
```
### Manual Installation
```bash
npm install @hourglass/performer
```
## 🔧 Core Concepts
### Worker Types
#### BaseWorker
For simple task processing without contract interaction:
```typescript
import { BaseWorker } from '@hourglass/performer';
class SimpleWorker extends BaseWorker {
async handleSimpleTask(input: any) {
// Process input and return result
return processInput(input);
}
}
```
#### SolidityWorker
For type-safe Solidity contract interaction:
```typescript
import { SolidityWorker } from '@hourglass/performer';
class ContractWorker extends SolidityWorker<MyContract, 'processTask'> {
async handleSolidityTask(params: ProcessTaskParams) {
// Fully typed parameters from your contract
return { result: params.amount * 2n };
}
}
```
### Server Architecture
The SDK provides a complete gRPC server implementation:
- **Automatic Configuration**: No manual gRPC setup required
- **Health Checks**: Built-in health monitoring
- **Metrics Collection**: Performance monitoring
- **Graceful Shutdown**: Clean shutdown handling
- **Error Handling**: Comprehensive error management
## 📚 API Reference
### BaseWorker
#### Methods
##### `handleSimpleTask(input: any): Promise<any>`
Override this method to implement your task processing logic.
```typescript
class MyWorker extends BaseWorker {
async handleSimpleTask(input: any) {
// Your processing logic
return result;
}
}
```
##### `start(port?: number): Promise<void>`
Start the performer server.
```typescript
const worker = new MyWorker();
await worker.start(8080); // Optional port override
```
##### `validateTask(task: TaskRequest): Promise<void>`
Custom task validation (optional override).
```typescript
class MyWorker extends BaseWorker {
async validateTask(task: TaskRequest) {
await super.validateTask(task);
// Additional validation logic
}
}
```
### SolidityWorker
#### Constructor Options
```typescript
interface SolidityWorkerConfig {
abi: any[]; // Contract ABI
functionName: string; // Function to handle
autoDetectPayload?: boolean; // Auto-detect payload format
strictMode?: boolean; // Strict validation mode
}
```
#### Methods
##### `handleSolidityTask(params: T): Promise<R>`
Type-safe contract function handling.
```typescript
class ContractWorker extends SolidityWorker<MyContract, 'processTask'> {
async handleSolidityTask(params: ProcessTaskParams): Promise<ProcessTaskReturn> {
// Fully typed based on contract ABI
return { result: params.amount * 2n };
}
}
```
### PerformerServer
#### Configuration
```typescript
interface PerformerServerConfig {
port?: number; // Server port (default: 8080)
timeout?: number; // Request timeout (default: 10000ms)
debug?: boolean; // Debug mode (default: false)
}
```
#### Advanced Usage
```typescript
import { PerformerServer } from '@hourglass/performer';
const server = new PerformerServer(worker, {
port: 8080,
timeout: 15000,
debug: true,
});
await server.start();
```
## 🔗 TypeChain Integration
### Setup
1. **Install TypeChain** (included in scaffolded projects):
```bash
npm install --save-dev typechain @typechain/ethers-v6
```
2. **Add contract ABIs** to `./contracts/`:
```bash
cp MyContract.json contracts/
```
3. **Generate TypeScript types**:
```bash
npm run typechain
```
### Usage
```typescript
// Import generated types
import type { MyContract } from './typechain-types';
// Use with SolidityWorker
class TypedWorker extends SolidityWorker<MyContract, 'processTask'> {
async handleSolidityTask(params: ProcessTaskParams): Promise<ProcessTaskReturn> {
// Full IntelliSense and type safety
const { taskId, amount, user } = params;
// Type-safe return
return {
result: amount * 2n,
success: true,
};
}
}
```
### Configuration
```typescript
// typechain.config.json
{
"files": ["contracts/**/*.json"],
"target": "ethers-v6",
"outDir": "typechain-types"
}
```
## ⚙️ Environment Configuration
### Environment Variables
```bash
# Server configuration
PORT=8080
HOST=0.0.0.0
TIMEOUT=10000
# Application configuration
NODE_ENV=production
DEBUG=false
LOG_LEVEL=info
# Performance
MAX_CONCURRENT_TASKS=10
TASK_TIMEOUT=30000
# TypeChain
TYPECHAIN_ENABLED=true
CONTRACTS_PATH=./contracts
# Security
CORS_ENABLED=true
CORS_ORIGINS=https://yourdomain.com
```
### Configuration Loading
```typescript
import { loadEnvironmentConfig } from '@hourglass/performer';
const config = loadEnvironmentConfig();
console.log(`Server will run on port ${config.port}`);
```
### Environment Files
```bash
# Development
.env.development
# Production
.env.production
# Local development
.env.local
```
## 🐳 Docker Deployment
### Basic Deployment
```dockerfile
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
RUN npm ci --only=production
# Copy built application
COPY dist/ ./dist/
# Run performer
CMD ["node", "dist/performer.js"]
```
### Docker Compose
```yaml
version: '3.8'
services:
performer:
build: .
ports:
- "8080:8080"
environment:
- NODE_ENV=production
- LOG_LEVEL=info
volumes:
- ./contracts:/app/contracts
restart: unless-stopped
```
### Build and Run
```bash
# Build
npm run docker:build
# Run
npm run docker:run
# Development with Docker Compose
npm run docker:dev
```
## 🎯 Examples
### Basic Number Processing
```typescript
import { BaseWorker } from '@hourglass/performer';
class NumberProcessor extends BaseWorker {
async handleSimpleTask(input: number) {
return {
original: input,
squared: input * input,
doubled: input * 2,
timestamp: Date.now(),
};
}
}
new NumberProcessor().start();
```
### ERC-20 Token Processing
```typescript
import { SolidityWorker } from '@hourglass/performer';
import type { ERC20 } from './typechain-types';
class TokenProcessor extends SolidityWorker<ERC20, 'transfer'> {
async handleSolidityTask(params: { to: string; amount: bigint }) {
const { to, amount } = params;
// Validate transfer
if (amount <= 0n) {
throw new Error('Invalid amount');
}
// Process transfer logic
return {
success: true,
txHash: '0x...',
};
}
}
new TokenProcessor().start();
```
### Data Aggregation
```typescript
import { BaseWorker } from '@hourglass/performer';
class DataAggregator extends BaseWorker {
async handleSimpleTask(data: { values: number[] }) {
const { values } = data;
return {
sum: values.reduce((a, b) => a + b, 0),
avg: values.reduce((a, b) => a + b, 0) / values.length,
min: Math.min(...values),
max: Math.max(...values),
count: values.length,
};
}
}
new DataAggregator().start();
```
## 🔍 Troubleshooting
### Common Issues
#### Port Already in Use
```bash
# Check what's using the port
lsof -i :8080
# Use a different port
PORT=8081 npm run dev
```
#### TypeChain Generation Fails
```bash
# Ensure contract ABIs are valid JSON
npm run typechain -- --show-stack-traces
```
#### Container Won't Start
```bash
# Check container logs
docker logs <container-id>
# Run in interactive mode
docker run -it my-performer sh
```
### Debug Mode
Enable debug logging:
```bash
DEBUG=true LOG_LEVEL=debug npm run dev
```
### Health Check
```bash
# Check performer health
curl http://localhost:8080/health
# Expected response
{
"status": "READY_FOR_TASK"
}
```
## 📊 Monitoring
### Built-in Metrics
The SDK includes comprehensive monitoring:
- **Task Metrics**: Execution time, success/failure rates
- **Health Monitoring**: System health checks
- **Performance Tracking**: Memory usage, request counts
- **Error Tracking**: Error rates and patterns
### Accessing Metrics
```bash
# Metrics endpoint (if enabled)
curl http://localhost:9090/metrics
# Health status
curl http://localhost:8080/health
```
## 🔄 Development Workflow
### Local Development
```bash
# Start development server with hot reload
npm run dev
# Run tests
npm test
# Type checking
npm run build
# Lint code
npm run lint
```
### Testing
```bash
# Unit tests
npm test
# Watch mode
npm run test:watch
# Coverage
npm run test:coverage
```
### Production Build
```bash
# Build for production
npm run build
# Start production server
npm start
```
## 🤝 Contributing
### Development Setup
```bash
# Clone repository
git clone https://github.com/Layr-Labs/hourglass-monorepo
# Navigate to TypeScript SDK
cd sdk/typescript
# Install dependencies
npm install
# Build the project
npm run build
# Run tests
npm test
```
### Code Style
- Use TypeScript strict mode
- Follow ESLint configuration
- Write tests for new features
- Document public APIs
### Pull Request Process
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests and documentation
5. Submit a pull request
## 📝 License
MIT License - see [LICENSE](LICENSE) for details.
## 🔗 Resources
- **Documentation**: [https://docs.hourglass.io](https://docs.hourglass.io)
- **Examples**: [https://github.com/Layr-Labs/hourglass-examples](https://github.com/Layr-Labs/hourglass-examples)
- **Discord**: [https://discord.gg/hourglass](https://discord.gg/hourglass)
- **GitHub**: [https://github.com/Layr-Labs/hourglass-monorepo](https://github.com/Layr-Labs/hourglass-monorepo)
## 📈 Version History
- **v0.1.0**: Initial release with basic performer support
- **v0.2.0**: Added TypeChain integration
- **v0.3.0**: Docker deployment support
- **v1.0.0**: Stable release with full feature set
---
Built with ❤️ by the Hourglass team for the EigenLayer ecosystem.