Transaction UX
Toasts, confirmations, retries, and error decoding for user-facing sends.
Search across all documentation pages
Toasts, confirmations, retries, and error decoding for user-facing sends.
type TxState = "idle" | "building" | "signing" | "sending" | "confirmed" | "failed";When to reach for this:
"use client";
import { useState } from "react";
export function useTxToast() {
const [state, setState] = useState<TxState>("idle");
const [signature, setSignature] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
async function run(sendFn: () => Promise<string>) {
try {
setError(null);
setState("signing");
const sig = await sendFn();
setSignature(sig);
setState("confirmed");
return sig;
} catch (e) {
setError(e instanceof Error ? e.message : "Transaction failed");
setState("failed");
throw e;
}
}
return { state, signature, error, run };
}What this demonstrates:
| Alternative | Use When | Don't Use When |
|---|---|---|
| Email on confirmed | High-value ops | Consumer game txs |
| Silent background send | Analytics | User-initiated transfers |
Providers in client layout.tsx; pages mix server + client components.
Server env only for keypairs; NEXT_PUBLIC_ for RPC URLs.
All examples use @solana/kit, not web3.js v1.
Signing only in client components.
Revalidate on-chain reads carefully - chain is source of truth.
HTTPS endpoints returning Solana Actions JSON.
Separate React Native app with MWA.
Surfpool for integration; mock RPC in unit tests.
Separate env files and program IDs.
Decode simulation logs for user-facing messages.
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.
Reviewed by Chris St. John·Last updated Jul 16, 2026