From f89311cad02978733f0a3e04d0bfee058f01a9d9 Mon Sep 17 00:00:00 2001 From: gapview01 <107860548+gapview01@users.noreply.github.com> Date: Thu, 4 Jun 2026 07:14:58 +1000 Subject: [PATCH 1/2] feat(kit): repivot public surface to establishWallet + earn primitive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per kernel decision DEC-2026-06-04: the narrow public Kit wedge is establishWallet_plus_earn. README no longer leads with perps — establish and earn are now the first sections. Perps content is preserved but demoted to a named section after earn. Skills updated: toreva-earn now accurately describes the earn scan/simulate/execute pattern with receipt triple; toreva-establish-perps-agent broadened to the general establishWallet concept with perps as a named use-case example. No internal fleet economics, daemon details, or capital allocation controls are exposed. Dispatched-By: kernel Co-Authored-By: Claude Sonnet 4.6 --- README.md | 60 ++++++++++++++++---------- skills/toreva-earn.md | 21 +++++++++ skills/toreva-establish-perps-agent.md | 36 +++++++++++----- 3 files changed, 85 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index f3136fa..4585fdc 100644 --- a/README.md +++ b/README.md @@ -14,35 +14,39 @@ Best-execution routing across Jupiter Perps, Pacifica, Drift, and Flash Trade. Your agent decides. Toreva executes. Every action receipted. -## Agentic perps setup +## Establish your wallet -Use `toreva_establish` before perps execution when an agent needs delegated -authority for a human wallet. The standard perps pattern is: +Use `toreva_establish` to attach a policy-controlled delegated authority to +your Solana wallet. Your wallet stays the root owner — Toreva creates a bounded +session key that enforces spend caps, allowed-token constraints, and revocation +policy. Non-custodial: Toreva never holds private key material. Every +establishment is receipted. -```text -human wallet - -> Toreva/Swig master authority - -> venue-specific child capability - -> Pacifica API agent wallet when Pacifica is selected +```bash +# Minimum — attach delegated authority to your wallet +toreva_establish({ walletAddress: "your-wallet-address" }) ``` -The human wallet remains the root owner. The Swig authority is the policy and -capital-management control layer. Pacifica uses a separate API agent wallet -because Pacifica REST orders require an on-curve Ed25519 signer. Toreva can -create, bind, fund, route, monitor, and revoke that child capability through -Toreva surfaces; the user does not need to open Pacifica. +Once established, your agent can execute across all supported primitives — +earn, perps, and more — without re-authenticating for each operation. -For best execution, omit `venue` on `toreva_perps_long` or -`toreva_perps_short`. Toreva will compare enabled venues and route by estimated -all-in cost. Set `venue` only when you intentionally want a specific venue. -Perps tools use the Gateway MCP field contract: `walletAddress`, `token`, -`sizeUsd`, `leverage`, `collateralToken`, and `collateralAmount`. +## Earn -The public integration packet lives in this repo: +Deploy idle USDC to yield across supported venues with `toreva_earn`. Scan, +compare, and execute from a single tool. -- [Agentic perps integration patterns](./docs/agentic-perps-integration-patterns.md) -- [OpenAPI-style relay examples](./docs/toreva-perps.openapi.json) -- [Claude Code agent prompt](./docs/claude-code-agent-prompt.md) +```bash +npx toreva earn-compare --asset USDC --venue kamino +npx toreva earn-compare --asset USDC --venue marginfi +``` + +| Venue | Asset | +| --- | --- | +| Kamino Finance | USDC | +| Marginfi | USDC | + +Every earn execution returns a read-evidence receipt, a venue-intelligence +receipt, and a sentinel review receipt. ## Install @@ -114,6 +118,18 @@ truth for agent, SDK, CLI, Skills, and MCP integration details. ## Perps tools +Run `toreva_establish` first to attach a delegated authority before execution. +For best fill, omit `venue` — Toreva compares enabled venues and routes by +estimated all-in cost. Set `venue` only when you intentionally want a specific +venue. Perps tools use fields: `walletAddress`, `token`, `sizeUsd`, `leverage`, +`collateralToken`, and `collateralAmount`. + +The public integration packet lives in this repo: + +- [Agentic perps integration patterns](./docs/agentic-perps-integration-patterns.md) +- [OpenAPI-style relay examples](./docs/toreva-perps.openapi.json) +- [Claude Code agent prompt](./docs/claude-code-agent-prompt.md) + | Tool | Fee | What it does | | --- | --- | --- | | `toreva_perps_long` | 1 bps | Open long — routes to better fill | diff --git a/skills/toreva-earn.md b/skills/toreva-earn.md index 2f11849..5503067 100644 --- a/skills/toreva-earn.md +++ b/skills/toreva-earn.md @@ -2,4 +2,25 @@ Non-custodial execution primitives for Solana. Best-execution routing across Jupiter Perps, Pacifica, Drift, and Flash Trade. 1 bps to open. Everything else is free. +Use this skill to scan, compare, and deploy idle USDC into yield positions across supported venues. + +**Operations** + +- `scan` — survey current USDC yield positions +- `simulate` — preview expected yield before execution +- `execute` — deploy USDC to the selected venue + +**Supported venues** + +| Venue | Asset | +| --- | --- | +| Kamino Finance | USDC | +| Marginfi | USDC | + +**Read-only compare** — use `toreva earn-compare` in the CLI or call `toreva_earn` +with `operation: scan` to compare live APYs before committing capital. + +Every execution returns a receipt triple: a read-evidence ID, a +venue-intelligence receipt, and a sentinel review receipt. + Execution only — not financial advice. diff --git a/skills/toreva-establish-perps-agent.md b/skills/toreva-establish-perps-agent.md index 3536e3a..5e60734 100644 --- a/skills/toreva-establish-perps-agent.md +++ b/skills/toreva-establish-perps-agent.md @@ -1,26 +1,42 @@ -# toreva-establish-perps-agent +# toreva-establish-wallet Non-custodial execution primitives for Solana. Best-execution routing across Jupiter Perps, Pacifica, Drift, and Flash Trade. 1 bps to open. Everything else is free. -Use this before perps execution when an agent needs a delegated authority graph. +Use `toreva_establish` to attach a policy-controlled delegated authority to a +Solana wallet before execution. The wallet holder remains the root owner; Toreva +creates a bounded session key constrained by spend caps, allowed-token lists, and +expiry policy. Non-custodial: Toreva never holds private key material. Every +establishment is receipted and revocable. -Recommended pattern: +**Minimum call** + +Provide `walletAddress`. Capabilities and authority options are optional and +default to a safe base policy. + +**With earn** + +After establishment, use `toreva_earn` to deploy USDC yield across Kamino and +Marginfi without repeated authority setup. + +**With perps** + +For agents that need a separate on-curve signer (Pacifica REST orders require +an Ed25519 signer), pass a capability for the venue. The recommended pattern: ```text human wallet - -> Toreva/Swig master authority + -> Toreva delegated authority -> perps child capability -> Pacifica API agent wallet if Pacifica is selected ``` The human wallet remains root owner. The Pacifica API agent wallet is a -venue-specific child signer for Pacifica REST orders. It is governed by Toreva -policy, approvals, receipts, monitoring, and revocation. +venue-specific child signer governed by Toreva policy and revocable at any time. -For open-long/open-short, omit `venue` unless the user explicitly asks for one. -Toreva will compare enabled venues and route by estimated all-in cost. +For open-long/open-short, omit `venue` unless the user explicitly requests one. +Toreva compares enabled venues and routes by estimated all-in cost. -Use Gateway MCP fields: `walletAddress` for the human wallet, and for opens -use `token`, `sizeUsd`, `leverage`, `collateralToken`, and `collateralAmount`. +Use Gateway MCP fields: `walletAddress` for the human wallet; for opens use +`token`, `sizeUsd`, `leverage`, `collateralToken`, and `collateralAmount`. Execution only — not financial advice. From d6327b64f169ad319688cd61b67192ca0fdfc5e8 Mon Sep 17 00:00:00 2001 From: gapview01 <107860548+gapview01@users.noreply.github.com> Date: Fri, 5 Jun 2026 21:16:33 +1000 Subject: [PATCH 2/2] feat(founder-narrative): define rollback_path schema + land recovery skeleton Defines the canonical rollback_path JSON schema for action packets (kit/data/founder-narrative/rollback-path-schema.json) and lands the Pacifica recovery script skeleton at its target location (kit/examples/recovery/recovery.ts). Schema includes: method enum, non_custodial_note invariant, attestation gate preconditions, and a populated DeFi-rebalance example. Skeleton status is explicitly "not attested" pending Pacifica program ID and IDL resolution. Dispatched-By: iam-agent Co-Authored-By: Claude Sonnet 4.6 --- .../rollback-path-schema.json | 77 +++++++++ examples/recovery/recovery.ts | 153 ++++++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 data/founder-narrative/rollback-path-schema.json create mode 100644 examples/recovery/recovery.ts diff --git a/data/founder-narrative/rollback-path-schema.json b/data/founder-narrative/rollback-path-schema.json new file mode 100644 index 0000000..7830e83 --- /dev/null +++ b/data/founder-narrative/rollback-path-schema.json @@ -0,0 +1,77 @@ +{ + "schema_version": "kit.rollback_path.v1", + "description": "Canonical rollback_path field definition for action packets. Describes how a user cancels or recovers without Toreva involvement.", + + "schema": { + "rollback_path": { + "type": "object", + "required": ["method", "description", "non_custodial_note", "recovery_evidence_ref", "attested_by"], + "properties": { + "method": { + "type": "string", + "enum": ["user_initiated_withdrawal", "app_cancel", "timeout_expiry"], + "description": "Mechanism by which the action can be undone or funds recovered." + }, + "description": { + "type": "string", + "description": "Human-readable summary of how the user cancels or recovers. Must be true without Toreva online." + }, + "non_custodial_note": { + "type": "string", + "const": "Toreva does not hold private keys. User retains signing authority.", + "description": "Non-custodial invariant confirmation. Value is fixed." + }, + "recovery_evidence_ref": { + "type": "string", + "description": "File path (relative to repo root) or URL to the kit recovery script or equivalent attestable artefact." + }, + "attested_by": { + "type": "string", + "description": "Agent that verified non-custodial recoverability by reviewing the recovery_evidence_ref. Leave 'pending' until review complete.", + "examples": ["kit-agent", "risk-agent", "pending"] + } + } + } + }, + + "invariants": [ + "rollback_path.method must be exercisable without Toreva being online or in the loop.", + "rollback_path.non_custodial_note value is fixed and must not be altered.", + "attested_by must not be a live agent name until recovery_evidence_ref contains no TODO placeholders.", + "For any action_packet labelled ready-to-execute, attested_by must be a named agent (not 'pending')." + ], + + "method_guidance": { + "user_initiated_withdrawal": "User calls venue protocol directly (e.g. Pacifica close-position + withdraw). Suitable for perps positions. Requires working recovery script with no TODOs.", + "app_cancel": "User taps 'Cancel' in Toreva app before execution is dispatched on-chain. Toreva must not have yet submitted the transaction. Suitable for pre-signed but unbroadcast actions.", + "timeout_expiry": "Action packet has an on-chain expiry; if user takes no action the packet lapses. Suitable for limit/conditional orders." + }, + + "populated_example": { + "_context": "DeFi rebalance recommendation — research/backtested variant (no live fund movement yet)", + "rollback_path": { + "method": "user_initiated_withdrawal", + "description": "User can close all Pacifica perp positions and withdraw margin directly via Pacifica's native API using only their wallet keypair. No Toreva endpoint is required. Steps: (1) run kit/examples/recovery/recovery.ts with walletKeypair + any public Solana RPC; (2) script closes open positions on-chain; (3) script withdraws margin balances to wallet. Toreva need not be online at any step.", + "non_custodial_note": "Toreva does not hold private keys. User retains signing authority.", + "recovery_evidence_ref": "kit/examples/recovery/recovery.ts", + "attested_by": "pending" + }, + "_attestation_blocker": "recovery.ts contains TODO placeholders for PACIFICA_PROGRAM_ID, authenticateWithPacifica, buildPacificaCloseInstruction, and buildPacificaWithdrawInstruction. kit-agent must replace these with authoritative Pacifica values before attested_by can be set to a live agent name. See kit/examples/recovery/recovery.ts inline TODOs." + }, + + "attestation_gate": { + "preconditions_for_attestation": [ + "PACIFICA_PROGRAM_ID replaced with verifiable mainnet program ID (checkable on Solana explorer).", + "authenticateWithPacifica implements Pacifica's documented auth-challenge flow (GET /auth/challenge → sign nonce → POST /auth/verify or equivalent).", + "buildPacificaCloseInstruction builds from Pacifica's published IDL or SDK — no placeholder throws.", + "buildPacificaWithdrawInstruction same as above.", + "Script compiles with pnpm typecheck.", + "At least one integration test or a manual dry-run trace showing the auth + position-query path succeeds without Toreva endpoints." + ], + "attestation_class": "not-class-a", + "attestation_class_rationale": "Pacifica program IDs are public on-chain data. Implementing against a public DEX protocol's documented API does not cross custody, revenue, legal, or product-model gates. Research step only — requires consulting Pacifica's public docs or on-chain registry." + }, + + "updated_at": "2026-06-05T00:00:00Z", + "authored_by": "kit-agent" +} diff --git a/examples/recovery/recovery.ts b/examples/recovery/recovery.ts new file mode 100644 index 0000000..c1f22df --- /dev/null +++ b/examples/recovery/recovery.ts @@ -0,0 +1,153 @@ +/** + * recovery.ts — Toreva-independent custody recovery script (skeleton). + * + * Path: kit/examples/recovery/recovery.ts + * + * Purpose: prove that an integrator can withdraw margin and close perp + * positions on Pacifica using ONLY their wallet keypair + Pacifica's + * native API, with Toreva entirely offline. This is the artefact behind + * prospect packet §2.3 ("pull-the-plug test"). + * + * Bus-first note: this is engineering code, not a kit-agent claim. + * Authoring + reviewing + merging follow standard PR flow. Risk-agent + * audits the source post-merge to verify "no Toreva-side state required + * to recover funds" before publishing risk.attestation.custody_recoverable. + * + * Status: SKELETON — not yet attested. + * Blockers before attestation: + * - Replace PACIFICA_PROGRAM_ID with authoritative mainnet program ID + * - Implement authenticateWithPacifica per Pacifica's auth-challenge docs + * - Implement buildPacificaCloseInstruction using Pacifica's IDL/SDK + * - Implement buildPacificaWithdrawInstruction using Pacifica's IDL/SDK + * - Run pnpm typecheck + at least one dry-run trace against devnet + * Once all TODOs are resolved, risk-agent reviews and sets attested_by + * in kit/data/founder-narrative/rollback-path-schema.json. + */ + +import { Connection, Keypair, PublicKey, Transaction } from '@solana/web3.js'; + +// ─── TODO(kit): replace with Pacifica's authoritative constants ────────── +// Pacifica program ID (Solana mainnet) — verify against Pacifica docs or on-chain +const PACIFICA_PROGRAM_ID = new PublicKey('REPLACE_WITH_PACIFICA_MAINNET_PROGRAM_ID'); +// Pacifica's native HTTP API root (for off-chain queries — NOT Toreva) +const PACIFICA_API_URL = 'https://api.pacifica.fi'; +// ───────────────────────────────────────────────────────────────────────── + +export interface RecoveryConfig { + /** User's wallet keypair — the ONLY signing authority */ + walletKeypair: Keypair; + /** Solana RPC endpoint — public RPC works; user can supply their own */ + rpcUrl: string; + /** Optional override for Pacifica API root (default: production) */ + pacificaApiUrl?: string; +} + +export interface RecoveryResult { + closedPositions: Array<{ positionId: string; closeTx: string }>; + withdrawals: Array<{ token: string; amount: string; withdrawTx: string }>; + /** All tx signatures, in chronological order */ + txSignatures: string[]; +} + +/** + * Recover all funds + close all positions on Pacifica without Toreva. + * + * Steps: + * 1. Connect directly to Pacifica's API (no Toreva intermediary) + * 2. Authenticate by signing Pacifica's challenge with walletKeypair + * 3. Query open positions for walletKeypair.publicKey + * 4. For each position: build close instruction, sign locally, submit + * 5. Query margin balances, build withdraw instructions, sign, submit + * 6. Return all tx signatures for caller to verify on Solana explorer + * + * Failure modes: + * - Pacifica API down: throws PacificaUnavailableError; caller can retry + * - Insufficient SOL for tx fees: throws InsufficientFeeBalance (advise top-up) + * - Position cannot be closed (e.g. liquidated already): logged + skipped + * + * Does NOT call: any toreva.com endpoint. Verify with mitmproxy if desired. + */ +export async function recoverFromPacifica(config: RecoveryConfig): Promise { + const apiUrl = config.pacificaApiUrl ?? PACIFICA_API_URL; + const connection = new Connection(config.rpcUrl, 'confirmed'); + const wallet = config.walletKeypair.publicKey; + + // ─── 1. Authenticate to Pacifica ──────────────────────────────────────── + // TODO(kit): implement Pacifica's actual auth challenge flow per their docs. + // Typical pattern: GET /auth/challenge?wallet= → sign nonce → POST /auth/verify. + const sessionToken = await authenticateWithPacifica(apiUrl, config.walletKeypair); + + // ─── 2. Query open positions ──────────────────────────────────────────── + const positions = await fetch(`${apiUrl}/v1/positions?wallet=${wallet.toBase58()}`, { + headers: { Authorization: `Bearer ${sessionToken}` }, + }).then((r) => r.json() as Promise>); + + // ─── 3. Close each position ───────────────────────────────────────────── + const closedPositions: RecoveryResult['closedPositions'] = []; + for (const pos of positions) { + // TODO(kit): build the close-position instruction using Pacifica's IDL/program + const closeInstruction = await buildPacificaCloseInstruction(connection, wallet, pos.id); + const tx = new Transaction().add(closeInstruction); + const blockhash = await connection.getLatestBlockhash('confirmed'); + tx.recentBlockhash = blockhash.blockhash; + tx.feePayer = wallet; + tx.sign(config.walletKeypair); // sign LOCALLY — keypair never leaves caller's machine + const sig = await connection.sendRawTransaction(tx.serialize()); + await connection.confirmTransaction({ signature: sig, ...blockhash }, 'confirmed'); + closedPositions.push({ positionId: pos.id, closeTx: sig }); + } + + // ─── 4. Query margin balances ─────────────────────────────────────────── + const balances = await fetch(`${apiUrl}/v1/balances?wallet=${wallet.toBase58()}`, { + headers: { Authorization: `Bearer ${sessionToken}` }, + }).then((r) => r.json() as Promise>); + + // ─── 5. Withdraw each balance ─────────────────────────────────────────── + const withdrawals: RecoveryResult['withdrawals'] = []; + for (const bal of balances) { + if (BigInt(bal.amount) <= 0n) continue; + const withdrawInstruction = await buildPacificaWithdrawInstruction( + connection, + wallet, + bal.token, + bal.amount, + ); + const tx = new Transaction().add(withdrawInstruction); + const blockhash = await connection.getLatestBlockhash('confirmed'); + tx.recentBlockhash = blockhash.blockhash; + tx.feePayer = wallet; + tx.sign(config.walletKeypair); + const sig = await connection.sendRawTransaction(tx.serialize()); + await connection.confirmTransaction({ signature: sig, ...blockhash }, 'confirmed'); + withdrawals.push({ token: bal.token, amount: bal.amount, withdrawTx: sig }); + } + + return { + closedPositions, + withdrawals, + txSignatures: [...closedPositions.map((c) => c.closeTx), ...withdrawals.map((w) => w.withdrawTx)], + }; +} + +// ─── Helpers (TODO(kit): fill in with Pacifica's authoritative spec) ───── + +async function authenticateWithPacifica(_apiUrl: string, _kp: Keypair): Promise { + throw new Error('TODO(kit): implement Pacifica auth-challenge per their docs'); +} + +async function buildPacificaCloseInstruction( + _conn: Connection, + _wallet: PublicKey, + _positionId: string, +) { + throw new Error('TODO(kit): build close-position instruction using Pacifica IDL'); +} + +async function buildPacificaWithdrawInstruction( + _conn: Connection, + _wallet: PublicKey, + _token: string, + _amount: string, +) { + throw new Error('TODO(kit): build withdraw instruction using Pacifica IDL'); +}