Setup and deployment
Prerequisites
- Node 20.9+ and pnpm 9 (
corepack enable). - A PostgreSQL database for web + worker (
pnpm db:devruns an embedded local server on port 15940;pglite://works for a single process; Neon/RDS for production). - Rust/Anchor are only needed to build the program; the repository ships the IDL. Builds and tests of the program are run inside the official
solanafoundation/anchor:v1.0.2container (see below).
Local development
pnpm install cp .env.example .env # fill SESSION_SECRET, LLM_PROVIDER, SIGNER_PROVIDER as needed pnpm db:dev # terminal 1: embedded PostgreSQL on 127.0.0.1:15940 pnpm dev # terminal 2: web on http://localhost:25800 (migrations run on first request) pnpm worker # terminal 3: the agent worker (durable loop, heartbeat)
pnpm signer:init prints a fresh OHGE_SIGNER_KEY for the local-file signer; the encrypted key files land in .local/signer/ (gitignored). LLM_PROVIDER=scripted is a deterministic provider for development; anthropic uses ANTHROPIC_API_KEY with the Claude Opus 5.5 model by default; openai talks to any OpenAI-compatible endpoint with JSON-schema responses.
Program build and tests (container)
cd onchain docker run --rm -v "$PWD":/workdir -w /workdir solanafoundation/anchor:v1.0.2 anchor build docker run --rm --security-opt seccomp=unconfined -v "$PWD":/workdir -w /workdir solanafoundation/anchor:v1.0.2 \ bash -lc "solana-keygen new --no-bip39-passphrase -s -o ~/.config/solana/id.json; yarn install; anchor test --validator legacy --skip-build"
--security-opt seccomp=unconfined is required because the Agave 3.x test validator uses io_uring, which Docker's default profile blocks. The test validator clones the Orca program, the SOL/USDC pool and the Pyth accounts from mainnet-beta at startup (see Anchor.toml), so it needs outbound access to api.mainnet-beta.solana.com.
After a build, copy target/idl/ohge_guard.json and target/types/ohge_guard.ts to src/onchain/idl/.
Devnet deployment
- Fund a deployer key with devnet SOL (
solana airdrop, subject to faucet limits). anchor deploy --provider.cluster devnet --provider.wallet <deployer.json>fromonchain/(inside the container). The program id is the keypair intarget/deploy/ohge_guard-keypair.jsonand must matchdeclare_id!.- Set
NEXT_PUBLIC_GUARD_PROGRAM_ID_DEVNET(browser) andGUARD_PROGRAM_ID(server/worker) and rebuild. - Devnet trades use the Orca SOL/devUSDC pool with reference protection off (the test token has no USD reference). devUSDC can be obtained by swapping devnet SOL through the pool.
Mainnet
Nothing in this repository deploys to mainnet or moves real funds by itself. Mainnet readiness has not been assessed; see Implementation status. The remaining operator steps for a mainnet deployment would be: an independent audit of onchain/, a reviewed deployment of the program with a multisig upgrade authority, a production signer (remote-http against an HSM/KMS service), private RPC endpoints, NEXT_PUBLIC_SOLANA_NETWORK=mainnet-beta with the mainnet program id, and AUTO_MIGRATE=0 with explicit pnpm db:migrate.
Worker on a VPS (Docker)
deploy/Dockerfile.worker + deploy/docker-compose.vps.yml: copy the repository (without node_modules) to the host, put the worker settings in deploy/worker.env (DATABASE_URL = the direct/unpooled PostgreSQL URL, SOLANA_RPC_URL, GUARD_PROGRAM_ID, LLM and signer settings, OHGE_SIGNER_DIR=/data/signer) and run docker compose -f deploy/docker-compose.vps.yml --env-file deploy/worker.env up -d --build. The signer volume ohge-signer holds the encrypted session keys; back it up together with OHGE_SIGNER_KEY. A web deployment without a signer asks this worker to mint session keys (job create_session_key).
Web deployment (Vercel or any Node host)
The web app is stateless apart from PostgreSQL. Set the environment from .env.example. The worker is a separate long-running process (pnpm worker) on a VM or container with the same DATABASE_URL, SOLANA_RPC_URL, LLM and signer settings. Do not run the worker inside a serverless function.
Useful scripts
| Script | Purpose |
|---|---|
pnpm typecheck / pnpm lint / pnpm test | TypeScript, ESLint, Vitest (unit tests for the math, auth, queue and agent validation) |
pnpm db:generate / pnpm db:migrate | Drizzle migrations |
pnpm worker:once | Process every due job once (cron-style setups and smoke checks) |
pnpm build / pnpm start | Production build on port 25810 |