Skip to main content
Pegana computes peg state from two numbers — intrinsic value (what the asset should be worth, per its own mechanism) and market value (what you’d actually receive swapping it). The spread between them, smoothed and bucketed, is the entire output.
spread = 1 − market / intrinsic
Smoothed with an EWMA at α = 0.3. Compared against per-asset, per-class thresholds. Resolved through a 5-state FSM with asymmetric hysteresis so a noisy signal does not produce noisy alerts.

Reading order

Intrinsic value

What the asset is supposed to be worth. Per-class definition (LST, stable, CDP, NAV, FX).

Market value

What you’d get swapping it. Jupiter routed quote, repriced via Pyth.

The spread

Formula, EWMA smoothing, per-asset thresholds, the 5-state FSM with hysteresis.

Honesty about limits

What we don’t model. Where the signal can lie. When to mistrust an alert.

Sources, in one table

SourceRead by PeganaUsed for
Sanctumsol_value per LST mint, every 15sSOL-pegged LST intrinsic
PythSOL/USD, FX crosses, Redemption Rate feedsAll USD conversion + yield-bearing NAV
Hylo (on-chain decode)total_sol_cache.total_sol from Exchange PDAhyUSD CDP collateral ratio
JupiterBest routed quote, USDC numeraireMarket value of every asset
Solayer / PiggybankMint-level rebasing rate / dashboard NAVSub-set of yield-bearing accounting
Each adapter lives in crates/indexer-rs/src/sources/. One source per asset class is a deliberate constraint — we do not “blend” prices.

The 5-state FSM, in one table

StateMeaningAlert?
PEGGEDSpread inside the calm bandNo
DRIFTSpread crossed the per-asset drift thresholdYes
DEPEGSpread crossed depeg (2.00 – 5.00%)Yes, urgent framing
CRITICALSpread > 5.00%Yes, Telegram urgent
UNKNOWNSource stale or low confidenceNo (sticky)
Plus BLACK_SWAN for spreads beyond any historically-observed level — terminal until human review.

Update cadence

  • Indexers poll their sources every 15s (Sanctum, Solayer, Piggybank, Hylo, Jupiter)
  • Pyth pushes via SSE — sub-second arrivals
  • Engine recomputes on every source event, publishes to Redis + Postgres
  • API snapshots are <1s old; the WebSocket pushes within ~200ms of the engine
  • Alert delivery (Telegram / Webhook) fires within 1–3s of the state transition

How to verify

Every parameter — threshold, dwell time, EWMA α, source endpoint — is committed in assets.toml and crates/engine-rs/src/config.rs. The methodology is reproducible from raw inputs. To inspect any asset’s live parameters:
curl https://api.pegana.xyz/v1/assets/USDC/extra
Or run the bot:
/thresholds USDC