¿Cómo envío el saldo completo de ether de una cuenta a otra cuenta?

Estoy tratando de usar web3 para transferir todo (o tanto como pueda) el saldo de una cuenta a otra cuenta. Aquí está el código que tengo hasta ahora:

var sender = web3.eth.accounts[0];
var receiver = web3.eth.accounts[1];
var totalBalance = web3.eth.getBalance(sender);
var valueToSend = totalBalance;

transactionObject = {
  from: sender,
  to: receiver,
  value: valueToSend
} 

web3.eth.sendTransaction(transactionObject);

Sin embargo sé que el código anterior tiene el siguiente problema:

  • No se puede enviar el saldo total porque no habría suficiente éter residual para usar como gas para la transacción.

Vi otra publicación hacer la siguiente recomendación:

  • reste el totalBalance por gas*price , por lo tanto:

    valueToSend = totalBalance - (gas*price);
    

PREGUNTA / PROBLEMA:

pero el problema que tengo aquí es ¿cómo se vería eso en el código? No sé cómo obtener la corriente priceen el código. Y para el gas, entiendo que hay diferentes valores para el gas dependiendo de qué tan rápido desee que vaya una transacción, pero ¿hay un web3código que defina lo mínimo y lo máximo que puede usar? ¿O hay un gráfico en alguna parte que lo define en línea? ¿Y cómo se vería eso en el código?

Buen post. ¿Es posible enviar el saldo completo en una transacción calculando antes del costo del gas enviando BNB en Binance Smart Chain en lugar de ETH usando web3?

Respuestas (3)

Si está enviando a una dirección que no es un contrato, el gas siempre es 21000.

Para un contrato se puede cotizar con web3.eth.estimateGas. Calcula el gas ejecutando el contrato localmente, por lo que cuando se extrae la transacción, el resultado puede ser diferente, generalmente agrega un extra para asegurarse de que funcionará.

Pero creo que los desarrolladores de Ethereum son conscientes del problema de dejar una cuenta con muy pocos éteres para realizar una nueva transferencia, hubo una discusión sobre quién puede pagar el gas.

Para determinar el precio del gas a utilizar puedes probar web3.eth.gasPrice, a partir de la documentación

Esta propiedad es de solo lectura y devuelve el precio actual del gas. El precio del gas está determinado por el precio medio del gas de x últimos bloques.

No se documenta cómo se determina el valor. Para un análisis más detallado, puede consultar ethgasstation.info, el sitio no parece proporcionar una API.

Gracias por la respuesta. las explicaciones ayudaron mucho. Cada vez estoy más cerca de lograr hacer mi primera transacción, cómo tengo otro problema. Si conoce la solución a este: ethereum.stackexchange.com/questions/19329/… Le estaría eternamente agradecido :)

Puede estimar el gas utilizando web3.eth.estimateGaspara obtener una estimación del gas utilizado por sus transacciones y luego puede restar el gas estimado del saldo total para obtenerlo valueTosend.

transactionObject = {
  from: sender,
  to: receiver,
  value: totalBalance
} 

var estimatedGas = web3.eth.estimateGas(transactionObject);
web3.eth.getGasPrice(function(error, result){
  gasPrice = result.toNumber();
  var gasValue = estimatedGas * gasPrice
  var valueToSend = totalBalance - gasValue;   
  });

Además, solo para mencionar, puede especificar gasPrice de su elección usando gasPriceen config. Sin embargo, es mejor si no modifica el gas predeterminado. Además, si está enviando etha EOA, el gas siempre es 21000, por lo que puede reemplazar el gas estimado con 21000 const.

¡Gracias por la explicación y el hombre del código! Ojalá pudiera darles tanto a usted como a Ismael la marca de verificación :(
espera, ¿no es necesario multiplicar el gas estimado por el precio del gas?
Gracias por señalar Me lo perdí, mi mal. He actualizado la respuesta.
Esto no funciona el 100% del tiempo. No funciona en absoluto para mí ahora. Todos los cálculos son correctos y sigo recibiendo el error "fondos insuficientes para gas * precio + valor". Parece que necesito agregar un valor adicional de epsilon ether que quedaría en la cuenta de envío para que no pueda vaciar completamente una cuenta. Si me equivoco por favor corrígeme.
Esto debería funcionar. Solo asegúrese de enviar el mismo precio de gas y gas para enviar tx que utilizó para estimar el valor para enviar.

Envío a una cuenta regular

Esta solución es para enviar todo el saldo de una cuenta a otra cuenta normal (no de contrato), donde el gas siempre es 21.000.

La parte importante de la respuesta a continuación es usar las matemáticas BigNumber, o a veces terminará con números incorrectos y su transacción será rechazada, o se quedará con algo de gasolina restante en su cuenta de origen.

var from = {from account};
var to = {to account};
var balance = eth.getBalance(from);
var gas = new BigNumber(21000);
// You can use gasPrice=web3.eth.gasPrice or look up http://ethgasstation.info/
var gasPrice = web3.utils.toWei(1, "gwei");
var cost = gas.mul(gasPrice);
var sendAmount = balance.sub(cost);
var tx = eth.sendTransaction({from: from, to: to, gas: gas, gasPrice: gasPrice, value: sendAmount});
eth.getTransaction(tx);


Envío a una cuenta de contrato

Si está tratando de enviar el saldo completo de una cuenta a una cuenta de contrato, el problema se vuelve mucho más difícil ya que el gas estimado (usando web3.eth.estimateGas(...)) rara vez será el gas real usado.



Cálculos con números grandes

Ejemplo de cálculo incorrecto

Y ejemplo de algunos cálculos incorrectos, cuando no se utilizan las matemáticas de BigNumber:

// eth.getBalance(...) returns BigNumber. Number simulated in this case
> balance=new BigNumber(49999979000000000000);
49999979000000000000
> balance
49999979000000000000
> gas=21000
21000
> gasPrice=web3.toWei(1, "gwei");
"1000000000"
> cost=gas*gasPrice;
21000000000000
> cost
21000000000000
> incorrectSendAmount=balance-cost
49999958000000010000
> balance-incorrectSendAmount
20999999995904
// Small error in the calculations
> balance-incorrectSendAmount-cost
-4096

Ejemplo de cálculo correcto

Y los mismos cálculos cuando se usan las matemáticas de BigNumber:

// eth.getBalance(...) returns BigNumber. Number simulated in this case
> balance=new BigNumber(49999979000000000000);
49999979000000000000
> balance
49999979000000000000
> gas=new BigNumber(21000)
21000
> cost=gas.mul(gasPrice);
21000000000000
> correctSendAmount=balance.sub(cost);
49999958000000000000
// No errors in the calculations
> balance.sub(correctSendAmount).sub(cost)
0