v0.9.0 — TTL-archive semantics + per-ledger dirty positions
What changed
TTL-lapse no longer deletes state. A Positions or ResConfig/ResData entry whose TTL lapses (or is evicted by a network sweep) is now archived in place — Archived/ArchivedLedgerSeq on UserReservePosition, PendingUserPosition, ReserveState — instead of being purged. Explicit on-chain deletes keep their existing semantics (discriminated via ContractDataChange.ChangeType). On mainnet the old behavior silently dropped 300+ dormant-but-live position holders from fold state.
Per-ledger dirty positions API. bindings.DirtyPosition/DirtyKind/DirtyPositionsProvider and Adapter.LastDirtyPositions() expose exactly which (address, pool) pairs changed each ledger, with upsert/removal kinds. Adapter.ProjectPositions projects a single user+pool in O(dirty) — ~20–60µs flat from 1k to 50k total users, vs 18–504ms for a full transform. Enables consumers to emit per-ledger position rows at fold speed.
Determinism fix. reserveByIndex was rebuilt from a randomized map range; now built from the sorted reserve slice. Pre-existing, exposed by dirty-set comparison in the parity suite.
Both fold strategies (paranoid | incremental) produce identical dirty sets and archived state — enforced by the parity suite, including new Positions TTL-eviction fixtures.
Compatibility: all serialization changes are additive; v0.8.0 snapshots load unchanged. No breaking API changes.
Merge: #27 · SHA: 459c5af · Compare: v0.8.0...v0.9.0
What's Changed
- fix(blend): archive TTL-lapsed/evicted positions; expose per-ledger dirty set by @koolamusic in #27
Full Changelog: v0.8.0...v0.9.0