feat(prometheus+spawn): Prometheus engine (stubbed) + manual Pump.fun creator

Built by 2 parallel agents (+ image-API research):
- @pyre/prometheus: generateSpawn() engine — deterministic §9 meta-mixer
  (40/25/20/15), prompt builder ("inspired mutation, not a clone" + no
  people/brands), name/ticker/lore/tagline gen, image-prompt, denylist + moderation
  safety. PROVIDER-ABSTRACTED (TextProvider/ImageProvider/ModerationProvider) with
  deterministic STUBS so it runs keyless today; real call shapes documented (Claude
  Haiku text · FLUX schnell image · OpenAI omni-moderation). 13 tests.
- @pyre/db: migration 002 (prometheus_generations, spawn_records) + record/list/get.
- @pyre/api: admin-gated POST /api/prometheus/generate + /api/spawn/launch
  (x-admin-token; CLOSED with 403 when ADMIN_API_TOKEN unset; timing-safe compare),
  public GET /api/spawns + /api/spawn/:id.
- @pyre/web: public /spawn record page; @pyre/core SpawnRecord type.

Verified: typecheck 8/8, 134 tests (core 91 + prometheus 13 + solana 30), web build
(+/spawn), migrate 002 live, /api/spawns OK, admin gate returns 403 (unconfigured).
Follow-ups: set ADMIN_API_TOKEN to use admin endpoints; wire real provider keys;
receiptId→DB-id wiring; admin generation UI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 07:09:53 +00:00
parent 28064c5131
commit 8b58faf7c1
16 changed files with 1882 additions and 76 deletions

View File

@@ -9,3 +9,4 @@ export * from "./fee";
export * from "./sell";
export * from "./receipt";
export * from "./prometheus";
export * from "./spawn";

View File

@@ -0,0 +1,51 @@
/**
* Spawn-record schema (§10, §15) — the public, immutable record of a Spawn whose
* token was created on Pump.fun.
*
* In the MVP the Pump.fun launch is MANUAL / approval-gated (§10): Prometheus
* generates a Spawn package, an operator reviews it and creates the token on
* Pump.fun by hand, then records the mint / metadata URI / Pump.fun URL / launch
* tx here. These records are read-only to the public and never imply an
* investment, yield, or profit — they are ritual/entertainment artifacts.
*
* PYRE never holds keys and never signs a launch (§3, §16): the launch tx is
* produced by the operator's own wallet on Pump.fun and merely *recorded* here.
*/
/** Lifecycle status of a {@link SpawnRecord}. */
export type SpawnStatus = "launched" | "pending";
/**
* A public record of a Spawn whose token was (manually) created on Pump.fun.
*
* Mirrors the `spawn_records` table (§15). `mint` / `metadataUri` / `pumpfunUrl`
* / `launchTx` are optional because a record may be filed before every field is
* known, though the manual-launch endpoint requires the launch identifiers.
*/
export interface SpawnRecord {
/** Stable record id (string form of the DB BIGSERIAL). */
id: string;
/** The Prometheus generation this Spawn was launched from. */
generationId: string;
spawnName: string;
ticker: string;
/** SPL mint address of the launched token (base58). */
mint?: string;
/** URI of the token metadata JSON (IPFS/Arweave/etc.). */
metadataUri?: string;
/** Public Pump.fun page for the token. */
pumpfunUrl?: string;
/** Confirmed launch (create) transaction signature. */
launchTx?: string;
status: SpawnStatus;
/** ISO-8601 creation timestamp. */
createdAt: string;
/**
* Optional display image URL surfaced to the public page. Derived from the
* generation metadata (e.g. `metadata.imageUrl`) when present; the launch
* endpoint does not require it.
*/
imageUrl?: string;
/** Optional Spawn lore, carried over from the generation for display. */
lore?: string;
}