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: