Files
com_r35157_nenjim-hubd-impl…/openspec/changes/89-add-evelyn-liquidity-service/design.md
T

3.9 KiB

Design

Context

See proposal.md for motivation. Raydium already discovers position NFTs and decodes pool/position state but does not execute liquidity decrease. SolanaWallet provides external jup signer validation, signing/submission and SPL transfer with ATA creation; JupiterSwapService confirms exact-input swaps. The Hub has a constructor catalogue and explicit ordered process selection.

Goals / Non-Goals

Goals: Implement the specified pipeline with fresh direct RPC reads and exact eligibility math; leave an offline-verifiable, inactive deployment template.

Non-Goals: No generic strategy, service-container framework, durable pending transaction queue or new currency ValueTags.

Decisions

  • Keep the public service a domain marker, mirroring the burner; the reference implementation additionally owns NenjimProcess startup and AutoCloseable shutdown. One scheduled executor uses fixed delay and propagates interruption across step boundaries.
  • Keep the existing shared Hub graph eager; construct/register liquidity deployment configuration and dedicated passive dependencies only at the selected liquidity entry, as reflected by the Hub/Registry deltas.
  • Build a dedicated direct Raydium instance when selected so cached pool/position state cannot trigger stale decisions. Resolve currencies through CIS and programs/precision from validated mint accounts.
  • Compare squared Q64.64 values by exact cross multiplication. Decimal factors cancel because pool and position share mints. For reversed ordering compare current raw price to lower-bound raw price times the retained percentage. This avoids display rounding and inversion rounding.
  • Port the official CLMM integer tick algorithm into a small Raydium math helper, reusing it for exact integer principal amounts. Existing display math remains unchanged.
  • Execute decrease_liquidity_v2 (legacy and Token-2022) with owner NFT holding, personal/protocol position PDA, vaults, tick arrays, destination ATAs and bitmap extension. Create missing ATAs idempotently in the same transaction and request a 600,000 compute-unit limit for the combined operation. Account details stay in the Raydium implementation; a private legacy transaction encoder uses existing address codec, PDA and wallet primitives.
  • Validate pool and personal-position discriminators, token metadata and owner holding before signing. Apply explicit slippage to integer expected principal. Fail closed on unsupported transfer-affecting Token-2022 extensions rather than silently weakening minimums. Required reward accounts, if present, only collect into this wallet and never enter swaps/payouts.
  • Parse only conf/evelyn-liquidity.conf with format-version validation, unknown/duplicate key rejection and required keys. Deployment addresses/signer remain placeholders in the ignored local runtime file and tracked example. Existing Hub example stays unchanged.
  • Use controlled JUnit fixtures explicitly requested by issue #89, including transaction bytes. No test constructs a real signer or submits a financial operation.

Risks / Trade-offs

  • [Pool moves between read and execution] → Minimum principal limits cause atomic failure; later iterations reread state.
  • [Unknown transaction outcome] → Log signature when available, preserve ordinary underlying confirmation; subsequent iterations use current balances/positions as requested.
  • [Mint extension or program layout changes] → Validate discriminators/layout and fail safely on unsupported extensions; document official source references and exact supported behavior.
  • [SOL starvation] → Document funding for transaction fees and token-account rent; no hidden token reserves.

Migration Plan

Copy/edit the example, bind a dedicated external signer, fund SOL and manually select evelyn.liquidity.prod in the Hub runtime plan. Stop/remove the selection to disable; positions and wallet balances remain the recovery state. Keep the OpenSpec change active for user review; no commit, push or deployment.