In Ethereum development, sending a transaction is just the first step. To ensure your transaction is successfully processed, you need to wait for confirmation on the blockchain. This guide will walk you through monitoring Ethereum transactions in Go, checking their status, and handling success or failure scenarios.
How Ethereum Transaction Confirmation Works
Ethereum produces a new block approximately every 15 seconds. When you send a transaction:
- It enters the pending state while waiting to be included in a block
- Once mined, it transitions to either success or failure state
- You can then verify the final status through transaction receipts
๐ Learn more about Ethereum transaction lifecycle
Checking Transaction Status in Go
The Ethereum Go client (ethclient) provides essential methods for tracking transactions:
_, isPending, err := ec.TransactionByHash(ctx, txHash)Key indicators:
isPending = true: Transaction awaiting confirmationisPending = false: Transaction has been mined (check receipt for final status)
After confirmation, examine the transaction receipt:
receipt, err := ec.TransactionReceipt(ctx, txHash)The receipt contains a Status field where:
0indicates failure1indicates success
Implementing Transaction Waiting Logic
For robust applications, implement a waiting function with timeout:
func waitConfirm(ctx context.Context, ec *ethclient.Client, txHash common.Hash, timeout time.Duration) error {
pending := true
for pending {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(timeout):
return errors.New("timeout")
case <-time.After(time.Second):
_, isPending, err := ec.TransactionByHash(ctx, txHash)
if err != nil {
return err
}
if !isPending {
pending = false
}
}
}
receipt, err := ec.TransactionReceipt(ctx, txHash)
if err != nil {
return err
}
if receipt.Status == 0 {
return fmt.Errorf("transaction failed: %s", receipt.TxHash)
}
return nil
}This function:
- Checks transaction status every second
- Respects context cancellation
- Implements a timeout (10 minutes in this example)
- Returns success/failure status once confirmed
Complete Transaction Sending Example
Here's a full implementation combining transaction sending and confirmation:
package main
import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"log"
"math/big"
"os"
"time"
)
func main() {
client, err := ethclient.Dial(os.Getenv("INFURA_URL"))
if err != nil {
log.Fatalf("Connection error: %v", err)
}
privateKey, err := crypto.HexToECDSA(os.Getenv("PRIVATE_KEY"))
if err != nil {
log.Fatalf("Private key error: %v", err)
}
recipient := common.HexToAddress("0xReceiverAddress")
amount := big.NewInt(100000000000000000) // 0.1 ETH
txHash, err := sendTransaction(context.Background(), client, privateKey, recipient, amount)
if err != nil {
log.Fatalf("Transaction failed: %v", err)
}
log.Println("Transaction sent:", txHash)
if err := waitConfirm(context.Background(), client, *txHash, 10*time.Minute); err != nil {
log.Fatalf("Confirmation failed: %v", err)
}
log.Println("Transaction confirmed successfully!")
}
func sendTransaction(ctx context.Context, client *ethclient.Client, pk *ecdsa.PrivateKey, to common.Address, amount *big.Int) (*common.Hash, error) {
// Implementation similar to example above
// ...
}
func waitConfirm(ctx context.Context, client *ethclient.Client, txHash common.Hash, timeout time.Duration) error {
// Implementation as shown above
// ...
}Best Practices for Production
- Set appropriate timeouts based on network conditions
- Implement retry logic for temporary failures
- Monitor gas prices to ensure timely inclusion
- Provide user feedback during waiting periods
๐ Advanced Ethereum development techniques
FAQ
Q: How long does Ethereum transaction confirmation typically take?
A: On average, 15-30 seconds per block, but network congestion can cause delays.
Q: What status code indicates a failed transaction?
A: Status 0 in the transaction receipt indicates failure.
Q: Should I use TransactionByHash or TransactionReceipt?
A: Use TransactionByHash to check pending status, and TransactionReceipt for final confirmation.
Q: What's a reasonable timeout value?
A: 5-10 minutes for most cases, but adjust based on network conditions.
Q: Can transactions become stuck permanently?
A: Yes, if gas is too low. You may need to replace-by-fee in such cases.
Conclusion
Proper transaction confirmation is crucial for reliable Ethereum applications. By implementing status checks and timeouts in your Go applications, you ensure robust transaction handling and better user experience.
Remember to always:
- Verify transaction status
- Handle both success and failure cases
- Provide clear feedback to users
- Monitor network conditions for optimal performance