How to use a smart contract from a java application
In Part I of my tutorial I’ve explained how to develop and deploy a simple smart contract. Today we will see how this deployed contract can be used in java applications.
We are going to use Parity as Ethereum client and Web3j java library for interaction with Parity. I’m assuming that you already have installed Web3j, solc and Parity following “Prepare” instructions in Part I.
5. Get Parity Synced
First of all your Parity needs to get synchronized with the Ethereum testnet Rinkeby, meaning it needs to download the current database status to your local machine. Start your local parity with
$parity --chain rinkeby --rpcapi "eth,net,web3,personal"
See also this documentation of Parity about getting synced.
In the meantime, we can prepare everything that we need to call our smart contract from a java application.
6. Create A Smart Contract Wrapper
Generate a smart contract wrapper in java, go to the folder where we stored your smart contract and compile the contract using solc:
$ cd myproject/contracts/
$ mkdir target
$ solc Ownable.sol --bin --abi --optimize -o target/
Now generate the java wrapper class for your token, replacing `/yourpath/to/src/main/java` and `com.your.organisation.name` with the correct path to the target output dir and java package name.
$ web3j solidity generate target/Ownable.bin target/Ownable.abi -o /yourpath/to/src/main/java -p your.package.name
Type web3j -h to see more options.
7. Import Your Ethereum Account to Parity
Do you remember from our Part I that we used MetaMask and Remix to test our smart contract directly? Now it’s time to test it via the java application. To do so we need to import the private key of the account that was created via MetaMask to our local Parity. Parity stores credentials in so-called keyfiles. To import your private key from MetaMask into Parity take the following steps (at the time of writing this article, you need to take an indirect way over Geth – probably Parity will provide a direct way later):
- From MetaMask select Export private key
- Copy the private key and paste it into a file called pass.txt
- Import the account’s private key into Geth
$geth --testnet account import ~/pass.txt
- Geth will create a keystore file in ~/.ethereum/testnet/keystore/ or
- Now import the keystore file into Parity:
$parity --chain=rinkeby account import ./Library/Ethereum/testnet/keystore
$parity --chain=rinkeby account import ~/.ethereum/testnet/keystore/
Thanks to Filip Bielejec for providing good instructions for importing a private key into Parity.
8. Call the Smart Contract from Java
Now we have an account in Parity, java wrapper is generated for the contract and our Parity client is synced with Rinkeby. (You can check this looking into the Parity logs. The number of the last imported block should be the same as the number of the last block shown in Rinkeby Block Explorer).
Here is a simplified code excerpt on how to call smart contract with web3j, Parity and our account:
// Don't forget to import org.web3j.* and of course our contract
// wrapper class Ownable
// With our contract deployed at address
// and the deployer address
// we can do the following:
final String keystorefile = "/path/to/your/parity/keyfile";
final String smartContractAddress = "0xc1c29f4ccd7c22e62e7f3aba83ae48e05295acbb";
final Parity parityClient = Parity.build(new HttpService("http://localhost:8545/"));
final BigInteger gasPrice = BigInteger.valueOf(2200000);
final BigInteger gasLimit = BigInteger.valueOf(4300000);
// Load credentials from the keystore file created in step
// "Import your Ethereum account to parity"
final Credentials credentials = WalletUtils.loadCredentials(adminPassword, new File(keystorefile));
// Load the smart contract using this credentials
final Ownable contract = Ownable.load(smartContractAddress, parityClient, credentials, gasPrice, gasLimit);
// Call getContractOwner(). This should return
final String contractOwner = contract.getContractOwner().send();
// Call isContractOwner
// This should return true
final boolean isContractOwner = contract.isContractOwner("0x4cc685fC4903dD267F0aE2C27232A81bBFCED751").send();
// This should return false
final boolean isContractOwner2 = contract.isContractOwner("0xc2f16d5040deDa48Fe9292c183c5D76321e83467").send();
We are done, we created a smart contract, tested it, deployed it and called it from a java application.
When you will develop smart contracts for production, you will need to consider some security questions and probably a role-based access to your smart contract. Please let me know if it would be an interesting topic to be described in a separate article.