Documentation Index
Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
Nonce
Type-safe transaction nonces for Ethereum transaction ordering and replay protection.
Overview
Branded bigint type representing a transaction nonce. Nonces are sequential counters that ensure transactions from an account are processed in order and prevent replay attacks. Each account has a nonce that increments with each transaction.
Quick Start
Basic Usage
Transaction Building
Nonce Management
import * as Nonce from '@tevm/voltaire/Nonce'
// Create nonce from various types
const nonce = Nonce.from(42)
const fromBigInt = Nonce.from(42n)
const fromHex = Nonce.from("0x2a")
// Convert to number/bigint
Nonce.toNumber(nonce) // 42
Nonce.toBigInt(nonce) // 42n
// Increment nonce
const nextNonce = Nonce.increment(nonce)
Nonce.toNumber(nextNonce) // 43
import * as Nonce from '@tevm/voltaire/Nonce'
// Get nonce from RPC
async function getAccountNonce(
rpcUrl: string,
address: string
): Promise<Nonce.NonceType> {
const response = await fetch(rpcUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'eth_getTransactionCount',
params: [address, 'pending'],
id: 1
})
})
const { result } = await response.json()
return Nonce.from(result)
}
// Build transaction with nonce
const nonce = await getAccountNonce(rpcUrl, myAddress)
const tx = {
nonce: Nonce.toNumber(nonce),
to: recipient,
value: amount,
// ... other tx fields
}
import * as Nonce from '@tevm/voltaire/Nonce'
class NonceManager {
private currentNonce: Nonce.NonceType
constructor(initialNonce: number | bigint) {
this.currentNonce = Nonce.from(initialNonce)
}
getNext(): Nonce.NonceType {
const nonce = this.currentNonce
this.currentNonce = Nonce.increment(this.currentNonce)
return nonce
}
current(): number {
return Nonce.toNumber(this.currentNonce)
}
reset(nonce: number | bigint) {
this.currentNonce = Nonce.from(nonce)
}
}
const manager = new NonceManager(0)
console.log(manager.getNext()) // 0
console.log(manager.getNext()) // 1
console.log(manager.getNext()) // 2
How Nonces Work
Every Ethereum account has a nonce that:
- Starts at 0 for new accounts
- Increments by 1 with each transaction sent
- Must be used exactly once (no gaps, no reuse)
- Determines transaction ordering from an account
Account: 0x123...
Nonce: 5 (has sent 5 transactions: 0, 1, 2, 3, 4)
Next valid transaction must have nonce = 5
Transaction with nonce 6 will be pending until nonce 5 is mined
Transaction with nonce 4 will be rejected (already used)
API Reference
Constructors
import * as Nonce from '@tevm/voltaire/Nonce'
// Universal constructor
const nonce = Nonce.from(42)
// Various input types
Nonce.from(42) // from number
Nonce.from(42n) // from bigint
Nonce.from("42") // from string
Nonce.from("0x2a") // from hex string
Conversions
import * as Nonce from '@tevm/voltaire/Nonce'
const nonce = Nonce.from(42)
// To number
Nonce.toNumber(nonce) // 42
// To bigint
Nonce.toBigInt(nonce) // 42n
Operations
import * as Nonce from '@tevm/voltaire/Nonce'
const nonce = Nonce.from(42)
// Increment by 1
const next = Nonce.increment(nonce)
Nonce.toNumber(next) // 43
Use Cases
Sequential Transaction Sending
import * as Nonce from '@tevm/voltaire/Nonce'
async function sendMultipleTransactions(
rpcUrl: string,
from: string,
transactions: { to: string; value: bigint }[]
) {
// Get current nonce
const response = await fetch(rpcUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'eth_getTransactionCount',
params: [from, 'pending'],
id: 1
})
})
const { result } = await response.json()
let nonce = Nonce.from(result)
// Send each transaction with incrementing nonce
for (const tx of transactions) {
await sendTransaction({
from,
to: tx.to,
value: tx.value,
nonce: Nonce.toNumber(nonce)
})
nonce = Nonce.increment(nonce)
}
}
Transaction Replacement (Speed Up / Cancel)
import * as Nonce from '@tevm/voltaire/Nonce'
// To replace a pending transaction, use the same nonce
// with higher gas price
async function speedUpTransaction(
originalTx: { nonce: number; gasPrice: bigint },
newGasPrice: bigint
) {
const nonce = Nonce.from(originalTx.nonce)
return {
nonce: Nonce.toNumber(nonce), // Same nonce!
gasPrice: newGasPrice, // Higher gas price
// ... other fields
}
}
// To cancel, send 0 value to yourself with same nonce
async function cancelTransaction(
originalNonce: number,
from: string,
gasPrice: bigint
) {
const nonce = Nonce.from(originalNonce)
return {
nonce: Nonce.toNumber(nonce),
to: from, // Send to self
value: 0n, // Zero value
gasPrice: gasPrice, // Higher than original
}
}
Pending Transaction Detection
import * as Nonce from '@tevm/voltaire/Nonce'
async function getPendingTransactionCount(
rpcUrl: string,
address: string
): Promise<number> {
// Get confirmed nonce
const confirmedResponse = await fetch(rpcUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'eth_getTransactionCount',
params: [address, 'latest'],
id: 1
})
})
const { result: confirmed } = await confirmedResponse.json()
// Get pending nonce
const pendingResponse = await fetch(rpcUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'eth_getTransactionCount',
params: [address, 'pending'],
id: 2
})
})
const { result: pending } = await pendingResponse.json()
const confirmedNonce = Nonce.from(confirmed)
const pendingNonce = Nonce.from(pending)
return Nonce.toNumber(pendingNonce) - Nonce.toNumber(confirmedNonce)
}
Common Issues
Nonce Too Low
// Error: "nonce too low" or "replacement transaction underpriced"
// Cause: Trying to use a nonce that was already used
// Solution: Fetch current nonce from network
const nonce = await getAccountNonce(rpcUrl, address)
Nonce Gap
// Transaction stuck in pending
// Cause: Earlier nonce transaction failed/missing
// Solution: Fill the gap or cancel all pending
// If nonce 5 is pending but nonce 4 is missing,
// submit a transaction with nonce 4 first
Concurrent Transactions
// Problem: Multiple parts of app sending transactions
// Solution: Use a centralized nonce manager
// Bad: Each component fetches its own nonce
// Good: Single nonce manager tracks and assigns nonces
References