chore: scaffold PYRE MVP monorepo (structure + docs)
pnpm + TypeScript workspace per design doc §13:
- apps/{web,api,worker} skeletons (Next.js 16, Fastify 5, BullMQ)
- packages/{core,solana,prometheus,db,config} (core has real types/DTOs;
solana/prometheus are stubs)
- programs/pyre-core placeholder (future Anchor, v1.0)
- docs/: PYRE_MVP_DESIGN (canonical), ARCHITECTURE, SECURITY, TOKEN_CLASSIFICATION
- CLAUDE.md, README, .env.example (no private-key var by design)
Skeleton + docs only — no Solana/business logic yet. All workspaces typecheck clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
38
packages/config/README.md
Normal file
38
packages/config/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# @pyre/config
|
||||
|
||||
Shared configuration and environment loading for PYRE.
|
||||
|
||||
## Purpose
|
||||
|
||||
Per §13: shared config and environment loading. Provides a typed `Env` interface
|
||||
and a `loadConfig()` loader that maps the variables in the repo-root
|
||||
`.env.example` into typed config.
|
||||
|
||||
## Trust rule
|
||||
|
||||
There is intentionally **no** wallet private-key / mnemonic variable here, and
|
||||
there never will be (§3). All signing happens client-side in the user's wallet.
|
||||
|
||||
## Variables (mirrors `.env.example`)
|
||||
|
||||
- **Solana** — `SOLANA_RPC_URL`, `SOLANA_RPC_WS_URL`, `SOLANA_CLUSTER`
|
||||
- **Database** — `DATABASE_URL`
|
||||
- **Redis** — `REDIS_URL`
|
||||
- **AI** — `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `IMAGE_GEN_PROVIDER`,
|
||||
`IMAGE_GEN_API_KEY`
|
||||
- **App URLs / ports** — `WEB_PORT`, `API_PORT`, `WEB_PUBLIC_URL`,
|
||||
`API_PUBLIC_URL`
|
||||
- **Admin / security** — `ADMIN_API_TOKEN`, `RATE_LIMIT_SCAN_PER_MIN`
|
||||
- **Classification thresholds** — `PROTECTED_USD_THRESHOLD`,
|
||||
`MAX_PRICE_IMPACT_BPS`, `QUOTE_MAX_AGE_MS`
|
||||
- **Optional / later phases** — `IPFS_OR_ARWEAVE_ENDPOINT`,
|
||||
`IPFS_OR_ARWEAVE_TOKEN`, `PUMPFUN_CREATOR_WALLET_PUBKEY` (public key only)
|
||||
|
||||
## Status
|
||||
|
||||
**Skeleton.** Defines `Env`; `loadConfig()` is a stub.
|
||||
|
||||
## TODO
|
||||
|
||||
- Implement `loadConfig()` — read `process.env`, validate/coerce, apply defaults,
|
||||
fail fast on missing required values. Never hardcode secrets.
|
||||
17
packages/config/package.json
Normal file
17
packages/config/package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "@pyre/config",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "echo \"lint: ok (placeholder)\"",
|
||||
"test": "echo \"test: ok (placeholder)\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
72
packages/config/src/index.ts
Normal file
72
packages/config/src/index.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @pyre/config — shared config & environment loading (SKELETON).
|
||||
*
|
||||
* Responsibilities (§13): shared config and environment loading. Variables mirror
|
||||
* `.env.example` at the repo root.
|
||||
*
|
||||
* TRUST RULE (§3): there is intentionally NO wallet private-key / mnemonic
|
||||
* variable here, and there never will be. All signing happens client-side.
|
||||
*
|
||||
* Do NOT hardcode secrets — values come from the process environment at runtime.
|
||||
*/
|
||||
|
||||
export type SolanaCluster = "mainnet-beta" | "devnet" | "testnet";
|
||||
|
||||
/**
|
||||
* Typed view of the supported environment variables.
|
||||
* Mirrors `.env.example` (sans the deliberately-absent private-key var).
|
||||
*/
|
||||
export interface Env {
|
||||
// ---- Solana ----
|
||||
solanaRpcUrl: string;
|
||||
solanaRpcWsUrl?: string;
|
||||
solanaCluster: SolanaCluster;
|
||||
|
||||
// ---- Database (PostgreSQL) ----
|
||||
databaseUrl: string;
|
||||
|
||||
// ---- Redis (queues, cache, rate limiting) ----
|
||||
redisUrl: string;
|
||||
|
||||
// ---- AI services (Prometheus) ----
|
||||
anthropicApiKey?: string;
|
||||
openaiApiKey?: string;
|
||||
/** e.g. "openai" | "stability" | "replicate". */
|
||||
imageGenProvider?: string;
|
||||
imageGenApiKey?: string;
|
||||
|
||||
// ---- App URLs / ports ----
|
||||
webPort: number;
|
||||
apiPort: number;
|
||||
webPublicUrl: string;
|
||||
apiPublicUrl: string;
|
||||
|
||||
// ---- Admin / security ----
|
||||
adminApiToken?: string;
|
||||
rateLimitScanPerMin: number;
|
||||
|
||||
// ---- Classification safety thresholds ----
|
||||
/** Skip tokens valued above this (USD). */
|
||||
protectedUsdThreshold: number;
|
||||
/** Skip swap routes above this price impact (basis points). */
|
||||
maxPriceImpactBps: number;
|
||||
/** Skip stale quotes older than this (ms). */
|
||||
quoteMaxAgeMs: number;
|
||||
|
||||
// ---- Optional: metadata / launch (later phases) ----
|
||||
ipfsOrArweaveEndpoint?: string;
|
||||
ipfsOrArweaveToken?: string;
|
||||
/** Public key ONLY — operator signs Pump.fun launches manually in the MVP. */
|
||||
pumpfunCreatorWalletPubkey?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and validate configuration from the process environment.
|
||||
*
|
||||
* TODO: read from `process.env` (mapping the variables in `.env.example`),
|
||||
* validate/coerce types, apply defaults, and fail fast on missing required
|
||||
* values. Never hardcode secrets. There is intentionally no private-key var.
|
||||
*/
|
||||
export function loadConfig(): Env {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
8
packages/config/tsconfig.json
Normal file
8
packages/config/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
32
packages/core/README.md
Normal file
32
packages/core/README.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# @pyre/core
|
||||
|
||||
Shared types and business logic for PYRE / Prometheus Protocol.
|
||||
|
||||
## Purpose
|
||||
|
||||
The canonical home for cross-cutting type definitions and (eventually) pure
|
||||
business logic shared by `apps/*` and the other `packages/*`. Per §13 its
|
||||
responsibilities are:
|
||||
|
||||
- **Classification enums** — `TokenClassification` (§6).
|
||||
- **Risk rules** — conservative safety-rule types/constants (§7). _Placeholder._
|
||||
- **Shared DTOs** — request/response shapes for the HTTP API (§14).
|
||||
- **Receipt schema** — `CleanupReceipt` (§8, §15).
|
||||
- **Prometheus I/O schema** — `PrometheusInput` / `PrometheusOutput` (§9).
|
||||
|
||||
This package carries **real type definitions** but **no application logic** in
|
||||
the skeleton.
|
||||
|
||||
## Modules
|
||||
|
||||
- `src/classification.ts` — `TokenClassification` enum.
|
||||
- `src/dto.ts` — API request/response DTOs.
|
||||
- `src/receipt.ts` — cleanup receipt schema.
|
||||
- `src/prometheus.ts` — Prometheus meta-mixer input/output.
|
||||
- `src/risk.ts` — risk-rule placeholder.
|
||||
|
||||
## TODO
|
||||
|
||||
- Define concrete risk-rule identifiers, threshold shapes, and pure evaluators.
|
||||
- Tighten DTO shapes flagged `TODO` once the scan/classify/build pipeline lands.
|
||||
- Define the concrete token `metadata` JSON shape used by receipts and Prometheus.
|
||||
17
packages/core/package.json
Normal file
17
packages/core/package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "@pyre/core",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "echo \"lint: ok (placeholder)\"",
|
||||
"test": "echo \"test: ok (placeholder)\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
45
packages/core/src/classification.ts
Normal file
45
packages/core/src/classification.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Conservative token-account classification categories.
|
||||
*
|
||||
* See §6 (Token Classification) and §7 (Token Safety Rules) of
|
||||
* `docs/PYRE_MVP_DESIGN.md`. The classifier must be conservative — it must never
|
||||
* assert that a token is "safe", only that it "appears eligible based on current
|
||||
* checks". Anything that cannot be reasoned about safely defaults to
|
||||
* `PROTECTED_SKIP` / `UNSUPPORTED` ("Unknown means skip").
|
||||
*/
|
||||
export enum TokenClassification {
|
||||
/**
|
||||
* Zero balance; the associated token account (ATA) can be closed.
|
||||
* Action: close the ATA and return the recovered rent to the user wallet.
|
||||
*/
|
||||
EMPTY_CLOSE_ONLY = "EMPTY_CLOSE_ONLY",
|
||||
|
||||
/**
|
||||
* Has a balance but no safe swap route; the balance may, however, be burnable.
|
||||
* Action: the user may burn the balance to zero; if the account then becomes
|
||||
* empty it can be closed, and recovered rent returns to the user.
|
||||
*/
|
||||
INCINERATE_ONLY = "INCINERATE_ONLY",
|
||||
|
||||
/**
|
||||
* Has a safe swap route and passes risk checks.
|
||||
* Action: the user may swap the token into SOL; net swapped SOL may become
|
||||
* Essence ONLY if the user explicitly opts in.
|
||||
*/
|
||||
TRANSMUTABLE = "TRANSMUTABLE",
|
||||
|
||||
/**
|
||||
* Not touched by default. Examples: SOL/WSOL special cases, USDC/USDT/major
|
||||
* assets, valuable meme tokens, NFTs, LP tokens, receipt tokens, staked
|
||||
* tokens, suspicious tokens, frozen accounts, delegated accounts, and
|
||||
* high-value balances. Requires explicit manual opt-in to act on.
|
||||
*/
|
||||
PROTECTED_SKIP = "PROTECTED_SKIP",
|
||||
|
||||
/**
|
||||
* The system cannot safely reason about the account. Examples: Token-2022 in
|
||||
* the MVP, unknown token program, bad metadata, unsupported account layout, or
|
||||
* accounts with extension behavior not yet handled.
|
||||
*/
|
||||
UNSUPPORTED = "UNSUPPORTED",
|
||||
}
|
||||
172
packages/core/src/dto.ts
Normal file
172
packages/core/src/dto.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* Shared API DTOs for the PYRE HTTP API.
|
||||
*
|
||||
* Shapes are derived from §14 (API Design) of `docs/PYRE_MVP_DESIGN.md`.
|
||||
*
|
||||
* NOTE: lamport amounts are represented as `string` (not `number`) to avoid
|
||||
* precision loss with large u64 values, matching the design doc's JSON shapes.
|
||||
*
|
||||
* TODO: several shapes below are approximate and will be tightened once the
|
||||
* scan/classify/build pipeline is implemented. Approximations are flagged inline.
|
||||
*/
|
||||
import type { TokenClassification } from "./classification.js";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// POST /api/scan
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface ScanRequest {
|
||||
/** Wallet public key (base58). */
|
||||
wallet: string;
|
||||
}
|
||||
|
||||
export interface ScanSummary {
|
||||
totalAccounts: number;
|
||||
emptyCloseOnly: number;
|
||||
incinerateOnly: number;
|
||||
transmutable: number;
|
||||
protectedSkip: number;
|
||||
unsupported: number;
|
||||
/** Total estimated recoverable rent across closeable accounts, in lamports. */
|
||||
estimatedRentLamports: string;
|
||||
}
|
||||
|
||||
export interface TokenAccountDto {
|
||||
/** Associated token account address (base58). */
|
||||
ata: string;
|
||||
/** Owner wallet (base58). */
|
||||
owner: string;
|
||||
/** Token mint (base58). */
|
||||
mint: string;
|
||||
/** Owning token program (base58). Classic SPL only in the MVP. */
|
||||
tokenProgram: string;
|
||||
/** Raw on-chain balance (u64 as string). */
|
||||
rawBalance: string;
|
||||
/** Human-readable balance (raw / 10^decimals). */
|
||||
uiBalance: number;
|
||||
decimals: number;
|
||||
/** Token symbol, if metadata is available. */
|
||||
symbol?: string;
|
||||
/** Token name, if metadata is available. */
|
||||
name?: string;
|
||||
classification: TokenClassification;
|
||||
/** Human-readable warnings surfaced to the user (e.g. "frozen account"). */
|
||||
warnings: string[];
|
||||
/** Estimated rent recoverable by closing this account, in lamports. */
|
||||
estimatedRentLamports: string;
|
||||
/** Whether the account is frozen, if known. TODO: confirm availability. */
|
||||
frozen?: boolean;
|
||||
/** Whether the account is delegated, if known. TODO: confirm availability. */
|
||||
delegated?: boolean;
|
||||
}
|
||||
|
||||
export interface ScanResponse {
|
||||
/** UUID of the persisted scan. */
|
||||
scanId: string;
|
||||
wallet: string;
|
||||
summary: ScanSummary;
|
||||
accounts: TokenAccountDto[];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// POST /api/build/close-empty
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface BuildCloseEmptyRequest {
|
||||
wallet: string;
|
||||
/** ATA addresses to close (must be EMPTY_CLOSE_ONLY). */
|
||||
accountAddresses: string[];
|
||||
}
|
||||
|
||||
export interface BuildCloseEmptyPreview {
|
||||
accountsToClose: string[];
|
||||
estimatedRentReturnedLamports: string;
|
||||
/** Destination for recovered rent — must default to the user's own wallet. */
|
||||
rentDestination: string;
|
||||
}
|
||||
|
||||
export interface BuildCloseEmptyResponse {
|
||||
/** Unsigned transaction, base64-encoded. Signed client-side only. */
|
||||
transactionBase64: string;
|
||||
preview: BuildCloseEmptyPreview;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// POST /api/build/burn
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface BurnItem {
|
||||
/** Token account holding the balance to burn (base58). */
|
||||
tokenAccount: string;
|
||||
/** Mint of the token being burned (base58). */
|
||||
mint: string;
|
||||
/** Raw amount to burn (u64 as string). */
|
||||
amount: string;
|
||||
}
|
||||
|
||||
export interface BuildBurnRequest {
|
||||
wallet: string;
|
||||
items: BurnItem[];
|
||||
}
|
||||
|
||||
export interface BuildBurnPreview {
|
||||
tokensToBurn: BurnItem[];
|
||||
/** Accounts that may become closeable once their balance reaches zero. */
|
||||
accountsPotentiallyClosable: string[];
|
||||
/** TODO: include estimated rent and fees once the builder is implemented. */
|
||||
estimatedRentReturnedLamports?: string;
|
||||
}
|
||||
|
||||
export interface BuildBurnResponse {
|
||||
/** Unsigned transaction, base64-encoded. Signed client-side only. */
|
||||
transactionBase64: string;
|
||||
preview: BuildBurnPreview;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// POST /api/receipt
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface ReceiptRequest {
|
||||
wallet: string;
|
||||
/** Confirmed transaction signature. */
|
||||
txSignature: string;
|
||||
/** UUID of the originating scan. */
|
||||
scanId: string;
|
||||
}
|
||||
|
||||
export interface ReceiptResponse {
|
||||
receiptId: string;
|
||||
txSignature: string;
|
||||
rentReturnedLamports: string;
|
||||
/** Addresses of accounts that were closed. */
|
||||
closedAccounts: string[];
|
||||
/** Mints (or token accounts) that were burned. TODO: confirm element shape. */
|
||||
burnedTokens: string[];
|
||||
/** Accounts intentionally skipped. TODO: confirm element shape. */
|
||||
skippedTokens: string[];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// POST /api/prometheus/generate
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface PrometheusGenerateRequest {
|
||||
receiptId: string;
|
||||
/** Chaos factor 0..1 controlling mutation strength. */
|
||||
chaos: number;
|
||||
/** Optional manual operator theme seed. */
|
||||
operatorSeed?: string;
|
||||
}
|
||||
|
||||
export interface PrometheusGenerateResponse {
|
||||
generationId: string;
|
||||
spawnName: string;
|
||||
ticker: string;
|
||||
lore: string;
|
||||
imagePrompt: string;
|
||||
/** Token metadata JSON blob. TODO: define concrete metadata shape. */
|
||||
metadata: Record<string, unknown>;
|
||||
/** Safety/compliance flags raised during generation. */
|
||||
riskFlags: string[];
|
||||
}
|
||||
5
packages/core/src/index.ts
Normal file
5
packages/core/src/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from "./classification.js";
|
||||
export * from "./dto.js";
|
||||
export * from "./receipt.js";
|
||||
export * from "./prometheus.js";
|
||||
export * from "./risk.js";
|
||||
43
packages/core/src/prometheus.ts
Normal file
43
packages/core/src/prometheus.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Prometheus AI meta-mixer I/O schema.
|
||||
*
|
||||
* Input/output shapes from §9 (Prometheus AI Meta Mixer) of
|
||||
* `docs/PYRE_MVP_DESIGN.md`. Prometheus generates Spawn *identity* only — it
|
||||
* never controls funds.
|
||||
*/
|
||||
|
||||
/** A token contributing to a Spawn, summarized from a cleanup receipt. */
|
||||
export interface PrometheusTokenRef {
|
||||
mint: string;
|
||||
symbol?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface PrometheusInput {
|
||||
burnedTokens: PrometheusTokenRef[];
|
||||
transmutedTokens: PrometheusTokenRef[];
|
||||
tokenSymbols: string[];
|
||||
tokenNames: string[];
|
||||
metadataDescriptions: string[];
|
||||
/** Dominant thematic archetypes inferred from the inputs. */
|
||||
dominantArchetypes: string[];
|
||||
/** Chaos factor 0..1 controlling mutation strength. */
|
||||
chaosFactor: number;
|
||||
/** Optional manual operator theme seed. */
|
||||
manualThemeSeed?: string;
|
||||
}
|
||||
|
||||
export interface PrometheusOutput {
|
||||
spawnName: string;
|
||||
spawnTicker: string;
|
||||
spawnLore: string;
|
||||
spawnTagline: string;
|
||||
spawnDescription: string;
|
||||
imagePrompt: string;
|
||||
/** Token metadata JSON blob. TODO: define concrete metadata shape. */
|
||||
metadataJson: Record<string, unknown>;
|
||||
/** Marketing/launch copy. */
|
||||
launchCopy: string;
|
||||
/** Safety/compliance flags raised during generation. */
|
||||
riskFlags: string[];
|
||||
}
|
||||
60
packages/core/src/receipt.ts
Normal file
60
packages/core/src/receipt.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Cleanup receipt schema.
|
||||
*
|
||||
* Models the receipt produced after a confirmed burner transaction. Fields are
|
||||
* drawn from §8 (Burner Transaction Flow — step 8) and §15 (cleanup_receipts
|
||||
* table) of `docs/PYRE_MVP_DESIGN.md`.
|
||||
*
|
||||
* This is the canonical, enriched receipt persisted as `receipt_json`; the API
|
||||
* surfaces a subset via `ReceiptResponse` in `dto.ts`.
|
||||
*/
|
||||
|
||||
export interface ClosedAccountEntry {
|
||||
/** ATA address that was closed (base58). */
|
||||
ata: string;
|
||||
mint: string;
|
||||
/** Rent reclaimed from closing this account, in lamports. */
|
||||
rentLamports: string;
|
||||
}
|
||||
|
||||
export interface BurnedTokenEntry {
|
||||
tokenAccount: string;
|
||||
mint: string;
|
||||
/** Raw amount burned (u64 as string). */
|
||||
amount: string;
|
||||
symbol?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface SkippedTokenEntry {
|
||||
ata: string;
|
||||
mint: string;
|
||||
/** Why this account was skipped (classification + warnings). */
|
||||
reason: string;
|
||||
}
|
||||
|
||||
export interface CleanupReceipt {
|
||||
/** Receipt UUID. */
|
||||
receiptId: string;
|
||||
/** Originating scan UUID. */
|
||||
scanId: string;
|
||||
/** Owner wallet (base58). */
|
||||
wallet: string;
|
||||
/** Confirmed transaction signature. */
|
||||
txSignature: string;
|
||||
/** Total rent returned to the user, in lamports. */
|
||||
rentReturnedLamports: string;
|
||||
/** Destination wallet for recovered rent — defaults to the user's wallet. */
|
||||
rentDestination: string;
|
||||
closedAccounts: ClosedAccountEntry[];
|
||||
burnedTokens: BurnedTokenEntry[];
|
||||
skippedTokens: SkippedTokenEntry[];
|
||||
/** Network/transaction fees paid, in lamports. */
|
||||
feeLamports?: string;
|
||||
/** Warnings shown to the user before signing. */
|
||||
warnings: string[];
|
||||
/** ISO-8601 timestamp the receipt was finalized. */
|
||||
createdAt: string;
|
||||
/** Optional shareable receipt image URL. */
|
||||
shareImageUrl?: string;
|
||||
}
|
||||
15
packages/core/src/risk.ts
Normal file
15
packages/core/src/risk.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Risk-rule types and constants (placeholder).
|
||||
*
|
||||
* The conservative safety rules from §7 (Token Safety Rules) live here once the
|
||||
* classifier is implemented. Thresholds are operator-tunable via `@pyre/config`
|
||||
* (e.g. PROTECTED_USD_THRESHOLD, MAX_PRICE_IMPACT_BPS, QUOTE_MAX_AGE_MS).
|
||||
*
|
||||
* Guiding principle: the system must never assert a token is "safe" — only that
|
||||
* it "appears eligible based on current checks". Unknown means skip.
|
||||
*
|
||||
* TODO: define risk-rule identifiers, a RiskRuleResult type, threshold config
|
||||
* shape, and the (pure) evaluation function signatures. No implementation yet.
|
||||
*/
|
||||
|
||||
export {};
|
||||
8
packages/core/tsconfig.json
Normal file
8
packages/core/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
44
packages/db/README.md
Normal file
44
packages/db/README.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# @pyre/db
|
||||
|
||||
Database schema, migrations, and table definitions for PYRE (PostgreSQL).
|
||||
|
||||
## Purpose
|
||||
|
||||
Per §13: the schema, migrations, and table definitions. Uses `pg` for
|
||||
connectivity. Connection details come from `DATABASE_URL` via `@pyre/config` —
|
||||
**never** hardcode credentials.
|
||||
|
||||
## Tables (§15)
|
||||
|
||||
### Initial MVP tables
|
||||
|
||||
- `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
|
||||
|
||||
### Future tables
|
||||
|
||||
- `token_classifications`
|
||||
- `burn_events`
|
||||
- `close_account_events`
|
||||
- `spawn_candidates`
|
||||
- `system_events`
|
||||
|
||||
## Status
|
||||
|
||||
**Skeleton.** Exports table-name constants and a connection-factory stub. No
|
||||
queries, no schema DDL, no migrations yet.
|
||||
|
||||
## TODO
|
||||
|
||||
- Implement the `createPool()` connection factory (read `DATABASE_URL` via
|
||||
`@pyre/config`).
|
||||
- Add SQL migrations under `migrations/` and a migration runner.
|
||||
- Add typed table definitions and a query layer.
|
||||
0
packages/db/migrations/.gitkeep
Normal file
0
packages/db/migrations/.gitkeep
Normal file
15
packages/db/migrations/README.md
Normal file
15
packages/db/migrations/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Migrations
|
||||
|
||||
SQL migrations for the PYRE PostgreSQL database.
|
||||
|
||||
**Empty for now** (skeleton). Migration files and a runner will be added here.
|
||||
|
||||
## Convention (TODO)
|
||||
|
||||
- One forward migration per file, ordered/timestamped (e.g.
|
||||
`0001_init.sql`, `0002_<change>.sql`).
|
||||
- The first migration creates the initial MVP tables listed in the package
|
||||
README (§15): `wallet_scans`, `token_accounts`, `cleanup_receipts`,
|
||||
`prometheus_generations`, `spawn_records`.
|
||||
- A migration runner (in `@pyre/db`) applies pending migrations against
|
||||
`DATABASE_URL`.
|
||||
22
packages/db/package.json
Normal file
22
packages/db/package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "@pyre/db",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "echo \"lint: ok (placeholder)\"",
|
||||
"test": "echo \"test: ok (placeholder)\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@pyre/config": "workspace:*",
|
||||
"pg": "^8.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/pg": "^8.11.10",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
44
packages/db/src/index.ts
Normal file
44
packages/db/src/index.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @pyre/db — database schema, migrations, and table definitions (SKELETON).
|
||||
*
|
||||
* Responsibilities (§13): database schema, migrations, table definitions.
|
||||
* Schema reference: §15 (MVP Database Schema) of `docs/PYRE_MVP_DESIGN.md`.
|
||||
*
|
||||
* No queries are implemented here yet — only table-name constants and a
|
||||
* connection-factory stub.
|
||||
*/
|
||||
import type { Pool } from "pg";
|
||||
|
||||
/**
|
||||
* Canonical table names. Centralized so query/migration code references a single
|
||||
* source of truth.
|
||||
*/
|
||||
export const TABLES = {
|
||||
// Initial MVP tables (§15)
|
||||
WALLET_SCANS: "wallet_scans",
|
||||
TOKEN_ACCOUNTS: "token_accounts",
|
||||
CLEANUP_RECEIPTS: "cleanup_receipts",
|
||||
PROMETHEUS_GENERATIONS: "prometheus_generations",
|
||||
SPAWN_RECORDS: "spawn_records",
|
||||
|
||||
// Future tables (§15)
|
||||
TOKEN_CLASSIFICATIONS: "token_classifications",
|
||||
BURN_EVENTS: "burn_events",
|
||||
CLOSE_ACCOUNT_EVENTS: "close_account_events",
|
||||
SPAWN_CANDIDATES: "spawn_candidates",
|
||||
SYSTEM_EVENTS: "system_events",
|
||||
} as const;
|
||||
|
||||
export type TableName = (typeof TABLES)[keyof typeof TABLES];
|
||||
|
||||
/**
|
||||
* Connection-factory stub.
|
||||
*
|
||||
* TODO: create and cache a `pg` Pool from DATABASE_URL (resolved via
|
||||
* `@pyre/config` — never hardcode credentials). Then add a migration runner and
|
||||
* typed table-definition / query layer. No queries are implemented yet.
|
||||
*/
|
||||
export function createPool(): Pool {
|
||||
// TODO: const { databaseUrl } = loadConfig(); return new Pool({ connectionString: databaseUrl });
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
8
packages/db/tsconfig.json
Normal file
8
packages/db/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
36
packages/prometheus/README.md
Normal file
36
packages/prometheus/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# @pyre/prometheus
|
||||
|
||||
AI generation logic for the Prometheus meta mixer.
|
||||
|
||||
## Purpose
|
||||
|
||||
Generates Spawn **identity** (name, ticker, lore, image prompt, metadata) from
|
||||
cleanup receipts. Per §13 its responsibilities are:
|
||||
|
||||
- Prompt templates.
|
||||
- Meta mixer.
|
||||
- Output parser.
|
||||
- Safety checks.
|
||||
- Image-prompt generator.
|
||||
|
||||
See §9 (meta mixer) and §10 (Pump.fun creator workflow). Prometheus never
|
||||
controls funds; it only produces creative identity for **manual, human-reviewed**
|
||||
launch in the MVP.
|
||||
|
||||
## Design rules
|
||||
|
||||
- Meta influence is probabilistic, not deterministic.
|
||||
- Produce inspired mutations, not direct clones — reject exact copyrighted or
|
||||
existing meme identities.
|
||||
|
||||
## Status
|
||||
|
||||
**Stubs only.** Every exported function throws `Error("not implemented")`.
|
||||
|
||||
## TODO
|
||||
|
||||
- Implement `buildPrompt`, `runMetaMixer`, `parseOutput`, `runSafetyChecks`,
|
||||
`generateImagePrompt`.
|
||||
- The AI client (Anthropic / OpenAI / image-gen provider) is configured via
|
||||
`@pyre/config` and injected here. This package adds **no** SDK dependencies of
|
||||
its own.
|
||||
20
packages/prometheus/package.json
Normal file
20
packages/prometheus/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "@pyre/prometheus",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "echo \"lint: ok (placeholder)\"",
|
||||
"test": "echo \"test: ok (placeholder)\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@pyre/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
72
packages/prometheus/src/index.ts
Normal file
72
packages/prometheus/src/index.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @pyre/prometheus — AI generation logic (STUBS ONLY).
|
||||
*
|
||||
* Responsibilities (§13): prompt templates, the meta mixer, output parser,
|
||||
* safety checks, and the image-prompt generator. See §9 (Prometheus AI Meta
|
||||
* Mixer) and §10 (Pump.fun Creator Workflow) of `docs/PYRE_MVP_DESIGN.md`.
|
||||
*
|
||||
* Design notes:
|
||||
* - Prometheus generates Spawn *identity* only — it never controls funds.
|
||||
* - Meta influence is probabilistic, not deterministic.
|
||||
* - Do not allow users to force exact copyrighted/existing meme identities;
|
||||
* produce inspired mutations, not direct clones.
|
||||
*
|
||||
* TODO: the AI client (Anthropic / OpenAI / image-gen provider) is configured
|
||||
* via `@pyre/config` and injected here — this package adds NO SDK dependencies
|
||||
* of its own. Wire the client through function parameters or a small interface.
|
||||
*
|
||||
* Nothing here is implemented yet — every function throws "not implemented".
|
||||
*/
|
||||
import type { PrometheusInput, PrometheusOutput } from "@pyre/core";
|
||||
|
||||
const NOT_IMPLEMENTED = "not implemented";
|
||||
|
||||
/**
|
||||
* Build the text-generation prompt from mixer input.
|
||||
*
|
||||
* TODO: apply prompt templates and the probabilistic meta-influence weighting
|
||||
* (burned archetypes / Essence themes / chaos mutation / operator seed).
|
||||
*/
|
||||
export function buildPrompt(_input: PrometheusInput): string {
|
||||
throw new Error(NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the meta mixer end-to-end: build prompt, call the AI client, parse, and
|
||||
* run safety checks, producing a Spawn package.
|
||||
*
|
||||
* TODO: orchestrate buildPrompt -> AI client -> parseOutput -> runSafetyChecks.
|
||||
* The AI client is injected (configured via @pyre/config).
|
||||
*/
|
||||
export function runMetaMixer(_input: PrometheusInput): Promise<PrometheusOutput> {
|
||||
throw new Error(NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a raw model response into a structured `PrometheusOutput`.
|
||||
*
|
||||
* TODO: validate/normalize the model JSON into the output schema.
|
||||
*/
|
||||
export function parseOutput(_raw: string): PrometheusOutput {
|
||||
throw new Error(NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run safety/compliance checks over generated output.
|
||||
*
|
||||
* TODO: moderation + copyright/clone guards; return risk flags. Must reject
|
||||
* attempts to clone exact copyrighted or existing meme identities.
|
||||
*/
|
||||
export function runSafetyChecks(_output: PrometheusOutput): Promise<string[]> {
|
||||
throw new Error(NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an image prompt for the Spawn artwork.
|
||||
*
|
||||
* TODO: derive an image prompt from the Spawn identity, honoring the same
|
||||
* anti-clone safety rules.
|
||||
*/
|
||||
export function generateImagePrompt(_output: PrometheusOutput): string {
|
||||
throw new Error(NOT_IMPLEMENTED);
|
||||
}
|
||||
8
packages/prometheus/tsconfig.json
Normal file
8
packages/prometheus/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
33
packages/solana/README.md
Normal file
33
packages/solana/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# @pyre/solana
|
||||
|
||||
Solana transaction helpers for PYRE.
|
||||
|
||||
## Purpose
|
||||
|
||||
Token-account reading and **unsigned** transaction construction for the burner
|
||||
flow. Per §13 its responsibilities are:
|
||||
|
||||
- Token-account parsing.
|
||||
- Close-account transaction builder.
|
||||
- Burn transaction builder.
|
||||
- Simulation helpers.
|
||||
- Transaction decoder (for preview matching).
|
||||
|
||||
## Trust rules (load-bearing)
|
||||
|
||||
- PYRE never holds private keys — this package builds **unsigned** transactions;
|
||||
signing happens client-side in the user's wallet.
|
||||
- Recovered ATA rent defaults to the user's own wallet.
|
||||
- Always simulate, then **decode** and match against the user-facing preview
|
||||
before requesting a signature.
|
||||
- Classic SPL only in the MVP. Skip Token-2022, NFTs, and unsupported layouts.
|
||||
|
||||
## Status
|
||||
|
||||
**Stubs only.** Every exported function throws `Error("not implemented")`.
|
||||
|
||||
## TODO
|
||||
|
||||
- Implement `parseTokenAccounts`, `buildCloseEmptyAccountsTx`, `buildBurnTx`,
|
||||
`simulateTransaction`, and `decodeTransaction`.
|
||||
- Wire classification through `@pyre/core`.
|
||||
22
packages/solana/package.json
Normal file
22
packages/solana/package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "@pyre/solana",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "echo \"lint: ok (placeholder)\"",
|
||||
"test": "echo \"test: ok (placeholder)\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@pyre/core": "workspace:*",
|
||||
"@solana/web3.js": "^1.98.0",
|
||||
"@solana/spl-token": "^0.4.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
94
packages/solana/src/index.ts
Normal file
94
packages/solana/src/index.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @pyre/solana — Solana transaction helpers (STUBS ONLY).
|
||||
*
|
||||
* Responsibilities (§13): token-account parsing, close-account tx builder, burn
|
||||
* tx builder, simulation helpers, and a transaction decoder.
|
||||
*
|
||||
* IMPORTANT (trust rules, §3/§7/§16):
|
||||
* - PYRE never holds private keys; these helpers build **unsigned** transactions
|
||||
* only. Signing happens client-side in the user's wallet.
|
||||
* - Recovered ATA rent must default to the user's own wallet.
|
||||
* - Every transaction must be simulated and **decoded**, then matched against the
|
||||
* preview shown to the user before any signature is requested.
|
||||
* - Classic SPL only in the MVP. Skip Token-2022 / NFTs / unsupported layouts.
|
||||
*
|
||||
* Nothing here is implemented yet — every function throws "not implemented".
|
||||
*/
|
||||
import type { Connection, PublicKey } from "@solana/web3.js";
|
||||
import type {
|
||||
TokenAccountDto,
|
||||
BuildCloseEmptyPreview,
|
||||
BuildBurnPreview,
|
||||
BurnItem,
|
||||
} from "@pyre/core";
|
||||
|
||||
const NOT_IMPLEMENTED = "not implemented";
|
||||
|
||||
/**
|
||||
* Parse a wallet's SPL token accounts into classified DTOs.
|
||||
*
|
||||
* TODO: fetch token accounts via RPC, decode account state (balance, decimals,
|
||||
* frozen/delegated, token program), resolve metadata, and hand off to the
|
||||
* classifier in `@pyre/core`. Classic SPL only.
|
||||
*/
|
||||
export function parseTokenAccounts(
|
||||
_connection: Connection,
|
||||
_wallet: PublicKey,
|
||||
): Promise<TokenAccountDto[]> {
|
||||
throw new Error(NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an UNSIGNED transaction that closes the given empty ATAs, returning rent
|
||||
* to the user wallet.
|
||||
*
|
||||
* TODO: assemble CloseAccount instructions, set fee payer + rent destination to
|
||||
* the user, return a base64 transaction plus a matching preview.
|
||||
*/
|
||||
export function buildCloseEmptyAccountsTx(
|
||||
_connection: Connection,
|
||||
_wallet: PublicKey,
|
||||
_accountAddresses: PublicKey[],
|
||||
): Promise<{ transactionBase64: string; preview: BuildCloseEmptyPreview }> {
|
||||
throw new Error(NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an UNSIGNED transaction that burns the given token balances (optionally
|
||||
* closing accounts that become empty).
|
||||
*
|
||||
* TODO: assemble Burn (and optional CloseAccount) instructions, return a base64
|
||||
* transaction plus a matching preview.
|
||||
*/
|
||||
export function buildBurnTx(
|
||||
_connection: Connection,
|
||||
_wallet: PublicKey,
|
||||
_items: BurnItem[],
|
||||
): Promise<{ transactionBase64: string; preview: BuildBurnPreview }> {
|
||||
throw new Error(NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate a transaction before signing.
|
||||
*
|
||||
* TODO: run `connection.simulateTransaction`, surface logs/errors, and confirm
|
||||
* the simulation succeeds. All transactions must be simulated before signing.
|
||||
*/
|
||||
export function simulateTransaction(
|
||||
_connection: Connection,
|
||||
_transactionBase64: string,
|
||||
): Promise<unknown> {
|
||||
throw new Error(NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode an unsigned transaction so its contents can be matched against the
|
||||
* preview shown to the user (accounts to close, tokens to burn, rent amount,
|
||||
* rent destination, fees, warnings).
|
||||
*
|
||||
* TODO: deserialize the transaction, decode SPL instructions, and return a
|
||||
* structured, human-comparable summary.
|
||||
*/
|
||||
export function decodeTransaction(_transactionBase64: string): unknown {
|
||||
throw new Error(NOT_IMPLEMENTED);
|
||||
}
|
||||
8
packages/solana/tsconfig.json
Normal file
8
packages/solana/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
Reference in New Issue
Block a user