Skip to content

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)

  1. User clicks "Claim Rewards" in staker console
  2. User selects vaults and amounts
  3. Console sends initiateClaimRewards(amountWei) tx to vault contract (only while vault balance is below principalTargetWei)
  4. Rate limit verified: claims are capped at maxClaimPerPeriod per 30-day period (reverts with RateLimitExceeded if exceeded)
  5. 24-hour timer starts
  6. After 24 hours, user returns and signs finalizeClaimRewards(to) tx
  7. 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 /health
  • GET /v1/validators/:address
  • GET /v1/validator/:pubkey

Admin surface (internal only)

  • All other routes require Authorization: Bearer session:<token> or Bearer <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

  1. Read model depends on DB freshness: if watchers lag, user-visible status can lag.
  2. Post-deposit revoke is operational only: validator still exists on-chain after revocation.
  3. Wallet mapping: ownership inferred from beneficiary address / withdrawal credentials. Not a multi-tenant identity system.
  4. 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.