Backend service để quản lý Hydra Head trên Cardano blockchain.
Hydra Hexcore là một NestJS backend service giúp:
- Quản lý Cardano accounts (wallets)
- Tạo và quản lý Hydra Parties
- Khởi động/dừng Hydra Node containers
- Tương tác với Hydra Head (init, commit, close...)
┌─────────────────────────────────────────────────────────────────┐
│ HYDRA HEXCORE SYSTEM │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Client │ │ Admin │ │ Consumer │ │
│ │ (curl) │ │ (UI) │ │ (dApp) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┬┴─────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────┐ │
│ │ Hydra Hexcore API │ │
│ │ (Port 3010) │ │
│ └────────────────┬───────────────────┘ │
│ │ │
│ ┌────────────────┼────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ MySQL │ │ Ogmios │ │ Docker │ │
│ │ (Database) │ │ (Query) │ │ Engine │ │
│ └─────────────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Cardano │ │ Hydra │ │
│ │ Node │ │ Nodes │ │
│ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
| Component | Port | Vai trò |
|---|---|---|
| Hydra Hexcore | 3010 | API Server chính |
| MySQL | 3306 | Lưu accounts, parties, nodes |
| Redis | 6379 | Cache |
| Cardano Node | 8091 | Sync blockchain |
| Ogmios | 1337 | Query blockchain API |
| Hydra Node(s) | 10005+ | Layer 2 nodes |
┌─────────────────────────────────────────────────────────────────┐
│ DATA FLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ configs/cardano/ │
│ ├── config.json ──────┐ │
│ ├── topology.json │ │
│ └── *-genesis.json ▼ │
│ ┌─────────────┐ │
│ │ Cardano │ │
│ │ Node │ │
│ └──────┬──────┘ │
│ │ socket │
│ ▼ │
│ ┌─────────────┐ │
│ │ Ogmios │ │
│ └──────┬──────┘ │
│ │ HTTP │
│ ▼ │
│ hydra-data/ ┌─────────────┐ ┌─────────────┐ │
│ └── preprod/ │ Hexcore │◄────►│ MySQL │ │
│ └── party-X/ ◄─────│ API │ └─────────────┘ │
│ ├── *.sk └──────┬──────┘ │
│ └── *.vk │ Docker API │
│ ▼ │
│ ┌─────────────┐ │
│ │ Hydra Node │ │
│ │ Containers │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ SETUP FLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Step 1: Start Docker Stack │
│ ──────────────────────── │
│ $ docker compose -f docker-compose.local.yml up -d │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ MySQL │ │ Redis │ │ Cardano │ │ Ogmios │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └────────────┴─────┬──────┴────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Hexcore │ │
│ └──────────┘ │
│ │
│ Step 2: Wait for Cardano Node Sync (3-8 hours) │
│ ────────────────────────────────────────────── │
│ $ curl http://localhost:1337/health | jq '.networkSync' │
│ → Wait until = 1.0 (100%) │
│ │
│ Step 3: Create Admin & Login │
│ ──────────────────────────── │
│ $ POST /hydra-main/login → Get JWT Token │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ HYDRA HEAD LIFECYCLE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ │
│ │ IDLE │ ← Initial state │
│ └────┬────┘ │
│ │ create-account │
│ ▼ │
│ ┌─────────┐ │
│ │ ACCOUNT │ ← Wallet created │
│ │ CREATED │ │
│ └────┬────┘ │
│ │ create-party │
│ ▼ │
│ ┌─────────┐ │
│ │ PARTY │ ← Keys generated │
│ │ CREATED │ │
│ └────┬────┘ │
│ │ active-party │
│ ▼ │
│ ┌─────────┐ │
│ │ HYDRA │ ← Container running │
│ │ ACTIVE │ │
│ └────┬────┘ │
│ │ Init (WebSocket) │
│ ▼ │
│ ┌─────────┐ │
│ │ HEAD │ ← On-chain tx submitted │
│ │ INIT │ │
│ └────┬────┘ │
│ │ Commit │
│ ▼ │
│ ┌─────────┐ │
│ │ HEAD │ ← Ready for L2 transactions │
│ │ OPEN │ (instant, free) │
│ └────┬────┘ │
│ │ Close │
│ ▼ │
│ ┌─────────┐ │
│ │ HEAD │ ← Contestation period │
│ │ CLOSED │ │
│ └────┬────┘ │
│ │ Fanout │
│ ▼ │
│ ┌─────────┐ │
│ │ HEAD │ ← Funds back to L1 │
│ │ FINAL │ │
│ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
┌────────┐ ┌─────────┐ ┌───────┐
│ Client │ │ Hexcore │ │ MySQL │
└───┬────┘ └────┬────┘ └───┬───┘
│ │ │
│ POST /create-account │
│ {mnemonic: "..."} │ │
│───────────────────►│ │
│ │ │
│ │ Generate keys │
│ │ from mnemonic │
│ │ │
│ │ INSERT account │
│ │──────────────────►│
│ │ │
│ │ OK │
│ │◄──────────────────│
│ │ │
│ {id, baseAddress} │ │
│◄───────────────────│ │
│ │ │
┌────────┐ ┌─────────┐ ┌───────┐ ┌────────────┐
│ Client │ │ Hexcore │ │ MySQL │ │ hydra-data │
└───┬────┘ └────┬────┘ └───┬───┘ └─────┬──────┘
│ │ │ │
│ POST /create-party │ │ │
│ {nodes:1, ids:[1]} │ │ │
│───────────────────►│ │ │
│ │ │ │
│ │ Generate Hydra │ │
│ │ signing keys │ │
│ │ │ │
│ │ Write keys │ │
│ │───────────────────┼───────────────►│
│ │ │ │
│ │ │ party-1/ │
│ │ │ ├── *.sk │
│ │ │ └── *.vk │
│ │ │ │
│ │ INSERT party │ │
│ │──────────────────►│ │
│ │ │ │
│ {id, status} │ │ │
│◄───────────────────│ │ │
│ │ │ │
┌────────┐ ┌─────────┐ ┌────────┐ ┌─────────────┐
│ Client │ │ Hexcore │ │ Docker │ │ Hydra Node │
└───┬────┘ └────┬────┘ └───┬────┘ └──────┬──────┘
│ │ │ │
│ POST /active-party │ │ │
│ {id: 1} │ │ │
│───────────────────►│ │ │
│ │ │ │
│ │ Create container │ │
│ │──────────────────►│ │
│ │ │ │
│ │ │ Start container │
│ │ │─────────────────►│
│ │ │ │
│ │ │ Running │
│ │◄──────────────────│◄─────────────────│
│ │ │ │
│ │ Update status │ │
│ │ = ACTIVE │ │
│ │ │ │
│ {status: ACTIVE} │ │ │
│◄───────────────────│ │ │
│ │ │ │
┌────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────┐
│ Client │ │ Hydra Node │ │ Cardano │ │ Ogmios │
│ │ │ (WS:10005) │ │ Node │ │ │
└───┬────┘ └──────┬──────┘ └──────┬──────┘ └────┬─────┘
│ │ │ │
│ WS Connect │ │ │
│─────────────────►│ │ │
│ │ │ │
│ {"tag":"Init"} │ │ │
│─────────────────►│ │ │
│ │ │ │
│ │ Submit Init Tx │ │
│ │───────────────────►│ │
│ │ │ │
│ │ Tx Confirmed │ │
│ │◄───────────────────│ │
│ │ │ │
│ HeadIsInitializing │ │
│◄─────────────────│ │ │
│ │ │ │
│ Commit UTxOs │ │ │
│─────────────────►│ │ │
│ │ │ │
│ │ Submit Commit Tx │ │
│ │───────────────────►│ │
│ │ │ │
│ HeadIsOpen │ │ │
│◄─────────────────│ │ │
│ │ │ │
│ Now: Instant L2 │ │ │
│ transactions! │ │ │
│ │ │ │
┌────────┐ ┌─────────────┐
│ Client │ │ Hydra Node │
└───┬────┘ └──────┬──────┘
│ │
│ {"tag":"NewTx", │
│ "transaction": │
│ {...}} │
│─────────────────►│
│ │
│ │ Validate & Apply
│ │ (no blockchain!)
│ │
│ TxValid │
│◄─────────────────│
│ │
│ ⚡ ~200ms │
│ 💰 0 fees │
│ │
┌────────┐ ┌─────────────┐ ┌─────────────┐
│ Client │ │ Hydra Node │ │ Cardano │
└───┬────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ {"tag":"Close"} │ │
│─────────────────►│ │
│ │ │
│ │ Submit Close Tx │
│ │───────────────────►│
│ │ │
│ HeadIsClosed │ │
│◄─────────────────│ │
│ │ │
│ ⏳ Wait contestation period (60s) │
│ │ │
│ {"tag":"Fanout"} │ │
│─────────────────►│ │
│ │ │
│ │ Submit Fanout Tx │
│ │───────────────────►│
│ │ │
│ HeadIsFinalized │ │
│◄─────────────────│ │
│ │ │
│ ✅ Funds back │ │
│ on Layer 1 │ │
│ │ │
- Docker >= 24.0
- Node.js >= 18
- pnpm
# 1. Clone & vào thư mục
cd hydra-hexcore
# 2. Tạo file .env
cp .env.example .env
# Sửa passwords trong .env
# 3. Khởi động Docker Stack
docker compose -f docker-compose.local.yml up -d --build
# 4. Chờ Cardano Node sync (3-8 giờ)
watch -n 60 'curl -s http://localhost:1337/health | jq ".networkSynchronization"'
# 5. Tạo admin user
docker exec -it hexcore-mysql mysql -u hexcore -p$MYSQL_PASSWORD hexcore -e "
INSERT INTO user (username, password, role)
VALUES ('admin', '123456', 'admin');
"
# 6. Sử dụng API
curl -X POST http://localhost:3010/hydra-main/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "123456"}'| Method | Endpoint | Mô tả |
|---|---|---|
| POST | /hydra-main/login |
Đăng nhập, lấy JWT token |
| GET | /hydra-main/auth |
Verify token |
| Method | Endpoint | Mô tả |
|---|---|---|
| POST | /hydra-main/create-account |
Tạo Cardano account từ mnemonic |
| GET | /hydra-main/list-account |
Danh sách accounts |
| Method | Endpoint | Mô tả |
|---|---|---|
| POST | /hydra-main/create-party |
Tạo Hydra party |
| GET | /hydra-main/list-party |
Danh sách parties |
| POST | /hydra-main/active-party |
Kích hoạt party (start Hydra Node) |
| Method | Endpoint | Mô tả |
|---|---|---|
| GET | http://localhost:10005/protocol-parameters |
Protocol params |
| GET | http://localhost:10005/snapshot/utxo |
UTxOs trong Head |
| WS | ws://localhost:10005 |
WebSocket commands |
{"tag":"Init"} // Khởi tạo Head
{"tag":"Abort"} // Hủy Head
{"tag":"NewTx","transaction":{...}} // Gửi transaction L2
{"tag":"Close"} // Đóng Head
{"tag":"Fanout"} // Fanout sau contestation
{"tag":"Decommit","utxoToDecommit":{...}} // Rút tiền từ Headhydra-hexcore/
├── src/ # Source code NestJS
│ ├── hydra-main/ # Module chính (API core)
│ ├── hydra-consumer/ # Module cho end-users
│ ├── auth/ # Authentication
│ └── utils/ # Utilities
│
├── configs/
│ └── cardano/ # Cardano Node configs
│
├── hydra-data/ # Generated keys & state
│ └── preprod/
│ └── party-X/
│
├── tests/ # E2E tests
├── docs/ # Documentation
│
├── docker-compose.local.yml # Docker stack
├── Dockerfile # Build image
└── .env # Environment variables
UNLICENSED - Private project