36 KiB
evelyn-iou-burner-service Specification
Purpose
Defines the Evelyn-specific service that safely converts prioritized wallet assets into Evelyn IOU, accumulates EVE for burns above a configured minimum while retaining an EVE reserve, and announces only finalized burns without automatically repeating transactions whose outcomes may be unknown.
Requirements
Requirement: Evelyn-specific public service boundary
The system SHALL expose an empty lifecycle-free EvelynIOUBurnerService under com.fanitas.evelyn.service.burner as the typed domain service and Registry view until external domain operations exist, and SHALL keep its reference implementation under com.fanitas.evelyn.service.burner.impl.ref. The same reference implementation object SHALL implement both EvelynIOUBurnerService and NenjimProcess; the Hub SHALL start it only through its NenjimProcess view. Neither the service interface nor the implementation SHALL expose a general stop, restart, worker-control, or other lifecycle operation. The service SHALL remain specific to Evelyn IOU and SHALL NOT introduce a generic token-burner abstraction, burner-specific input interfaces, records, or class hierarchies.
Scenario: Downstream lifecycle consumer
- WHEN a downstream component depends on the Evelyn burner API
- THEN it receives a typed component contract with no callable lifecycle or domain operation and does not depend on reference-implementation types or a generic burner model
Scenario: Input model remains domain-level
- WHEN the Hub configures accepted buyback currencies while constructing the process implementation
- THEN it uses existing
MoneyAmountvalues rather than burner-specific Solana, SPL-token, or input-asset types
Requirement: Ordered AssetAZ input configuration
The authoritative constructor SHALL accept a non-null ordered List<MoneyAmount> named inputCurrencyMinimumReserves, defensively copy it without changing order, and interpret inclusion as acceptance, list position as priority, each currencyType().id() as the authoritative AssetAZ identity, and each amount() as the minimum balance that must remain. It SHALL ignore supplied currency name and symbol metadata by resolving each UUID through the injected Currency Identity Service and using the canonical returned currency for processing. The constructor SHALL also accept a non-null List<MoneyAmount> named inputCurrencyMaximumSwapAmounts, defensively copy its values, and match each maximum to an accepted input by canonical currency UUID, independently of maximum-list order or supplied metadata. Each maximum SHALL be expressed in that same currency's own units. The constructor SHALL additionally accept inputCurrencyMinimumSwapAmounts, defensively copy its values and match strictly positive token-denominated minima by canonical UUID independently of order/name/symbol. Empty reserves, minima and maxima lists SHALL be valid and SHALL still permit directly deposited EVE to be burned.
Scenario: Stale configured metadata
- WHEN a configured
MoneyAmountcarries a known UUID but stale name or symbol metadata - THEN the service processes the current canonical currency resolved for that UUID
Scenario: Priority is preserved
- WHEN multiple configured entries have rounded amounts at/above their own minimum and usable Solana data
- THEN the earliest entry in the defensively copied list is the only input selected in that iteration
Scenario: Empty input list
- WHEN no buyback inputs are configured but the wallet contains EVE
- THEN the service skips input selection and still evaluates the complete EVE balance for burning
Scenario: Maximum list order is independent
- WHEN maxima are supplied in a different order from the reserve list or carry stale display metadata for known UUIDs
- THEN each input receives the maximum for its UUID and reserve-list priority is preserved
Scenario: Caller changes its configuration lists
- WHEN a caller changes any supplied list after construction
- THEN the accepted currencies, their priority, reserves, minima and maxima remain as validated during construction
Scenario: Minimum list order and display metadata are independent
- WHEN minima are reordered or use stale names/symbols for known canonical UUIDs
- THEN each input receives its UUID's minimum and only reserve-list order controls priority
Requirement: Complete constructor validation
Construction SHALL require all injected services, all three input configuration lists, and durations to be non-null; every list entry, entry amount, entry currency, and currency UUID to be non-null; each reserve to be zero or greater; each minimum and maximum to be strictly positive; each minimum to be no greater than its matched maximum; each UUID to be known to the injected Currency Identity Service; UUIDs to be unique within each list; both minimum and maximum UUID sets to exactly equal the accepted reserve UUID set; and EVE not to be an input currency. It SHALL require slippage to be from 0 through 10000 basis points inclusive, maximumPriceAge to be greater than zero milliseconds, and both finalization timeout and iteration interval to be positive and non-zero.
Every configured non-SOL UUID SHALL resolve through reverse CIS lookup to exactly one external reference in the solana-mint namespace, and that reference's external ID SHALL be non-null and non-blank. Construction SHALL fail for a missing, ambiguous, null, or blank non-SOL mint representation. These burner-specific rules SHALL NOT change the general-purpose MoneyAmount contract.
Scenario: Valid configuration
- WHEN every dependency and value is valid, reserves are non-negative, every accepted input has exactly one positive minimum and maximum with minimum <= maximum, UUIDs are distinct and known within each list, EVE is absent, and every non-SOL input has one non-blank Solana mint reference
- THEN construction succeeds and preserves the configured priority order
Scenario: Invalid reserve or operating limit
- WHEN a reserve is negative or null, a token maximum is null or non-positive, slippage is outside its inclusive range, maximum price age is non-positive, or either duration is null or non-positive
- THEN construction fails before a worker or transaction is created
Scenario: Invalid input identity
- WHEN an entry or its currency or UUID is null, a UUID is unknown or duplicated, or the EVE UUID is configured as input
- THEN construction fails with a diagnostic identifying the invalid configuration
Scenario: Non-SOL representation is not unique and usable
- WHEN a configured non-SOL currency has zero or multiple
solana-mintreferences or its sole external ID is null or blank - THEN construction fails without adding mint or token-program selection to Evelyn's configuration model
Scenario: Maximum configuration is incomplete or ambiguous
- WHEN a maximum is missing for an accepted input, duplicated by UUID, or supplied for an unaccepted currency
- THEN construction fails before a worker or transaction is created
Scenario: Invalid maximum identity or value
- WHEN a maximum entry, amount, currency or UUID is null, or its UUID is unknown or resolves to an invalid canonical identity
- THEN construction fails with a diagnostic identifying the invalid maximum configuration
Scenario: Invalid minimum configuration
- WHEN the minimum list or an entry, amount, currency or UUID is null; a UUID is unknown, duplicated, extra or missing; a minimum is non-positive; or it exceeds that UUID's maximum
- THEN construction fails before a worker or transaction is created
Scenario: Minimum equals maximum
- WHEN a strictly positive minimum is numerically equal to its matched maximum
- THEN that amount configuration is accepted without requiring equal decimal scales
Scenario: Direct EVE only configuration
- WHEN all three configuration lists are empty
- THEN construction succeeds and direct EVE remains eligible for burning
Requirement: Fixed Evelyn domain values and internally resolved integration values
The service SHALL fix the EVE mint as meveYG2iXYSkgSUn1T1uxcthH1EGMZdRHGgCntXZA3Y, construct the EVE/USDT notification-price pair from canonical CIS resolutions of the stable EVE and USDT UUIDs, and use fixed notification wording. Native SOL SHALL be identified only by the stable SOL UUID; when sent to Jupiter, its input mint SHALL be the canonical CIS Solana-mint reference So11111111111111111111111111111111111111112. Mint addresses, token programs, price pairs, notification wording, and a separate SOL reserve SHALL NOT be constructor configuration.
Scenario: Native SOL configuration
- WHEN a configured input UUID is the stable SOL UUID
- THEN the service reads the native wallet balance and later supplies Jupiter with the CIS-resolved canonical SOL/WSOL mint rather than treating SOL as an SPL-token holding
Scenario: Fixed EVE behavior
- WHEN the service evaluates a burn and notification
- THEN it uses the fixed EVE mint and the canonical EVE/USDT pair without accepting replacements through construction
Requirement: Immediate sequential fixed-delay lifecycle
Each reference implementation instance SHALL own at most one dedicated background worker. A successful Hub-owned NenjimProcess.start() SHALL begin the first iteration immediately; every later iteration SHALL begin only after the previous iteration completes and the configured fixed delay elapses; and iterations SHALL never overlap. A repeated process start while active SHALL NOT create another worker. If scheduling the worker fails during startup, the implementation SHALL stop the newly created executor, clear its worker reference and process-local state, and report startup failure.
Pending swap/burn information and manual swap/burn suspension flags SHALL be process-local only. A complete process restart SHALL clear those states. The public JavaDoc SHALL disclose that restart loses reconciliation state and can weaken duplicate prevention until unknown transactions have been reconciled externally. Neither the service interface nor the implementation SHALL expose ordinary stop or restart operations.
Scenario: First and later iterations
- WHEN the Hub starts the Burner process and one iteration takes longer than usual
- THEN the first iteration starts without initial delay and the next starts only after completion plus the configured interval
Scenario: Active service is started again
- WHEN
NenjimProcess.start()is called while the instance already owns an active worker - THEN the call is rejected without creating an overlapping worker
Scenario: Explicit lifecycle reset
- WHEN a complete process restart occurs after pending or suspended process-local state has been externally reconciled
- THEN the new process begins without that prior in-memory state and reloads wallet and chain state normally
Requirement: Pending burn is handled before all new work
At the start of an iteration, if a prior burn signature is pending, the service SHALL only await that exact signature at FINALIZED. It SHALL submit no swap or burn in that iteration. An unknown timeout or I/O outcome SHALL retain the pending state and end the iteration; definitive success SHALL make the one associated notification attempt and end the iteration; and definitive on-chain failure SHALL log the slot and complete failure details, clear pending state, send no notification, and defer any new wallet decision to a later iteration.
Scenario: Pending result remains unknown
- WHEN awaiting the retained signature times out or fails through I/O
- THEN the service retains that signature and performs no swap, burn, or notification in the iteration
Scenario: Pending burn succeeds
- WHEN the retained signature reaches
FINALIZEDwith a successful outcome - THEN the service performs its sole notification attempt and does no other transaction work in that iteration
Scenario: Pending burn fails definitively
- WHEN the retained signature reaches
FINALIZEDwith an on-chain failure - THEN the service logs its slot and complete failure details, clears it without notification, and waits until a later iteration before evaluating another burn
Requirement: Prioritized input inspection with internal Solana translation
Unless swaps are suspended, an iteration SHALL inspect configured input entries in order until it finds the first usable candidate. For every entry it SHALL resolve the configured UUID to its canonical currency. Native SOL SHALL use getSolanaBalance().amount() and nine-decimal precision. Every other input SHALL use its unique CIS-resolved Solana mint; the service SHALL inspect the mint account owner to detect the original SPL Token Program or Token-2022, use that program for wallet balance lookup, and obtain precision from Solana mint metadata. A missing SPL-token account SHALL equal zero balance.
For each entry the service SHALL subtract its configured reserve and skip non-positive spendable balance. Missing or unusable balance, mint account, supported program, or mint metadata SHALL produce a warning and allow later configured entries to be examined. Interruption SHALL preserve the thread interrupt state and end processing rather than becoming a skipped candidate. Failure to select an input SHALL NOT prevent the later complete-EVE burn evaluation.
Scenario: Missing token account
- WHEN a configured non-SOL mint is valid but the wallet has no token account under its detected program
- THEN that input is treated as a zero balance and later inputs are considered
Scenario: Missing or unsupported mint account
- WHEN a configured token's mint account is absent or owned by an unsupported program
- THEN the service warns, skips that input, considers later priorities, and still reaches the EVE-balance step
Scenario: Candidate read is interrupted
- WHEN wallet, CIS-adjacent processing, or Solana access is interrupted while inspecting an input
- THEN the service preserves interruption and ends processing without treating the input as an ordinary failure
Requirement: At most one confirmed swap attempt per iteration
After selecting a positive exact amount and satisfying the current below-reference price condition, the service SHALL invoke the existing Jupiter exact-input operation once with the selected CIS-resolved input mint, fixed EVE output mint, selected amount, and configured slippage. Normal return SHALL be treated as already CONFIRMED and SHALL NOT trigger a second confirmation wait. Once invoked, no later input currency SHALL be attempted in that iteration regardless of success or failure, and the service SHALL proceed to reload the complete EVE balance whenever processing was not interrupted.
A structured definitive on-chain swap failure SHALL be logged without suspending later-process swaps. A timed-out outcome or known-signature confirmation communication error SHALL retain process-local pending swap signature, canonical input, attempted amount and original validity metadata for later read-only reconciliation. Proven pre-submission errors SHALL permit a fresh attempt in a later scheduled iteration. An ambiguous post-submission error without a trustworthy signature SHALL retain manual suspension. Interruption SHALL preserve available pending context and propagate normally. No unknown outcome SHALL cause automatic rebuilding, re-signing or resubmission; pending swaps SHALL still permit existing EVE burn evaluation.
Scenario: First swap fails definitively
- WHEN the first attempted input returns a definitive on-chain failure
- THEN no second input is attempted in that iteration, the EVE balance is still reloaded, and a later iteration may attempt a new swap
Scenario: Swap outcome is unknown
- WHEN the attempted swap times out, throws an I/O failure that permits unknown post-submission status, or is interrupted
- THEN no equivalent or alternative swap is attempted while its outcome is unresolved; a known signature is checked in later iterations and a signature-less ambiguous submission requires manual reconciliation
Scenario: Swap returns normally
- WHEN Jupiter returns a successful result whose transaction already reached
CONFIRMED - THEN the burner performs no additional confirmation wait and reloads the wallet instead of deriving its burn amount only from the returned output amount
Requirement: Complete visible EVE balance is eligible
After the optional swap attempt, the service SHALL detect the fixed EVE mint's supported token program internally and reload the wallet's complete available EVE balance. A missing EVE mint account, unsupported program, absent wallet token account, zero balance, or negative/invalid balance SHALL cause no burn or notification in that iteration. The service SHALL subtract its configured EVE reserve, clamp negative available amounts to zero and round down to validated EVE mint precision using the detected token program. It SHALL submit a new burn only when the actual rounded amount is positive and at least the configured minimum burn amount; equality qualifies. It SHALL burn the entire eligible amount above reserve, without a maximum or fixed batch size, including EVE deposited before the iteration or visible after a failed or absent swap. Below threshold or with unusable mint precision it SHALL retain the EVE and send no burn notification. This threshold SHALL NOT suppress independent buybacks.
Scenario: Existing EVE without buyback
- WHEN no swap is performed but the wallet contains a positive EVE balance
- THEN the service evaluates that complete balance under the EVE reserve, precision and burn-minimum rules
Scenario: EVE account is absent or empty
- WHEN the wallet has no EVE token account or its complete balance is zero
- THEN the iteration submits no burn and sends no notification
Scenario: Issue example threshold and reserve
- WHEN minimum is 1 EVE and reserve is 0.1 EVE
- THEN balances 0, 0.05, 0.1, 1.05 and 1.099999 produce no burn; balance 1.1 burns 1 and balance 1.35 burns 1.25, retaining 0.1 after success
Scenario: Accumulation across small buybacks
- WHEN individually eligible small buybacks accumulate EVE over multiple iterations
- THEN each below-threshold iteration still permits its buyback and sends no burn message; the first qualifying iteration burns all eligible EVE and subsequent accumulation starts with the retained reserve
Scenario: Exact configuration exceeds mint precision
- WHEN six-decimal mint precision rounds available 1.0000009 to 1.000000 while minimum is 1.0000001
- THEN no burn occurs; no amount is rounded upward and the reserve is never consumed to reach the minimum
Requirement: Fresh EVE value is required before submission
Immediately before a new burn, the service SHALL obtain the latest canonical EVE/USDT observation and require a positive price, non-null observation timestamp, and age no greater than maximumPriceAge milliseconds. USDT SHALL be treated as USD for notification value, calculated as the actual rounded eligible EVE amount above reserve multiplied by that fresh price. If the pair is unsupported or the observation is missing, invalid, or stale, the service SHALL warn, postpone the burn, send no notification, and retry only by re-evaluating state in a later scheduled iteration.
Scenario: Fresh EVE price exists
- WHEN a positive rounded EVE amount at or above the burn minimum and sufficiently fresh positive EVE/USDT observation are available
- THEN the service calculates the notification's USD value from that actual eligible burn amount, excluding reserve before submitting the burn
Scenario: EVE price is stale
- WHEN EVE is present but its observation is older than the configured age limit
- THEN the service leaves EVE unburned and sends no notification in that iteration
Requirement: Single complete-balance burn submission and pending state
For a positive rounded EVE amount at or above the minimum with a usable price, the service SHALL call the wallet burn operation exactly once with the fixed EVE mint and entire eligible rounded amount above reserve. It SHALL NOT automatically retry, rebuild, re-sign, or resubmit within or across iterations. Immediately after a non-blank signature is returned, it SHALL retain process-local pending data containing that signature, actual submitted EVE amount excluding reserve, and its calculated notification value or complete notification text before awaiting the signature.
If burn submission fails without a usable signature and its outcome may be unknown, including an I/O or interruption path whose contract permits post-submission uncertainty, the service SHALL conservatively suspend further burn submissions for the current process. It MAY continue ordinary iteration work that does not submit another burn. Recovery SHALL require external reconciliation followed by a complete process restart, not a Burner service stop/start operation.
Scenario: Burn returns a signature
- WHEN the wallet submits the entire eligible rounded amount above reserve and returns a non-blank signature
- THEN pending state is retained before the service begins finalization waiting
Scenario: Submission outcome may be unknown without a signature
- WHEN burn submission fails or is interrupted without providing a usable signature and may already have reached Solana
- THEN the service performs no further burn submission until external reconciliation and a complete process restart
Scenario: Pending burn bypasses new threshold evaluation
- WHEN a retained burn signature remains pending while balance is now below the minimum or at the reserve
- THEN only the original signature is awaited, its original submitted amount/value are preserved and it is never re-evaluated, rebuilt or resubmitted
Requirement: Finalized burn outcome governs completion
Every known burn signature SHALL be awaited through the Solana blockchain at FINALIZED with exactly the configured finalization timeout. SUCCEEDED SHALL authorize notification; FAILED SHALL log the slot and complete on-chain failure details, clear pending state, and send no notification; TIMED_OUT and IOException SHALL keep the pending signature because its result remains unknown; and InterruptedException SHALL preserve interruption and pending state. None of these outcomes SHALL cause automatic transaction resubmission.
Scenario: Burn finalizes successfully
- WHEN the submitted signature reaches
FINALIZEDwithout an on-chain error - THEN the service may perform the notification attempt associated with that exact burn
Scenario: Burn fails on-chain
- WHEN the signature reaches
FINALIZEDwith an on-chain error - THEN the service logs its slot and complete error, clears pending state, and never announces that burn
Scenario: Finalized result remains unknown
- WHEN finalization times out or communication fails
- THEN the service retains the exact signature and later awaits it again without submitting another burn
Requirement: Exactly one post-finalization notification attempt
Only after a burn reaches successful FINALIZED status, the service SHALL invoke the bound notification service exactly once with this structure, using the burn signature rather than any swap signature:
🔥🔥🔥 We have bought back and burned <EVE_AMOUNT> EVE (Evelyn IOU tokens, value $<USD_VALUE>) to reduce the circulating supply! 🔥🔥🔥
Proof:
https://solscan.io/tx/<BURN_TRANSACTION_SIGNATURE>
The EVE amount SHALL use plain decimal notation without unnecessary trailing zeroes or scientific notation. The USD value SHALL have exactly two decimal places using half-up monetary rounding. The blank line before Proof: SHALL be preserved. Before invoking delivery, the service SHALL make the completed pending burn ineligible for another attempt. Delivery failure SHALL be logged without notification secrets and SHALL NOT retry notification or repeat the burn.
Scenario: Successful finalized burn is announced
- WHEN 10 EVE with a calculated value of 150.225 USDT reaches successful
FINALIZEDstatus under a burn signature - THEN one message reports
10 EVE,$150.23, preserves the blank line, and links to that burn signature
Scenario: Notification delivery fails
- WHEN the sole notification invocation throws
- THEN the service logs a non-secret failure, clears completed state, and never retries either notification or burn
Requirement: Exact token-capped amount and per-currency reserve
The service SHALL select the lesser of positive balance - minimumReserve and the input UUID's maximum token amount, then round downward to mint precision. It SHALL skip non-positive results and actual rounded amounts below that UUID's minimum, continuing to later inputs in the same iteration without counting a swap attempt. Equality SHALL qualify. It SHALL never round upward, top up from reserves or exceed either existing bound. Input selection SHALL require no input/USDC Ticker observation. Minima and maxima SHALL constrain buyback inputs only; EVE burns SHALL remain uncapped and governed independently by their own EVE minimum and reserve. Native SOL reserves SHALL use observed balance without estimating future fees.
Scenario: SyrupUSDC maximum is lower than spendable balance
- WHEN SyrupUSDC balance is 0.5, its reserve is 0.095, its minimum is 0.045 and its maximum is 0.2
- THEN 0.2 SyrupUSDC is selected without requesting a SyrupUSDC/USDC observation
Scenario: SyrupUSDC spendable balance is lower than the maximum
- WHEN SyrupUSDC balance is 0.245, its reserve is 0.095, its minimum is 0.045 and its maximum is 0.2
- THEN 0.150 SyrupUSDC is selected before downward mint-precision rounding
Scenario: Reserve consumes the balance
- WHEN the current balance is equal to or below that entry's minimum reserve
- THEN no amount of that currency is intentionally swapped
Scenario: USDT maximum preserves the production bound
- WHEN USDT balance is 0.35, its reserve is 0.1, its minimum is 0.05 and its maximum is 0.25
- THEN 0.25 USDT is selected before downward mint-precision rounding
Scenario: Precision rounding never increases the spend
- WHEN the lesser of spendable balance and maximum is 0.1509999, the mint supports six decimals and its minimum is no greater than 0.150999
- THEN the service selects 0.150999, and if downward rounding instead produces zero the input is skipped
Scenario: Native transaction fees
- WHEN native SOL is selected with a configured reserve
- THEN the service enforces the reserve against the observed balance only and does not estimate fees, even though later fees may reduce the final balance or cause execution to fail
Scenario: USDT below and at its minimum
- WHEN USDT reserve is 0.1 and minimum is 0.05
- THEN balances 0.14 and 0.149999 are skipped, while balance 0.15 selects exactly 0.05
Scenario: Tiny first input permits useful later input
- WHEN USDT balance is 0.100001 with reserve 0.1/minimum 0.05, and SyrupUSDC balance is 0.502048 with reserve 0.095/minimum 0.045/maximum 0.2
- THEN the USDT remainder is skipped and 0.2 SyrupUSDC is the only attempted swap
Scenario: SyrupUSDC minimum boundary
- WHEN SyrupUSDC reserve is 0.095 and minimum is 0.045
- THEN balance 0.14 selects exactly 0.045 while 0.139999 is skipped
Scenario: Actual rounded candidate falls below a fractional minimum
- WHEN six-decimal input precision rounds candidate 0.0500009 down to 0.050000 and its minimum is 0.0500001
- THEN the candidate is skipped without rounding up or using reserves
Scenario: Input minima do not suppress direct EVE burn
- WHEN every configured input is below its minimum but the wallet contains EVE with a usable EVE/USDT price
- THEN the complete EVE balance is still evaluated and its rounded eligible amount above the EVE reserve is burned if it meets the EVE burn minimum
Requirement: Production burner accepts USDT and SyrupUSDC
The production Hub SHALL configure USDT first with reserve 0.1, minimum input 0.05 and maximum input 0.25 USDT, and SyrupUSDC second with reserve 0.095, minimum input 0.045 and maximum input 0.2 SyrupUSDC. These SHALL be token-denominated limits without a USD-value guarantee. The production EVE burn minimum SHALL be 0.1 EVE and its retained reserve SHALL be 0.01 EVE, as selected by the owner on 2026-10-06, configured as MoneyAmount values using the canonical EVE UUID. The production Hub SHALL supply its corresponding Production Evelyn status service for current reference-price decisions. The existing burner wallet, Jupiter route selection, registration, hourly interval, slippage, EVE/USDT freshness, confirmation settings and burn recovery behavior SHALL be preserved without new Ticker sources or history storage.
Scenario: Production inputs and settings
- WHEN the Hub constructs the production burner
- THEN it supplies the exact reserves, minima and maxima as MoneyAmount values in USDT-then-SyrupUSDC priority, supplies minimum burn 0.1 EVE/reserve 0.01 EVE and the Production status service, and retains the other existing production arguments
Scenario: Production burn threshold
- WHEN production EVE balance is below 0.11, exactly 0.11, or 0.135 with usable mint precision and fresh price
- THEN below 0.11 produces no burn, 0.11 burns 0.1 and 0.135 burns 0.125; successful burns retain 0.01 EVE
Requirement: Pending swaps reconcile before new input selection
After pending-burn priority, a retained swap SHALL be checked read-only by its original signature at CONFIRMED or stronger in a bounded operation. Success, on-chain failure or demonstrated non-executed expiry SHALL clear it and permit newly read balances to drive at most one new swap. Unknown, absent without expiry proof or I/O outcomes SHALL remain pending without a new swap while allowing existing EVE burns. Interruption SHALL propagate with pending state intact.
Scenario: Original swap resolves
- WHEN a later check resolves the original signature as successful, definitively failed or proven non-executed and expired
- THEN pending swap state is cleared, complete failure details are logged when applicable, and any new selection uses newly read balances
Scenario: Original swap remains unresolved
- WHEN a later check times out, lacks trustworthy expiry/history evidence, observes only lower commitment or encounters I/O failure
- THEN the same pending signature is retained for the next scheduled iteration, no new swap occurs and the existing EVE burn path still runs
Scenario: Burn remains pending
- WHEN both a swap and a burn are pending at iteration start
- THEN only the burn signature is awaited and no swap reconciliation or new transaction is performed
Requirement: Safe swap recovery diagnostics
Swap diagnostics SHALL identify canonical input symbol/UUID, attempted amount, known signature, submission or reconciliation state, safe cause details and next action. Timeout SHALL be described as unknown. Credentials, arbitrary provider/signer bodies and serialized transaction payloads SHALL NOT be logged. Pending swap state SHALL remain process-local; restart SHALL lose it and require external reconciliation before safely resuming uncertain activity.
Scenario: Unknown outcome is diagnosed
- WHEN a swap outcome remains unknown
- THEN diagnostics identify whether its original signature will be checked next iteration or manual investigation is required, without exposing secret or payload data
Requirement: Independent EVE burn policy configuration
The constructor SHALL accept minimumBurnAmount and eveReserve as EVE-denominated MoneyAmount values identified by canonical EVE UUID regardless of supplied display metadata. Both values, their amounts, currencies and UUIDs SHALL be non-null; minimum SHALL be strictly positive and reserve non-negative. Zero reserve SHALL be valid. Invalid burn configuration SHALL fail before worker startup without changing existing input validation.
Scenario: Invalid burn configuration
- WHEN either value, amount, currency or UUID is null, a UUID is not EVE, the minimum is zero/negative, or the reserve is negative
- THEN construction fails before creating a worker or transaction
Scenario: Stale EVE metadata and zero reserve
- WHEN both values carry the EVE UUID with stale names/symbols and the reserve is zero
- THEN construction succeeds and uses canonical EVE identity with the configured exact numeric amounts
Requirement: New buybacks require a below-reference market price
An otherwise eligible new buyback SHALL require a fresh canonical EVE/USDT observation within the existing maximum price age and a usable canonical EVE/USDT reference price from the injected corresponding Evelyn status service at the current decision instant. Both prices SHALL be positive. Only actual price strictly below reference SHALL permit submission; equality SHALL not qualify. The existing public reference operation SHALL be reused without copying curve calculations or reading stored history.
Scenario: Strict boundary below reference
- WHEN an input is otherwise eligible and reference price is 15 USDT/EVE
- THEN market price 14.99 permits the existing buyback, while 15.00 and 15.01 submit no new swap from any input in that iteration
Scenario: Required prices are unusable
- WHEN market observation is missing, stale, incomplete, unavailable or has an invalid pair/non-positive price, or reference lookup throws, is missing or has an invalid pair/non-positive price
- THEN no new swap is submitted and a safe diagnostic explains why the purchase was skipped
Scenario: Reference uses the current decision instant
- WHEN the first usable input is ready for a new swap
- THEN the corresponding status service is asked for its reference price at the current instant rather than using a sampled history point or the observation timestamp
Requirement: Price skips preserve independent burn processing and recovery
A rejected buyback price condition SHALL skip purchases only, continue complete EVE-balance processing under the existing independent burn requirements, and SHALL NOT create a suspension. Each subsequent otherwise eligible iteration SHALL re-evaluate prices. Pending-burn priority and read-only pending-swap reconciliation SHALL remain independent of the new-purchase condition; any newly permitted purchase after reconciliation SHALL pass the current price check.
Scenario: Existing EVE burns at or above reference
- WHEN market price is equal to or above reference and existing EVE satisfies its own reserve, minimum, precision, fresh valuation and transaction requirements
- THEN no new swap occurs and the existing eligible EVE is burned normally
Scenario: Reference unavailable but burn valuation is usable
- WHEN reference lookup is unavailable or invalid but existing EVE and its fresh canonical valuation satisfy the burn requirements
- THEN the purchase is skipped and the independent eligible burn still occurs
Scenario: Next scheduled iteration recovers
- WHEN one iteration skips a purchase because its prices do not qualify and a later otherwise eligible iteration has usable prices below reference
- THEN the later iteration can attempt its one new swap without a restart or manual reset
Scenario: Pending swap is resolved above reference
- WHEN a pending swap resolves read-only at or above reference
- THEN it is cleared normally, any otherwise eligible new purchase is price-checked and skipped, and existing EVE burn evaluation continues
Scenario: Unresolved swap and pending burn retain priority
- WHEN a swap remains unresolved or the iteration starts with a pending burn
- THEN existing transaction-priority rules apply without evaluating a new-purchase price condition or submitting a new swap