Web3j Vs Geth - Code Comparison

Shay Baz
Kin Blog
Published in
6 min readDec 24, 2017

Code snippet comparison between Web3j and Geth — integrating Ethereum with Android client.

As part of building the Kin open source sdk , we wanted to experiment with several Ethereum mobile client solutions and pick the best fit for our use case. We decided to run the experiment in parallel and test the most promising direction. I was tasked with exploring the web3j library: evaluating its API, integration, ease of use and stability.

While eventually (spoiler alert!) we decided to go with go-ethereum, I believe it is valuable to share the differences between the two. In this article, I will present a few code snippets to help you get started and have a broader understanding of each implementation.

From now on I will describe the API calls and how it is implemented with the web3j lightweight Java library as well as with the go-ethereum Go implementation of the Ethereum protocol.

Getting started

Setting up build.gradle app configuration:

Web3j:

Geth:

Initialize Client

The client library hides the complexity of communicating with the blockchain as well as provides interfaces to create transactions and communicates with the Kin token contract.

In order to initialize a client, we must first provide a ‘service provider’ that enables connecting to the Ethereum network (either testnet or mainnet). For our preliminary investigation we used the Ropsten testnet service provider by Infura. Please note that each network has a unique and specific network id that will be used later on, while sending transactions to the network.

In order to use Infura, you need to register to get a valid token.

Web3j:

The web3j is a basic object that will be used in my other code snippets. More about working with Infura using Web3j can be found here.

Geth:

The ethereumClient is a basic object that will be used in my other code snippets

Client version (Web3j only)

Returns the current client version

This Web3 call (as many other Web3j methods that need to access the network) provides an async callback such as RxJava and Observables.

In comparison, with Geth you will need to handle the synchronisation completely by yourself.

Creating a new wallet

The wallet allows the user to manage her accounts and balance. In order to create a wallet you need to provide a permanent path to a file that will reside internally within the client’s device where the private key is encrypted and stored . The user must provide a password (Web3j terminology) or a passphrase (Geth terminology) in order to create and access the wallet.

Web3j:

The walletFile string returned when generating a new wallet is the filename that will be saved in dirPath. This is used to load user credentials, hence this String filename and the dirPath need to be saved in the client’s device so they can be accessed every time the application is launched.

The credentials give us access to the user’s public address and private key.

Geth:

The Keystore manages the client’s accounts and holds the encrypted private keys for each created account. The keystore can be exported to another device, allowing the client to use her wallet in another device or for backup purposes.

The Account holds information about the public address of the user’s account.

Getting the Public Address

The public address of the client is used to identify the account.

Web3j:

The Credential object lets us access the public address and the private key of the user’s account.

Geth:

If the user hasn’t created an account yet, an exception will be thrown. Geth as seen here does not expose the account’s private key.

Getting the Ether balance

Web3j:

In order to get current Ethereum balance for some public address, Web3j provides a callback system once there is response from the network.

The balance is received in Wei units so we need to convert it to Ether. Fortunately, Web3j provides a utility to perform this conversion.

Geth:

-1 indicates to look at the last known block and retrieve the most updated data. This returns the balance in Wei and the developer needs to do the conversion to Ether units.

Sending an Ether transaction

Web3j:

In order to transfer some amount of Ether to an address Web3j provides the static method Transfer.sendFundsAsync

Geth:

In order to perform a transaction we first build the Transaction object with a nonce parameter which makes each transaction unique. We then sign the transaction with the passphrase and network id as mentioned above (in our case Ropsten), and send the transaction.

Kin Token Contract

More about our Kin Token Contract can be found here

Web3j:

In order to communicate with our Kin contract we must first generate a Java class from our Kin contract. The Web3j Command Line Tools ship with a command line utility for generating the contract function wrappers from Solidity ABI files. The ABI files reside in our Kin contract. (Mainnet Kin contract ABI can be found here)

Usage of the command line:

This will generate the java class KinContract which encapsulates all the methods that are exposed in our Kin contract.

Note that the Kin contract address we’re using here is only valid for Testnet (Ropsten). In Mainnet, you’ll need to provide a different address.

Loading Kin Contract

Web3j:

To check its validity use isValid this returns true, and you can check other info about the contract.

Geth:

As will be shown in the next code snippet, Geth and Web3j offer different APIs to communicate with the contract. While Web3j offers simple static methods, Geth takes a more generic route: each call must provide the method name as a String parameter along with other raw parameters.

Getting the Kin balance

To retrieve the Kin balance of an address:

Web3j:

To retrieve the balance, call the balanceOf method on the Kin token contract with the requested address.

Geth:

As explained above — we will use the method name — ‘balanceOf’ and execute the generic call method. The returned value will be stored in the results interface.

Transfering Kin

In order to transfer some amount of Kin to an address

Web3j:

This returns the transaction hash.

Geth:

We create a TransactionOps object, set the signer into it and use the BoundContract object to call the transfer method on the Kin Contract with the required params. The returned Transaction object has the hashcode for this transaction.

Conclusion

Personally I preferred Web3j for a couple of reasons: I found that the API it offers are more intuitive and generally easier to use, rich with features and has a helpful unit conversion utility class. In addition, integration with Android was almost flawless and Web3j’s has a more moderate learning curve when compared with Geth’s. Web3j’s documentation is much better. Furthermore, when developing for Android, it’s easier to integrate with a native Java library. Working with the generated Kin contract class is trivial, making the whole communication with the contract very straight forward. Ultimately, I was able to implement most of the requirements in just a few days.

However, keep in mind that Web3j uses many dependencies to support its asynchronous calls such as RxJava. This may be very handy when calling methods over the network, but maybe some clients would rather not add these dependencies to their codebase.

More than that some clients who are less familiar with Observables would need to make effort to learn it before using it.

In contrast, Geth is based on a native Go language implementation wrapped within a thin layer of Java code, making it much heavier in terms of size. Communication with the native Go layer is via JNI which makes the code more cumbersome. In addition, its documentation is lacking compared with Web3j’s. To make things worse, while working with Geth, we ran into some major issues along the way as described in Oren’s post.

In my opinion, if you need to implement an Android-only application for a small user base, I highly recommend using the Web3j library. However, In our case, we also need to support an iOS client. This requirement tipped the scale towards Geth as its native Go implementation is cross-platform. In addition, Geth is also commonly used by more wallet applications and has a larger and stronger community and its code is maintained more often.

All this lead us to the conclusion that Geth is a more suitable solution for our needs.

Even though we choose Geth for our SDK, ultimately you will have to decide for yourself which works better for you. I hope this article provided a good overview of the differences between the two and how to get started working with each one.

--

--