Files
com_r35157_nenjim-hubd-impl…/openspec/specs/evelyn-perps-service/spec.md
T

4.6 KiB

evelyn-perps-service Specification

Purpose

Provide a view-only source of current Evelyn perpetual positions independently of Mission Control presentation and refresh timing.

Requirements

Requirement: Read-only current positions snapshot

The Perps service SHALL expose only a read operation returning its complete current in-memory snapshot. Wallets, venues within wallets, and positions within venues SHALL have stable identifiers across reads. Responses SHALL be immutable domain data without UI components, colors or formatting. Reading the snapshot SHALL make no Jupiter or Phoenix requests.

Scenario: Repeated reads

  • WHEN clients repeatedly retrieve the started service's snapshot
  • THEN they receive the latest published positions with stable identifiers and cannot mutate service-owned collections
  • AND the reads trigger no exchange requests or position-management operations

Requirement: Hub owns Perps startup

The service SHALL run as two separate Hub-managed processes registered as evelyn.perps.test and evelyn.perps.prod. The service API SHALL expose no lifecycle operations. Snapshot reads before process startup SHALL fail clearly. Startup SHALL schedule asynchronous retrieval without waiting for integration I/O.

Scenario: Service starts

  • WHEN the Hub starts either registered Perps process
  • THEN its service view is available without waiting for retrieval, initially empty until data arrives
  • AND no placeholder positions are generated before successful retrieval

Requirement: Wallet configuration belongs to service construction

The Hub SHALL supply the six PROD wallet addresses and one TEST wallet address specified in issue #98 and the corresponding existing Jupiter integration plus a read-only Phoenix integration at construction. Each service SHALL retain immutable configuration and own its snapshot. Wallet addresses SHALL be used as stable identities and display labels. EMC SHALL neither own nor pass wallet configuration; reads SHALL remain parameterless.

Scenario: Separate configured instances

  • WHEN the Hub constructs and starts both instances
  • THEN each instance queries only its configured wallets through its injected integrations
  • AND the implementation does not define the wallet list internally

Requirement: Background Jupiter refresh

The service SHALL refresh immediately after startup and wait 60 seconds between completed cycles, without overlapping cycles or depending on EMC visibility. It SHALL use Jupiter and Phoenix read operations and respect the existing Jupiter cache. Snapshot reads SHALL make no integration calls. No transaction signing or position-management operation SHALL occur.

Scenario: Background update while EMC is hidden

  • WHEN EMC is hidden and the next refresh is due
  • THEN the service still refreshes configured wallets and publishes immutable snapshots
  • AND no freshness guarantee bypasses the existing 60-second integration cache

Requirement: Position mapping is stable and complete

The service SHALL map position account to stable ID, mint to known instrument label or raw mint fallback, direction to Long/Short, and positionSize to USD size. Wallet order SHALL follow configuration, and positions SHALL be ordered deterministically by position account. Phoenix SHALL use PDA index, subaccount index and symbol as stable identity, signed quantity for direction and absolute current USD notional for size. Jupiter and Phoenix SHALL appear as separate venues, with no subaccount tree level.

Scenario: Changed and unknown positions

  • WHEN a successful read returns newly opened positions including an unknown token mint
  • THEN all returned positions appear with stable IDs and exact USD sizes, and the unknown mint is displayed rather than dropped

Requirement: Refresh failures are isolated per wallet

A failed read or mapping SHALL retain the last successful data for that wallet and venue, log the failure and allow other wallets and venues to refresh. Successful empty results SHALL remove only that wallet/venue's previous positions. Interruption SHALL stop the current cycle. Failed first reads SHALL not invent positions.

Scenario: Failure followed by recovery

  • WHEN one wallet fails while another succeeds
  • THEN only the successful wallet/venue's data is replaced
  • AND a later successful empty read clears the recovered wallet/venue's previous positions

Scenario: One venue fails

  • WHEN Phoenix fails for a wallet while Jupiter succeeds, or vice versa
  • THEN only the successful venue is updated and the failed venue retains its previous data
  • AND subsequent wallets are still attempted