Skip to main content
Check the status of a transaction after sending it to the network. Useful for showing users when their transaction is confirmed.
import { Connection } from "@solana/web3.js";
import { useEffect, useState } from "react";

type TransactionStatus = "pending" | "confirmed" | "finalized" | "failed";

function TransactionStatus({ signature }: { signature: string }) {
  const [status, setStatus] = useState<TransactionStatus>("pending");
  const [transaction, setTransaction] = useState<any>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const connection = new Connection("https://api.mainnet-beta.solana.com");

    const checkStatus = async () => {
      try {
        // Get transaction status
        const txStatus = await connection.getSignatureStatus(signature);

        if (txStatus.value?.err) {
          setStatus("failed");
          setError(JSON.stringify(txStatus.value.err));
          return;
        }

        if (txStatus.value?.confirmationStatus === "finalized") {
          setStatus("finalized");
        } else if (txStatus.value?.confirmationStatus === "confirmed") {
          setStatus("confirmed");
        } else {
          setStatus("pending");
        }

        // Get full transaction details
        const txDetails = await connection.getTransaction(signature, {
          maxSupportedTransactionVersion: 0,
        });

        setTransaction(txDetails);
      } catch (err) {
        setError(err instanceof Error ? err.message : "Unknown error");
      }
    };

    // Check immediately
    checkStatus();

    // Poll every 2 seconds until finalized
    const interval = setInterval(() => {
      if (status !== "finalized" && status !== "failed") {
        checkStatus();
      } else {
        clearInterval(interval);
      }
    }, 2000);

    return () => clearInterval(interval);
  }, [signature, status]);

  return (
    <div>
      <h3>Transaction Status</h3>
      <p>
        <strong>Signature:</strong> {signature}
      </p>
      <p>
        <strong>Status:</strong> {status}
      </p>
      {error && <p style={{ color: "red" }}>Error: {error}</p>}
      {transaction && (
        <div>
          <p>
            <strong>Slot:</strong> {transaction.slot}
          </p>
          <p>
            <strong>Block Time:</strong>{" "}
            {transaction.blockTime
              ? new Date(transaction.blockTime * 1000).toLocaleString()
              : "N/A"}
          </p>
          <a
            href={`https://explorer.solana.com/tx/${signature}`}
            target="_blank"
            rel="noopener noreferrer"
          >
            View on Explorer
          </a>
        </div>
      )}
    </div>
  );
}

// Usage
function SendTransaction() {
  const [txSignature, setTxSignature] = useState<string | null>(null);

  const sendTx = async () => {
    // ... send transaction logic
    // const { hash } = await solana.signAndSendTransaction(transaction);
    // setTxSignature(hash);
  };

  return (
    <div>
      <button onClick={sendTx}>Send Transaction</button>
      {txSignature && <TransactionStatus signature={txSignature} />}
    </div>
  );
}

Confirmation statuses

Solana transactions have three confirmation statuses:
  • Pending: Transaction has been submitted but not yet confirmed
  • Confirmed: Transaction has been confirmed by the cluster (not yet finalized)
  • Finalized: Transaction has been finalized and cannot be rolled back
Transactions are typically confirmed within 1-2 seconds and finalized within ~30 seconds on mainnet. Use “confirmed” status for most UI updates, and “finalized” for critical operations.