Staker Console Integration¶
This document defines how centurion-staker-console interacts with centurion-seat-manager in a production setup.
1. Integration Contract¶
staker-console is a wallet-facing read client for validator visibility and reward claims.
seat-manager is the control plane and source of truth for seat lifecycle + allowlist operations.
| System | Role |
|---|---|
| Staker Console | Reads GET /v1/validators/:address, displays dashboard, handles claim transactions directly against vault contracts |
| Seat Manager API | Serves public read endpoints, token-gated admin endpoints, maintains seat state in PostgreSQL |
| Admin Frontend | Separate Next.js app for operator-facing seat/user/operator management |
2. API Surface¶
Public routes (no auth required)¶
| Method | Route | Consumer |
|---|---|---|
| GET | /health |
Monitoring, console health checks |
| GET | /v1/validators/:address |
Staker console — wallet-scoped validator list |
| GET | /v1/validator/:pubkey |
Staker console — single validator lookup |
Admin routes (session or token required)¶
All other routes require authentication and are consumed by the admin frontend, not the staker console.
Route prefix compatibility¶
The API normalizes these prefixes:
- /api/mainnet/v1/...
- /api/centurion/v1/...
- /api/seat-manager/v1/...
All resolve to the same handlers, allowing reverse-proxy compatibility with frontend routing conventions.
3. Data Flow¶
Admin flow (operator side)¶
┌────────────────────────────┐
│ Admin Frontend (Next.js) │
│ or CLI commands │
└─────────────┬──────────────┘
│ generate / approve / deposit / revoke
▼
┌────────────────────────────┐
│ Fastify API (session auth) │
│ RBAC: ADMIN / OPERATOR │
└─────────────┬──────────────┘
│
▼
┌────────────────────────────┐
│ PostgreSQL (Prisma) │
│ seats / operators / audit │
└─────────────┬──────────────┘
│
▼
┌────────────────────────────┐
│ EL + CL Nodes │
│ Deposit contract + beacon │
└────────────────────────────┘
User flow (staker console)¶
┌────────────────────────────┐
│ User Wallet │
│ (EVM-compatible wallet) │
└─────────────┬──────────────┘
│ wallet address
▼
┌────────────────────────────┐
│ Staker Console │
│ GET /v1/validators/:addr │
└─────────────┬──────────────┘
│
▼
┌────────────────────────────┐
│ Seat Manager API │
│ Filters by beneficiary │
│ Returns validator payload │
└────────────────────────────┘
│
▼
┌────────────────────────────┐
│ User sees matched validators│
│ + vault balances + rewards │
└─────────────┬──────────────┘
│ claim rewards
▼
┌────────────────────────────┐
│ WithdrawalVault contract │
│ (direct on-chain tx) │
└────────────────────────────┘
4. Wallet Ownership Mapping¶
Seat Manager maps a seat to a wallet address via beneficiary_address on the seat record. The API filters seats where the beneficiary matches the requested wallet address.
Additionally, withdrawal credentials are parsed:
- Accepts 0x01 or 0x02 prefix (execution/compounding credentials)
- Extracts last 20 bytes as the execution address
- Users see only validators whose beneficiary or wc execution address matches their connected wallet
5. Response Mapping¶
The API returns a deposit-backend-compatible validator object derived from PostgreSQL state:
| Response field | DB source |
|---|---|
validator.pubkey |
seats.pubkey_hex |
validator.withdrawal_credentials |
seats.withdrawal_credentials_hex |
balance |
Sum of deposits.amount_gwei |
index |
Last observed deposits.deposit_index |
status mapping: |
|
— ACTIVE |
→ active_ongoing |
— DEPOSITED, SEEN_BY_CL |
→ pending_initialized |
— REVOKED with deposits |
→ exited_unslashed |
| — otherwise | → unknown |
When live beacon data is available, the API enriches the response with real-time consensus balance and validator status.
6. Staker Console Dashboard Metrics¶
| Metric | Source | What it shows |
|---|---|---|
| Foundation Principal | validatorCount × 32 |
Total Foundation-funded capital |
| Validator Consensus Balance | Live beacon API | Current CL balance |
| Your Available Rewards | sum(claimableRewardsWei) from vaults |
What user can claim now |
| Rewards Paid to You | sum(rewardsClaimedWei) from vaults |
Lifetime payouts |
"Rewards Paid to You" is accurate: rewardsClaimedWei is only incremented by beneficiary calls (finalizeClaimRewards in Running phase, claimRewards in ExitSettlement). Treasury claimPrincipal increments a separate principalClaimedWei counter.
7. Claim Flow (User's Single Write Action)¶
Running Phase (normal operation)¶
- User clicks "Claim Rewards" in staker console
- User selects vaults and amounts
- Console sends
initiateClaimRewards(amountWei)tx to vault contract (only while vault balance is belowprincipalTargetWei) - Rate limit verified: claims are capped at
maxClaimPerPeriodper 30-day period (reverts withRateLimitExceededif exceeded) - 24-hour timer starts
- After 24 hours, user returns and signs
finalizeClaimRewards(to)tx - Rate limit enforced and CTN transferred to user's wallet
User can cancelPendingClaim() anytime before finalization.
If vault balance is at/above the principal target (32 CTN), Running-phase claim flow is blocked on-chain (PrincipalProtectionActive), and rewards are claimed after settlement via claimRewards.
SettlementProposed Phase (transition)¶
When treasury calls proposeSettlement(), all beneficiary claims are paused (claimableRewardsWei = 0). Any pending claim is cancelled automatically. This phase lasts at least 1 hour (SETTLEMENT_DELAY). Treasury may cancel the proposal to return to Running phase, or finalize to enter ExitSettlement.
Users cannot claim during this phase — the staker console should show a "settlement pending" status.
ExitSettlement Phase¶
Claims are instant — no delay, no rate limit. User calls claimRewards(to, amount) directly.
After 90 days (DRAIN_DELAY), treasury may call drainRemainder() to sweep any residual balance (e.g., late protocol inflows).
8. Security Model¶
Public surface (expose via reverse proxy)¶
GET /healthGET /v1/validators/:addressGET /v1/validator/:pubkey
Admin surface (internal only)¶
- All other routes require
Authorization: Bearer session:<token>orBearer <admin-token> - RBAC enforced: ADMIN for mutations, VIEWER for reads
- Bind host defaults to
127.0.0.1
Key isolation¶
- Owner/depositor private keys are never in the frontend stack
- Session tokens are HMAC-SHA256 hashed before storage
- Admin token comparison uses
timingSafeEqual - 5xx errors return generic messages (no stack traces)
Admin frontend security headers¶
The Next.js admin frontend sets:
- Content-Security-Policy (restrictive, frame-ancestors 'none')
- X-Frame-Options: DENY
- X-Content-Type-Options: nosniff
- Referrer-Policy: strict-origin-when-cross-origin
9. Deployment Topology¶
┌──────────────────────────────────────┐
│ Public Internet │
└─────────────┬────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ Reverse Proxy │
│ Public: /health, /v1/validators/* │
│ Admin: internal-only (VPN/SSH) │
└─────────────┬────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ Seat Manager API (:8080, localhost) │
│ + Admin Frontend (:3003) │
│ + Watchers (separate process) │
└─────────────┬────────────────────────┘
│
▼
┌──────────────────────────────────────┐
│ PostgreSQL + EL/CL Nodes │
└──────────────────────────────────────┘
10. Known Constraints¶
- Read model depends on DB freshness: if watchers lag, user-visible status can lag.
- Post-deposit revoke is operational only: validator still exists on-chain after revocation.
- Wallet mapping: ownership inferred from beneficiary address / withdrawal credentials. Not a multi-tenant identity system.
- CL peer connectivity: if the local CL loses its peers, the CL watcher may fall behind. Production deployments should use a multi-node topology with diverse CL clients.