UX.SOL

Hook

useSmartRetry

Retries asynchronous Solana operations with configurable backoff and error handling.

Installation

terminal
$npx shadcn@latest add https://uxdotsol.xyz/r/use-smart-retry.json

Usage

use-smart-retry.tsx
"use client";
 
import { useState } from "react";
import {
LAMPORTS_PER_SOL,
type Connection,
type PublicKey,
} from "@solana/web3.js";
import { useSmartRetry } from "@/hooks/use-smart-retry";
 
export function SolBalanceRefresh({
connection,
owner,
}: {
connection: Connection;
owner: PublicKey;
}) {
const [balance, setBalance] = useState<number | null>(null);
const retry = useSmartRetry<number>({ client: connection, maxAttempts: 4 });
 
async function refreshBalance() {
setBalance(null);
try {
const lamports = await retry.execute(() =>
connection.getBalance(owner, "confirmed"),
);
setBalance(lamports / LAMPORTS_PER_SOL);
} catch {
// The hook exposes the final error for the UI.
}
}
 
return (
<section>
<p>SOL balance: {balance === null ? "Not loaded" : balance.toFixed(4)}</p>
<button disabled={retry.isRetrying} onClick={refreshBalance}>
{retry.isRetrying
? `RPC busy, retrying (${retry.attempt}/4)...`
: "Refresh balance"}
</button>
{!retry.isRetrying && retry.error && balance === null ? (
<p role="alert">Could not reach the Solana RPC.</p>
) : null}
</section>
);
}

Options

NameTypeDefaultDescription
maxAttemptsnumber4Maximum operation attempts before surfacing the error.
refreshBlockhash() => Promise<unknown>undefinedOptional callback used when a stale blockhash error is detected.
baseDelayMs / maxDelayMsnumber400 / 6000Exponential backoff delay bounds.
shouldRetry(error, attempt, decision) => booleandecision.retryableOverride for retry decisions after Solana error classification.
onAttempt / onRetry / onSuccess / onFailurecallbacksundefinedLifecycle callbacks for telemetry or UI updates.

Functions

NameTypeDefaultDescription
execute(operation: (attempt: number) => Promise<T>, override?: Partial<SmartRetryOptions<T>>) => Promise<T>-Runs an async operation with retry behavior.
cancel() => void-Stops future retry attempts.
classifySolanaRetry(error: unknown) => SmartRetryDecision-Classifies blockhash, rate-limit, node, simulation, and transport errors.

Types

NameTypeDefaultDescription
SolanaRetryReason'blockhash-expired' | 'rate-limited' | 'node-unhealthy' | 'simulation-failed' | 'transport' | 'unknown'-Known retry reason categories.
SmartRetryDecision{ reason; retryable; refreshBlockhash }-Classifier output used by retry logic.

Returns

NameTypeDefaultDescription
isRetrying / attemptboolean / numberfalse / 0Current retry activity and attempt count.
errorunknownnullLast caught operation error.