If you want to use Android dependency, just append -android at the end of the version string. (e.g. 1.0.1-android)
If you want to see details of the JSON-RPC requests and responses, please include LOGBack dependency in your project. Below is a Gradle build file example. You can add the dependency to Maven as well. Since caver-java uses the SLF4J logging facade, you can switch to your preferred logging framework instead of LOGBack.
Note: In the central repository, the RC, Android, and Java versions are listed together. If you use wildcards to get a version, you may be using a version that is not appropriate for your platform.
Installation
If you want to generate transactions related with a smart contract, you need to install a Solidity compiler and caver-java command-line tool first.
Solidity Compiler
You can install the Solidity compiler locally, following the instructions as per the project documentation. Klaytn recommends you to install Solidity version either 0.4.24 or 0.5.6. If you are a macOS user, you can install the versions via Homebrew:
$ brew install klaytn/klaytn/solidity@0.4.24 # version 0.4.24
$ brew install klaytn/klaytn/solidity@0.5.6 # version 0.5.6
Command-line Tool
The command-line tool allows you to generate Solidity smart contract function wrappers from the command line.
Installation (Homebrew)
Java 1.8+ is required to install this.
$ brew tap klaytn/klaytn
$ brew install caver-java
After installation you can run command 'caver-java' like below:
After creating an account, you can receive some Baobab testnet KLAY for the Baobab testnet via Baobab Faucet, available at https://baobab.wallet.klaytn.foundation/. The received testnet KLAY will be used for transaction fee later.
After you get a Caver instance and create an account which has some KLAY, you can send 1 peb to a certain address(0xe97f27e9a5765ce36a7b919b1cb6004c7209217e) with a gas limit BigInteger.valueOf(100_000) like below:
TransactionManager is introduced to hide the complexity of transaction types. For example, a FeeDelegatedValueTransferTransaction object can be transformed from a ValueTransferTransaction object. For more details, see Fee Delegation. In addition to Fee Delegation, TransactionManager can be used with GetNonceProcessor, ErrorHandler, and TransactionReceiptProcessor.
If you use ValueTransfer class, you can more easily compose and send a transaction. This is because ValueTransfer class makes the processes above simple like below:
KlayTransactionReceipt.TransactionReceipt transactionReceipt=ValueTransfer.create(caver, credentials,ChainId.BAOBAB_TESTNET).sendFunds(redentials.getAddress(),// fromAddress"0xe97f27e9a5765ce36a7b919b1cb6004c7209217e",// toAddressBigDecimal.ONE,// value Convert.Unit.PEB,// unit BigInteger.valueOf(100_000) // gasLimit ).send();
Checking Receipts
If you send a transaction via sendFunds, caver-java tries to get a transaction receipt by default. After you get a receipt, you can see the following log in the console.
In this receipt, you can check the status of the transaction execution. If the 'status' field in the receipt is "0x1", it means the transaction is processed successfully. If not, the transaction failed. The detailed error message is presented in the txError field. For more detail, see txError.
Sending Other Transaction Types
Account Update
If you want to update the key of the given account to a new AccountKeyPublic key:
An account key represents the key structure associated with an account. To get more details and types about the Klaytn account key, please read AccountKey.
Smart Contract
caver-java supports auto-generation of smart contract wrapper code. Using the wrapper, you can easily deploy and execute a smart contract. Before generating a wrapper code, you need to compile the smart contract first. Note: This will only work if a Solidity compiler is installed in your computer. See Solidity Compiler.
<type> result = contract.<someMethod>(<param1>,...).send();
Example
This section describes how to deploy and execute a smart contract on the Baobab testnet. In this example, we use a smart contract ERC20Mock. If contract deployment fails and an empty contract address is returned, it will throw RuntimeException.
Klaytn provides Fee Delegation feature which allows service providers to pay transaction fees instead of the users.
Value Transfer
On the client side, client who initiates the transaction will generate a fee-delegated value transfer transaction as follows: A sender creates a default ValueTransferTransaction object, then transactionManager.sign() returns a signed FeeDelegatedValueTransferTransaction object if the second parameter is set to true.
A signed transaction, senderRawTransaction, is generated. Now the sender delivers the transaction to the fee payer who will pay for the transaction fee instead. Transferring transactions between the sender and the fee payer is not performed on the Klaytn network. The protocol should be defined by themselves.
After the fee payer gets the transaction from the sender, the fee payer can send the transaction using the FeePayerManager class as follows. FeePayerManager.executeTransaction() will sign the received transaction with the fee payer's private key and send the transaction to the Klaytn network.
The difference between fee-delegated smart contract execution and fee-delegated value transfer above is that this needs input data to call a function of a smart contract. A sender can generate a fee-delegated smart contract execution transaction as shown below. Note that transactionManager.sign() returns a TxTypeFeeDelegatedSmartContractExecution object if you pass true to the second parameter. The example below invokes the transfer method of ERC20Mock contract which is described in Smart Contract.
caver-java introduces new classes to support the various types of AccountKey supported by the platform. This feature is supported starting with version 1.2.0.
AccountKey
To update the account key on the Klaytn platform, caver-java provides the AccountKey interface. The following describes AccountKey implementations, AccountKeyPublic, AccountKeyWeightedMultiSig, and AccountKeyRoleBased. See Account Update for how to update an Account.
AccountKeyPublic
AccountKeyPublic is an implementation of AccountKey with one public key. You can create it like this:
To use the account updated with AccountKeyPublic, you need to create KlayCredentials as follows:
KlayCredentials validCredentails =KlayCredentials.create(newKeyPair,oldCredentials.getAddress());// Because the account address is decoupled from the AccountKeyPublic (public key), you can't use the account if you create the credentials without address as below.
KlayCredentials invalidCredentails =KlayCredentials.create(newKeyPair);
AccountKeyWeightedMultiSig
AccountKeyWeightedMultiSig is an account key that contains multiple public keys with varying weights. AccountKeyWeightedMultiSig also defines the threshold, the sum of the weights of the keys that must be signed in order to use the account. The maximum number of keys supported is 10. You can create AccountKeyWeightedMultiSig as below:
AccountKeyRoleBased is a list of AccountKey. Each AccountKey is assigned to a specific role according to its position. AccountKey can be AccountKeyPublic, AccountKeyWeightedMultiSig, or AccountKeyFail. If AccountKeyNil is used for a specific role, the key will not be updated for that role and the existing AccountKey will be used. If AccountKeyFail is used, signing for the role will fail always, so be careful using AccountKeyFail.
List<AccountKey> roleBasedAccountKeyList =newArrayList<>();ECKeyPair newKeyPair1 =Keys.createEcKeyPair(); // for RoleTransactionroleBasedAccountKeyList.add(AccountKeyPublic.create(newKeyPair1.getPublicKey()));ECKeyPair newKeyPair2 =Keys.createEcKeyPair(); // for RoleAccountUpdateroleBasedAccountKeyList.add(AccountKeyPublic.create(newKeyPair2.getPublicKey()));ECKeyPair newKeyPair3 =Keys.createEcKeyPair(); // for RoleFeePayerroleBasedAccountKeyList.add(AccountKeyPublic.create(newKeyPair3.getPublicKey()));newAccountKey =AccountKeyRoleBased.create(roleBasedAccountKeyList);
To use the account updated with AccountKeyRoleBased, you can create KlayCredentials as follows:
If an account has AccountKeyMultiSig or AccountKeyRoleBased, each key can be managed by different people.
This section describes how to collect signatures and send the transaction if there are multiple signers.
Sequential sender signing
The rawTransaction has an RLP encoded transaction that contains both txSignatures and feePayerSignatures. feePayerSignature is included only when the transaction is a fee delegated transaction.
In the absence of a fee payer, the process of repeatedly signing and executing a transaction can be divided into three parts. 1. RLP-encode the transaction and send it to the signer in the form of rawTransaction. 2. Signer signs with its own key for the received rawTransaction. 3. Sending the signed rawTransaction to EN. Step 2 can be repeated if there are multiple signers.
//// 1. Alice creates a transaction, signs it, and sends it to Bob.//// Alice SideValueTransferTransaction transactionTransformer =ValueTransferTransaction.create(from, to,BigInteger.ONE, GAS_LIMIT);TransactionManager transactionManager_alice =new TransactionManager.Builder(caver, senderCredential_alice).setTransactionReceiptProcessor(newPollingTransactionReceiptProcessor(caver,1000,10)).setChaindId(LOCAL_CHAIN_ID).build();String rawTransaction_signed_alice =transactionManager_alice.sign(transactionTransformer).getValueAsString();//// 2. Bob signs the received transaction and sends it to Charlie.//// Bob SideTransactionManager transactionManager_bob =new TransactionManager.Builder(caver, senderCredential_bob).setTransactionReceiptProcessor(newPollingTransactionReceiptProcessor(caver,1000,10)).setChaindId(LOCAL_CHAIN_ID).build();String rawTransaction_signed_alice_and_bob = transactionManager_bob.sign(rawTransaction_signed_alice).getValueAsString();
//// 3. Charlie signs the received transaction and sends it to Klaytn EN.//// Charlie SideTransactionManager transactionManager_charlie =new TransactionManager.Builder(caver, senderCredential_charlie).setTransactionReceiptProcessor(newPollingTransactionReceiptProcessor(caver,1000,10)).setChaindId(LOCAL_CHAIN_ID).build();KlayTransactionReceipt.TransactionReceipt transactionReceipt = transactionManager_charlie.executeTransaction(rawTransaction_signed_alice_and_bob);
Sequential fee-payer signing
Fee-payer signature(s) can also be added sequentially. Signing with FeePayerManager accumulates feePayerSignatures in the transaction. The signing order is not important. If you sign with TransactionManager, the txSignature is added. If you sign with FeePayerManger, the feePayerSignatures is added to the raw transaction.
//// 1. Bob receives a transaction from Alice and signs the transaction as a fee payer.//// Bob SideFeePayerManager feePayerManager_bob =new FeePayerManager.Builder(caver, feePayerCredentials_bob).setTransactionReceiptProcessor(newPollingTransactionReceiptProcessor(caver,1000,10)).setChainId(LOCAL_CHAIN_ID).build();String rawTransaction_signed_alice_and_bob =feePayerManager_bob.sign(rawTransaction_signed_alice).getValueAsString();//// 2. Charlie signs the received transaction and sends it to Klaytn EN.//// Charlie SideFeePayerManager feePayerManager_charlie =new FeePayerManager.Builder(caver, feePayerCredentials_charlie).setTransactionReceiptProcessor(newPollingTransactionReceiptProcessor(caver,1000,10)).setChainId(LOCAL_CHAIN_ID).build();KlayTransactionReceipt.TransactionReceipt transactionReceipt = feePayerManager_charlie.executeTransaction(rawTransaction_signed_alice_and_bob);