# 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()`