Ethereum Token Development Using Java and web3j [An Overview]

Author profile picture

@nschapelerNicolas Schapeler

For the purpose of this, we’ll be using a basic ERC20 smart contract I created called JavaToken you can find here. We’ll be using it and the repository it’s in for demonstration purposes, so feel free to clone it and follow along! The network we will be deploying and running it on will be a local Ganache Testnet using Truffle.

I recently wrote an article about getting started with Ethereum development using Android where I demonstrated how to set up web3j in Android and how to transfer ether. Upon publishing it, I got a request to write a piece about interacting with custom ERC20 tokens using web3j which lead to the creation of this article. Enjoy!

Step 0.9: Generate a smart contract java wrapper

The 0.9th step is getting a java wrapper for our smart contract. It’s step 0.9 because technically it’s not mandatory if your contract is already deployed, but it will make things a lot easier later on when interacting with the contract. Do this by first compiling your solidity contract using a solidity compiler. If you’re using Truffle you can do this by simply running the following command inside the Truffle directory of the JavaToken repository:
truffle compile
Next, install the web3j command line interface.
curl -L | sh
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString(''))
Now that we’ve got all that installed, simply run
web3j truffle generate Truffle/build/contracts/JavaToken.json -o src -p com.javaToken
from within the JavaToken directory. This will generate a wrapper for the JavaToken smart contract to make interacting with it in Ethereum easier.

Step 1: Deploying your contract

To deploy our token, we set up some credentials and simply call the deploy() method with them.
// The Ganache TestNet listens at port 7545
Web3j w3 = HttpService("HTTP://"));
String privateKey = "YourPrivateKeyHere";
Credentials credentials = Credentials.create(privateKey);
// Sets the initial supply of JavaTokens in existence
BigInteger initialSupply = BigInteger.valueOf(100000);

JavaToken javaToken = JavaToken.deploy(w3, credentials, new DefaultGasProvider(), initialSupply).send()
And there you go, you just deployed a brand new Ethereum token!
Alternatively, if your contract is already deployed and you’re just looking to interact with it, you can simply load it using:
// The Ganache TestNet listens at port 7545
Web3j w3 = HttpService("HTTP://"));
String privateKey = "YourPrivateKeyHere";
Credentials credentials = Credentials.create(privateKey);
String contractAddress = "YourContractAddress";

JavaToken javaToken = JavaToken.load(contractAddress,w3,credentials,new DefaultGasProvider());

Step 2: Getting your balance

The contract is configured to give its deployer the whole initial supply. Let’s check if we really got everything. If we have our wrapper from step 0.9, this is as easy as:
// With java wrapper
BigInteger balance = javaToken.balanceOf(credentials.getAddress()).send()

// Without java wrapper
String contractAddress = "YourDeployedContractAddress";

// Define the function we want to invoke from the smart contract
Function function = new Function("balanceOf", Arrays.asList(new Address(credentials.getAddress())),
                                 Arrays.asList(new TypeReference<Uint256>() {}));

// Encode it for the contract to understand
String encodedFunction = FunctionEncoder.encode(function);

Send the request and wait for the response using eth call since
it's a read only transaction with no cost associated
EthCall response = w3.ethCall(
  Transaction.createEthCallTransaction(credentials.getAddress(), contractAddress, encodedFunction),

balance = Numeric.toBigInt(response.getValue());
Otherwise, it’s a bit more complicated: First we need to manually input in our transaction the details of the function we want to invoke in our contract, in this case it’s name is balanceOf, the parameter we are providing is an address, and we want the function to return a uint256. Then, we encode this data and put it into a transactions along with the contract we wish to send it to and from who the call comes (our address). Finally, we decode the hexadecimal result into a BigInteger.
Now we’ve got 100.000 JavaTokens to our name. Let’s send some to a friend!

Step 3: Transferring some tokens

Again, the difference between having the wrapper and not having the wrapper is rather significant:
String addressTo = "YourFriendsAddress";
BigInteger amount = BigInteger.valueOf(500);

// With java wrapper
TransactionReceipt receipt = javaToken.transfer(addressTo,amount).send();

// Without java wrapper

// Define the function we want to invoke from the smart contract
Function function = new Function("transfer", Arrays.asList(new Address(addressTo), new Uint256(amount)),

// Encode it for the contract to understand
String encodedFunction = FunctionEncoder.encode(function);

Need to use a TransactionManager here since transfer actually alters the state of the blockchain
and credentials are therefore relevant
TransactionManager transactionManager = new FastRawTransactionManager(w3, credentials);

// Send the transaction off using transactionManager and wait for the hash
String transactionHash = transactionManager.sendTransaction(DefaultGasProvider.GAS_PRICE,
                                                            DefaultGasProvider.GAS_LIMIT, contractAddress, encodedFunction,

// Fetch the transaction receipt
Optional<TransactionReceipt> transactionReceipt =
  receipt = null;
  receipt = transactionReceipt.get();
Without the wrapper is a little bit different this time, as we need to actually prove this transaction comes from our account because we are altering the state of the blockchain by transferring tokens rather than just reading data like previously.
We start off the same way by creating a function object. Though the smart contract function returns a Boolean, we don’t specify it here because we don’t need it, as we’re checking whether the transaction was successful via the transaction receipt, so we specify the return as simply an empty list. Next, we create a transaction manager.
This distinction is important, as said manager takes our credentials as a parameter, meaning transactions sent through it are attributed to us (unlike the balanceOf call above). Finally, we send off the transaction and verify if it was successful by checking the receipt.


And that’s all! You just learned how to deploy your own ERC20 token using web3j. Congratulations! The code for all this can be found here.
Thanks for following along!
If you liked this, give this story a couple of claps so more people can see it!
If you LOVED this, buy me a coffee :)
Ethereum: 0x190d71ba3738f43dc6075f5561e58ac9d4e3dfc2
Bitcoin: 1BRucWzs2vnrkfmbfss14ZQErW74A1H1KE
Litecoin: LbNfoJfTFVCj7GFaAUtWqhitHJcJ3m8y3V
(Originally published here)


The Noonification banner

Subscribe to get your daily round-up of top tech stories!