harb/web-app/AGENTS.md
johba 2ef2e48f8a chore: gardener housekeeping 2026-03-23
AGENTS.md watermarks refreshed to HEAD (209e0c7). Key content updates:
- root AGENTS.md: added packages/analytics/ to directory map
- landing/AGENTS.md: documented @harb/analytics integration and Umami funnel tracking
- web-app/AGENTS.md: documented analytics events (wallet_connect, swap_initiated, stake_created)
- onchain/AGENTS.md: documented AttackRunner fixes (taxRate as index, vm.warp, same-broadcast recenter), 2000-trade floor-ratchet evidence

Pending actions (6): promote #1083 and #1086 to backlog, unblock #1099.
2026-03-23 18:07:12 +00:00

3.3 KiB

Web App - Agent Guide

Vue 3 + TypeScript staking interface for KRAIKEN, enabling users to stake tokens, manage positions, and interact with Harberger-tax mechanics.

Technology Snapshot

  • Vue 3 (Composition API) with TypeScript and Vite toolchain
  • Wagmi/Viem for wallet connection and blockchain interaction
  • Vue Router for navigation
  • Axios for GraphQL queries to Ponder indexer
  • Sass-based component styling

Architecture

Chain Configuration

src/services/chainConfig.ts centralizes endpoint resolution. All composables accept chainId as a parameter and resolve endpoints via chainConfigService.getEndpoint(chainId, type). Supported chains: 31337 (Anvil), 84532 (Base Sepolia), 8453 (Base Mainnet).

Wagmi Integration

src/wagmi.ts manages wallet connection. Wagmi is the source of truth for which chain the wallet is on. Composables don't import wallet state directly — they accept chainId for testability.

Key Composables

  • useWallet() — Wallet connection, balance, account state
  • usePositions(chainId) — Loads staking positions from Ponder GraphQL
  • useStatCollection(chainId) — Protocol-wide statistics
  • useSnatchSelection(demo, taxRateIndex, chainId) — Calculates snatchable positions
  • useStake() — Executes staking transactions
  • useAdjustTaxRate() — Tax rate adjustment
  • useUnstake() — Position exit transactions

Key Components

  • StakeView.vue — Main staking dashboard (route: /dashboard)
  • StakeHolder.vue — Staking form with accessibility-focused UI
  • ConnectWallet.vue — Wallet connection modal
  • ChartComplete.vue — Position visualization
  • CollapseActive.vue — Expandable position card with actions

Development Workflow

  • Boot full stack: ./scripts/dev.sh start (see root AGENTS.md)
  • Targeted: npm run dev (assumes Ponder/Anvil already running)
  • Build: npm run build
  • E2E tests: npm run test:e2e from repo root (Playwright)

Testing

  • E2E tests in tests/e2e/ (repo root) cover complete user journeys
  • Uses mocked wallet provider with Anvil accounts
  • Relies on semantic HTML and ARIA attributes for selectors
  • StakeHolder test hooks: page.getByRole('slider', { name: 'Token Amount' }), page.getByLabel('Tax')

Analytics

The web app uses @harb/analytics (self-hosted Umami wrapper) for funnel event tracking. initAnalytics(VITE_UMAMI_URL, VITE_UMAMI_WEBSITE_ID) is called in main.ts. Tracked events:

Event Where Helper
wallet_connect useWallet.ts — on first address set trackWalletConnect()
swap_initiated useSwapKrk.ts — before buy/sell tx trackSwapInitiated('buy'|'sell')
stake_created useStake.ts — after PositionCreated event trackStakeCreated()

All calls are silent no-ops if Umami is unavailable. Env vars: VITE_UMAMI_URL, VITE_UMAMI_WEBSITE_ID.

Quality Guidelines

  • Composables accept chainId parameter instead of importing wallet state directly
  • Each composable maintains its own watchChainId() listener for independence
  • Always expose xxxError and loading refs for UI feedback
  • Use strongly typed interfaces for Position, StatsRecord, etc.
  • Use semantic HTML, ARIA attributes, and keyboard navigation
  • Clear watchers and retry timers in onUnmounted()