Java Web3 API for Blockchain Interaction
Web3 refers to a new iteration of the internet, where decentralized applications (DApps) run on blockchain technology. Ethereum is one of the most popular platforms for Web3 applications, and Java developers can interact with Ethereum and other blockchain networks using Web3j, a lightweight Java library.
The Web3j API allows Java developers to connect to the Ethereum blockchain, interact with smart contracts, send transactions, query blockchain data, and much more. Web3j facilitates seamless interaction between Java applications and Ethereum, providing an easy-to-use interface for blockchain-based applications.
Key Features of Web3j:
- Blockchain Interaction: Enables reading data from and writing data to the blockchain (transactions, smart contracts, etc.).
- Smart Contract Deployment: Allows developers to deploy Solidity-based smart contracts from Java.
- Transaction Handling: Helps in sending transactions, interacting with tokens (ERC-20, ERC-721), and calling smart contract functions.
- Wallet and Credentials: Manages wallet creation, encryption, and signing of transactions.
- Event Listening: Web3j can listen to events emitted by smart contracts.
- Interacting with Nodes: Web3j can connect to an Ethereum node (via HTTP, IPC, or WebSocket) to interact with the blockchain.
Setting Up Web3j in a Java Project
1. Add Web3j as a Dependency
You need to add the Web3j library to your project. If you are using Maven, you can add the following dependency:
Maven Dependency:
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.8.4</version>
</dependency>
If you’re using Gradle:
Gradle Dependency:
implementation 'org.web3j:core:4.8.4'
2. Setting Up Web3j to Connect to Ethereum Node
To connect to the Ethereum network, you can either run your own Ethereum node using Geth or Parity or use a service like Infura that provides public access to the Ethereum network.
Here’s how you can connect to the Ethereum node using Infura:
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
public class Web3jExample {
public static void main(String[] args) {
// Connect to Infura Ethereum node
Web3j web3j = Web3j.build(new HttpService("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"));
// Get blockchain information
try {
String blockchainId = web3j.ethBlockNumber().send().getBlockNumber().toString();
System.out.println("Blockchain ID: " + blockchainId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Interacting with Smart Contracts
1. Deploying a Smart Contract Using Web3j
To interact with an Ethereum smart contract (written in Solidity), you first need to compile it and deploy it to the Ethereum network.
Here’s an example of how to deploy a simple Solidity smart contract using Web3j.
Solidity Contract (SimpleToken.sol):
pragma solidity ^0.8.0;
contract SimpleToken {
string public name = "SimpleToken";
string public symbol = "STK";
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
balanceOf[msg.sender] = initialSupply;
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(balanceOf[msg.sender] >= amount, "Insufficient balance");
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
return true;
}
}
To deploy the contract from Java, first compile the contract using Solidity Compiler or Truffle to get the ABI and bytecode, then deploy it using Web3j.
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.crypto.Credentials;
import org.web3j.tx.gas.GasProvider;
import org.web3j.tx.gas.StaticGasProvider;
import org.web3j.utils.Convert;
import java.math.BigInteger;
public class DeployContract {
public static void main(String[] args) throws Exception {
// Connect to the Ethereum network (Infura)
Web3j web3j = Web3j.build(new HttpService("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"));
// Load credentials (private key)
Credentials credentials = Credentials.create("YOUR_PRIVATE_KEY");
// Gas provider
GasProvider gasProvider = new StaticGasProvider(BigInteger.valueOf(20000000000L), BigInteger.valueOf(6721975));
// Deploy contract with an initial supply
SimpleToken contract = SimpleToken.deploy(web3j, credentials, gasProvider, BigInteger.valueOf(1000000)).send();
// Print contract address
System.out.println("Contract deployed at address: " + contract.getContractAddress());
}
}
In this example:
SimpleToken.deploy()
deploys the contract.gasProvider
defines the gas price and limit.- Replace
"YOUR_INFURA_PROJECT_ID"
and"YOUR_PRIVATE_KEY"
with actual values.
2. Interacting with an Existing Smart Contract
Once a smart contract is deployed, you can interact with it by calling its functions.
Here’s how to interact with the deployed contract:
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.crypto.Credentials;
import org.web3j.tx.gas.StaticGasProvider;
import java.math.BigInteger;
public class InteractWithContract {
public static void main(String[] args) throws Exception {
// Connect to the Ethereum network (Infura)
Web3j web3j = Web3j.build(new HttpService("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"));
// Load credentials (private key)
Credentials credentials = Credentials.create("YOUR_PRIVATE_KEY");
// Load the deployed contract using the contract address
SimpleToken contract = SimpleToken.load(
"DEPLOYED_CONTRACT_ADDRESS",
web3j,
credentials,
new StaticGasProvider(BigInteger.valueOf(20000000000L), BigInteger.valueOf(6721975))
);
// Call the transfer function
contract.transfer("RECIPIENT_ADDRESS", BigInteger.valueOf(100)).send();
// Query the balance of an address
BigInteger balance = contract.balanceOf(credentials.getAddress()).send();
System.out.println("Balance: " + balance);
}
}
In this example:
SimpleToken.load()
loads an existing contract by specifying the contract’s deployed address.transfer()
transfers tokens to another address.balanceOf()
queries the token balance of an address.
3. Listening to Events
Smart contracts can emit events, which you can listen to and respond to in real time. Web3j allows you to subscribe to these events.
Example for listening to a Transfer
event:
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.tx.gas.StaticGasProvider;
import org.web3j.utils.Async;
import org.web3j.event.Event;
import java.math.BigInteger;
import java.util.Arrays;
public class EventListener {
public static void main(String[] args) throws Exception {
Web3j web3j = Web3j.build(new HttpService("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"));
// Create a filter for Transfer events
String contractAddress = "DEPLOYED_CONTRACT_ADDRESS";
Event transferEvent = new Event("Transfer",
Arrays.asList(
org.web3j.abi.TypeReference.create(org.web3j.abi.datatypes.Address.class),
org.web3j.abi.TypeReference.create(org.web3j.abi.datatypes.Address.class),
org.web3j.abi.TypeReference.create(org.web3j.abi.datatypes.Uint.class)
));
// Subscribe to the event
web3j.ethLogFlowable(
new org.web3j.protocol.core.methods.request.EthFilter()
.addOptionalTopics(transferEvent.getSignature())
.addOptionalTopics(contractAddress)
).subscribe(event -> {
Log log = (Log) event;
System.out.println("Transfer event detected: " + log);
});
}
}
In this example:
- We subscribe to the Transfer event emitted by the contract and print the log when an event is detected.