Files
com_r35157_nenjim-hubd-impl…/openspec/specs/solana-transaction-awaiting/spec.md
T

9.4 KiB

solana-transaction-awaiting Specification

Purpose

Defines how callers await a definitive Solana transaction outcome at an explicitly requested commitment without resubmitting the transaction.

Requirements

Requirement: Separate transaction awaiting API

The Solana blockchain API SHALL expose a blocking operation that accepts an existing 64-byte Base58 transaction signature, a requested commitment of PROCESSED, CONFIRMED, or FINALIZED, and a strictly positive overall timeout. Submission and awaiting SHALL remain separate operations, and existing consumers SHALL NOT begin awaiting automatically.

Scenario: Valid await request

  • WHEN a caller supplies a valid signature, non-null commitment, and positive timeout
  • THEN the service observes that already submitted transaction without submitting or resubmitting it

Scenario: Invalid arguments

  • WHEN the signature is null, blank, invalid Base58, or does not decode to exactly 64 bytes, the commitment is null, or the timeout is null, zero, or negative
  • THEN the service rejects the call locally before making an RPC request

Requirement: Commitment-aware definitive outcomes

The commitment order SHALL be PROCESSED < CONFIRMED < FINALIZED, and an observed level SHALL satisfy the same or any lower requested level. The service SHALL return SUCCEEDED or FAILED only after the observed transaction has reached or exceeded the requested commitment. FAILED SHALL exclusively represent a non-null Solana on-chain err; lower-commitment success or error observations SHALL remain inconclusive.

Scenario: Success reaches requested commitment

  • WHEN the transaction is observed at or above the requested commitment with err: null
  • THEN the service returns SUCCEEDED with the transaction slot and no failure details

Scenario: Failure reaches requested commitment

  • WHEN the transaction is observed at or above the requested commitment with a non-null err
  • THEN the service returns FAILED with the transaction slot and the complete err value as compact JSON

Scenario: Observation is below requested commitment

  • WHEN a successful or failed transaction is observed below the requested commitment
  • THEN the service continues polling rather than returning a definitive outcome

Requirement: Transaction outcome invariants

Every public transaction outcome SHALL enforce that SUCCEEDED has a non-null slot and null failure details, FAILED has a non-null slot and non-blank failure details, and TIMED_OUT has null slot and null failure details.

Scenario: Invalid outcome construction

  • WHEN an outcome is constructed with fields inconsistent with its status
  • THEN construction fails immediately

Requirement: Signature status polling contract

The service SHALL poll HTTP JSON-RPC getSignatureStatuses with exactly the supplied signature and searchTransactionHistory: true. It SHALL use only result.value[0].slot, err, and confirmationStatus; a null sole value SHALL remain inconclusive. A present status SHALL contain a Long-representable slot and one of processed, confirmed, or finalized.

Scenario: Signature is not found yet

  • WHEN result.value contains exactly one null element
  • THEN the service continues polling until a definitive outcome or timeout

Scenario: Valid status is observed

  • WHEN the sole status contains a valid slot, recognized confirmation status, and err value
  • THEN the service evaluates it against the requested commitment

Requirement: Overall monotonic deadline

The timeout SHALL define one monotonic deadline covering RPC-gate acquisition, shared throttling, HTTP calls, response processing, and subsequent polls. Gate and throttle waiting SHALL be interruptible and deadline-aware, no request SHALL start after the deadline, and an HTTP request SHALL as far as reasonably possible be bounded by the remaining time.

Scenario: Deadline expires before RPC access

  • WHEN the deadline expires while waiting for the shared gate or remaining throttle interval
  • THEN the service returns TIMED_OUT without starting another RPC request

Scenario: Deadline expires during HTTP request

  • WHEN the deadline-bound status HTTP request times out
  • THEN the service returns TIMED_OUT

Scenario: Caller is interrupted

  • WHEN interruption occurs during gate acquisition, throttling, HTTP communication, or another internal wait
  • THEN InterruptedException propagates directly and no subsequent request is made

Requirement: Unknown timeout semantics

TIMED_OUT SHALL mean the requested definitive outcome remains unknown and SHALL NOT imply rejection, failure, expiration, or permission to resubmit. It SHALL not retain a slot previously observed below the requested commitment.

Scenario: Deadline passes without definitive outcome

  • WHEN the signature remains unseen or below the requested commitment until the deadline
  • THEN the service returns TIMED_OUT with null slot and null failure details and does not resubmit the transaction

Requirement: Shared RPC throttling

Status polling SHALL reuse the same shared mechanism that preserves at least five seconds between Solana RPC calls. It SHALL add no independent polling sleep, interval, or limiter, and existing RPC operations SHALL preserve their public behavior and common throttling.

Scenario: Inconclusive poll

  • WHEN a status response is inconclusive and time remains
  • THEN the next poll is naturally delayed by the shared five-second RPC throttle only

Requirement: Communication and protocol errors

Non-success HTTP responses, JSON-RPC errors, invalid JSON, missing or invalid result.value, arrays with other than exactly one element, invalid slots, missing or unknown confirmation status, and other network or protocol failures SHALL result in IOException, not FAILED. Error messages SHALL identify getSignatureStatuses and include relevant context. The service SHALL NOT automatically retry after an IOException.

Scenario: Invalid RPC response

  • WHEN a status response violates the required HTTP, JSON-RPC, result-array, slot, or confirmation-status contract
  • THEN the service throws a contextual IOException

Scenario: Communication failure

  • WHEN status communication fails for a reason other than expiration of the overall deadline or thread interruption
  • THEN the service throws IOException without automatically polling again

Requirement: Cached decorator delegates directly

The cached Solana blockchain decorator SHALL delegate every transaction-await call directly to its underlying blockchain without caching, reuse, or deduplication.

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