Web3j – How to Change the Nonce Between Transactions in Web3j

javaweb3j

I have this line of code where it registers a transaction in blockchain. And I wanted to know how I can make the nonce different between the transactions?

txhash = careercertificate
            .createCertificate(id, fecha, nombre, rutalumno, instituto, rutinstituto, titulo, totalhash, fechatitulacion, registronumber, codigoV)
            .send().getTransactionHash();

Best Answer

Under the hood, the Web3J SmartContract Java Wrapper calculates the nonce by getting the number of transactions getTransactionCount for the account (credential).

EthGetTransactionCount ethGetTransactionCount = web3.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.PENDING).send();
BigInteger nonce =  ethGetTransactionCount.getTransactionCount();

If for some reasons, you want to manually set the nonce (because you're sending multiple parallel transactions I guess), it is not an easy task and you gonna have to replicate what web3j is doing behind the scene.

i. Some constants

    final String privateKey = "48c2210576121c68883b2f96ae82cdf5fd845d99f4243b9c44651316accaac97"; // Dummy private key !!!
    final String contractAddress = "0x5e417E6d4e15471912743e1173D5fD3a3617aD9f"; // Smart contract after deployment on Ganache
    final BigInteger gasLimit = new BigInteger("6721975"); // Block gas limit (Ganache)
    final BigInteger gasPrice = new BigInteger("20000000000"); // 20 gwei - Gas Price (Ganache) 

ii. Connect to the node and initiate web3j

// Connect to the node
Web3j web3 = Web3j.build(new HttpService());  // defaults to http://localhost:8545/

iii. Read the private key

// Read Private Key
Credentials credentials = Credentials.create(privateKey)

iv. Calculate the transaction data

A transaction is constituted of several information like from account, to account, value, gasPrice, gasLimit, nonce and data. data in the case of a smart contact represents the encoding of the function, the parameter types and the parameters.

You can calculate data like this:

// Extract the  function from the Smart Contract wrapper generated by web3j cli
final Function function = new Function(
        Counter.FUNC_INCREMENT, 
        Arrays.<Type>asList(), 
        Collections.<TypeReference<?>>emptyList());

// Encode to data
String data = FunctionEncoder.encode(function);

v. Choose a nonce

Based on whatever you want, select a nonce (/!\ must be greater than the nonce of the last transaction on this account)

// Calculate nonce 
(...)
BigInteger nonce =  new BigInteger("101");

vi. Prepare the transaction

// Prepare transaction
RawTransaction rawTransaction = RawTransaction.createTransaction(
        nonce,
        gasPrice,
        gasLimit,
        contractAddress,
        BigInteger.ZERO, // No Value
        data);

vii. Send the transaction

// Transaction manager
RawTransactionManager transactionManager = new RawTransactionManager(web3, credentials);
EthSendTransaction transaction = transactionManager.signAndSend(rawTransaction);

log.debug("transaction hash = {}", transaction.getTransactionHash());

You can find the code here:

Related Topic