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

67 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# evelyn-liquidity-service Specification
## Purpose
Realize Evelyn's manually funded EVE/SyrupUSDC concentrated liquidity into USDC payouts using one dedicated wallet and current on-chain state.
## Requirements
### Requirement: Owned positions qualify by their normalized upper boundary
The service SHALL discover positions owned by its wallet in its configured CLMM pool and withdraw positive liquidity only when the upper EVE/SyrupUSDC boundary U satisfies U <= P*(1-h/100). P SHALL come from a fresh on-chain pool read for each owned positive-liquidity position after NFT discovery and previous withdrawals have completed. The same state SHALL be used for that position's eligibility decision and withdrawal quote; an earlier position's price SHALL NOT be reused. Both orientations SHALL be normalized, and decisions SHALL use pool precision. Unusable P SHALL skip the remaining withdrawals in that iteration while allowing later steps.
#### Scenario: Inclusive threshold and upper boundary
- **WHEN** P is 15, h is 10 and positions span 13–13.5 and 13.5–14
- **THEN** only the first qualifies, including equality
#### Scenario: Reversed pool ordering
- **WHEN** mint A is SyrupUSDC and mint B is EVE
- **THEN** the inverted lower raw boundary determines the normalized upper price and the same eligibility rule applies
#### Scenario: Other or empty positions and falling market
- **WHEN** a position belongs to another wallet or pool, has zero liquidity, or its upper boundary exceeds the threshold after a price decline
- **THEN** it retains its state and the service neither withdraws it nor creates or refills positions
#### Scenario: Price declines during discovery or an earlier withdrawal
- **WHEN** a position qualifies before discovery or an earlier withdrawal, but its upper boundary exceeds the threshold at the new pool price
- **THEN** the service reads that new price before deciding and preserves the position's liquidity in either token orientation
#### Scenario: Pool read fails between positions
- **WHEN** an earlier position was withdrawn but the next current pool price is unavailable or unusable
- **THEN** no remaining position is withdrawn in that iteration and swap and payout still run on their independent balances
### Requirement: Swap and payout use independent current balances
The service SHALL read SyrupUSDC at step 2 and USDC at step 3 and operate on the entire respective balance above its nonnegative reserve. Absent or at/below-reserve balances SHALL be skipped. Exact-input swap SHALL use explicit maximum slippage. SPL payout SHALL target the configured wallet owner with existing account-creation support. Amounts SHALL never round upward. EVE and reward tokens SHALL remain untouched by this pipeline.
#### Scenario: Nonzero reserves
- **WHEN** SyrupUSDC balance is 1.01 with reserve 0.01 and USDC balance is 2.5 with reserve 0.5
- **THEN** 1.00 SyrupUSDC is swapped and 2.0 USDC is sent
#### Scenario: Zero reserves and empty accounts
- **WHEN** reserves are zero
- **THEN** full positive balances are eligible, absent/zero balances are skipped and empty source accounts are not closed
### Requirement: Failure recovery uses on-chain state
Each iteration SHALL attempt withdrawal, swap and payout independently in that order, isolating ordinary per-position failures. Subsequent iterations and restarts SHALL reread positions and balances without a persistent queue, attribution, pending-signature gate, immediate retries or replay. Logs SHALL identify operations, positions, amounts and returned signatures without signer secrets. Interruption SHALL stop work.
#### Scenario: Independent failures and restart
- **WHEN** withdrawal or swap fails or returns an unknown outcome
- **THEN** independent later work can proceed and the next iteration or restart acts on current state, skipping completed empty positions
### Requirement: Configuration is validated before worker start
A dedicated version-1 runtime configuration SHALL validate wallet/signer binding, pool type/token identity, address syntax, 0<=h<100, positive fixed delay, nonnegative reserves with mint precision and explicit slippage limits. Currencies, mints and programs SHALL use canonical identity and chain metadata. The public example SHALL have zero reserves and SHALL never be a runtime fallback.
#### Scenario: Invalid input or missing deployment file
- **WHEN** configuration is invalid or only the example exists
- **THEN** startup fails before financial work
### Requirement: Optional process owns a sequential worker
The Hub SHALL select evelyn.liquidity.prod through its existing catalogue and Registry, constructing deployment configuration and dedicated signer/swap dependencies only when selected. Existing selections and ordering SHALL be preserved. The domain interface SHALL expose no lifecycle operations. A single worker SHALL run the first and subsequent iterations identically, with a fixed delay after completion and ordinary shutdown interruption.
#### Scenario: Optional process is omitted
- **WHEN** the Hub plan omits evelyn.liquidity.prod
- **THEN** no liquidity configuration or dedicated signer is loaded and the checked-in Hub example activates no financial operation
#### Scenario: Slow iteration and shutdown
- **WHEN** an iteration exceeds the configured interval or shutdown interrupts it
- **THEN** no iterations overlap and interruption prevents further steps