Cómo enviar muchas transacciones a ethereum, usando js

Estoy tratando de enviar muchas transacciones a Ethereum con un programa escrito en js. Uso node js, web3 e infura ropsten. El problema es: si envío transacciones a la vez, la mayoría de ellas simplemente desaparecen. Tratando de resolver este problema, envío transacciones con intervalos. Funciona, pero muy lentamente. Paso una hora para enviar solo 100 transacciones. ¿Hay alguna solución para que funcione más rápido y correctamente? Estaba pensando en enviar la transacción después de que la anterior comenzara a estar pendiente, pero no veo cómo puedo hacerlo. La función sendRaw obtiene el número de transacción solo después de un tiempo. Este código lee el archivo, obtiene la dirección, la cantidad y los datos opcionales y utiliza el método de contrato inteligente para transferir tokens. Aquí está el código:

function sendRaw(rawTx) {
var privateKey = new Buffer(key, 'hex');
var transaction = new tx(rawTx);
transaction.sign(privateKey);
var serializedTx = transaction.serialize().toString('hex');
web3.eth.sendRawTransaction(
'0x' + serializedTx, function(err, result) {
    if(err) {
        console.log(err);
    } else {

        console.log(result);
        Ntrans=result;
    }
});
}


var nonce = web3.eth.getTransactionCount(address);
var gasPrice = web3.eth.gasPrice;
var gasLimit = 90000;

var fs = require("fs");
var buf1 = new Buffer(1024);
var buf2 = new Buffer(1024);
var buf3 = new Buffer(1024);
var i = 0;
var j = 0;
var k = 0;

var fd = fs.openSync('/home/kate/Desktop/file.txt', 'r+');


function recurs()
{
    if(k==5) return -1;
    j = 0;
    do
    {
          fs.readSync(fd, buf1, j, 1, i);
          i++;
          j++;
    }
    while(buf1[j-1] != 32);
    AddressC = String(buf1.slice(0, j-1))
    console.log(AddressC);
    j = 0;
    do
    {
          fs.readSync(fd, buf2, j, 1, i)
          i++;
          j++;
    }
    while(buf2[j-1]!=32);
    ValueT = Number(buf2.slice(0, j-1))
    console.log(ValueT);
    j = 0;
    do
    {
          fs.readSync(fd, buf3, j, 1, i);
          i++;
          j++;
    }
    while(buf3[j-1]!=10);
    TxC = String(buf3.slice(0, j-1));

    txOptions =
    {
         nonce: web3.toHex(nonce),
         gasLimit: web3.toHex(gasLimit),
         gasPrice: web3.toHex(gasPrice),
         to: contractAddress

    }

    console.log(TxC);
    console.log(txOptions);
    rawTx = txutils.functionTx(interface, 'foreignBuy', [AddressC, 
    ValueT, TxC], txOptions);
    sendRaw(rawTx);
    k++;
    nonce++;
   /* while(web3.eth.getTransactionReceipt(Ntrans)=="null")
    {

    } */
}

setTimeout(function(){
    recurs();
}, 5000);
}
recurs();
Sospecho que se trata de un error: consulte github.com/ethereum/go-ethereum/issues/14893
Infura es un servicio público tienen algún tipo de límite de tarifa como medida de seguridad, si quieres un límite superior debes contactar con ellos.
¿Puede también formatear su código para que sea más legible para los posibles respondedores?
Es antiguo, pero si tuvo algún progreso, publique su respuesta.
Cambiamos a Alchemy ( alchemyapi.io ) después de enfrentar los mismos problemas de limitación de velocidad y problemas de confiabilidad de Infura. Recomendaría hacer lo mismo para cualquier aplicación de calidad de producción.

Respuestas (3)

La mayor parte de la confusión con el manejo de grandes volúmenes de transacciones se deriva de suposiciones ocultas que afectarán a escala.

Hay algunos hechos importantes y no obvios para entender.

  1. La transacción nonce es administrada por el remitente.
  2. Las transacciones del mismo remitente serán extraídas en orden nonce.

Implícitamente, se sigue que:

  1. Si una transacción no se extrae, las transacciones con un nonce más alto no se pueden extraer. Una brecha violaría el #2 y es por eso que una cuenta puede parecer bloqueada.

Por último:

  1. Los mineros tienen total discreción para incluir transacciones en bloques o ignorarlas.

Es posible enviar transacciones rápidamente pero exige precisión a nivel de transacción. Las cosas pueden salir mal, como:

  1. GasPrecio demasiado bajo
  2. Transacción perdida (sin motivo)

Las transacciones faltantes son ambiguas. De hecho, se pueden extraer si uno espera lo suficiente, o es posible que nunca se extraigan. La ambigüedad es un problema para las actividades no triviales a escala. El proceso necesita hacer algo proactivo para eliminar la ambigüedad.

Para cada transacción, incremente el nonce y envíe, luego espere a que la transacción aparezca en la cadena con confirmaciones. Después de unos minutos, comience a lidiar con el caso de falla.

Para el uso diario, puede ser suficiente enviar una transacción de cancelación. Aquí hay un truco útil para "desbloquear" una billetera que envió una transacción con un precio de gas demasiado bajo. La cuenta debe enviarse cero éter a sí misma especificando el nonce de la transacción a cancelar y un gasPrice mayor que la transacción a cancelar. Cuando la transacción de reemplazo aparece en un bloque, la transacción original (cualquiera que haya sido) no se extraerá, debido al precio más alto del gas y al nonce idéntico: una cancelación confirmada. Es recomendable esperar varias confirmaciones como lo haría con cualquier otra transacción.

El mismo principio se puede aplicar al reintento. Utilice los mismos datos y nonce que la transacción que falta y un gasPrice más alto. Esto implica que el remitente está administrando el nonce a medida que avanza y conoce los datos, la carga útil, el nonce y el precio de gas de cada transacción que envió para que pueda abordar las fallas de transacción con precisión.

Para obtener más información sobre los problemas técnicos, eche un vistazo a la discusión de Singleton Nonce Manager aquí: Patrones de simultaneidad para cuenta nonce

Espero eso ayude.

¿ Quizás los métodos por lotes web3 1.0 funcionarían?

var contract = new web3.eth.Contract(abi, address);

var batch = new web3.BatchRequest();
batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback));
batch.add(contract.methods.balance(address).call.request({from: '0x0000000000000000000000000000000000000000'}, callback2));
batch.execute();

Este era un problema común en el mundo de los juegos, por lo que se formuló EIP 1155 . Usted y otros pueden beneficiarse de tratar únicamente con ERC-1155 o envolviendo los tokens de interés (suponiendo que sean ERC-20 o ERC-721) en ERC-1155.