# PYRE — Engineering Architecture > Companion to [`PYRE_MVP_DESIGN.md`](./PYRE_MVP_DESIGN.md). The design document is > the canonical source of truth; this file describes *how the system is wired > together*. Where they appear to disagree, the design document wins. **Tagline:** *Burn the dead. Feed the PYRE. Claim the Spawn.* --- ## 1. System Overview PYRE is a Solana wallet-cleanup and ritual meme-rebirth protocol. The MVP runs as three runtime services backed by two stateful stores, and it depends on two classes of external service: a Solana RPC provider and AI APIs. Runtime services: - **`apps/web`** (`pyre-web`) — Next.js frontend. Wallet connect, scanner UI, cleanup preview, signing, receipt rendering, Prometheus review, admin pages. - **`apps/api`** (`pyre-api`) — Node.js/Fastify (or Express) HTTP API. Scan coordination, classification, **unsigned** transaction building, receipt storage, AI orchestration, admin API. The only service the browser talks to. - **`apps/worker`** (`pyre-worker`) — Node.js BullMQ worker. Slow/async jobs: metadata enrichment, AI generation, image prompts, safety/collision checks, confirmation tracking, receipt enrichment. Stateful stores: - **PostgreSQL** — durable record of scans, classifications, receipts, generations, and Spawn records. - **Redis** — BullMQ job queue, scan cache, rate limiting, quote cache, generation status. External dependencies (never self-hosted on the MVP VPS): - **Solana RPC** — external provider only. No validator/RPC node on the VPS. - **AI APIs** — text, image, and moderation APIs only. No local LLM/image models. ### Component / Data-Flow Diagram ``` ┌──────────────┐ │ Wallet │ (Phantom / Solflare via Wallet Adapter) │ (browser) │ signs locally — keys never leave the client └──────┬───────┘ │ connect / sign / send ▼ ┌──────────────┐ static assets / SSR │ apps/web │◀───────────────────────────┐ │ (Next.js) │ │ └──────┬───────┘ │ │ HTTPS (JSON) │ ▼ │ ┌───────────────────────────────────────────────┐ │ │ apps/api │ │ │ scan · classify · build (UNSIGNED) · receipt │ │ │ prometheus/generate · admin │ │ └───┬─────────────┬──────────────┬────────────────┘ │ │ │ │ │ │ SQL │ cache/queue │ getAccounts / simulate / │ ▼ ▼ │ sendTx / confirm │ ┌──────────┐ ┌──────────┐ ▼ │ │ Postgres │ │ Redis │ ┌──────────────┐ │ │ │ │ (BullMQ) │ │ Solana RPC │ (external) │ └──────────┘ └────┬─────┘ └──────────────┘ │ │ │ │ jobs pulled from queue │ ▼ │ ┌──────────────┐ ┌──────────────┐ │ │ apps/worker │───▶│ AI APIs │ (external) │ │ (BullMQ) │ │ text/image/ │ │ │ │ │ moderation │ │ └──────┬───────┘ └──────────────┘ │ │ writes results / status │ ├───────────────▶ Postgres │ └───────────────▶ Redis ────────────────────┘ (generation status read back by web/api) ``` The browser only ever talks to `apps/web` and `apps/api`. The worker is not network-exposed; it consumes jobs from Redis and writes results back to Postgres and Redis. RPC and AI calls flow outbound only. --- ## 2. Component Responsibilities ### `apps/web` — User-facing frontend Next.js + TypeScript + Tailwind + Solana Wallet Adapter, with React Query or Zustand for state. Responsibilities (§11): - Wallet connect via Solana Wallet Adapter. - Token-account display and classification grouping (closeable / burnable / transmutable / protected / unsupported). - User confirmations and **transaction preview** UI. - Transaction **signing** (client-side, via the connected wallet only). - Receipt rendering and optional share image. - Prometheus Spawn-package review and public round/Spawn pages. - Admin / generation review UI. ### `apps/api` — Backend HTTP API Node.js + Fastify/Express + TypeScript, fronting PostgreSQL, Redis, BullMQ. Responsibilities (§11): - Token-scan coordination (calls RPC, persists results). - Classification helpers and route evaluation. - **Builds UNSIGNED Solana transactions** — never signs, never holds keys. - Metadata preparation and AI generation orchestration (enqueues worker jobs). - Receipt storage and Spawn-record storage. - Public API and protected admin API. ### `apps/worker` — Background worker Node.js worker process driven by BullMQ over Redis, with AI API clients. Responsibilities (§11): - Slow token-metadata enrichment. - AI generation jobs (Prometheus). - Image-prompt generation. - Safety checks and ticker/name collision checks. - Background confirmation tracking. - Receipt enrichment. ### `packages/core` — Shared types & business logic The single home for cross-service domain definitions (§13): - Classification **enums**: `EMPTY_CLOSE_ONLY`, `INCINERATE_ONLY`, `TRANSMUTABLE`, `PROTECTED_SKIP`, `UNSUPPORTED`. - Conservative **risk rules** (the §7 safety rules: classic SPL only, skip Token-2022/NFTs/LP/frozen/delegated, USD threshold, price-impact and stale-quote guards). - Shared **DTOs** for the API request/response shapes. - **Receipt schema**. - **Prometheus input/output schema**. ### `packages/solana` — Solana transaction helpers Everything that touches the chain at the instruction level (§13): - Token-account **parsing** (decode raw account state into the scan model). - **Close-account** transaction builder. - **Burn** transaction builder. - **Simulation** helpers (simulate before signing — §7). - **Transaction decoder** (decode the built tx so it can be matched against the preview — §8 step 5, §16). ### `packages/prometheus` — AI generation logic The creative engine's code (§13), invoked by the worker: - Prompt **templates**. - The **meta mixer** (probabilistic influence blend — §9). - Output **parser**. - **Safety checks** (blocked terms, scam/impersonation/copyright filters). - **Image-prompt generator**. ### `packages/db` — Database layer Schema, migrations, and table definitions (§13/§15). Owns the canonical SQL and migration history; `apps/api` and `apps/worker` depend on it for data access. ### `packages/config` — Shared config Shared configuration and environment loading (§13). Centralizes reading `.env`-supplied secrets (RPC URL, AI keys, DB/Redis connection strings) so no secret is hard-coded. ### `programs/pyre-core` — Future Anchor program NOT part of the first burner MVP. The future on-chain trust core (rounds, Essence vault, claims, refunds) — built only at Phase 7 / v1.0. --- ## 3. Request / Data Flow — The Burner Journey The core flow is the 8-step burner sequence from §8. The critical trust property: **the server builds an UNSIGNED transaction, the client signs it, and the decoded transaction is matched against the preview before signing.** ``` 1. Connect ──▶ 2. Scan ──▶ 3. Classify ──▶ 4. Preview ──▶ 5. Build (UNSIGNED) │ ▼ 8. Receipt ◀── 7. Confirm ◀── 6. Sign (client) ◀── decode & match against preview ``` 1. **Wallet Connect** — user connects via Solana Wallet Adapter (`apps/web`). No keys leave the browser. 2. **Account Scan** — `apps/web` calls `POST /api/scan`. `apps/api` queries token accounts via the external RPC, capturing for each: owner, ATA address, mint, token program, balance, decimals, rent estimate, metadata (if available), token-program type, frozen/delegated state. Results persist to `wallet_scans` / `token_accounts`; slow metadata enrichment may be deferred to a worker job. Scan results are cached in Redis. 3. **Classification** — each account is classified server-side into the §6 categories and grouped for the UI. **Client-submitted classifications are not trusted** — the server recomputes where needed (§16). 4. **Preview** — before any signing the user sees: accounts to close, tokens to burn, accounts skipped, estimated rent returned, transaction fees, warnings, and the destination wallet for recovered rent (which is the user's own wallet). 5. **Build Transaction** — `apps/web` calls `POST /api/build/close-empty` (and/or `/api/build/burn`). `apps/api` uses `packages/solana` to build an **unsigned** transaction and returns it base64-encoded plus the preview. The client decodes the transaction (`packages/solana` decoder) and **matches it against the preview**; any mismatch aborts before signing. 6. **User Signs** — locally, with the connected wallet. PYRE never requests private keys and never performs custodial signing. 7. **Confirmation** — the signed transaction is sent and confirmed via RPC. A worker confirmation-tracking job may follow the signature to durable finality. 8. **Receipt** — `apps/web` calls `POST /api/receipt`; `apps/api` records and returns the receipt: tx signature, accounts closed, tokens burned, rent returned, accounts skipped, warnings, timestamp, optional share image. A worker receipt-enrichment job may backfill metadata. All transactions are simulated before final signing (§7), and all build requests are logged (§16). --- ## 4. API Surface Reproduced from §14. All endpoints are served by `apps/api`. Admin endpoints are authenticated and protected separately (§16). ### `POST /api/scan` ```jsonc // in: { "wallet": "wallet_pubkey" } // out: { "scanId": "uuid", "wallet": "wallet_pubkey", "summary": { "totalAccounts": 0, "emptyCloseOnly": 0, "incinerateOnly": 0, "transmutable": 0, "protectedSkip": 0, "unsupported": 0, "estimatedRentLamports": 0 }, "accounts": [] } ``` ### `POST /api/build/close-empty` ```jsonc // in: { "wallet": "...", "accountAddresses": ["ata1", "ata2"] } // out: { "transactionBase64": "...", "preview": { "accountsToClose": [], "estimatedRentReturnedLamports": 0, "rentDestination": "user_wallet_pubkey" } } ``` ### `POST /api/build/burn` ```jsonc // in: { "wallet": "...", "items": [{ "tokenAccount": "...", "mint": "...", "amount": "..." }] } // out: { "transactionBase64": "...", "preview": { "tokensToBurn": [], "accountsPotentiallyClosable": [] } } ``` ### `POST /api/receipt` ```jsonc // in: { "wallet": "...", "txSignature": "...", "scanId": "uuid" } // out: { "receiptId": "uuid", "txSignature": "...", "rentReturnedLamports": 0, "closedAccounts": [], "burnedTokens": [], "skippedTokens": [] } ``` ### `POST /api/prometheus/generate` ```jsonc // in: { "receiptId": "uuid", "chaos": 0.25, "operatorSeed": "optional" } // out: { "generationId": "uuid", "spawnName": "...", "ticker": "...", "lore": "...", "imagePrompt": "...", "metadata": {}, "riskFlags": [] } ``` ### Admin endpoints Admin / generation-review endpoints (approve/reject generations, record Pump.fun launches, view system events) are protected and not part of the public surface. They back the admin review UI and the Spawn-record workflow (§10, §16). --- ## 5. Data Model ### Initial PostgreSQL tables (§15) ``` wallet_scans: id, wallet, status, created_at, completed_at, summary_json token_accounts: id, scan_id, wallet, ata, mint, token_program, raw_balance, ui_balance, decimals, symbol, name, classification, warnings_json, estimated_rent_lamports, created_at cleanup_receipts: id, wallet, scan_id, tx_signature, rent_returned_lamports, closed_accounts_count, burned_tokens_count, status, created_at, receipt_json prometheus_generations: id, receipt_id, input_json, output_json, status, risk_flags_json, created_at, approved_at, rejected_at spawn_records: id, generation_id, spawn_name, ticker, mint, metadata_uri, pumpfun_url, launch_tx, status, created_at ``` Additional initial tables called out in §11/§15: `token_classifications`, `burn_events`, `close_account_events`, `spawn_candidates`, and `system_events` (audit/event log). ### Future tables (NOT in the burner MVP) These arrive with the Essence ledger and PYRE Core program (Phases 6–7): - `pyre_rounds` — round state machine. - `essence_contributions` — recorded Essence per wallet per round. - `claim_records` — Spawn claim accounting. - `refund_records` — refunds for failed rounds. - `influence_fields` — meta-influence inputs for Prometheus weighting. > Per §5/§15: Essence may start in the database, but it must not be called a > deposit until an on-chain custody model exists, and claims must not be promised > until claim logic exists. --- ## 6. Redis Usage Redis serves five roles (§11): - **Job queue** — backs BullMQ; `apps/api` enqueues, `apps/worker` consumes. - **Scan cache** — caches scan results so repeat views don't re-hit RPC. - **Rate limiting** — throttles scan and build endpoints (§16). - **Temporary quote cache** — short-lived swap/route quotes; stale quotes are rejected by classification (§7). - **Generation status** — live status of in-flight Prometheus jobs, read back by `apps/web` / `apps/api`. ### BullMQ Worker Jobs `apps/worker` processes these job types (§11): - **Metadata enrichment** — slow token name/symbol/metadata lookups. - **AI generation** — Prometheus Spawn generation. - **Image prompts** — image-prompt generation for the Spawn. - **Safety checks** — moderation of generated names/tickers/lore. - **Collision checks** — ticker/name duplicate detection. - **Confirmation tracking** — follow tx signatures to finality in the background. - **Receipt enrichment** — backfill receipt detail after confirmation. --- ## 7. Solana RPC Requirements PYRE uses an **external RPC provider only**. Per §11/§12, the MVP VPS must **not** run a Solana validator or RPC node. Required RPC capabilities (§11): - Get token accounts by owner. - Get account info. - Simulate transactions. - Send transactions. - Confirm transactions. - Parse token-account state. The RPC endpoint URL is supplied via environment config (`packages/config`) and treated as a secret. All chain access flows through `packages/solana`. --- ## 8. AI Services AI is **API-based only** (§11/§12). The MVP server must **not** run local LLMs or local image-generation models. Service classes used: - **Text generation** — Spawn name, ticker, lore, tagline, description, launch copy (§9 outputs). - **Image generation** — from the generated image prompt. - **Moderation / safety** — filtering hate/explicit/extremist/copyrighted/ impersonation/scam-like output (§16). All AI calls are made from `apps/worker` using clients configured via secrets in `packages/config`. Prometheus generates a *candidate package for human review* — it never launches tokens or controls funds (§9). --- ## 9. Infrastructure & Deployment A single **8GB VPS** is sufficient for the MVP (§12). It runs: - `pyre-web`, `pyre-api`, `pyre-worker` - PostgreSQL - Redis - **nginx** (reverse proxy / TLS termination in front of web + api) - **PM2 or systemd** (process supervision for the three Node services) - logs / log rotation - admin dashboard The VPS must **NOT** run (§12): - a Solana validator, - a Solana RPC node, - a large local LLM, - local image generation, - heavy indexing at scale. **Base setup already completed (§12/§19):** `pyre` user created, root login disabled, SSH key auth, UFW firewall, Fail2ban, basic hardening. **Next setup (§12/§19):** Node.js 22, pnpm, Git, nginx, PostgreSQL, Redis, PM2, Claude Code, project repo, environment files, backup script, log rotation. **External accounts required (§19):** Solana RPC provider, OpenAI/Anthropic API key, image-generation provider, domain name, GitHub repo, Pump.fun creator wallet, optional IPFS/Arweave metadata service. --- ## 10. Build-Order Note (Phased Roadmap) Components map to the §18 development phases so a reader knows *what gets built when*: | Phase | Focus | Components touched | |-------|-------|--------------------| | **0 — Server & Repo Setup** | VPS, pnpm workspace, web/api/worker skeletons, Postgres + Redis, nginx, env templates | all apps (skeleton), `packages/config`, `infra/` | | **1 — Wallet Scanner** | Wallet connect, scan endpoint, token-account fetch, basic classification, results + protected/skipped UI | `apps/web`, `apps/api`, `packages/solana` (parsing), `packages/core` (enums/rules), `packages/db` (`wallet_scans`, `token_accounts`) | | **2 — Close Empty ATAs** | Build close-account tx, decode/preview, signing, confirmation tracking, receipt page | `packages/solana` (close builder + decoder + simulation), `apps/api` (`/build/close-empty`, `/receipt`), `apps/worker` (confirmation tracking), `packages/db` (`cleanup_receipts`, `close_account_events`) | | **3 — Burn Junk** | `INCINERATE_ONLY` classification, burn builder, burn-then-close, stronger confirmations, receipt update | `packages/solana` (burn builder), `apps/api` (`/build/burn`), `packages/db` (`burn_events`) | | **4 — Prometheus Generator** | Generation input from receipt, meta mixer, name/ticker/lore + image prompt, safety checks, admin approval UI | `packages/prometheus`, `apps/worker` (AI/safety/collision jobs), `apps/api` (`/prometheus/generate`, admin), `apps/web` (review UI), `packages/db` (`prometheus_generations`, `spawn_candidates`) | | **5 — Manual Pump.fun Launch** | Approved package, metadata JSON, operator checklist, record mint/url/tx, public Spawn page | `apps/web` (public Spawn page), `apps/api` (admin record endpoints), `packages/db` (`spawn_records`) | | **6 — Essence / Round Prototype** | Swap-candidate detection, route quote preview, net Essence estimate, round dashboard, DB-only contribution record (no claim promises) | `packages/solana` (route eval), `apps/api`, `packages/db` (future `pyre_rounds`, `essence_contributions`, `influence_fields`) | | **7 — PYRE Core Program** | Anchor program: create round, contribute Essence, contribution-receipt PDA, lock round, register Spawn, claim, refund, tests | `programs/pyre-core`, future tables `claim_records`, `refund_records` | The first three phases deliver the trust-building burner (v0.1). The Anchor program in `programs/pyre-core` is explicitly **not** needed until Phase 7 / v1.0. --- > **PYRE returns your rent. The scraps feed the fire.**