web3j — integrasi Java ke smart contract
web3j adalah pustaka Java paling dipakai luas untuk bicara ke Ethereum. Bagian paling berharga dari web3j bukan sekadar wrapper JSON-RPC — melainkan generator yang mengubah ABI kontrak jadi class Java bertipe.
Intisari
Web3j.build(new HttpService(rpcUrl))adalah titik masuk — satu objek yang merepresentasikan koneksi ke node provider.Credentials.create(privateKey)membungkus private key untuk menandatangani transaksi — hanya untuk kode contoh/testnet, produksi memakai KMS (Fase 4).- Perintah
web3j generate soliditymengubah ABI + bytecode kontrak jadi class Java bertipe — parameter dan tipe kembalian Solidity terpetakan otomatis ke tipe Java. ContractGasProvidermenentukan gas limit dan gas price yang dipakai transaksi —DefaultGasProvideruntuk belajar, provider kustom untuk produksi (Fase 5).- Semua panggilan kontrak (baca maupun tulis) berbentuk
RemoteFunctionCall<T>— objek yang baru benar-benar dieksekusi saat kamu panggil.send().
Dependency
<!-- pom.xml -->
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.14.0</version>
</dependency>
Koneksi
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
Web3j web3j = Web3j.build(new HttpService(
"https://eth-sepolia.g.alchemy.com/v2/API_KEY_KAMU"
));
// Cek koneksi hidup — pola health check paling sederhana
BigInteger blockTerbaru = web3j.ethBlockNumber().send().getBlockNumber();
Generate wrapper Java dari ABI
Menulis manual encoding/decoding ABI untuk setiap panggilan fungsi sangat rawan salah. web3j menyediakan generator yang mengubah ABI (dan opsional bytecode) jadi satu class Java lengkap dengan method bertipe untuk setiap fungsi kontrak:
# Dari hasil kompilasi Solidity (Fase 1): GoldToken.abi + GoldToken.bin
web3j generate solidity \
-a build/GoldToken.abi -b build/GoldToken.bin \
-o src/main/java -p com.contoh.kontrak
Hasilnya, class GoldToken.java yang setiap fungsi Solidity-nya jadi method Java —
mintGold(...), balanceOf(...), redeemGold(...) — lengkap dengan tipe
parameter yang sudah dipetakan (uint256 → BigInteger, address →
String, dst).
Memuat kontrak yang sudah ter-deploy
import org.web3j.crypto.Credentials;
import org.web3j.tx.gas.DefaultGasProvider;
Credentials kredensial = Credentials.create("PRIVATE_KEY_TESTNET_SAJA");
ContractGasProvider gasProvider = new DefaultGasProvider();
GoldToken kontrak = GoldToken.load(
"0xAlamatKontrakYangSudahDiDeploy",
web3j,
kredensial,
gasProvider
);
Memanggil read dan write
// READ — lihat Fase 3 sebelumnya: instan, tanpa gas
BigInteger saldo = kontrak.balanceOf("0xAlamatPengguna").send();
// WRITE — butuh gas, menunggu konfirmasi block
TransactionReceipt receipt = kontrak
.mintGold("0xAlamatPengguna", BigInteger.valueOf(100), "bukti-001")
.send();
if (!receipt.isStatusOK()) {
throw new RuntimeException("Transaksi revert: " + receipt.getTransactionHash());
}
Kenapa keduanya sama-sama RemoteFunctionCall<T>.send(). web3j sengaja
menyeragamkan API-nya — perbedaan read/write ditentukan oleh mutability fungsi di ABI (dibaca
otomatis oleh generator), bukan oleh method Java yang berbeda. Ini nyaman untuk konsistensi kode, tapi
bisa menyembunyikan fakta penting: satu baris .send() mungkin instan, baris lain mungkin
memblokir puluhan detik. Baca definisi fungsinya di Solidity, bukan cuma nama methodnya di Java, untuk
tahu mana yang mana.
Menangani exception
try {
TransactionReceipt receipt = kontrak.mintGold(alamat, jumlah, bukti).send();
} catch (org.web3j.protocol.exceptions.TransactionException e) {
// Transaksi TERKIRIM tapi revert di EVM — gas tetap hangus
log.error("Revert: {}", e.getMessage());
} catch (java.io.IOException e) {
// Gagal terhubung ke node — belum tentu transaksi terkirim sama sekali
log.error("Koneksi RPC gagal: {}", e.getMessage());
}
Dua jenis kegagalan yang butuh penanganan berbeda. TransactionException berarti
transaksimu benar-benar diproses jaringan dan revert — kamu tahu pasti hasilnya, gas sudah terpakai.
IOException lebih berbahaya: kamu tidak tahu apakah transaksi sempat terkirim ke
mempool sebelum koneksi putus. Backend produksi harus punya cara memeriksa ulang status transaksi lewat
hash-nya sebelum memutuskan mengirim ulang — mengirim ulang transaksi yang sebenarnya sudah berhasil
berarti membayar gas dua kali untuk aksi yang sama.
Latihan: buat proyek Maven kosong, tambahkan dependency web3j-core, generate
wrapper Java dari ABI kontrak GoldToken milikmu (Fase 2), lalu tulis satu method Java yang
memanggil balanceOf() dan mencetak hasilnya. Tidak perlu private key sama sekali untuk
latihan ini — buktikan sendiri bahwa read tidak membutuhkannya.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.