91: Reconcile timed-out Evelyn IOU burner swaps in later iterations

This commit is contained in:
2026-10-06 07:47:34 +02:00
parent adb5f0235a
commit 152137ed87
25 changed files with 1057 additions and 184 deletions
@@ -81,7 +81,7 @@ The service SHALL fix the EVE mint as `meveYG2iXYSkgSUn1T1uxcthH1EGMZdRHGgCntXZA
### 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 burn information and 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.
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
@@ -130,7 +130,7 @@ For each entry the service SHALL subtract its configured reserve and skip non-po
### Requirement: At most one confirmed swap attempt per iteration
After selecting a positive exact amount, 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 structured outcome SHALL suspend all later swaps in that process. Because the Jupiter `IOException` and interruption contracts can represent an unknown post-submission result, either SHALL conservatively suspend later swaps. The service SHALL never automatically rebuild, re-sign, retry, or resubmit such a swap; while swaps are suspended, later iterations SHALL continue only their burn path. Recovery SHALL require external reconciliation followed by a complete process restart, not a Burner service stop/start operation.
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
@@ -138,7 +138,7 @@ A structured definitive on-chain swap failure SHALL be logged without suspending
#### 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 and all later swaps remain suspended until external reconciliation and a complete process restart
- **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`
@@ -242,8 +242,30 @@ The service SHALL select the lesser of positive `balance - minimumReserve` and t
- **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
### Requirement: Production burner accepts USDT and SyrupUSDC
The production Hub SHALL configure USDT first with reserve 0.1 and maximum input 0.25 USDT, and SyrupUSDC second with reserve 0.095 and maximum input 0.2 SyrupUSDC. These SHALL be token-denominated limits without a USD-value guarantee. The existing burner wallet, Jupiter route selection, registration, hourly interval, slippage, EVE/USDT freshness, confirmation and recovery behavior SHALL be preserved without new Ticker sources or history storage.
The production Hub SHALL configure USDT first with reserve 0.1 and maximum input 0.25 USDT, and SyrupUSDC second with reserve 0.095 and maximum input 0.2 SyrupUSDC. These SHALL be token-denominated limits without a USD-value guarantee. 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 two exact reserves and maxima as MoneyAmount values in USDT-then-SyrupUSDC priority and retains the other existing production arguments
### 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
+27 -4
View File
@@ -102,7 +102,7 @@ The service SHALL first accept a Jupiter execution response only when it has sta
#### Scenario: Provider succeeds but confirmation times out
- **WHEN** a fully validated Jupiter execution response contains a signature whose independent `CONFIRMED` outcome is `TIMED_OUT`
- **THEN** the service throws a structured checked outcome exception preserving the signature, requested commitment, and unknown outcome warning and does not automatically resubmit an equivalent transaction
- **THEN** the service throws a structured checked outcome exception preserving the signature, requested commitment, original validity metadata and unknown outcome warning and does not automatically resubmit an equivalent transaction
### Requirement: Swap confirmation timeout policy
The reference service SHALL accept a constructor-injected, non-null, strictly positive confirmation timeout and SHALL preserve its existing constructor with a two-minute default. The configured duration SHALL be passed unchanged to independent confirmation after submission and SHALL begin governing only when awaiting the known signature starts.
@@ -116,15 +116,15 @@ The reference service SHALL accept a constructor-injected, non-null, strictly po
- **THEN** construction fails before any operation can be submitted
### Requirement: Post-submission communication and interruption policy
If independent confirmation fails with an I/O error after the signature is known, the service SHALL throw an `IOException` whose message identifies the swap operation, includes the signature, and states that the on-chain outcome is unknown, with the original error retained as its cause. Interruption SHALL propagate directly as `InterruptedException` without another RPC or Jupiter request. Neither condition SHALL trigger rebuilding, re-signing, retrying, or resubmitting a transaction.
If independent confirmation fails with an I/O error after the signature is known, the service SHALL throw a structured `IOException` preserving the original signature, original transaction-validity metadata, submission uncertainty and underlying cause. Interruption SHALL propagate as `InterruptedException` while preserving known signature/validity context in structured form without another RPC or Jupiter request. Neither condition SHALL trigger rebuilding, re-signing, retrying, or resubmitting a transaction.
#### Scenario: Confirmation communication fails
- **WHEN** independent confirmation throws an I/O error for a known submitted signature
- **THEN** the service reports the signature and unknown on-chain outcome while preserving the original error and performs no retry or resubmission
- **THEN** the service reports the structured signature, original validity metadata and unknown on-chain outcome while preserving the original error and performs no retry or resubmission
#### Scenario: Confirmation is interrupted
- **WHEN** independent confirmation throws `InterruptedException`
- **THEN** that interruption propagates directly and the service performs no subsequent request
- **THEN** that interruption retains its known signature and validity context, propagates normally and the service performs no subsequent request
### Requirement: API and implementation separation
The stable service interface and result value SHALL reside in the Jupiter swap API package, while HTTP DTOs, endpoint handling, throttling, and the reference implementation SHALL remain in the reference-implementation package.
@@ -132,3 +132,26 @@ The stable service interface and result value SHALL reside in the Jupiter swap A
#### Scenario: Downstream API consumer
- **WHEN** downstream code depends only on the Jupiter swap API package
- **THEN** it can invoke swaps and inspect results without depending on private wire DTOs or reference-implementation mechanics
### Requirement: Submission certainty and original validity remain structured
The integration SHALL expose submission certainty, known signature, original cause and original validity in structured form. Original validity SHALL retain the order height, actual blockhash, taker and finalized submission anchor. Signing SHALL preserve the hash and required taker signer. Expiry evidence SHALL be bound to a populated local first signature; contradictory provider identity SHALL require manual handling. Existing perps outcome construction SHALL remain compatible.
#### Scenario: Preparation fails
- **WHEN** mint/order acquisition, validation, signing or pre-submission validity preparation fails before execution submission
- **THEN** the error is structured as pre-submission and no execution or automatic retry occurs
#### Scenario: Execution response is lost
- **WHEN** execution may have been submitted and no trustworthy signature is available
- **THEN** the error remains structured as uncertain submission and does not authorize automatic recovery or resubmission
#### Scenario: Provider identity contradicts the signed transaction
- **WHEN** an execution response signature differs from the populated first signature of the signed payload
- **THEN** the result is not treated as confirmed and uncertain submission requires manual reconciliation
#### Scenario: Sponsor identity is completed by Jupiter
- **WHEN** Jupiter supplies a valid provider signature while the local first signature is blank
- **THEN** the signature can be awaited and reconciled by status, but original local validity cannot establish non-executed expiry
#### Scenario: Timeout retains original validity
- **WHEN** confirmation of a known submitted signature times out
- **THEN** the exceptional outcome exposes its original validity data without substituting a new transaction or blockhash
@@ -96,3 +96,33 @@ The cached Solana blockchain decorator SHALL delegate every transaction-await ca
#### Scenario: Repeated awaits through cached decorator
- **WHEN** callers invoke transaction awaiting multiple times through the cached decorator
- **THEN** every invocation reaches the delegate independently
### Requirement: Read-only transaction reconciliation
The blockchain SHALL support bounded reconciliation of an existing signature at CONFIRMED or stronger, retaining normal await behavior and outcome statuses. Reconciliation SHALL distinguish definitive success/failure, demonstrated non-executed expiry and unresolved evidence. It SHALL use the existing shared RPC gate/deadline and historical status lookup without submission, caching, immediate retries or a new pacing mechanism. Unsupported expiry evidence SHALL remain unresolved.
#### Scenario: Definitive historical status
- **WHEN** the original signature is observed at or above requested commitment
- **THEN** reconciliation returns its successful or failed outcome with slot and complete failure details as applicable
#### Scenario: Below commitment or interrupted
- **WHEN** the signature is only observed below commitment or the check is interrupted
- **THEN** expiry is not inferred; an unresolved result is returned for lower commitment and interruption propagates normally
#### Scenario: Cached decorator
- **WHEN** reconciliation is invoked through the cached decorator
- **THEN** it reaches the delegate independently on every call
### Requirement: Expiry requires original validity and reliable local history absence
Expiry SHALL require signature-bound original validity, finalized height above its last valid height, original blockhash invalidity, retained local history through its submission anchor and fresh finalized signer-history absence. Missing, pruned, stale, lower-commitment or inconsistent evidence SHALL remain unresolved. Absence, elapsed time or blockhash invalidity alone SHALL NOT authorize clearing a pending transaction.
#### Scenario: Non-executed expiry is established
- **WHEN** all original-validity, finalized-height, original-blockhash, local-history-coverage and finalized signer-history absence checks succeed, with `minContextSlot` at/after the expired finalized context and a bounded page reaching before the submission anchor or exhausting covered retained history
- **THEN** reconciliation identifies a non-executed expired transaction without resubmitting it
#### Scenario: Evidence is incomplete
- **WHEN** original metadata is missing, history is unavailable/pruned, a lookup fails, a response is inconsistent/stale or the original blockhash is still valid
- **THEN** no expiry result is returned and the diagnostic explains the missing evidence
#### Scenario: Bounded history page is incomplete
- **WHEN** a full history page ends at or after the submission anchor
- **THEN** the transaction remains unresolved instead of treating partial absence as proof