caver-java is a lightweight, high modular, convenient Java and Android library to interact with clients (nodes) on the kaia network: This library is an interface which allows Java applications to easily communicate with kaia network.
- Complete implementation of kaia’s JSON-RPC client API over HTTP and IPC
- Support of kaia transaction, account, and account key types
- Auto-generation of Java smart contract wrapper to deploy and execute a smart contract from native Java code
- Creation of a new wallet and managing kaia wallets
- Command line tools
- Android compatible
To install caver-java, you should add a jitpack repository for IPFS feature.
maven
<repositories><repository><id>jitpack.io</id><url>https://jitpack.io</url></repository></repositories>gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}maven
<dependency><groupId>com.klaytn.caver</groupId><artifactId>core</artifactId><version>X.X.X</version></dependency>gradle
compile 'com.klaytn.caver:core:X.X.X'If you want to use Android dependency, just append -android at the end of version. (e.g. 1.5.4-android)
You can find latest caver-java version at release page.
If you want to run your own EN (Endpoint Node), see EN Operation Guide to set up.
Cavercaver = newCaver(Caver.DEFAULT_URL);When you send transactions, caver-java provides easy-to-use wrapper classes.
Here's an example of transferring KLAY using keystore.json and ValueTransfer class:
Cavercaver = newCaver(Caver.DEFAULT_URL);
//Read keystore json file.Filefile = newFile("./keystore.json");
//Decrypt keystore.ObjectMapperobjectMapper = ObjectMapperFactory.getObjectMapper();
KeyStorekeyStore = objectMapper.readValue(file, KeyStore.class);
AbstractKeyringkeyring = KeyringFactory.decrypt(keyStore, "password");
//Add to caver wallet.caver.wallet.add(keyring);
BigIntegervalue = newBigInteger(Utils.convertToPeb(BigDecimal.ONE, "KLAY"));
//Create a value transfer transactionValueTransfervalueTransfer = newValueTransfer.Builder()
.setKlaytnCall(caver.rpc.getKlay())
.setFrom(keyring.getAddress())
.setTo("0x8084fed6b1847448c24692470fc3b2ed87f9eb47")
.setValue(value)
.setGas(BigInteger.valueOf(25000))
.build();
//Sign to the transactionvalueTransfer.sign(keyring);
//Send a transaction to the kaia blockchain platform (kaia)Bytes32result = caver.rpc.klay.sendRawTransaction(valueTransfer.getRawTransaction()).send();
if(result.hasError()) {
thrownewRuntimeException(result.getError().getMessage());
}
//Check transaction receipt.TransactionReceiptProcessortransactionReceiptProcessor = newPollingTransactionReceiptProcessor(caver, 1000, 15);
TransactionReceipt.TransactionReceiptDatatransactionReceipt = transactionReceiptProcessor.waitForTransactionReceipt(result.getResult());If you have address and private key(s) of keyring, you can make keyring directly through KeyringFactory.create.
<valueUnit> means a unit of value that is used in kaia. It is defined as an enum type. Examples of possible values are as below.
PEB, KPEB, MPEB, GPEB, STON, UKLAY, MKLAY, KLAY, KKLAY, MKLAY, GKLAY
If <valueUnit> is not given as a parameter, default unit of <value> is PEB. You can use Utils.convertToPeb or Utils.convertFromPeb to easily convert a value to another unit like below.
Utils.convertToPeb("1", KLAY).toBigInteger(); // 1000000000000000000Utils.convertFromPeb("1000000000000000000", KLAY).toBigInteger(); // 1kaia provides Fee Delegation feature. Here's an example code. When you are a sender:
Cavercaver = newCaver(Caver.DEFAULT_URL);
SingleKeyringsenderKeyring = KeyringFactory.createFromPrivateKey("0x{privateKey}");
caver.wallet.add(senderKeyring);
FeeDelegatedValueTransferfeeDelegatedValueTransfer = newFeeDelegatedValueTransfer.Builder()
.setKlaytnCall(caver.rpc.klay)
.setFrom(senderKeyring.getAddress())
.setTo("0x176ff0344de49c04be577a3512b6991507647f72")
.setValue(BigInteger.valueOf(1))
.setGas(BigInteger.valueOf(30000))
.build();
caver.wallet.sign(senderKeyring.getAddress(), feeDelegatedValueTransfer);
StringrlpEncoded = feeDelegatedValueTransfer.getRLPEncoding();
System.out.println(rlpEncoded);After signing a transaction, the sender can get the RLP-encoded string through feeDelegatedValueTransfer.getRLPEncoding().
Then, the sender sends the transaction to the fee payer who will pay for the transaction fee instead.
When you are a fee payer:
Cavercaver = newCaver(Caver.DEFAULT_URL);
SingleKeyringfeePayerKeyring = KeyringFactory.createFromPrivateKey("0x{privateKey}");
caver.wallet.add(feePayerKeyring);
StringrlpEncoded = "0x{RLP-encoded string}"; // The result of feeDelegatedValueTransfer.getRLPEncoding() in above exampleFeeDelegatedValueTransferfeeDelegatedValueTransfer = FeeDelegatedValueTransfer.decode(rlpEncoded);
feeDelegatedValueTransfer.setFeePayer(feePayerKeyring.getAddress());
caver.wallet.signAsFeePayer(feePayerKeyring.getAddress(), feeDelegatedValueTransfer);
TransactionReceiptProcessorreceiptProcessor = newPollingTransactionReceiptProcessor(caver, 1000, 15);
StringrlpEncoded = feeDelegatedValueTransfer.getRLPEncoding();
try {
// Send the transaction using `caver.rpc.klay.sendRawTransaction`.Bytes32sendResult = caver.rpc.klay.sendRawTransaction(rlpEncoding).send();
if(sendResult.hasError()) {
//do something to handle error
}
StringtxHash = sendResult.getResult();
TransactionReceipt.TransactionReceiptDatareceiptData = receiptProcessor.waitForTransactionReceipt(txHash);
} catch (IOException | TransactionExceptione) {
// do something to handle exception.
}After the fee payer gets the transaction from the sender, the fee payer can sign with signAsFeePayer.
For more information about kaia transaction types, visit Transactions.
An account in kaia is a data structure containing information about a person's balance or a smart contract. If you require further information about kaia accounts, you can refer to the Accounts.
An account key represents the key structure associated with an account. Each account key has its own unique role. To get more details about the kaia account key, please read Account Key. These are 6 types of Account Keys in kaia:
- AccountKeyNil
- AccountKeyLegacy
- AccountKeyPublic
- AccountKeyFail
- AccountKeyWeightedMultiSig
- AccountKeyRoleBased
If you want to update the key of the given account, follow below steps :
- Create new private key(s) to use
- Create a keyring instance using the new private key(s) and the account address to update. After the AccountKey has been successfully updated in kaia, you can use the Keyring instance created here.
- To update the AccountKey of kaia Account, create an Account instance using the toAccount function.
- Create an AccountUpdate transaction (AccountUpdate/FeeDelegatedAccountUpdate/FeeDelegatedAccountUpdateWithRatio).
- Sign the AccountUpdate transaction
- Send signed transaction through
caver.rpc.klay.sendRawTransaction
Cavercaver = newCaver(Caver.BAOBAB_URL);
SingleKeyringsenderKeyring = KeyringFactory.createFromPrivateKey("0x{privateKey}");
caver.wallet.add(senderKeyring);
StringnewPrivateKey = KeyringFactory.generateSingleKey();
SingleKeyringnewKeyring = KeyringFactory.createFromPrivateKey(newPrivateKey);
Accountaccount = newKeyring.toAccount();
AccountUpdateaccountUpdate = newAccountUpdate.Builder()
.setKlaytnCall(caver.rpc.klay)
.setFrom(senderKeyring.getAddress())
.setAccount(account)
.setGas(BigInteger.valueOf(50000))
.build();
try {
caver.wallet.sign(senderKeyring.getAddress(), accountUpdate);
StringrlpEncoded = accountUpdate.getRLPEncoding();
Bytes32sendResult = caver.rpc.klay.sendRawTransaction(rlpEncoded).send();
if(sendResult.hasError()) {
//do something to handle error
}
StringtxHash = sendResult.getResult();
TransactionReceiptProcessorreceiptProcessor = newPollingTransactionReceiptProcessor(caver, 1000, 15);
TransactionReceipt.TransactionReceiptDatareceiptData = receiptProcessor.waitForTransactionReceipt(txHash);
} catch (IOException | TransactionExceptione) {
// do something to handle exception.
}
senderKeyring = caver.wallet.updateKeyring(newKeyring);Caver supports Contract class to make it easy to interact with smart contract in kaia.
Before generating a wrapper code, you need to compile the smart contract first (Note: This will only work if solidity compiler is installed in your computer).
$ solc --abi --bin ./test.solYou can create a contract instance as below using the result of compiling the smart contract:
Cavercaver = newCaver(Caver.DEFAULT_URL);
try {
Contractcontract = newContract(caver, ABI);
contract.getMethods().forEach((methodName, contractMethod) -> {
System.out.println("methodName : " + methodName + ", ContractMethod : " + contractMethod);
});
System.out.println("ContractAddress : " + contract.getContractAddress());
} catch (IOExceptione) {
//handle exception..
}If you want to deploy the smart contract at Baobab testnet, you could do like this:
Cavercaver = newCaver(Caver.DEFAULT_URL);
SingleKeyringdeployer = KeyringFactory.createFromPrivateKey("0x{private key}");
caver.wallet.add(deployer);
try {
Contractcontract = newContract(caver, ABI);
ContractDeployParamsparams = newContractDeployParams(byteCode, null);
SendOptionssendOptions = newSendOptions();
sendOptions.setFrom(deployer.getAddress());
sendOptions.setGas(BigInteger.valueOf(40000))
ContractnewContract = contract.deploy(params, sendOptions);
System.out.println("Contract address : " + newContract.getContractAddress());
} catch (IOException | TransactionException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessExceptione) {
//handle exception..
}After the smart contract has been deployed, you can load the smart contract as below:
Cavercaver = newCaver(Caver.DEFAULT_URL);
StringcontractAddress = "0x3466D49256b0982E1f240b64e097FF04f99Ed4b9";
try {
Contractcontract = newContract(caver, ABI, contractAddress);
contract.getMethods().forEach((methodName, contractMethod) -> {
System.out.println("methodName : " + methodName + ", ContractMethod : " + contractMethod);
});
System.out.println("ContractAddress : " + contract.getContractAddress());
} catch (IOExceptione) {
//handle exception..
}To transact with a smart contract:
Cavercaver = newCaver(Caver.DEFAULT_URL);
SingleKeyringexecutor = KeyringFactory.createFromPrivateKey("0x{private key}");
caver.wallet.add(executor);
try {
Contractcontract = newContract(caver, ABI, '0x{address in hex}');
SendOptionssendOptions = newSendOptions();
sendOptions.setFrom(executor.getAddress());
sendOptions.setGas(BigInteger.valueOf(40000))
TransactionReceipt.TransactionReceiptDatareceipt = contract.getMethod("set").send(Arrays.asList("testValue"), sendOptions);
} catch (IOException | TransactionException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessExceptione) {
//handle exception..
}TBD
We made caver-java as similar as possible to web3j for easy usability.
/* start a client */Web3jweb3 = Web3j.build(newHttpService(<endpoint>)); // Web3jCavercaver = Caver.build(newHttpService(<endpoint>)); // caver-java/* get nonce */BigIntegernonce = web3j.ethGetTransactionCount(<address>, <blockParam>).send().getTransactionCount(); // Web3jQuantitynonce = caver.klay().getTransactionCount(<address>, <blockParam>).send().getValue(); // caver-java/* convert unit */Convert.toWei("1.0", Convert.Unit.ETHER).toBigInteger(); // Web3jConvert.toPeb("1.0", Convert.Unit.KLAY).toBigInteger(); // caver-java/* generate wallet file */WalletUtils.generateNewWalletFile(<password>, <filepath>); // Web3jKlayWalletUtils.generateNewWalletFile(<address>, <password>, <filepath>); // caver-java/* load credentials */Credentialscredentials = WalletUtils.loadCrendetials(<password>, <filepath>"); // Web3j
KlayCredentials credentials = KlayWalletUtils.loadCredentials(<password>, <filepath>); // caver-java
/* Value Transfer */
TransactionReceipt transactionReceipt = Transfer.sendFunds(...),send(); // Web3j
KlayTransactionReceipt.TransactionReceipt transactionReceipt = ValueTransfer.create(...).sendFunds(...).send(); // caver-javaA caver-java fat jar is distributed with open repository. The 'caver-java' allows you to generate Solidity smart contract function wrappers from the command line:
- Generate Solidity smart contract function wrappers Installation
$ brew tap kaiachain/kaia
$ brew install caver-javaAfter installation you can run command 'caver-java'
$ caver-java solidity generate -b <smart-contract>.bin -a <smart-contract>.abi -o <outputPath> -p <packagePath>caver-js for a javascript
TBD
TBD
- The web3j project for the inspiration. 🙂