El método eth_getTransactionCount
devuelve el número de transacciones enviadas desde una dirección específica, que también se conoce como "nonce". Este valor es crucial para crear nuevas transacciones, ya que cada transacción desde una cuenta debe usar un valor de nonce exactamente uno más alto que la transacción anterior.
Este método devuelve el valor de nonce actual para una dirección, que representa el número de transacciones enviadas desde esa dirección.
La dirección para verificar el contador de transacciones
Número de bloque en formato hex o etiqueta de bloque
El número de transacciones enviadas desde la dirección (hexadecimal)
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x4b9" // 1209 en decimal
}
El parámetro blockNumber
acepta varios valores especiales:
latest
: Estado actual después de que todas las transacciones pendientes sean ejecutadaspending
: Estado actual más transacciones pendientes en el mempoolearliest
: Estado del bloque génesissafe
: Último bloque considerado seguro por la redfinalized
: Último bloque que ha logrado finalidadUsar pending
es especialmente importante para la gestión de nonce al enviar múltiples transacciones en secuencia.
// Ejemplo: Crear y firmar múltiples transacciones en secuencia
async function sendTransactionBatch(privateKey, toAddress, values) {
const wallet = new ethers.Wallet(privateKey, provider);
const fromAddress = wallet.address;
// Obtener el nonce actual
const nonce = await provider.send('eth_getTransactionCount', [fromAddress, 'pending']);
const currentNonce = parseInt(nonce, 16);
console.log(`Nonce inicial: ${currentNonce}`);
// Crear y enviar múltiples transacciones
const txPromises = values.map((value, index) => {
const txNonce = currentNonce + index;
console.log(`Preparando transacción con nonce ${txNonce}`);
const tx = {
from: fromAddress,
to: toAddress,
value: ethers.utils.parseEther(value.toString()),
nonce: txNonce,
gasLimit: 21000,
gasPrice: ethers.utils.parseUnits('50', 'gwei'),
};
return wallet.sendTransaction(tx);
});
return Promise.all(txPromises);
}
// Uso
const recipientAddress = '0x742d35Cc6634C0532925a3b844Bc454e4438f44e';
const valueArray = [0.01, 0.02, 0.03]; // Valores ETH a enviar
sendTransactionBatch(privateKey, recipientAddress, valueArray)
.then((results) => console.log(`Enviadas ${results.length} transacciones`))
.catch((error) => console.error('Transacción fallida:', error));
// Ejemplo: Analizando y corrigiendo brechas de nonce
async function analyzeNonceGaps(address) {
// Obtener nonce confirmado
const confirmedNonceHex = await provider.send('eth_getTransactionCount', [address, 'latest']);
// Obtener nonce pendiente (incluyendo transacciones en mempool)
const pendingNonceHex = await provider.send('eth_getTransactionCount', [address, 'pending']);
const confirmedNonce = parseInt(confirmedNonceHex, 16);
const pendingNonce = parseInt(pendingNonceHex, 16);
console.log(`Dirección: ${address}`);
console.log(`Nonce confirmado: ${confirmedNonce}`);
console.log(`Nonce pendiente: ${pendingNonce}`);
if (pendingNonce > confirmedNonce) {
console.log(`Hay ${pendingNonce - confirmedNonce} transacciones pendientes`);
// Obtener transacciones pendientes para analizar
// Nota: Esto normalmente requeriría un método RPC especializado o servicio
// ya que los nodos Ethereum estándar no proporcionan una forma de listar transacciones pendientes para una dirección
}
return {
address,
confirmedNonce,
pendingNonce,
pendingCount: pendingNonce - confirmedNonce,
};
}
// Ejemplo: Resolver transacciones atascadas reemplazándolas con un precio de gas más alto
async function replaceStuckTransaction(wallet, originalNonce, newGasPrice) {
// Crear una transacción de "reemplazo" con el mismo nonce pero mayor precio de gas
const tx = {
from: wallet.address,
to: wallet.address, // Enviar a sí mismo
value: 0, // Valor cero (solo pagando gas)
nonce: originalNonce,
gasLimit: 21000,
gasPrice: newGasPrice, // Debe ser al menos 10% más alto que el original
};
// Firmar y enviar la transacción de reemplazo
return wallet.sendTransaction(tx);
}
// Ejemplo: Analizar actividad de cuenta a lo largo del tiempo
async function analyzeAccountActivity(address, startBlock, endBlock, interval = 1000) {
const result = [];
// Procesar en fragmentos para evitar sobrecargar el nodo
for (let blockNum = startBlock; blockNum <= endBlock; blockNum += interval) {
const blockHex = `0x${blockNum.toString(16)}`;
const count = await provider.send('eth_getTransactionCount', [address, blockHex]);
result.push({
blockNumber: blockNum,
nonce: parseInt(count, 16),
});
}
// Calcular actividad en cada intervalo
for (let i = 1; i < result.length; i++) {
const txCount = result[i].nonce - result[i - 1].nonce;
result[i].newTransactions = txCount;
const blockSpan = result[i].blockNumber - result[i - 1].blockNumber;
result[i].txPerBlock = txCount / blockSpan;
}
return result;
}
pending
es crucial cuando se crean múltiples transacciones en secuencia