diff --git a/.gitignore b/.gitignore index 4d33aae..fb801a6 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ services/ponder/.ponder/ # Temporary files /tmp/ +logs/ diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..eea0a37 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,120 @@ +# ARCHITECTURE.md — System Map + +Compressed overview for AI agents. Read this first, drill into source for details. + +## Contract Architecture + +``` +Kraiken.sol (ERC-20 token) +├── liquidityManager: address (set once, immutable after) +│ └── LiquidityManager.sol (ThreePositionStrategy) +│ ├── optimizer: Optimizer (private immutable ref) +│ ├── pool: IUniswapV3Pool +│ ├── kraiken: Kraiken +│ └── Positions: Floor, Anchor, Discovery +├── stakingPool: address +│ └── Stake.sol +│ ├── Staking positions with tax rates +│ ├── Snatch mechanics (competitive staking) +│ └── getPercentageStaked(), getAverageTaxRate() +└── feeDestination: address (protocol revenue) + +Optimizer.sol (UUPS Upgradeable Proxy) +├── Reads: stake.getPercentageStaked(), stake.getAverageTaxRate() +├── Computes: sentiment → 4 liquidity params +├── Versions: Optimizer, OptimizerV2, OptimizerV3, OptimizerV3Push3 +└── Admin: single address, set at initialize() +``` + +## Key Relationships + +- **Kraiken → LiquidityManager**: set once via `setLiquidityManager()`, reverts if already set +- **LiquidityManager → Optimizer**: `private immutable` — baked into constructor, never changes +- **LiquidityManager → Kraiken**: exclusive minting/burning rights +- **Optimizer → Stake**: reads sentiment data (% staked, avg tax rate) +- **Optimizer upgrades**: UUPS proxy, admin-only `_authorizeUpgrade()` + +## Three-Position Strategy + +All managed by LiquidityManager via ThreePositionStrategy abstract: + +| Position | Purpose | Behavior | +|----------|---------|----------| +| **Floor** | Safety net | Deep liquidity at VWAP-adjusted prices | +| **Anchor** | Price discovery | Near current price, 1-100% width | +| **Discovery** | Fee capture | Borders anchor, ~3x price range (11000 tick spacing) | + +**Recenter** = atomic repositioning of all three positions. Triggered by anyone, automated by txnBot. + +## Optimizer Parameters + +`getLiquidityParams()` returns 4 values: +1. `capitalInefficiency` (0 to 1e18) — capital buffer level +2. `anchorShare` (0 to 1e18) — % allocated to anchor position +3. `anchorWidth` (ticks) — width of anchor position +4. `discoveryDepth` (0 to 1e18) — depth of discovery position + +Sentiment calculation: `sentiment = f(averageTaxRate, percentageStaked)` +- High sentiment (bull) → wider discovery, aggressive fees +- Low sentiment (bear) → tight around floor, maximum protection + +## Stack + +### On-chain +- Solidity, Foundry toolchain +- Uniswap V3 for liquidity positions +- OpenZeppelin for UUPS proxy, Initializable +- Base L2 (deployment target) + +### Indexer +- **Ponder** (`services/ponder/`) — indexes on-chain events +- Schema: `services/ponder/ponder.schema.ts` +- Stats table with 168-slot ring buffer (7d × 24h × 4 segments) +- Ring buffer segments: [ethReserve, minted, burned, tax] (slot 3 being changed to holderCount) +- GraphQL API at port 42069 + +### Landing Page +- Vue 3 + Vite (`landing/`) +- Three variants: HomeView (default), HomeViewOffensive (degens), HomeViewMixed +- Docs section: HowItWorks, Tokenomics, Staking, LiquidityManagement, AIAgent, FAQ +- LiveStats component polls Ponder GraphQL every 30s + +### Staking Web App +- Vue 3 (`web-app/`) +- Password-protected (multiple passwords in LoginView.vue) +- ProtocolStatsCard shows real-time protocol metrics + +### Infrastructure +- Docker Compose on 8GB VPS +- Woodpecker CI at ci.niovi.voyage +- Codeberg repo: johba/harb (private) +- Container registry: registry.niovi.voyage + +## Directory Map + +``` +harb/ +├── onchain/ # Solidity contracts + Foundry +│ ├── src/ # Contract source +│ ├── test/ # Forge tests +│ └── foundry.toml # via_ir = true required +├── services/ +│ └── ponder/ # Indexer service +│ ├── ponder.schema.ts +│ ├── src/ +│ │ ├── helpers/stats.ts # Ring buffer logic +│ │ ├── lm.ts # LiquidityManager indexing +│ │ └── stake.ts # Stake indexing +├── landing/ # Landing page (Vue 3) +│ ├── src/ +│ │ ├── components/ # LiveStats, KFooter, WalletCard, etc. +│ │ ├── views/ # HomeView variants, docs pages +│ │ └── router/ +├── web-app/ # Staking app (Vue 3) +│ ├── src/ +│ │ ├── components/ # ProtocolStatsCard, etc. +│ │ └── views/ # LoginView, StakeView, etc. +├── containers/ # Docker configs, entrypoints +├── docs/ # This file, PRODUCT-TRUTH.md +└── .woodpecker/ # CI pipeline configs +``` diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md new file mode 100644 index 0000000..ab7c9f0 --- /dev/null +++ b/docs/ENVIRONMENT.md @@ -0,0 +1,99 @@ +# ENVIRONMENT.md — Local Dev Stack + +How to start, stop, and verify the harb development environment. + +## Stack Overview + +Docker Compose services (in startup order): + +| Service | Purpose | Port | Health Check | +|---------|---------|------|-------------| +| **anvil** | Local Ethereum fork (Base Sepolia) | 8545 | JSON-RPC response | +| **postgres** | Ponder database | 5432 | pg_isready | +| **bootstrap** | Deploys contracts to anvil | — | One-shot, exits 0 | +| **ponder** | On-chain indexer + GraphQL API | 42069 | HTTP /ready or GraphQL | +| **landing** | Landing page (Vue 3 + Vite) | 5174 | HTTP response | +| **webapp** | Staking app (Vue 3) | 5173 | HTTP response | +| **txn-bot** | Automated recenter/tx bot | — | Process alive | +| **caddy** | Reverse proxy / TLS | 80/443 | — | +| **otterscan** | Block explorer | 5100 | — | + +## Quick Start + +```bash +cd /home/debian/harb + +# Start everything +docker compose up -d + +# Wait for bootstrap (deploys contracts, ~60-90s) +docker compose logs -f bootstrap + +# Check all healthy +docker compose ps +``` + +## Verify Stack Health + +```bash +# Anvil (local chain) +curl -s http://localhost:8545 -X POST -H 'Content-Type: application/json' \ + -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' | jq .result + +# Ponder (indexer + GraphQL) +curl -s http://localhost:42069/graphql -X POST \ + -H 'Content-Type: application/json' \ + -d '{"query":"{ stats { id } }"}' | jq . + +# Landing page +curl -sf http://localhost:5174 | head -5 + +# Staking app +curl -sf http://localhost:5173 | head -5 +``` + +## Container Network + +Services communicate on `harb-network` Docker bridge. +Internal hostnames match service names (e.g., `ponder:42069`). + +Landing page container IP (for Playwright testing): check with +```bash +docker inspect landing --format '{{.NetworkSettings.Networks.harb_harb-network.IPAddress}}' +``` + +## Common URLs (for testing/review) + +- **Landing:** `http://172.18.0.6:5174` (container IP) or `http://localhost:5174` +- **Staking app:** `http://localhost:5173/app/` +- **Ponder GraphQL:** `http://localhost:42069/graphql` +- **Anvil RPC:** `http://localhost:8545` + +## Resource Notes + +- 8GB VPS — running full stack uses ~4-5GB RAM +- npm install inside containers can OOM with all services running +- Landing container takes ~2min to restart (npm install + vite startup) +- 4GB swap is essential for CI + stack concurrency + +## Staking App Passwords + +For testing login: `lobsterDao`, `test123`, `lobster-x010syqe?412!` +(defined in `web-app/src/views/LoginView.vue`) + +## Contract Addresses + +After bootstrap, addresses are in `/home/debian/harb/tmp/containers/contracts.env`. +Landing sources this file on startup for `VITE_KRAIKEN_ADDRESS` and `VITE_STAKE_ADDRESS`. + +## Playwright Testing + +```bash +# Chromium path +/home/debian/.cache/ms-playwright/chromium-1209/chrome-linux64/chrome + +# Run against landing (block fonts for speed) +NODE_PATH=$(npm root -g) node test-script.cjs +``` + +See `tmp/user-test-r4.cjs` for the most recent test script pattern. diff --git a/docs/PRODUCT-TRUTH.md b/docs/PRODUCT-TRUTH.md new file mode 100644 index 0000000..d023178 --- /dev/null +++ b/docs/PRODUCT-TRUTH.md @@ -0,0 +1,109 @@ +# PRODUCT-TRUTH.md — What We Can and Cannot Claim + +This file is the source of truth for all product messaging, docs, and marketing. +If a claim isn't here or contradicts what's here, it's wrong. Update this file +when the protocol changes — not the marketing copy. + +**Last updated:** 2026-02-22 +**Updated by:** Johann + Clawy after user test review session + +--- + +## Target Audience + +- **Crypto natives** who know DeFi but don't know KrAIken +- NOT beginners. NOT "new to DeFi" users. +- Think: people who've used Uniswap, understand liquidity, know what a floor price means + +## The Floor + +✅ **Can say:** +- Every KRK token has a minimum redemption price backed by real ETH +- The floor is enforced by immutable smart contracts +- The floor is backed by actual ETH reserves, not promises +- No rug pulls — liquidity is locked in contracts +- "Programmatic guarantee" (borrowed from Baseline — accurate for us too) + +❌ **Cannot say:** +- "The floor can never decrease" — **FALSE.** Selling withdraws ETH from reserves. The floor CAN decrease. +- "Guaranteed profit" or "risk-free" — staking is leveraged exposure, it has real downside +- "Floor always goes up" — only true if fee income exceeds sell pressure, which isn't guaranteed + +## The Optimizer + +✅ **Can say:** +- Reads staker sentiment (% staked, average tax rate) to calculate parameters +- Returns 4 parameters: capitalInefficiency, anchorShare, anchorWidth, discoveryDepth +- Runs autonomously on-chain — no human triggers needed for parameter reads +- Is a UUPS upgradeable proxy — can be upgraded to new versions +- Currently admin-upgradeable (single admin key set at initialization) +- Multiple versions exist: Optimizer, OptimizerV2, OptimizerV3, OptimizerV3Push3 +- "The optimizer evolves" — true in the sense that new versions get deployed + +❌ **Cannot say:** +- "No admin keys" — **FALSE.** UUPS upgrade requires admin. Admin key exists. +- "No proxy patterns" — **FALSE.** It IS a UUPS proxy. +- "Stakers vote for new optimizers" — **NOT YET.** This is roadmap, not current state. +- "Simply evolves" / "evolves without upgrades" — misleading. It's an explicit upgrade via proxy. +- "Three strategies" — **FALSE.** It's ONE strategy with THREE positions (Floor, Anchor, Discovery). +- "AI learns from the market" — overstated. The optimizer reads staking sentiment, not market data directly. + +🔮 **Roadmap (can say "planned" / "coming"):** +- Staker governance for optimizer upgrades (vote with stake weight) +- On-chain training data → new optimizer contracts via Push3 transpiler +- Remove admin key in favor of staker voting + +## Liquidity Positions + +✅ **Can say:** +- Three positions: Floor, Anchor, Discovery +- Floor: deep liquidity at VWAP-adjusted prices (safety net) +- Anchor: near current price, fast price discovery (1-100% width) +- Discovery: borders anchor, captures fees (wide range, ~3x current price) +- The optimizer adjusts position parameters based on sentiment +- "Recenter" = atomic repositioning of all liquidity in one transaction +- Anyone can trigger a recenter; the protocol bot does it automatically +- Bull mode: wider discovery, aggressive fee capture. Bear mode: tight around floor. + +❌ **Cannot say:** +- "Three trading strategies" — it's three positions in ONE strategy +- "Token-owned liquidity" — ⚠️ USE CAREFULLY. KRK doesn't "own" anything in the legal/contract sense. The LiquidityManager manages positions. Acceptable as metaphor in marketing, not in technical docs. + +## Staking + +✅ **Can say:** +- Staking = leveraged directional exposure +- Stakers set tax rates; positions can be "snatched" by others willing to pay higher tax +- Tax rates influence optimizer sentiment → bull/bear positioning +- "Stakers profit when the community grows" (via supply expansion + leverage) +- Staking is optional — most holders just hold + +❌ **Cannot say:** +- "Start Earning" / "Earn yield" / "APY" — staking is NOT yield farming +- "Guaranteed returns" — leveraged positions amplify losses too +- "Passive income" — tax payments are a cost, not income + +## Supply Mechanics + +✅ **Can say:** +- Elastic supply: buy = mint, sell = burn +- Protocol controls minting exclusively through LiquidityManager +- LiquidityManager address is set once on Kraiken contract and cannot be changed + +## Code / Open Source + +✅ **Can say:** +- Smart contracts are verifiable on Basescan +- Key contracts are viewable on the docs/code page +- "Full source will be published at mainnet launch" (if that's the plan) + +❌ **Cannot say:** +- "Open source" — the Codeberg repo is **private**. This is currently false. +- "Audited" — unless an audit has been completed + +## General Rules + +1. When in doubt, understate. "The floor is backed by ETH" > "The floor guarantees you'll never lose money" +2. Separate current state from roadmap. Always. +3. Technical docs: be precise. Marketing: metaphors OK but never contradict technical reality. +4. If you're not sure a claim is true, check this file. If it's not here, verify against contract source before writing it. diff --git a/landing/src/components/LiveStats.vue b/landing/src/components/LiveStats.vue index 733bb03..93d0ceb 100644 --- a/landing/src/components/LiveStats.vue +++ b/landing/src/components/LiveStats.vue @@ -5,6 +5,9 @@