# Execution Layer

`uforia` now includes an `Execution` family for operator-driven DEX trading across:

- `derive` for options/perps-style execution
- `hyperliquid` for perps
- `lighter` for perps
- `bebop` for quote-first spot routing

## Scope

This phase is an operator-driven live execution layer, not autonomous trading:

- venue capability discovery
- normalized order/quote/cancel requests
- explicit risk gating
- immutable audit writes
- DB-backed execution state serving
- thin operator UI

Modes:

- `dry_run`: validate, normalize, and persist the request only
- `paper`: persist a simulated operator action without touching the venue
- `live`: send the request through the venue adapter after risk checks

Current live capability matrix:

- `hyperliquid`
  - live market metadata, balances, positions, orders, fills
  - live order placement, cancel, cancel-all
- `lighter`
  - live market metadata, balances, positions, orders, fills
  - live order placement, cancel, cancel-all
- `derive`
  - live market metadata, balances, positions, orders, fills
  - live order placement, cancel, cancel-all
- `bebop`
  - live quote request
  - self-execution by signing and broadcasting prepared EVM transaction bundles from the quote payload
  - gasless execution path when signed order payload fields are supplied
  - no standing-order lifecycle is assumed

## Datasets

Execution state is stored in:

- `execution_order_intent`
- `execution_order_event`
- `execution_fill_event`
- `execution_position_snapshot`
- `execution_balance_snapshot`
- `execution_quote_snapshot`
- `execution_market_snapshot`
- `execution_health_snapshot`

These follow the same Parquet + Timescale dual-write pattern as the rest of `uforia`.

## API

Read endpoints:

- `GET /api/v1/execution/venues`
- `GET /api/v1/execution/markets`
- `GET /api/v1/execution/accounts`
- `GET /api/v1/execution/orders`
- `GET /api/v1/execution/fills`
- `GET /api/v1/execution/positions`
- `GET /api/v1/execution/balances`
- `GET /api/v1/execution/health`

Mutating endpoints:

- `POST /api/v1/execution/quote`
- `POST /api/v1/execution/order`
- `POST /api/v1/execution/cancel`
- `POST /api/v1/execution/cancel-all`

All mutating paths write immutable audit rows even when blocked or dry-run only.

## Rust runtime

Execution crates live under `engines/execution/`:

- `execution-core`
- `hyperliquid-adapter`
- `bebop-adapter`
- `derive-adapter`
- `lighter-adapter`
- `execution-app`

The current Rust runtime writes an execution health heartbeat file and supports venue-native dry-run payload construction. This is the base for later private-stream and live-order expansion.

## Accounts and risk

Execution accounts are loaded from `config/execution_accounts.json`.

Use `config/execution_accounts.example.json` as the template.

Required credential env vars depend on venue:

- `hyperliquid`
  - `UFORIA_HYPERLIQUID_PRIVATE_KEY`
- `lighter`
  - `UFORIA_LIGHTER_API_PRIVATE_KEY`
- `derive`
  - `UFORIA_DERIVE_SESSION_KEY`
  - `UFORIA_DERIVE_PRIVATE_KEY` if `wallet_address` is not set directly
- `bebop`
  - `UFORIA_BEBOP_PRIVATE_KEY`
  - `UFORIA_BEBOP_RPC_URL` for self-execution broadcasting

Risk checks enforced before every request:

- global kill switch
- account kill switch
- allowed asset/symbol filters
- max order notional
- reduce-only support enforcement
- venue capability enforcement

## Mac Mini

Runner scripts:

- `ops/run-execution-engine.sh`
- `ops/run-execution-state-sync.sh`
- `ops/run-execution-reconcile.sh`

LaunchAgents:

- `launchd/com.uforia.execution-engine.plist`
- `launchd/com.uforia.execution-state-sync.plist`

The state sync loop now:

- ingests the Rust execution health heartbeat file
- performs live venue state sync into:
  - `execution_market_snapshot`
  - `execution_balance_snapshot`
  - `execution_position_snapshot`
  - `execution_order_event`
  - `execution_fill_event`

Useful manual commands:

```bash
uv run uforia-admin execution seed-markets --asset BTC
uv run uforia-admin execution sync-state --health-path data/execution_live/health/latest.json
uv run uforia-admin execution sync-live-state --venue hyperliquid --account hyperliquid-main --asset BTC
```

Bebop live execution notes:

- quotes should be requested first and persisted via `POST /api/v1/execution/quote`
- `POST /api/v1/execution/order` for Bebop should include a `quote_id`
- if no `quote_payload` is supplied explicitly, `uforia` will hydrate the latest stored quote payload for that `quote_id`
- self-execution uses the prepared transaction bundle from the stored quote payload and signs/broadcasts it through the configured RPC
