Getting Started
What's new?
In caver-java 1.5.0, we adopt Common Architecture. Common Architecture is a new software architecture for Klaytn development environment, which is shared by all Klaytn SDKs (caver-js/caver-java). It is designed for your streamlined development experience and ease of extensibility to other programming languages.
As caver-java is updated to 1.5.0, the APIs used in 1.4.0 are deprecated except for some APIs.
The APIs newly provided in caver-java 1.5.0 are as follows.
caver.account
caver.account is a package used to update AccountKey, which could be one or more public keys (AccountKeyPublic, AccountKeyWeightedMultiSig, and AccountKeyRoleBased) or a special type of keys (AccountKeyLegacy and AccountKeyFail), for a Klaytn account.
caver.accountreplacescaver.tx.accountin caver-java 1.4.0
caver.wallet
caver.wallet is a package that manages Keyring instances in in-memory wallet. A Keyring is an instance that stores the address of a Klaytn account and its private key(s), and it is used when the address of this account signs a transaction. caver.wallet accepts all types of Keyring (SingleKeyring, MultipleKeyring, and RoleBasedKeyring) and manages them with their Klaytn account address.
caver.walletreplacescaver.cryptoin caver-java 1.4.0caver.wallet.KeyStorereplacescaver.wallet.WalletFilein caver-java 1.4.0
caver.transaction
caver.transaction is a package that provides functionality related to Transaction.
caver.transactionreplacescaver.txin caver-java 1.4.0
caver.rpc
caver.rpc is a package that provides functionality related to rpc call with Klaytn Node.
caver.rpc.klayandcaver.rpc.netreplacesKlay,Netinterfaces in caver-java 1.4.0, respectively
caver.util
caver.utils provides utility functions.
caver.contract
caver.contract is a package that makes it easy to handle smart contracts in Klaytn. With caver.contract, you can deploy smart contracts and execute them by calling their functions. caver.contract first converts smart contract functions and events from ABI(Application Binary Interface), calls those functions, and obtains the event information.
Prerequisites
Adding a Repository
A library repository should be added before using IPFS. Please add the following repository first.
maven
gradle
Adding a Dependency
maven
gradle
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.
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.
After installation you can run command 'caver-java' like below:
Installation (Other)
Currently, we do not support other package managers. As another solution, we provide a method to build the CLI below.
Download or fork caver-java.
Do task 'shadowDistZip' in the console module using Gradle. As a result, console/build/distributions/console-shadow-{version}.zip is generated.
Unzip the zip file in the build directory
Execute the binary file to run the command-line tool like below. You can find a shell script file for macOS users and a batch file for Window users.
Sending KLAY at a glance
This section describes a simple example of using a keystore file to send KLAY with a value transfer transaction. The keystore file can be created in Klaytn Wallet. If you need KLAY for testing, you can get Baobab testnet KLAY from the Klaytn Wallet.
Starting with caver-java
Connecting to a Klaytn Node
If you are running an EN, you can connect it to your own node by changing the host and port like below:
Managing Keyrings
Keyring is a structure that contains the address of the Klaytn account and the private key(s).
Keyring can be classified into three types depending on the type of key being stored: SingleKeyring to store one address and one private key, MultipleKeyring to store one address and multiple private keys, and RoleBasedKeyring to store one address and one or more private keys for each role.
SingleKeyring defines key property inside, and this key stores one private key.
MultipleKeyring defines keys property inside, and this keys is implemented as an array to store multiple private keys.
The keys property defined in RoleBasedKeyring is implemented as a List object having 3 arrays of private key(s) as its elements (empty keys will look like [ [], [], [] ]) and so that it can include multiple keys for each role. The first element of the array is filled with the private key(s) to be used for roleTransactionKey, the second element the private key(s) to be used for roleAccountUpdateKey, and the third element the private key(s) to be used for roleFeePayerKey.
Creating a Keyring
Generating a SingleKeyring
You can randomly generate a single keyring as shown below.
Creating a SingleKeyring from private key
Also, if you own a specific private key, you can use it to create a keyring as shown below.
Creating a SingleKeyring with a private key and an address
If your private key for your Klaytn account is decoupled from the address, you can create a keyring using the given address and the given private key like below.
Also, you can derive SingleKeyring instance from Klaytn wallet key.
Creating a MultipleKeyring with multiple private keys
If you want to use multiple private keys, you can create a MultipleKeyring using an address and multiple private keys. The below examples show how to create a MultipleKeyring with multiple private keys.
Creating a RoleBasedKeyring with private keys
To use different private key(s) for each role, caver.wallet.keyring.createWithRoleBasedKey is used. Each array element represents a role described in RoleBasedKeyring. The example below shows how to create a RoleBasedKeyring instance from different keys for each role.
Adding Keyrings to caver-java from a keystore json string.
You can use a keyring more easily by adding it to the in-memory wallet provided by caver-java. The following examples illustrate how to add a keyring to caver.wallet using a keystore JSON file string generated by Klaytn Wallet.
Looking at the output above, you can query your keyring from caver.wallet after adding it to caver.wallet.
If you have an address and private key(s) to use, you can easily create a keyring and add it directly to caver.wallet via caver.wallet.newKeyring.
When caver.wallet.newKeyring is executed with a private key, a Keyring instance with one private key is created and added to caver.wallet. For multiple private keys, a Keyring instance with multiple private keys is created and added to caver.wallet. When passing a 2D string array including one or more private keys for each role as an element, a Keyring instance that contains the different private key(s) for each role is created and also added to the caver.wallet.
caver.wallet.add or caver.wallet.newKeyring returns a Keyring instance after adding it to caver.wallet.
Sending a Transaction
This section will show you how to send KLAY using caver-java on the Baobab network.
Getting KLAY via Baobab Faucet
If you need KLAY for testing, you can get Baobab testnet KLAY from the Klaytn Wallet. Log in to the Klaytn Wallet using the private key or the keystore file and receive Baobab testnet KLAY via the faucet for testing.
Sending a Value Transfer Transaction
You can use a caver-java wallet to generate a signature of a transaction. You have to go through two steps below to send the transaction to the network.
Sign a transaction
If the keyring you want to use is added to
caver.wallet, you can usecaver.wallet.signfunction to sign.If you manage the keyring separately without adding it to
caver.wallet, you can sign the transaction throughtransaction.signfunction.
Send the RLP-encoded string of the signed transaction to the Klaytn via
caver.rpc.klay.sendRawTransaction.
Note: The sender should have enough number of KLAY to be transferred and also to pay the transaction fee.
Sign a transaction
Before sending a transaction to Klaytn, you should sign a transaction first.
Below is an example of how to sign a transaction if a keyring is added to the caver.wallet.
The above code adds a keyring to caver.wallet, creates a transaction, and signs the transaction through caver.wallet.sign.
Running the above code gives you the following result. When the above code is executed, the RLP-encoded string of the transaction is shown below. (The RLP-encoded string output you got could be different from the string output shown below.)
Send the RLP-encoded string of the signed transaction to the Klaytn
Now you can send a signed transaction to the network like below. If you want to run the below example, replace "rlpEncoding" with the value of rlpEncoded in the code above.
If you want to sign a transaction and send it to the network without caver.wallet, see the example below.
When the above code is executed, the transaction hash (txHash) is printed like the example below.
Checking Receipts
You can use the TransactionReceiptProcessor to get the receipt of the transaction when you transfer the transaction to the Klaytn by caver.rpc.klay.sendRawTransaction.
The following example shows how to get a receipt using PollingTransactionReceiptProcessor.
As described in the example above, you can get the result of sending a transaction through TransactionReceiptProcessor. The transactionHash field is defined inside the receipt object.
You can use caver.rpc.klay.getTransactionReceipt RPC call with txHash string to query the receipt of a transaction at any time from the network after the transaction is included in a block. The example below shows how to get a receipt using the caver.rpc.klay.getTransactionReceipt RPC call.
The result of the transaction can be found through the status of the receipt. For the details of the return values, see caver.rpc.klay.getTransactionReceipt. If a transaction is failed, you can check more about the error in txError of the receipt. For more information about txError, see txError: Detailed Information of Transaction Failures.
Executing Other Transaction Types
Klaytn provides various transaction types for extensibility and performance. For more information, see Transactions. This section describes some examples that can be used with caver-java.
Fee Delegation
Klaytn provides Fee Delegation feature. Here's an example of making a RLP-encoded transaction when you are a sender of this kind of transaction:
When the above code is executed, the RLP-encoded string will be printed. (The RLP-encoded string output you got could be different from the string output shown below.)
The fee payer can send the transaction to the Klaytn after attaching the feePayerSignatures to the RLP-encoded string (rawTransaction) signed by the transaction sender. If caver.wallet also has the fee payer's keyring, the fee payer's signature can be injected into feeDelegatedTx by calling caver.wallet.signAsFeePayer(feePayer.address, feeDelegatedTx). Otherwise, the fee payer has to create a feeDelegatedTx from the RLP-encoded string signed by the sender and add the fee payer's sign onto it, as illustrated below. If you want to run the below example, replace 0x{RLP-encoded string} with the value of rlpEncoded above.
When the above code is executed, the RLP-encoded string including the sender's signatures and fee payer's signatures is printed like below. (The output you got could be different from the string output shown below.)
The transaction is now signed by both the sender and the fee payer, and it can now be sent over the network. Replace 0x{RLP-encoded string} with the RLP-encoded string output of the example code above.
The result of the transaction can be found through the status of the receipt. For the details of the return values, see caver.rpc.klay.getTransactionReceipt. If a transaction is failed, you can check more about the error in txError of the receipt. For more information about txError, see [txError: Detailed Information of Transaction Failures].
Account Update
If you want to change the private key(s) for your Klaytn account, there are 3 important things you need to remember:
Klaytn validates every transaction you send to it.
The validation requires your public keys which exactly corresponds to your private key(s).
Thus, changing your private key(s) into the new one(s) is always be preceded by changing your old public key(s) to the new one(s). The new public key(s) must be derived from the new private key(s).
Keeping the 3 things above in your mind, you can change your private key(s) by following the steps below:
Prepare the new private key(s) to create a new keyring.
Create a keyring by its type (Single keyring, Multiple keyring, or Role-based keyring) you need.
Generate an Account instance from the new keyring. This Account instance holds the new public key(s) for your Klaytn account.
Send AccountUpdate transaction including Account instance to Klaytn.
Finally, replace your old keyring to the new one that was created in Step 2.
Please check Account Update for the details.
To change your AccountKey, you must provide an Account instance for the account field in the input argument object of caver.transaction.type.AccountUpdate. An Account instance contains the address of the Klaytn account and the AccountKey to be updated.
The code below is an example code that changes the private key(s) you use for your Klaytn account along with changing AccountKey of your Klaytn account to AccountKeyPublic. Don't forget to prepare your new private key(s).
If the above code is executed successfully, you are no longer able to use the old private key(s) to sign any transaction with the old keyring. So you must update the old keyring with the newKeyring through caver.wallet.updateKeyring(newKeyring). Once it is updated, the signing will be done by the newly updated private key(s).
Here comes how to update AccountKey of your Klaytn account with multiple AccountKeys? The example below explains how to create an Account instance with multiple private keys that what you want to use (You can create an Account instance with multiple public keys via caver.account.create). Same again, after feeding the account instance created to the account field inside the transaction object, the left rest of the updating process is just the same as the above example.
First, let's create an Account instance to update with AccountKeyWeightedMultiSig. For AccountKeyWeightedMultiSig, a threshold and a weight for each key must be defined. To do this, use caver.account.weightedMultiSigOptions. The first parameter is the threshold, and the second parameter is an array containing the weight for each key.
Now let's update AccountKey using AccountKeyRoleBased. AccountKeyRoleBased is an AccountKey type that defines the key to use for each role.
The AccountKeyRoleBased above is an example of using one public key for each role. As you can see from the code above, each of them corresponds to one private key. If you want to use multiple private keys for each role, caver.account.weightedMultiSigOptions must be defined for each role as shown below.
If you want to update AccountKey to AccountKeyLegacy or accountKeyFail, create an Account instance as shown below and assign it to the account field of the transaction. The rest of the update process is same to that of other AccountKey.
Smart Contract
The Contract class in caver.contract package makes it easy to interact with smart contracts on Klaytn. All functions of a smart contract automatically converted and stored inside contract instance, when its low-level ABI is given. This allows you to interact with a smart contract like you handle a contract instance in Java.
We begin our explanation of dealing with a smart contract in Java by writing a simple solidity example code below. Create a 'test.sol' file and write down the example below.
Then, compile this smart contract to get its bytecode and ABI.
NOTE: To compile a smart contract, you must have a solidity compiler installed. To compile the above program, you need to install solc:0.5.6.
To deploy a smart contract by its type, you can use caver-java classes described below:
Contractclass in thecaver.contractpackage when the sender or the fee payer of a smart contract transaction pays the feeSmartContractDeployclass in thecaver.transactionpackage when the sender of a smart contract transaction pays the feefeeDelegatedSmartContractDeployclass in thecaver.transactionpackage when the fee payer of a smart contract transaction pays the feefeeDelegatedSmartContractDeployWithRatioclass in thecaver.transactionpackage when the fee payer of a smart contract transaction pays the fee
Here is an example of exploiting Contract class in caver.contract package. You can create a contract instance like below from the bytecode and ABI you get after compiling the smart contract.
Running the code above gives you the following result.
Looking at the output above, you can see that the contract instance owns the smart contract method. And since it hasn't been deployed yet, you can see that the result of contract.getContractAddress() is output as null.
If this contract was already deployed and you knew the contract address where this contract was deployed at, pass the contract address as the third parameter of the constructor of the contract instance as below.
Running the code above gives you the following result.
A contract instance stores its contract address as contractAddress property when it was created. The address can be accessed through getter / setter function (getContractAddress() / setContractAddress()).
Once a contract instance is created, you can deploy the smart contract by passing its bytecode and constructor's arguments (when needed for deploying) as the example below.
Note that the deploy() method of the contract instance sends transactions for contract deployment and contract execution. For sending transactions, it uses Keyrings in caver.wallet to sign them. The keyring to be used must have been added to caver.wallet before signing.
In the code above, the deployer deploys the contract to the Klaytn and returns the deployed contract instance.
A smart contract can be deployed using one of the following classes, depending on the type of contract deploying transaction:
Contractclass in thecaver.contractpackage when the sender or the fee payer of a smart contract transaction pays the feeSmartContractDeployclass in thecaver.transactionpackage when the sender of a smart contract transaction pays the feefeeDelegatedSmartContractDeployclass in thecaver.transactionpackage when the fee payer of a smart contract transaction pays the feefeeDelegatedSmartContractDeployWithRatioclass in thecaver.transactionpackage when the fee payer of a smart contract transaction pays the fee
To deploy a smart contract through a fee-delegated transaction, define the feeDelegation and feePayer fields in the SendOptions class like the example below.
If you want to send a transaction with sender and feePayer signed seperately when deploying a smart contract through caver.contract, refer to the code below.
To execute a smart contract's function by its type, you can use caver-java classes described below:
Contractclass in thecaver.contractpackage when the sender of a smart contract transaction pays the feeSmartContractExecutionclass in thecaver.transactionpackage when the sender of a smart contract transaction pays the feeFeeDelegatedSmartContractExecutionclass in thecaver.transactionpackage when the fee payer of a smart contract transaction pays the feeFeeDelegatedSmartContractExecutionWithRatioclass in thecaver.transactionpackage when the fee payer of a smart contract transaction pays the fee
To show how to execute a function in a smart contract, here we send a contract execution transaction that puts a string "testValue" as the input parameter of the contract function set in the example code below.
To execute a smart contract's function through a fee-delegated transaction, define the feeDelegation and feePayer fields in the SendOptions class like the example below.
If you want to send a transaction with sender and feePayer signed separately when executing a smart contract through caver.contract, refer to the code below:
To load a contract instance and call one of its functions (not sending a transaction but just a call): the below example shows calling a get function in a contract.
When the above code is executed, the value is shown as an output below.
To find more information, see caver-java API
IPFS
IPFS (InterPlanetary File System) is a distributed file system for storing and accessing files, websites, application, and data.
You can upload and download a file through IPFS with Caver.
Connecting with IPFS
The IPFS class in the caver.ipfs package is defined as a class member variable in Caver, so you can interact with IPFS through Caver.
In order to use an IPFS instance through the Caver instance, you must call method setIPFSNode() first to connect to an IPFS node.
The function setIPFSNode() requires following parameters:
IPFS HTTP API Host URL
IPFS HTTP API Host port number
Whether the host use SSL or not.
Uploading a file through IPFS
To upload a file through IPFS, please use add() like below.
This function returns CID(Content Identifier) of the uploaded file.
The execution result of the above code is shown below.
Likewise, you can upload a byte array.
The execution result of the above code is shown below.
Downloading a file from IPFS
To download a file from IPFS, please use get() like below.
This function requires CID of the file to be downloaded.
Conversion between CID and multihash
You can convert a CID to a Multihash using toHex().
A CID is a Base58 encoded value of a multihash. toHex() decodes the CID and returns the corresponding multihash.
The execution result of the above code is shown below.
To convert a multihash to CID, please use fromHex().
The execution result of the above code is shown below.
Detect KCT interface
KCT (Klaytn Compatible Token) contracts such as KIP-7, KIP-17, and KIP-37 define and provide various interfaces, and KIP-13 allows you to see whether a contract complies with KCT specifications and which interface it implements, by sending a query to the contract.
KIP-13 was implemented in Caver v1.5.7. It could detect interface through detectInterface() for any of the KCT contract classes (KIP7, KIP17, and KIP37).
Detecting KIP-7 Interfaces
To detect KIP-7 interfaces, you can use detectInterface() in the KIP7 class. It returns the mapping between KIP-7 interface identifier and a boolean that the interface is supported or not.
detectInterface() supports both static and instance methods, so you can select and use the method that suits your needs.
The interface detected through detectInterface() for KIP7 is shown in the table below.
IKIP7
0x65787371
IKIP7Metadata
0xa219a025
IKIP7Mintable
0xeab83e20
IKIP7Burnable
0x3b5a0bf8
IKIP7Pausable
0x4d5507ff
The execution result of the above code is shown below.
Detecting KIP-17 Interfaces
To detect the interface implemented in a KIP-17 token contract, you can use detectInterface() in the KIP17 class. It returns the mapping between KIP-17 interface identifier and interface support.
detectInterface() supports both static and instance methods, so you can select and use the method that suits your needs.
The interface detect through detectInterface() for KIP17 is shown in the table below.
IKIP17
0x80ac58cd
IKIP17Metadata
0x5b5e139f
IKIP17Enumerable
0x780e9d63
IKIP17Mintable
0xeab83e20
IKIP17MetadataMintable
0xfac27f46
IKIP17Burnable
0x42966c68
IKIP17Pausable
0x4d5507ff
The execution result of the above code is shown below.
Detecting KIP-37 interfaces
To detect the interface implemented in a KIP-37 token contract, you can use detectInterface() in the KIP37 class. It returns the mapping between KIP-37 interface identifier and interface support.
detectInterface() supports both static and instance methods, so you can select and use the appropriate method.
The interface detection through detectInterface() for KIP37 is shown in the table below.
IKIP37
0x6433ca1f
IKIP37Metadata
0x0e89341c
IKIP37Mintable
0xdfd9d9ec
IKIP37Burnable
0x9e094e9e
IKIP37Pausable
0x0e8ffdb7
The execution result of the above code is shown below.
Last updated