## Context

See `proposal.md` for motivation. `SolanaBlockChainImpl` currently serializes every RPC request through a synchronized `sendThrottled()` method, sleeps until five seconds have elapsed since the preceding RPC response, performs HTTP while holding the monitor, and records completion time in `finally`. Monitor acquisition is neither interruptible nor deadline-aware, while issue #67 requires both without changing existing RPC behavior.

## Goals / Non-Goals

**Goals:**

- Preserve one shared five-second gate for all RPC calls while allowing awaiting calls to stop at a monotonic deadline.
- Keep definitive transaction state, timeout, protocol failure, and interruption as distinct outcomes.
- Strictly validate all wire data that controls a returned outcome.
- Keep the API and outcome types generic to Solana rather than any consuming domain.

**Non-Goals:**

- Combining submission and awaiting, resubmission, WebSockets, signature subscriptions, or blockhash-expiration inference.
- Updating any existing wallet, Jupiter, burn, Evelyn, or Discord consumer.
- Adding automated tests or test-only transport, time, or throttling seams in this implementation.

## Decisions

### Replace the intrinsic monitor with one interruptible shared lock

A private `ReentrantLock` will serialize all RPC traffic. Existing calls acquire it interruptibly, perform the same five-second wait and HTTP exchange, update the shared completion timestamp in `finally`, and release it. Awaiting calls use timed `tryLock` with their remaining deadline. A separate polling lock or rate limiter was rejected because it would violate the shared throttle and permit polling to interfere unpredictably with other calls.

### Measure shared throttling and awaiting deadlines monotonically

The completion timestamp and deadline calculations use `System.nanoTime()`. A small private deadline value tracks the call's start and saturated timeout nanoseconds and computes remaining time by elapsed duration. Wall-clock time was rejected because clock adjustments could extend or shorten both throttling and the caller's timeout.

### Build each status HTTP request only after gate and throttle admission

The deadline-aware send path acquires the gate and waits only up to the remaining deadline. Once admitted, it creates a request whose `HttpRequest.timeout` equals the then-current remaining duration. A request-timeout exception is translated to `TIMED_OUT`; other I/O failures remain `IOException`. Building the request after admission avoids assigning the full original timeout to an HTTP exchange that starts after gate/throttle delay.

### Return an internal no-request signal on deadline expiry

The deadline-aware send helper returns no response when the deadline expires before request start. The public loop converts this only to the invariant `TIMED_OUT` value. This keeps deadline expiry separate from communication/protocol exceptions and ensures a previously seen lower-commitment slot cannot leak into the timeout result.

### Parse only authoritative signature-status fields

Each response must contain a successful HTTP result, no JSON-RPC error, and exactly one `result.value` element. A null element remains inconclusive. A status object requires a Long-representable non-negative `slot` and recognized `confirmationStatus`; only after its commitment satisfies the request is `err` interpreted as success or failure. `result.context`, `confirmations`, and legacy `status` are ignored.

### Preserve the complete on-chain error as compact JSON

Jackson's compact serialization of the non-null `err` node becomes `failureDetails`. The blockchain layer does not classify program-specific errors. Any issue outside this `err` node remains an exception or timeout rather than `FAILED`.

### Validate transaction signatures with the existing Base58 implementation

The reference implementation reuses its existing private Base58 decoder and requires exactly 64 decoded bytes before entering the RPC gate. Introducing a second codec dependency or general transaction parser was rejected as unrelated scope.

### Make cached awaiting a transparent pass-through

`CachedSolanaBlockChain.awaitTransaction` calls its delegate directly. Transaction status is deadline-sensitive and mutable, so cache keys, reuse, and in-flight deduplication would violate the contract.

## Risks / Trade-offs

- [An HTTP client can complete at the edge of its timeout after the monotonic deadline] → Use the remaining deadline as the request timeout and re-check the deadline before interpreting an inconclusive response; this is the strongest practical bound offered by Java `HttpClient`.
- [Replacing synchronization changes the internal locking primitive] → Keep the same lock scope, completion-based five-second spacing, and exception behavior for every existing RPC operation.
- [No automated deterministic coverage is added now] → Keep deadline, parsing, and gate concerns in narrow private methods and document that focused tests remain deferred by explicit task instruction.

## Migration Plan

This is additive at the public API. Existing implementations in this repository are updated together, while existing consumers remain unchanged. Rollback removes the new method/types and restores the prior private monitor without data migration.
