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:
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 price
en 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 web3
có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?
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.
Puede estimar el gas utilizando web3.eth.estimateGas
para 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 gasPrice
en config. Sin embargo, es mejor si no modifica el gas predeterminado. Además, si está enviando eth
a EOA, el gas siempre es 21000, por lo que puede reemplazar el gas estimado con 21000 const.
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);
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.
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
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
jonathan