@exodus/bitcoin-api
Transaction monitors, fee monitors, RPC with the blockchain node, and other networking code for Bitcoin and Bitcoin-like assets (e.g. dogecoin, litecoin, zcash). See Asset Packages for more detail on this package's role.
Insight read recovery
Insight JSON reads retry malformed JSON, common transient network failures, and HTTP 500/502/503/504 responses at most twice. Retries wait one then two seconds with 0–20% positive jitter, respecting longer Retry-After seconds or HTTP dates. All attempts, response-body reads, and waits share a 30-second deadline, or a shorter caller timeout (ten seconds for block height). A retry that would exceed that deadline fails rather than waiting longer or retrying before the server permits it.
Cancellation and permanent HTTP errors, including 429, are not retried by this policy. Existing transaction-not-found behavior is preserved; malformed JSON is never treated as an empty balance or missing transaction. Address-history reads retain their separate configurable retry policy without nested retries. Broadcasts do not use the read-retry policy.
Mempool WebSocket-assisted confirmation checks
Confirmation-only scans reuse WebSocket transaction statuses and block heights for ten seconds, with at most 1,000 statuses per client. Missing or expired hints fall back to /api/tx/:txid/status instead of full transaction/outspend reads. New or replacement blocks, disconnect, stop, and backend changes invalidate the caches; standalone confirmations require a fresh tip lookup. Full history, UTXO, address-event, and reconnect reconciliation remain unchanged, as do Insight-backed monitors.
Confirmation checks recheck their inputs if a WebSocket update, disconnect, or backend change arrives during a lookup. They retry once, then fail rather than return obsolete confirmations if invalidated again.
Mempool Retry-After
Every HTTP 429 starts a process-local cooldown shared across clients and endpoints on the same origin. Valid Retry-After seconds or HTTP dates take precedence, using the server's Date header for clock skew when available, and are capped at five minutes. Missing or invalid values use a ten-second fallback; failed recovery doubles it with 0–20% positive jitter, also capped at five minutes. Concurrent responses from the original burst do not multiply backoff, but longer server deadlines are preserved. A 429 from a broadcast dispatched during cooldown or recovery renews the read cooldown, including the fallback for missing or invalid Retry-After; an older recovery response cannot release that renewed cooldown. Broadcasts do not increase the fallback as failed recovery reads do.
Reads receiving HTTP 429 rejoin the end of the queue instead of immediately failing the monitor scan. Each read permits at most two retries, sharing its original 30-second queue deadline; cancellation, overflow, or expiry still fail finally. Exhausted retries fail with code 429, finalError, bounded retryAt/retryAfterMs, and hint mempoolRateLimited; generic retries stop. Queued reads wait until one recovery read can run, with a ten-second timeout including its body. Success or an ordinary 404 releases the cooldown; other HTTP, transport, or body failures renew it. No recovery request is generated when the queue is empty.
Mempool request scheduling
At most two REST requests run concurrently, including body consumption, with at least 200 ms between starts. Reads queue FIFO, bounded to 100 entries and a 30-second wait including cooldown. Abort signals remove queued requests; expired or cancelled entries never dispatch later. Normal requests have a 30-second dispatch-time timeout including the body, respecting shorter caller timeouts. History scans submit two address batches at a time while retaining full address coverage; Insight concurrency is unchanged.
Broadcasts jump ahead of queued reads only when request capacity is available. Active requests and broadcasts waiting for pacing reserve the two request slots; when both slots are occupied or reserved, a new broadcast fails immediately with MEMPOOL_REQUEST_BUSY and finalError, without automatic retry or later dispatch. The read queue limit does not consume broadcast capacity. Accepted broadcasts preserve FIFO order and 200 ms pacing, with the original one-second queue deadline; expired broadcasts fail finally with MEMPOOL_REQUEST_QUEUE_TIMEOUT. Active requests remain uninterrupted. New and queued broadcasts bypass local cooldown and recovery waits. Broadcasts never become recovery probes, and their success does not release read cooldown. Dispatched broadcasts receiving 429 still establish read cooldown and fail without automatic replay.
Queue and request deadlines apply per attempt. The send wrapper can retry one non-final broadcast failure after ten seconds, so pacing waits and network timeouts across both attempts can total about 72 seconds, excluding transaction preparation and post-failure checks. The broadcast client does not currently accept a caller cancellation signal; consumers should await the send result rather than assume an earlier UI timeout cancels it.
Recovery resumes paced traffic rather than a burst. This client budget is not a vendor quota and cannot guarantee freedom from rate limits or bans. The five-minute cap may permit requests earlier than the server requested; queues and cooldowns are not persisted or coordinated across processes.