Overview
The Batcher is a production-ready service for aggregating and batching user transactions across multiple blockchains. It provides a unified HTTP API for submitting inputs while abstracting away blockchain-specific complexity through a pluggable adapter system.
Quick Start
Get started quickly with these essential guides:
- Introduction - Overview and architecture
- Core Concepts - Understanding the building blocks
- Configuration - Setting up your batcher
- The Batching Pipeline - How inputs flow through the system
Key Features
🔗 Multi-Chain Support
Batch transactions for multiple blockchains simultaneously. Each blockchain gets its own adapter with independent batching rules and configuration.
🔄 Flexible Batching Strategies
Configure when batches are submitted using time-based, size-based, value-based, hybrid, or custom criteria—independently per blockchain.
💾 Crash-Safe Storage
All inputs are persisted immediately to storage (file, PostgreSQL, Redis, or custom). No in-memory queues that can be lost on restart.
🔌 Pluggable Architecture
- Adapters: Add support for new blockchains by implementing the
BlockchainAdapterinterface - Storage: Use any backend by implementing the
BatcherStorageinterface - Criteria: Define custom batching logic with user-defined functions
📊 Production-Ready
- RESTful HTTP API with OpenAPI documentation
- Event system for monitoring and observability
- Graceful shutdown with configurable hooks
- Structured concurrency using Effection
Architecture Overview
┌─────────────┐
│ HTTP Client │
└──────┬──────┘
│ POST /send-input
▼
┌──────────────────────────────────┐
│ Batcher Core │
│ - Validation │
│ - Storage Persistence │
│ - Batching Criteria Check │
└────────┬─────────────────────────┘
│
┌────┴─────┬──────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│EVM │ │Midnight│ │Custom │
│Adapter │ │Adapter │ │Adapter │
└───┬────┘ └───┬────┘ └───┬────┘
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│Ethereum│ │Midnight│ │Custom │
│Chain │ │Network │ │Chain │
└────────┘ └────────┘ └────────┘
Documentation Structure
Getting Started
- Introduction - What is the Batcher and why use it?
- Core Concepts - Key abstractions:
Batcher,BlockchainAdapter,Target,DefaultBatcherInput
Configuration & Setup
- Configuration - Complete setup guide with dynamic and unified configuration approaches
- The Batching Pipeline - Understanding the input lifecycle from submission to confirmation
Customization
- Custom Adapters - Implementing
BlockchainAdapterfor new blockchains - Advanced Topics - HTTP API, batching criteria, event system, storage backends, and Effection integration
Common Use Cases
Multi-Chain Gaming
Batch player actions across multiple chains with different batching rules per chain.
batcher
.addBlockchainAdapter("ethereum", ethAdapter, {
criteriaType: "hybrid",
timeWindowMs: 5000, // 5 seconds max wait
maxBatchSize: 50 // or 50 moves
})
.addBlockchainAdapter("polygon", polygonAdapter, {
criteriaType: "time",
timeWindowMs: 1000 // Submit every second (cheaper gas)
});
Financial Applications
Batch payments when accumulated value reaches a threshold.
batcher.addBlockchainAdapter("payments", paymentsAdapter, {
criteriaType: "value",
valueAccumulatorFn: (input) => input.amount,
targetValue: 100000 // Batch when $1000 accumulated
});
NFT Minting
Process mints in batches based on queue size.
batcher.addBlockchainAdapter("nft", nftAdapter, {
criteriaType: "size",
maxBatchSize: 20 // Mint 20 NFTs per batch
});
Example: Complete Setup
import { main, suspend } from "effection";
import { PaimaBatcher, FileStorage, PaimaL2DefaultAdapter } from "@effectstream/batcher";
// 1. Create adapter
const adapter = new PaimaL2DefaultAdapter(
"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", // Contract address
process.env.PRIVATE_KEY!, // Private key
0n, // Fee
"mainEvmRPC" // Sync protocol name
);
// 2. Create batcher
const batcher = new PaimaBatcher({
pollingIntervalMs: 1000,
port: 3334,
enableHttpServer: true,
enableEventSystem: true,
adapters: {} // Start empty, add dynamically
}, new FileStorage("./batcher-data"));
// 3. Wire adapter with criteria
batcher.addBlockchainAdapter("ethereum", adapter, {
criteriaType: "hybrid",
timeWindowMs: 5000,
maxBatchSize: 50
}).setDefaultTarget("ethereum");
// 4. Add monitoring
batcher.addStateTransition("startup", ({ publicConfig }) => {
console.log(`🚀 Batcher started on port ${publicConfig.port}`);
});
batcher.addStateTransition("batch:submit", ({ txHash }) => {
console.log(`🚀 Batch submitted: ${txHash}`);
});
// 5. Run with Effection
main(function* () {
yield* batcher.runBatcher();
yield* suspend();
});
API Endpoints
Once running, the batcher exposes these HTTP endpoints:
POST /send-input- Submit a new inputGET /status- Batcher status and configurationGET /queue-stats- Queue statistics per targetGET /health- Health checkPOST /force-batch- Manually trigger batching (dev)GET /documentation- Interactive OpenAPI docs
See HTTP API for complete documentation.
Next Steps
Choose your path:
I'm new to the batcher:
- Read Introduction
- Understand Core Concepts
- Follow Configuration Guide
I want to customize:
- Learn The Batching Pipeline
- Implement Custom Adapters
- Explore Advanced Topics
I'm ready to deploy:
- Review Configuration
- Set up Event System for monitoring
- Configure Storage for production