Nonce Management¶
New in v0.2.0.14
Comprehensive nonce management features were introduced in version 0.2.0.14 to prevent stuck transactions and provide automatic error recovery.
Overview¶
Nonce management is critical for Ethereum transactions. A nonce is a sequential number that ensures transactions are processed in order. When nonces get out of sync or transactions get stuck, subsequent transactions will fail.
The OGPU SDK now provides automatic nonce management with:
- ✅ Automatic error detection and retry
- ✅ Thread-safe nonce caching
- ✅ Stuck transaction recovery
- ✅ Manual override capabilities
Automatic Features (Default Behavior)¶
Auto-Retry on Errors¶
All transaction functions automatically detect and recover from common nonce errors:
from ogpu.client import publish_task, TaskInfo
# Just call the function - auto-retry is enabled by default
task_address = publish_task(task_info)
What happens behind the scenes:
- Transaction fails with "nonce too low" error
- SDK automatically calls
fix_nonce() - Pending transactions are cancelled
- Nonce cache is reset
- Transaction is retried
- Success! ✅
Supported Error Types¶
The SDK automatically handles:
| Error Type | Description | Action |
|---|---|---|
nonce too low |
Nonce already used | Auto-fix and retry |
known transaction |
Duplicate transaction | Auto-fix and retry |
replacement transaction underpriced |
Gas price too low | Wait and retry |
Manual Utilities¶
Check Nonce Status¶
Get detailed information about your account's nonce state:
from ogpu.client import get_nonce_info
info = get_nonce_info()
print(f"Mined transactions: {info['mined_nonce']}")
print(f"Pending transactions: {info['pending_count']}")
if info['has_pending']:
print(f"⚠️ Warning: {info['pending_count']} stuck transaction(s)")
Response:
{
'address': '0x...',
'mined_nonce': 42, # Confirmed transactions
'pending_nonce': 44, # Confirmed + pending
'cached_nonce': 44, # SDK cache
'has_pending': True, # Has pending transactions?
'pending_count': 2, # Number of pending
}
Fix Stuck Transactions¶
If transactions are stuck, manually trigger the fix:
from ogpu.client import fix_nonce
# Fix all stuck transactions
next_nonce = fix_nonce()
print(f"Ready! Next nonce: {next_nonce}")
What fix_nonce() does:
- Detects pending (stuck) transactions
- Sends cancellation transactions (0 ETH to self with higher gas)
- Clears SDK internal cache
- Returns next available nonce
Reset Nonce Cache¶
Clear the SDK's internal cache without canceling transactions:
from ogpu.client import reset_nonce_cache
# Clear cache for current account
reset_nonce_cache()
# SDK will fetch fresh nonce on next transaction
Clear All Caches¶
Reset everything (useful for testing):
Advanced Usage¶
Manual Nonce Override¶
For advanced users who need full control:
from ogpu.client import publish_task
# Specify exact nonce
task_address = publish_task(task_info, nonce=42)
Use with Caution
Manual nonce override bypasses SDK management. Only use if you know what you're doing!
Disable Auto-Fix¶
If you want to handle errors manually:
from ogpu.client import publish_task, fix_nonce
try:
# Disable auto-fix
task_address = publish_task(task_info, auto_fix_nonce=False)
except Exception as e:
if "nonce" in str(e).lower():
# Handle manually
fix_nonce()
# Retry
task_address = publish_task(task_info)
Custom Retry Settings¶
Control retry behavior:
from ogpu.client import publish_task
task_address = publish_task(
task_info,
auto_fix_nonce=True, # Enable auto-fix (default)
max_retries=5, # Try up to 5 times (default: 3)
)
Common Scenarios¶
Scenario 1: Transaction Stuck for Hours¶
Problem: Your transaction is stuck in the mempool with low gas price.
Solution:
from ogpu.client import fix_nonce, publish_task
# Fix stuck transactions
fix_nonce()
# Now send new transaction
task_address = publish_task(task_info)
Scenario 2: "Nonce Too Low" Error¶
Problem: Getting "nonce too low" error when sending transactions.
Solution 1 (Automatic):
Solution 2 (Manual):
from ogpu.client import fix_nonce, publish_task
# Manually fix
fix_nonce()
# Then retry
task_address = publish_task(task_info)
Scenario 3: Multiple Rapid Transactions¶
Problem: Need to send many transactions quickly without nonce collisions.
Solution:
from ogpu.client import publish_task
# SDK uses 'pending' block identifier and caching
# No nonce collisions!
for i in range(100):
task_address = publish_task(task_info)
print(f"Task {i+1}: {task_address}")
Scenario 4: Check Before Sending¶
Problem: Want to verify nonce status before sending important transactions.
Solution:
from ogpu.client import get_nonce_info, fix_nonce, publish_task
# Check status first
info = get_nonce_info()
if info['has_pending']:
print(f"⚠️ {info['pending_count']} pending transactions detected")
print("Fixing before sending...")
fix_nonce()
# Now safe to send
task_address = publish_task(task_info)
All Transaction Functions¶
Nonce management is available in all transaction functions:
Client Functions¶
from ogpu.client import (
publish_task,
publish_source,
confirm_response,
)
# All support: nonce, auto_fix_nonce, max_retries
task_address = publish_task(task_info, auto_fix_nonce=True)
source_address = publish_source(source_info, auto_fix_nonce=True)
tx_hash = confirm_response(response_addr, auto_fix_nonce=True)
Agent Functions¶
from ogpu.agent import set_agent
# Also supports nonce management
tx_hash = set_agent(
agent_address,
True,
private_key,
auto_fix_nonce=True
)
API Reference¶
fix_nonce(address=None, private_key=None) -> int¶
Fix stuck nonce issues by canceling pending transactions.
Parameters:
address(str, optional): Address to fix. If None, derived from private_key.private_key(str, optional): Private key. If None, usesCLIENT_PRIVATE_KEYenv var.
Returns:
int: Next available nonce after fixing
Example:
get_nonce_info(address=None, private_key=None) -> dict¶
Get detailed nonce information.
Parameters:
address(str, optional): Address to check.private_key(str, optional): Private key to derive address from.
Returns:
dict: Nonce information with keys:address: The addressmined_nonce: Confirmed transactionspending_nonce: Confirmed + pendingcached_nonce: SDK cache (or None)has_pending: Booleanpending_count: Number of pending
Example:
reset_nonce_cache(address=None, private_key=None) -> None¶
Reset SDK nonce cache.
Parameters:
address(str, optional): Address to reset.private_key(str, optional): Private key to derive address from.
Example:
clear_all_nonce_caches() -> None¶
Clear all nonce caches for all addresses.
Example:
Best Practices¶
1. Let SDK Handle Errors Automatically¶
The default behavior is best for most use cases:
2. Check Status Before Bulk Operations¶
Verify nonce state before sending many transactions:
# ✅ Good practice
info = get_nonce_info()
if info['has_pending']:
fix_nonce()
# Now safe for bulk operations
for task_info in task_list:
publish_task(task_info)
3. Use Manual Fix When Needed¶
If auto-retry fails, use manual fix:
# ✅ Good - manual recovery
try:
task_address = publish_task(task_info)
except Exception as e:
if "nonce" in str(e).lower():
fix_nonce()
task_address = publish_task(task_info)
4. Avoid Unnecessary Manual Override¶
Only override nonce if you have a specific reason:
# ❌ Bad - unnecessary manual control
task_address = publish_task(task_info, nonce=42)
# ✅ Good - let SDK manage
task_address = publish_task(task_info)
5. Reset Cache After External Changes¶
If you sent transactions outside the SDK:
# ✅ Good - reset after external changes
# (sent transaction via MetaMask, another script, etc.)
reset_nonce_cache()
# Now SDK cache is synced
task_address = publish_task(task_info)
Troubleshooting¶
Problem: "Nonce too low" persists¶
Solution:
from ogpu.client import clear_all_nonce_caches, fix_nonce
# Complete reset
clear_all_nonce_caches()
fix_nonce()
# Retry
task_address = publish_task(task_info)
Problem: Transaction stuck for >1 hour¶
Solution:
from ogpu.client import fix_nonce
# Cancel stuck transactions
fix_nonce()
# They'll be replaced with higher gas
Problem: Multiple failed retries¶
Solution:
from ogpu.client import get_nonce_info
# Diagnose the issue
info = get_nonce_info()
print(info)
# Check:
# - has_pending: Stuck transactions?
# - pending_count: How many?
# - cached_nonce: Cache out of sync?
Problem: "Replacement underpriced"¶
Solution:
import time
from ogpu.client import reset_nonce_cache, publish_task
# Wait for gas prices to update
reset_nonce_cache()
time.sleep(10)
# Retry
task_address = publish_task(task_info)
Thread Safety¶
The SDK's nonce management is thread-safe:
import threading
from ogpu.client import publish_task
def send_transaction(task_info):
task_address = publish_task(task_info)
print(f"Task: {task_address}")
# Safe to run concurrently
threads = []
for i in range(5):
t = threading.Thread(target=send_transaction, args=(task_info,))
threads.append(t)
t.start()
for t in threads:
t.join()
Features:
- Per-address locks prevent race conditions
- Nonces are sequential even with concurrent calls
- Thread-safe cache operations
Testing¶
Test your nonce management setup:
Tests included:
- ✅ Get nonce info
- ✅ Cache management
- ✅ Fix nonce functionality
- ✅ Thread safety
- ✅ Manual override
- ✅ Pending vs latest nonce
Migration from v0.2.0.13¶
No Breaking Changes
All existing code continues to work without modifications!
Before (v0.2.0.13):
# Manual error handling required
try:
task_address = publish_task(task_info)
except Exception as e:
if "nonce" in str(e):
# Had to handle manually
pass
After (v0.2.0.14):
New features available:
# Manual utilities
from ogpu.client import fix_nonce, get_nonce_info
# Check status
info = get_nonce_info()
# Fix issues
fix_nonce()
Under the Hood¶
NonceManager Class¶
Internal class managing nonces (you don't need to use this directly):
Features:
- Thread-safe operations with per-address locks
- Uses
pendingblock identifier (includes pending transactions) - Caches nonces to reduce RPC calls
- Automatically syncs with blockchain
Methods:
from ogpu.client.nonce_manager import NonceManager
# Get managed nonce (automatic)
nonce = NonceManager.get_nonce(address, web3)
# Increment after success (automatic)
NonceManager.increment_nonce(address, web3)
# Reset cache
NonceManager.reset_nonce(address, web3)
Summary¶
Nonce management in v0.2.0.14:
- ✅ Automatic - Detects and fixes errors
- ✅ Manual utilities - For when you need control
- ✅ Thread-safe - Concurrent operations supported
- ✅ Backward compatible - No code changes needed
- ✅ Well-tested - Comprehensive test suite
- ✅ Easy to use - Just call the function!
Forget about nonce issues and focus on building! 🚀