Skip to content

Build Gonka Operator Portal: React + Cosmos Kit web3 frontend for node operators #13

@mingles-agent

Description

@mingles-agent

From research #10

Overview

Build a web3 frontend operator portal that allows Gonka node operators to manage their mining nodes, collateral, and rewards through Keplr wallet — without using the CLI. The app uses React + TypeScript + Cosmos Kit + CosmJS, and talks to two backends: the chain RPC (for signed transactions) and the decentralized-api (for node management and monitoring data).

Architecture Summary

Stack: Vite + React 18 + TypeScript + Cosmos Kit v2 + @cosmjs/stargate + TanStack Query
Location: gonka/web/operator-portal/ (new directory in monorepo)
Backends:

  • Chain gRPC-gateway REST on port 1317 → read-only queries
  • Chain RPC on port 26657 → Keplr signing + broadcast
  • decentralized-api public on port 9000 → participant/epoch/monitoring data
  • decentralized-api admin on port 9200 → node management, setup report

Chain config:

  • chainId: gonka-mainnet
  • bech32Prefix: gonka
  • denom: ngonka (9 decimals, display: GONKA)
  • Cosmos SDK v0.50 (custom fork)

Amino/Ledger status: All RegisterLegacyAminoCodec functions are empty — Ledger signing is blocked for ALL custom messages until Research #9 amino fix lands. Keplr via SIGN_MODE_DIRECT works today.

Implementation Checklist

Phase 1: Project scaffold + chain integration (~3 days)

  • Scaffold web/operator-portal/ with npm create vite@latest (React + TypeScript)
  • Add deps: @cosmos-kit/react, @cosmos-kit/keplr, @cosmjs/stargate, @cosmjs/proto-signing, @tanstack/react-query, react-router-dom
  • Configure Cosmos Kit v2 with ChainProvider and GONKA_CHAIN_INFO (chainId, bech32Config, currencies, feeCurrencies as documented in research Research: Keplr + Ledger web3 app architecture for Gonka miner/validator management #10)
  • Add experimentalSuggestChain with Gonka chain config on app init
  • Generate TypeScript types from proto files using @cosmology/telescope or ts-proto with inference-chain/proto/buf.yaml as source
  • Create CosmosClientProvider wrapper: SigningStargateClient with custom message registry (MsgDepositCollateral, MsgWithdrawCollateral, MsgClaimRewards, MsgSubmitNewParticipant)
  • Create apiClient.ts utility for decentralized-api calls (configurable base URL)
  • Create chainQueryClient.ts utility for gRPC-gateway REST calls

Phase 2: Core wallet + registration flow (~3 days)

  • /wallet page: connect Keplr, add Gonka chain, display address + GONKA balance; show "Ledger unsupported for custom txs" warning when Ledger detected
  • /register wizard step 1: wallet check (is participant registered? calls GET /v1/participants/:address)
  • /register wizard step 2: node URL input + validator_key/worker_key input (with docs explaining how to get keys from a running node)
  • /register wizard step 3: sign + broadcast MsgSubmitNewParticipant via Keplr; show tx hash + explorer link
  • /register wizard step 4: guide through initial collateral deposit

Phase 3: Collateral management page (~2 days)

  • /collateral page: display active collateral balance from GET /productscience/inference/collateral/collateral/{participant}
  • Display unbonding collateral + completion epoch from GET /productscience/inference/collateral/unbonding/{participant}
  • Deposit form: amount input → sign + broadcast MsgDepositCollateral; auto-detect wallet balance
  • Withdraw form: amount input → sign + broadcast MsgWithdrawCollateral; show unbonding period warning
  • Handle jailed/slashed state: query collateral params for slash history display

Phase 4: Rewards claiming page (~2 days)

  • /rewards page: list unclaimed epochs with performance summary from GET /productscience/inference/inference/epoch_performance_summary
  • Per-epoch stats: inference count, miss rate, earned/rewarded/burned coins
  • Claim button per epoch: sign + broadcast MsgClaimRewards with creator, seed (from node config), epoch_index
  • Important: The seed field in MsgClaimRewards comes from the operator's running node — add documentation/input for how to retrieve it from the node's config or admin API
  • Display claim history and settle_amount from GET /productscience/inference/inference/settle_amount/{participant}

Phase 5: Monitoring dashboard (~2 days)

  • / dashboard: participant status, current epoch phase/stages from GET /v1/epochs/latest, quick stats
  • /monitoring page: detailed participant status from GET /v1/participants/:address (status, weight, coins owed, miss rate via currentEpochStats)
  • Node health check: embed output from GET /admin/v1/setup/report with pass/fail indicators
  • Model coverage: active models from GET /v1/models, current pricing from GET /v1/pricing

Phase 6: Node management page (~2 days)

  • /nodes page: list ML inference nodes from GET /admin/v1/nodes
  • Add node form: URL, port, max_concurrent, models list → POST /admin/v1/nodes
  • Delete node: DELETE /admin/v1/nodes/:id
  • Node health status per node (from setup report or direct check)

Phase 7: Polish + deployment config (~2 days)

  • Add REACT_APP_RPC_URL, REACT_APP_REST_URL, REACT_APP_DAPI_URL, REACT_APP_ADMIN_URL env config
  • Add CORS documentation: REST_API_ACTIVE=true needed for chain REST, decentralized-api needs CORS headers for web access
  • Add Dockerfile + serve static build via nginx
  • Add to docker-compose.explorer.yml or create docker-compose.portal.yml
  • Add README with setup instructions
  • Handle amino/Ledger gating: isLedgerSupported(msgType) utility that returns false for all custom msgs until Research: Amino codec coverage for all inference module transactions (Keplr/Ledger signing) #9 is merged

Dependencies & Blockers

  • Amino support (Research: Amino codec coverage for all inference module transactions (Keplr/Ledger signing) #9): Ledger signing for all custom messages is blocked. Keplr hot wallet works today. Design the isLedgerSupported() util to be easily flipped once Research: Amino codec coverage for all inference module transactions (Keplr/Ledger signing) #9 lands.
  • Chain RPC/REST endpoints: Need publicly accessible RPC and REST endpoints. The chain runs on port 26657 (RPC) and 1317 (REST, only when REST_API_ACTIVE=true). CORS must be enabled for browser access.
  • Admin API authentication: The admin API (port 9200) is currently unauthenticated and localhost-only. The portal can either run co-located with the node, or the admin API needs auth headers added.
  • Seed for MsgClaimRewards: The seed field is managed by the node's internal config. UX for retrieving this seed for the UI needs coordination with the node team (possibly expose it via admin API).

Estimated Total: 4-5 weeks

Phase 1: 3 days | Phase 2: 3 days | Phase 3: 2 days | Phase 4: 2 days | Phase 5: 2 days | Phase 6: 2 days | Phase 7: 2 days

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions