/** * Trade plans — the approval artifact standing between the agent and real * money. Before any trade-execution tool (swaps, prediction-market orders) * can run, the session must hold an APPROVED, unexpired plan whose remaining * budget covers the trade. The model proposes a structured plan (assets, * sizes, rationale, total spend); the user approves, requests changes, or * denies; executions draw down the plan's budget until it is consumed. * * This gate applies in EVERY permission mode including trust — moving money * differs in kind from editing files, the same reasoning that keeps * dangerous bash commands always-prompting. * * Persistence: one JSON per plan under ~/.blockrun/trade-plans/. Decisions * are audited to ~/.blockrun/approvals.jsonl. */ import type { CapabilityInvocation, CapabilityResult } from '../agent/types.js'; export type TradeVenue = 'jupiter' | 'zerox' | 'polymarket'; export interface PlannedTrade { venue: TradeVenue; action: 'buy' | 'sell' | 'swap' | 'bet'; /** Symbol, mint, token address, or market/outcome label. */ asset: string; direction?: 'long' | 'short' | 'yes' | 'no'; amountUsd: number; maxSlippageBps?: number; /** Human-readable exit/stop condition — enforced by goal loops, not code. */ stopCondition?: string; } export type TradePlanStatus = 'pending' | 'approved' | 'rejected' | 'expired' | 'consumed' | 'cancelled'; export interface TradePlan { id: string; sessionId: string; createdAt: number; expiresAt: number; status: TradePlanStatus; trades: PlannedTrade[]; totalSpendUsd: number; rationale: string; decidedBy?: string; changeRequest?: string; consumedUsd: number; } export declare const TRADE_PLAN_TTL_MS: number; export declare function tradePlansDir(): string; export declare function saveTradePlan(plan: TradePlan): void; export declare function loadTradePlan(id: string): TradePlan | null; export declare function listTradePlans(): TradePlan[]; export declare function validatePlannedTrades(trades: unknown): { trades: PlannedTrade[]; } | { error: string; }; export declare function createTradePlan(opts: { sessionId: string; trades: PlannedTrade[]; rationale: string; ttlMs?: number; }): TradePlan; export declare function decideTradePlan(plan: TradePlan, decision: 'approved' | 'rejected' | 'cancelled', by: string, reason?: string): TradePlan; export declare function formatTradePlanText(plan: TradePlan, walletBalanceUsd?: number): string; export declare function setTradePlanSessionId(id: string): void; /** The session's live (approved, unexpired, unconsumed) plan, if any. */ export declare function activeTradePlan(sessionId?: string): TradePlan | null; /** * Trade-plan gate — called from SessionToolGuard.beforeExecute for every * invocation. Returns a deny result when a trade-execution call lacks plan * coverage; null to proceed. On coverage, flags the invocation so the tool * skips its redundant per-swap confirm (the plan approval IS the confirm). */ export declare function checkTradePlanGate(invocation: CapabilityInvocation, sessionId?: string): CapabilityResult | null; /** * Draw down the plan budget after a successful gated execution. Called from * SessionToolGuard.afterExecute for every invocation (no-op for non-trades). */ export declare function recordTradeExecution(invocation: CapabilityInvocation, result: CapabilityResult, sessionId?: string): void;