Skip to content

Commit

Permalink
Merge pull request #39 from ground-x/release/v1.0.2
Browse files Browse the repository at this point in the history
[Master] release/v1.0.2 QA Sign-off
  • Loading branch information
jimni1222 authored Dec 23, 2020
2 parents f50422a + 25f27c3 commit ace1b20
Show file tree
Hide file tree
Showing 13 changed files with 4,512 additions and 69 deletions.
119 changes: 117 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,41 @@ caver-java-ext-kas is [caver-java](https://github.com/klaytn/caver-java)'s exten
* [Use Token History API](#use-token-history-api)
* [Use Wallet API](#use-wallet-api)
* [Use Anchor API](#use-anchor-api)
* [Introduced KASWallet](#introduced-kaswallet)
* [Test](#test)

## Installation

#### maven
### Installation

#### add a Repository

To install caver-java-ext-kas, you need to install caver-java.
To install the latest version of caver-java, you should add a jitpack repository for IPFS feature.

**maven**
```groovy
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
```

**gradle**
```groovy
allprojects {
repositories {
... //mavenCentral() or jcenter()
maven { url 'https://jitpack.io' }
}
}
```

#### add a dependency

**maven**
```groovy
<dependency>
<groupId>xyz.groundx.caver</groupId>
Expand All @@ -32,7 +62,8 @@ caver-java-ext-kas is [caver-java](https://github.com/klaytn/caver-java)'s exten
<type>pom</type>
</dependency>
```
#### gradle

**gradle**
```groovy
implementation 'xyz.groundx.caver:caver-java-ext-kas:X.X.X'
```
Expand Down Expand Up @@ -179,6 +210,90 @@ options.setFromTimestamp();
options.setToTimesatamp();
```

### Introduced KASWallet
KASWallet allows you to handle transaction instance in caver-java by using KAS Wallet API.
- Generate and manage accounts by using KAS Wallet API.
- Sign a transaction instance in caver-java by using KAS Wallet API.

KASWallet can be used as a member called `wallet` of the `CaverExtKAS` class.
The `CaverExtKAS` class can provide the same usability as the 'wallet' of `Caver` class in caver-java through KASWallet.
Also, `Contract`, `KIP7`, `KIP17` classes in caver-java can be used the same as the existing caver-java.

Here we introduced a simple example using Contract, KIP7 and KIP17 respectively. Please refer to Contract, KIP7 and KIP17 of [Klaytn Docs](https://docs.klaytn.com/bapp/sdk/caver-java/getting-started#smart-contract) for detailed usage.

#### Use Contract class with KASWallet
```java
final String ABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"key\",\"type\":\"string\"}],\"name\":\"get\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},...]";
final String BINARY = "Smart contract binary Data";
String accessKey = "your access key";
String secretAccessKey = "your secret access key";
CaverExtKAS caver = new CaverExtKAS(ChainId.BAOBAB_TESTNET, accessKey, secretAccessKey);

Contract contract = new Contract(caver, abi);

//Deploy Contract
String account = "0x{address}";
BigInteger gas = BigInteger.valueOf(10000000);
SendOptions sendOptions = new SendOptions(account, gas);
contract.deploy(sendOptions, BINARY);

//Execute contract's "set" function.
SendOptions sendOptions = new SendOptions(account, BigInteger.valueOf(5000000));
TransactionReceipt.TransactionReceiptData receiptData = contract.send(sendOptions, "set", "key", "value");
```

#### Use KIP7 class with KASWallet
```java
String accessKey = "your access key";
String secretAccessKey = "your secret access key";
CaverExtKAS caver = new CaverExtKAS(ChainId.BAOBAB_TESTNET, accessKey, secretAccessKey);

String from = "0x{from address}";
String to = "0x{to address}";
//deploy KIP7 contract
BigInteger initialSupply = BigInteger.TEN.multiply(BigInteger.TEN.pow(18)); // 10 * 10^18
KIP7 kip7 = KIP7.deploy(caver, from, "KAS", "SDK", 18, iniinitialSupply);
//execute KIP7's transfer function.
BigInteger transferAmount = BigInteger.ONE.multiply(BigInteger.TEN.pow(18));
SendOptions sendOptions = new SendOptions(from, (String)null);
TransactionReceipt.TransactionReceiptData receiptData = kip7.transfer(to, amount, sendOptions);
```
#### Use KIP17 class with KASWallet
```java
String accessKey = "your access key";
String secretAccessKey = "your secret access key";
CaverExtKAS caver = new CaverExtKAS(ChainId.BAOBAB_TESTNET, accessKey, secretAccessKey);
//deploy KIP17 contract.
String from = "0x{from address}";
KIP17 kip17 = KIP17.deploy(caver, from, name, symbol);
//execute KIP17's mint function.
SendOptions sendOptions = new SendOptions(from, (String)null);
TransactionReceipt.TransactionReceiptData receiptData = kip17.mint(kip17, from, BigInteger.ZERO);
```
#### Handling KASAPIException
When an error occurs while using KAS Wallet API in `KASWallet` class, it throws `KASAPIException`(extends RuntimeException).
KASAPIException has HTTP Error code and message and also it contains response body.
Below is an example code that handles the error that occurred while executing the KAS Wallet API.
```java
try {
String unKnownAddress = "0x785ba1146cc1bed97b9c8d73e9293cc3b6bc3691";
Account account = caver.wallet.getAccount(unKnownAddress);
} catch (KASAPIException e) {
System.out.println(e.getcode()); // 400
System.out.println(e.getMessage()); // "Bad Request"
System.out.println(e.getResponseBody().getCode()); // 1061010
System.out.println(e.getResponseBody().getMessage()); // "data don't exist"
}
```
## Test
Before testing, you need to either modify the data in "Config.java" or use ".env" to set the data required for testing.
If you use ".env", you must set variable below.
Expand Down
9 changes: 5 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.caver_version = '1.5.3-rc.2'
ext.caver_version = '1.5.6-rc.6'
}

plugins {
Expand All @@ -13,7 +13,7 @@ plugins {
}

allprojects {
version '1.0.1'
version '1.0.2'
group 'xyz.groundx.caver'
description 'An extension library of caver-java for using KAS (Klaytn API Service).'

Expand All @@ -27,7 +27,8 @@ allprojects {


repositories {
mavenCentral()
jcenter()
maven { url 'https://jitpack.io' }
}

javadoc {
Expand Down Expand Up @@ -156,8 +157,8 @@ allprojects {


testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile 'org.mockito:mockito-core:3.6.28'
testCompile "ch.qos.logback:logback-core:1.2.3",
"ch.qos.logback:logback-classic:1.2.3"
}
}

50 changes: 46 additions & 4 deletions src/main/java/xyz/groundx/caver_ext_kas/CaverExtKAS.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@

import com.klaytn.caver.Caver;
import com.klaytn.caver.rpc.RPC;
import com.klaytn.caver.wallet.IWallet;
import com.squareup.okhttp.Credentials;
import org.web3j.protocol.http.HttpService;
import xyz.groundx.caver_ext_kas.kas.KAS;
import xyz.groundx.caver_ext_kas.wallet.KASWallet;

/**
* Representing wrapping class that can use Klaytn API Service
Expand All @@ -37,12 +39,42 @@ public class CaverExtKAS extends Caver {
public KAS kas;

/**
* Creates a CaverExtKAS instance.
* The KAS wallet instance.
*/
public KASWallet wallet;

/**
* Creates a CaverExtKAS instance.<br>
* It need to init each KAS API manually.
*/
public CaverExtKAS() {
this.kas = new KAS();
}

/**
* Creates a CaverExtKAS instance.<br>
* It init all supported KAS API(Node API, Anchor API, Wallet API)
* @param chainId The Klaytn network chain id.
* @param accessKeyId The access key provided by KAS console.
* @param secretAccessKey The secret key provided by KAS console.
*/
public CaverExtKAS(int chainId, String accessKeyId, String secretAccessKey) {
this.kas = new KAS();
initKASAPI(chainId, accessKeyId, secretAccessKey);
}

/**
* Creates a CaverExtKAS instance.<br>
* It init all supported KAS API(Node API, Anchor API, Wallet API)
* @param chainId The Klaytn network chain id.
* @param accessKeyId The access key provided by KAS console.
* @param secretAccessKey The secret key provided by KAS console.
*/
public CaverExtKAS(String chainId, String accessKeyId, String secretAccessKey) {
this.kas = new KAS();
initKASAPI(chainId, accessKeyId, secretAccessKey);
}

/**
* Initialize all KAS API.
* @param chainId The Klaytn network chain id.
Expand Down Expand Up @@ -137,7 +169,7 @@ public void initAnchorAPI(int chainId, String accessKeyId, String secretAccessKe
* @param secretAccessKey The secret key provided by KAS console.
*/
public void initAnchorAPI(String chainId, String accessKeyId, String secretAccessKey) {
kas.initAnchorAPI(chainId, accessKeyId, secretAccessKey, URL_ANCHOR_API);
initAnchorAPI(chainId, accessKeyId, secretAccessKey, URL_ANCHOR_API);
}

/**
Expand Down Expand Up @@ -181,7 +213,7 @@ public void initWalletAPI(int chainId, String accessKeyId, String secretAccessKe
* @param secretAccessKey The secret key provided by KAS console.
*/
public void initWalletAPI(String chainId, String accessKeyId, String secretAccessKey) {
kas.initWalletAPI(chainId, accessKeyId, secretAccessKey, URL_WALLET_API);
initWalletAPI(chainId, accessKeyId, secretAccessKey, URL_WALLET_API);
}

/**
Expand All @@ -204,6 +236,7 @@ public void initWalletAPI(int chainId, String accessKeyId, String secretAccessKe
*/
public void initWalletAPI(String chainId, String accessKeyId, String secretAccessKey, String url) {
kas.initWalletAPI(chainId, accessKeyId, secretAccessKey, url);
setWallet(new KASWallet(this.kas.wallet));
}

/**
Expand All @@ -225,7 +258,7 @@ public void initTokenHistoryAPI(int chainId, String accessKeyId, String secretAc
* @param secretAccessKey The secret key provided by KAS console.
*/
public void initTokenHistoryAPI(String chainId, String accessKeyId, String secretAccessKey) {
kas.initTokenHistoryAPI(chainId, accessKeyId, secretAccessKey, URL_TH_API);
initTokenHistoryAPI(chainId, accessKeyId, secretAccessKey, URL_TH_API);
}

/**
Expand Down Expand Up @@ -258,11 +291,20 @@ public KAS getKas() {
return kas;
}

@Override
public IWallet getWallet() {
return this.wallet;
}

/**
* Setter function for KAS instance
* @param kas The KAS instance.
*/
public void setKas(KAS kas) {
this.kas = kas;
}

public void setWallet(KASWallet wallet) {
this.wallet = wallet;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package xyz.groundx.caver_ext_kas.exception;

public class ExceptionDetail {
int code;
String message = "";

public ExceptionDetail() {
}

public int getCode() {
return code;
}

public String getMessage() {
return message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package xyz.groundx.caver_ext_kas.exception;

import com.fasterxml.jackson.databind.ObjectMapper;
import xyz.groundx.caver_ext_kas.rest_client.io.swagger.client.ApiException;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public class KASAPIException extends RuntimeException {
private int code = 0;
private Map<String, List<String>> responseHeaders = null;
private ExceptionDetail responseBody = null;

public KASAPIException() {}

public KASAPIException(Throwable throwable) {
super(throwable);
}

public KASAPIException(String message) {
super(message);
}

public KASAPIException(String message, Throwable throwable) {
super(message, throwable);
}

public KASAPIException(ApiException e) {
this(e.getMessage(), e.getCause(), e.getCode(), e.getResponseHeaders(), e.getResponseBody());
}

public KASAPIException(String message, Throwable throwable, int code, Map<String, List<String>> responseHeaders, String responseBody) {
super(message, throwable);
this.code = code;
this.responseHeaders = responseHeaders;
if(responseBody != null && !responseBody.isEmpty()) {
setResponseBody(responseBody);
}
}

public KASAPIException(String message, int code, Map<String, List<String>> responseHeaders, String responseBody) {
this(message, (Throwable) null, code, responseHeaders, responseBody);
}

public KASAPIException(String message, Throwable throwable, int code, Map<String, List<String>> responseHeaders) {
this(message, throwable, code, responseHeaders, null);
}

public KASAPIException(int code, Map<String, List<String>> responseHeaders, String responseBody) {
this((String) null, (Throwable) null, code, responseHeaders, responseBody);
}

public KASAPIException(int code, String message) {
super(message);
this.code = code;
}

public KASAPIException(int code, String message, Map<String, List<String>> responseHeaders, String responseBody) {
this(code, message);
this.responseHeaders = responseHeaders;

if(responseBody != null && !responseBody.isEmpty()) {
setResponseBody(responseBody);
}
}

public int getCode() {
return code;
}

public Map<String, List<String>> getResponseHeaders() {
return responseHeaders;
}

public ExceptionDetail getResponseBody() {
return responseBody;
}

public void setResponseBody(String responseBody) {
try {
ExceptionDetail detail = new ObjectMapper().readValue(responseBody, ExceptionDetail.class);
this.responseBody = detail;
} catch (IOException e){
throw new RuntimeException("Failed to parsed json string : " + responseBody);
}
}
}
Loading

0 comments on commit ace1b20

Please sign in to comment.