defi-tracker-lifecycle 0.1.5

Pure-logic crate for DeFi order lifecycle tracking on Solana — classification, correlation, and state machine logic
Documentation
# defi-tracker-lifecycle

Pure-logic crate for DeFi order lifecycle tracking on Solana. No IO, no database — just classification, correlation, and state machine logic.

Documentation site: <https://defi-tracker-lifecycle.turbine.cash/>

## Supported Protocols

| Protocol | Program | Description |
|----------|---------|-------------|
| **DCA** | `DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M` | Jupiter Dollar-Cost Averaging |
| **Limit V1** | `jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu` | Jupiter Limit Orders V1 |
| **Limit V2** | `j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X` | Jupiter Limit Orders V2 |
| **Kamino** | `LiMoM9rMhrdYrfzUCxQppvxCSG1FcrUK9G8uLq4A1GF` | Kamino Limit Orders |

## Architecture

### Event Processing Pipeline

```mermaid
flowchart TD
    subgraph Input
        Raw["RawInstruction / RawEvent"]
    end
    subgraph Dispatch
        Lookup["from_program_id()"] --> Adapter["adapter_for()"]
    end
    subgraph Classify
        CI["classify_instruction()"]
        CE["classify_and_resolve_event()"]
    end
    subgraph Output
        ET["EventType"]
        CO["CorrelationOutcome"]
        EP["EventPayload"]
    end

    Raw --> Lookup
    Adapter --> CI & CE
    CI --> ET
    CE --> ET & CO & EP
```

### Order Lifecycle State Machine

```mermaid
flowchart TD
    Start(( )) -->|Create| Active
    Active -->|FillDelta / MetadataOnly| Active
    Active -->|"Close(Completed)"| Completed
    Active -->|"Close(Cancelled)"| Cancelled
    Active -->|"Close(Expired)"| Expired

    subgraph Terminal ["Terminal — only MetadataOnly accepted"]
        Completed
        Cancelled
        Expired
    end
```

## Core Concepts

**`ProtocolAdapter`** — trait implemented by each protocol. Two phases:
- **Classify**: maps instruction/event names to `EventType` (Created, FillCompleted, Closed, etc.)
- **Resolve**: extracts order PDAs (`CorrelationOutcome`) and structured data (`EventPayload`)

**`LifecycleEngine`** — stateless state machine that enforces transition rules:
- Non-terminal orders accept all transitions
- Terminal orders (Completed/Cancelled/Expired) only accept `MetadataOnly`
- Snapshot deltas are always non-negative; regressions tracked separately

**`ResolveContext`** — carries pre-fetched data needed for correlation (Kamino requires pre-fetched order PDAs since its events don't contain them directly)

## Usage

```rust
use defi_tracker_lifecycle::{
    EventPayload, Protocol, adapter_for, event_type_to_transition, ResolveContext,
    LifecycleEngine, TerminalStatus, TransitionDecision,
};

// 1. Identify protocol from program ID
let protocol = Protocol::from_program_id("DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M")
    .ok_or("unknown program")?;
let adapter = adapter_for(protocol);

// 2. Classify + resolve an event in one pass
let ctx = ResolveContext { pre_fetched_order_pdas: None };
let (event_type, correlation, payload) = adapter
    .classify_and_resolve_event(&raw_event, &ctx)
    .ok_or("unknown event variant")?  // None = unknown event variant
    .map_err(|e| e.to_string())?;     // Err = malformed known event payload

// 3. Map EventType to LifecycleTransition via the canonical mapping
let closed_status = match &payload {
    EventPayload::DcaClosed { status } => Some(*status),
    EventPayload::KaminoDisplay { terminal_status, .. } => *terminal_status,
    _ => None,
};
let transition = event_type_to_transition(&event_type, closed_status);

// 4. Check state transition (pass None if not terminal)
let current_terminal: Option<TerminalStatus> = None;
let decision = LifecycleEngine::decide_transition(current_terminal, transition);
match decision {
    TransitionDecision::Apply => { /* update order status */ }
    TransitionDecision::IgnoreTerminalViolation => { /* order is terminal, skip */ }
}
```

## Testing

```bash
cargo test
cargo test --all-features
cargo clippy --all-targets --all-features
```

### Test Layers

| Layer | What it catches |
|-------|----------------|
| Compile-time (`classify_decoded()`) | Upstream Carbon adds a new variant |
| Mirror enum alignment | Mirror enum drifts from Carbon variants |
| EventType reachability | A variant becomes dead/unreachable |
| Unit tests | Individual classify/resolve logic per protocol |
| Fixture tests | Real JSON from defi-tracker parses and classifies correctly |
| End-to-end lifecycle | Full pipeline: raw JSON → adapter → state machine → status tracking |

### Coverage (requires [cargo-llvm-cov]https://github.com/taiki-e/cargo-llvm-cov)

```bash
cargo llvm-cov                                        # text summary
cargo llvm-cov --html                                 # HTML report → target/llvm-cov/html/
cargo llvm-cov --lcov --output-path lcov.info         # LCOV for CI upload
```