Skip to content

Commit

Permalink
Koios Java Client 1.17.3 (#139)
Browse files Browse the repository at this point in the history
* Base Service Restructure

* Add Missing Script JsonNode Field to NativeScript Model

* Add Get Native Script by Script Hash Method

* Bump Version to 1.17.3

* Change Cost Models Object type to JsonNode

* Remove Rate Control Mechanism

* Limit Preprod Script Redeemers Response Test to 10

* Add API Token Support

* Revert Cost Models Object Type

* Cosmetics

---------

Co-authored-by: Dudi Edri <[email protected]>
  • Loading branch information
edridudi and Dudi Edri authored Sep 15, 2023
1 parent 9a81655 commit 84b8f14
Show file tree
Hide file tree
Showing 20 changed files with 252 additions and 115 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Resource and maintenance requirements for Cardano blockchain components (e.g. ca
- Pagination (Limit and Offset) Supported
- Horizontal Filtering Supported
- Sorting Supported
- Rate Control
- API Token Supported
- Inner Retry Mechanism upon Timeouts
<details open>
<summary>Supported REST Services</summary>
Expand Down Expand Up @@ -294,7 +294,7 @@ Resource and maintenance requirements for Cardano blockchain components (e.g. ca

| Koios Instance | Koios Java Client |
|:--------------:|:-----------------:|
| 1.0.10 | 1.17.2 |
| 1.0.10 | 1.17.3 |
| 1.0.9 | 1.16.3 |
| 1.0.8 | 1.15.2 |
| 1.0.7 | 1.14.1 |
Expand All @@ -310,7 +310,7 @@ Resource and maintenance requirements for Cardano blockchain components (e.g. ca
<dependency>
<groupId>io.github.cardano-community</groupId>
<artifactId>koios-java-client</artifactId>
<version>1.17.2</version>
<version>1.17.3</version>
</dependency>
```

Expand Down Expand Up @@ -375,6 +375,7 @@ Result<List<TxHash>> transactionsResult = addressService.getAddressTransactions(
| KOIOS_JAVA_LIB_RETRIES_COUNT | integer | Sets the max retry count upon request timeout | 5 |
| KOIOS_JAVA_LIB_READ_TIMEOUT_SEC | integer | Sets the default read timeout for new connections (seconds) | 60 |
| KOIOS_JAVA_LIB_CONNECT_TIMEOUT_SEC | integer | Sets the default connect timeout for new connections (seconds) | 60 |
| KOIOS_JAVA_LIB_RETRY_ON_TIMEOUT | boolean | Sets whether to retry upon request timeout | true |

## Clone & Build with Maven
```shell
Expand Down
8 changes: 1 addition & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.cardano-community</groupId>
<artifactId>koios-java-client</artifactId>
<version>1.17.2</version>
<version>1.17.3</version>
<name>${project.groupId}:${project.artifactId}</name>
<description>Koios Java Client is a Java REST Client library which allows interacting with Koios Server Instances using Java Objects</description>
<url>https://github.com/cardano-community/koios-java-client</url>
Expand All @@ -23,7 +23,6 @@
<swagger-annotations.version>2.2.9</swagger-annotations.version>
<lombok.version>1.18.26</lombok.version>
<bcprov-jdk15to18.version>1.73</bcprov-jdk15to18.version>
<bucket4j-core.version>7.6.0</bucket4j-core.version>
<junit-jupiter.version>5.9.3</junit-jupiter.version>
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<maven-javadoc-plugin.version>3.5.0</maven-javadoc-plugin.version>
Expand Down Expand Up @@ -105,11 +104,6 @@
<artifactId>bcprov-jdk15to18</artifactId>
<version>${bcprov-jdk15to18.version}</version>
</dependency>
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-core</artifactId>
<version>${bucket4j-core.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ public class AccountServiceImpl extends BaseService implements AccountService {
/**
* Account Service Implementation Constructor
*
* @param baseService Base Service
* @param baseUrl Base Url
* @param apiToken Authorization Bearer JWT Token
*/
public AccountServiceImpl(BaseService baseService) {
super(baseService);
public AccountServiceImpl(String baseUrl, String apiToken) {
super(baseUrl, apiToken);
accountApi = getRetrofit().create(AccountApi.class);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
package rest.koios.client.backend.api.address.impl;

import rest.koios.client.backend.api.address.model.AddressUtxo;
import rest.koios.client.backend.api.common.TxHash;
import rest.koios.client.backend.api.address.AddressService;
import rest.koios.client.backend.api.address.api.AddressApi;
import rest.koios.client.backend.api.address.model.AddressAsset;
import rest.koios.client.backend.api.address.model.AddressInfo;
import rest.koios.client.backend.api.base.BaseService;
import rest.koios.client.backend.api.base.Result;
import rest.koios.client.backend.api.base.exception.ApiException;
import rest.koios.client.backend.api.common.TxHash;
import rest.koios.client.backend.factory.options.Options;
import rest.koios.client.backend.factory.options.SortType;
import retrofit2.Call;
import retrofit2.Response;

import java.io.IOException;
import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

/**
* Address Service Implementation
Expand All @@ -27,10 +29,11 @@ public class AddressServiceImpl extends BaseService implements AddressService {
/**
* Address Service Implementation Constructor
*
* @param baseService Base Service
* @param baseUrl Base Url
* @param apiToken Authorization Bearer JWT Token
*/
public AddressServiceImpl(BaseService baseService) {
super(baseService);
public AddressServiceImpl(String baseUrl, String apiToken) {
super(baseUrl, apiToken);
addressApi = getRetrofit().create(AddressApi.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ public class AssetServiceImpl extends BaseService implements AssetService {
/**
* Asset Service Implementation Constructor
*
* @param baseService Base Service
* @param baseUrl Base Url
* @param apiToken Authorization Bearer JWT Token
*/
public AssetServiceImpl(BaseService baseService) {
super(baseService);
public AssetServiceImpl(String baseUrl, String apiToken) {
super(baseUrl, apiToken);
assetApi = getRetrofit().create(AssetApi.class);
}

Expand Down
94 changes: 55 additions & 39 deletions src/main/java/rest/koios/client/backend/api/base/BaseService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
import org.jetbrains.annotations.NotNull;
import rest.koios.client.backend.api.base.exception.ApiException;
import rest.koios.client.backend.factory.options.Options;
import rest.koios.client.utils.Bech32Util;
Expand All @@ -18,7 +19,6 @@

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand All @@ -33,49 +33,65 @@
public class BaseService {

private final Retrofit retrofit;
private final Bucket bucket;
private int retriesCount = 5;
private static final int SLEEP_TIME_MILLIS = 2000;
private boolean retryOnTimeout = true;
private final String apiToken;

public BaseService(BaseService baseService) {
this.retrofit = baseService.getRetrofit();
this.bucket = baseService.getBucket();
this.retriesCount = baseService.getRetriesCount();
/**
* Base Service Constructor
*
* @param baseUrl Base URL
*/
public BaseService(String baseUrl) {
this(baseUrl, null);
}

/**
* Base Service Constructor
*
* @param baseUrl Base URL
* @param apiToken Authorization Bearer JWT Token
*/
public BaseService(String baseUrl) {
bucket = Bucket.builder().addLimit(Bandwidth.simple(100, Duration.ofSeconds(10))).build();
public BaseService(String baseUrl, String apiToken) {
this.apiToken = apiToken;
int readTimeoutSec = getReadTimeoutSec();
log.info("Set Read Timeout to {} Seconds", readTimeoutSec);
int connectTimeoutSec = getConnectTimeoutSec();
log.info("Set Connect Timeout to {} Seconds", connectTimeoutSec);
boolean logging = Boolean.parseBoolean(System.getenv("KOIOS_JAVA_LIB_LOGGING"));
OkHttpClient okHttpClient;
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.readTimeout(readTimeoutSec, TimeUnit.SECONDS)
.connectTimeout(connectTimeoutSec, TimeUnit.SECONDS);
if (logging) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClient = new OkHttpClient.Builder()
.readTimeout(readTimeoutSec, TimeUnit.SECONDS)
.connectTimeout(connectTimeoutSec, TimeUnit.SECONDS)
.addInterceptor(interceptor).build();
} else {
okHttpClient = new OkHttpClient.Builder()
.readTimeout(readTimeoutSec, TimeUnit.SECONDS)
.connectTimeout(connectTimeoutSec, TimeUnit.SECONDS)
.build();
okHttpClientBuilder.addInterceptor(interceptor).build();
}
if (apiToken != null && !apiToken.isEmpty()) {
okHttpClientBuilder.addInterceptor(new Interceptor() {
@NotNull
@Override
public okhttp3.Response intercept(@NotNull Chain chain) throws IOException {
Request original = chain.request();

Request request = original.newBuilder()
.header("Authorization", "Bearer "+apiToken)
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
}
String strRetries = System.getenv("KOIOS_JAVA_LIB_RETRIES_COUNT");
if (strRetries != null && !strRetries.isEmpty()) {
retriesCount = Math.max(Integer.parseInt(strRetries), 1);
}
String retryOnTimeoutEnv = System.getenv("KOIOS_JAVA_LIB_RETRY_ON_TIMEOUT");
if (retryOnTimeoutEnv != null && !Boolean.parseBoolean(retryOnTimeoutEnv)) {
retryOnTimeout = false;
}
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(okHttpClient).addConverterFactory(JacksonConverterFactory
retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(okHttpClientBuilder.build()).addConverterFactory(JacksonConverterFactory
.create(objectMapper)).build();
}

Expand Down Expand Up @@ -141,24 +157,24 @@ protected <T> Result<T> processResponse(Response<T> response) throws IOException
public Response<Object> execute(Call<?> call) throws ApiException, IOException {
int tryCount = 1;
while (tryCount <= retriesCount) {
if (getBucket().tryConsume(1)) {
try {
Response<Object> response = (Response<Object>) call.clone().execute();
if (response.code() == 429) {
log.warn("429 Too Many Requests.");
tryCount = retry(tryCount);
} else if (response.code() == 504) {
log.warn(response.message());
tryCount = retry(tryCount);
} else {
return response;
}
} catch (SocketTimeoutException e) {
log.warn(e.getMessage());
try {
Response<Object> response = (Response<Object>) call.clone().execute();
if (response.code() == 429) {
log.warn("429 Too Many Requests.");
tryCount = retry(tryCount);
} else if (response.code() == 504) {
log.warn(response.message());
tryCount = retry(tryCount);
} else {
return response;
}
} catch (SocketTimeoutException e) {
log.warn(e.getMessage());
if (retryOnTimeout) {
tryCount = retry(tryCount);
} else {
throw new ApiException("Timeout Error");
}
} else {
throw new ApiException("HTTP Error (429) - Too Many Requests.");
}
}
throw new ApiException("Retry Count Exceeded (" + tryCount + "/" + retriesCount + ").");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ public class BlockServiceImpl extends BaseService implements BlockService {
/**
* Block Service Implementation Constructor
*
* @param baseService Base Service
* @param baseUrl Base Url
* @param apiToken Authorization Bearer JWT Token
*/
public BlockServiceImpl(BaseService baseService) {
super(baseService);
public BlockServiceImpl(String baseUrl, String apiToken) {
super(baseUrl, apiToken);
blockApi = getRetrofit().create(BlockApi.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import rest.koios.client.backend.api.epoch.model.EpochBlockProtocols;
import rest.koios.client.backend.api.epoch.model.EpochInfo;
import rest.koios.client.backend.api.epoch.model.EpochParams;
import rest.koios.client.backend.api.network.api.NetworkApi;
import rest.koios.client.backend.api.network.model.Tip;
import rest.koios.client.backend.factory.options.Limit;
import rest.koios.client.backend.factory.options.Options;
import retrofit2.Call;
Expand All @@ -25,17 +23,16 @@
public class EpochServiceImpl extends BaseService implements EpochService {

private final EpochApi epochApi;
private final NetworkApi networkApi;

/**
* Epoch Service Implementation Constructor
*
* @param baseService Base Service
* @param baseUrl Base Url
* @param apiToken Authorization Bearer JWT Token
*/
public EpochServiceImpl(BaseService baseService) {
super(baseService);
public EpochServiceImpl(String baseUrl, String apiToken) {
super(baseUrl, apiToken);
epochApi = getRetrofit().create(EpochApi.class);
networkApi = getRetrofit().create(NetworkApi.class);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ public class NetworkServiceImpl extends BaseService implements NetworkService {
/**
* Network Service Implementation Constructor
*
* @param baseService Base Service
* @param baseUrl Base Url
* @param apiToken Authorization Bearer JWT Token
*/
public NetworkServiceImpl(BaseService baseService) {
super(baseService);
public NetworkServiceImpl(String baseUrl, String apiToken) {
super(baseUrl, apiToken);
networkApi = getRetrofit().create(NetworkApi.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ public class PoolServiceImpl extends BaseService implements PoolService {
/**
* Pool Service Implementation Constructor
*
* @param baseService Base Service
* @param baseUrl Base Url
* @param apiToken Authorization Bearer JWT Token
*/
public PoolServiceImpl(BaseService baseService) {
super(baseService);
public PoolServiceImpl(String baseUrl, String apiToken) {
super(baseUrl, apiToken);
poolApi = getRetrofit().create(PoolApi.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ public interface ScriptService {
*/
Result<List<NativeScript>> getNativeScriptList(Options options) throws ApiException;

/**
* Native Script by Script Hash
* Get Specific native script by script hash along with their creation transaction hashes
* <p><b>200</b> - native script and creation tx hash pairs
* <p><b>401</b> - The selected server has restricted the endpoint to be only usable via authentication. The authentication supplied was not authorized to access the endpoint
* <p><b>404</b> - The server does not recognise the combination of endpoint and parameters provided
*
* @param scriptHash Hash of a script
* @return Result of Type {@link NativeScript}
* @throws ApiException if an error occurs while attempting to invoke the API
*/
Result<NativeScript> getNativeScript(String scriptHash) throws ApiException;

/**
* Plutus Script List with Filtering, Pagination, Ordering Options
* List of all existing Plutus script hashes along with their creation transaction hashes
Expand Down
Loading

0 comments on commit 84b8f14

Please sign in to comment.