iota.lib.java/src/main/java/jota/IotaAPICore.java
2017-02-18 20:37:26 +01:00

299 lines
10 KiB
Java

package jota;
import jota.dto.request.*;
import jota.dto.response.*;
import jota.error.InvalidTrytesException;
import jota.utils.InputValidator;
import okhttp3.OkHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
/**
* This class provides access to the Iota core API
*
* @author Adrian
*/
public class IotaAPICore {
private static final Logger log = LoggerFactory.getLogger(IotaAPICore.class);
private IotaAPIService service;
private String protocol, host, port;
/**
* Build the API core.
*
* @param builder The builder.
*/
protected IotaAPICore(final Builder builder) {
protocol = builder.protocol;
host = builder.host;
port = builder.port;
postConstruct();
}
/**
* @param call
* @param <T>
* @return
*/
protected static <T> Response<T> wrapCheckedException(final Call<T> call) {
try {
final Response<T> res = call.execute();
if (res.code() == 400) {
throw new IllegalAccessError("400 " + res.errorBody().string());
} else if (res.code() == 401) {
throw new IllegalAccessError("401 " + res.errorBody().string());
} else if (res.code() == 500) {
throw new IllegalAccessError("500 " + res.errorBody().string());
}
return res;
} catch (IOException e) {
log.error("Execution of the API call raised exception. IOTA Node not reachable?", e);
throw new IllegalStateException(e.getMessage());
}
}
/**
* @param env
* @param def
* @return
*/
private static String env(String env, String def) {
final String value = System.getenv(env);
if (value == null) {
log.warn("Environment variable '{}' is not defined, and actual value has not been specified. "
+ "Rolling back to default value: '{}'", env, def);
return def;
}
return value;
}
/**
*
*/
private void postConstruct() {
final String nodeUrl = protocol + "://" + host + ":" + port;
final OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(5000, TimeUnit.SECONDS)
.connectTimeout(5000, TimeUnit.SECONDS)
.build();
final Retrofit retrofit = new Retrofit.Builder()
.baseUrl(nodeUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
service = retrofit.create(IotaAPIService.class);
log.debug("Jota-API Java proxy pointing to node url: '{}'", nodeUrl);
}
public GetNodeInfoResponse getNodeInfo() {
final Call<GetNodeInfoResponse> res = service.getNodeInfo(IotaCommandRequest.createNodeInfoRequest());
return wrapCheckedException(res).body();
}
public GetNeighborsResponse getNeighbors() {
final Call<GetNeighborsResponse> res = service.getNeighbors(IotaCommandRequest.createGetNeighborsRequest());
return wrapCheckedException(res).body();
}
public AddNeighborsResponse addNeighbors(String... uris) {
final Call<AddNeighborsResponse> res = service.addNeighbors(IotaNeighborsRequest.createAddNeighborsRequest(uris));
return wrapCheckedException(res).body();
}
public RemoveNeighborsResponse removeNeighbors(String... uris) {
final Call<RemoveNeighborsResponse> res = service.removeNeighbors(IotaNeighborsRequest.createRemoveNeighborsRequest(uris));
return wrapCheckedException(res).body();
}
public GetTipsResponse getTips() {
final Call<GetTipsResponse> res = service.getTips(IotaCommandRequest.createGetTipsRequest());
return wrapCheckedException(res).body();
}
public FindTransactionResponse findTransactions(String[] addresses, String[] tags, String[] approvees, String[] bundles) {
final IotaFindTransactionsRequest findTransRequest = IotaFindTransactionsRequest
.createFindTransactionRequest()
.byAddresses(addresses)
.byTags(tags)
.byApprovees(approvees)
.byBundles(bundles);
final Call<FindTransactionResponse> res = service.findTransactions(findTransRequest);
return wrapCheckedException(res).body();
}
public FindTransactionResponse findTransactionsByAddresses(final String... addresses) {
return findTransactions(addresses, null, null, null);
}
public FindTransactionResponse findTransactionsByBundles(final String... bundles) {
return findTransactions(null, null, null, bundles);
}
public FindTransactionResponse findTransactionsByApprovees(final String... approvees) {
return findTransactions(null, null, approvees, null);
}
public FindTransactionResponse findTransactionsByDigests(final String... digests) {
return findTransactions(null, digests, null, null);
}
public GetInclusionStateResponse getInclusionStates(String[] transactions, String[] tips) {
final Call<GetInclusionStateResponse> res = service.getInclusionStates(IotaGetInclusionStateRequest
.createGetInclusionStateRequest(transactions, tips));
return wrapCheckedException(res).body();
}
public GetTrytesResponse getTrytes(String... hashes) {
final Call<GetTrytesResponse> res = service.getTrytes(IotaGetTrytesRequest.createGetTrytesRequest(hashes));
return wrapCheckedException(res).body();
}
public GetTransactionsToApproveResponse getTransactionsToApprove(Integer depth) {
final Call<GetTransactionsToApproveResponse> res = service.getTransactionsToApprove(IotaGetTransactionsToApproveRequest.createIotaGetTransactionsToApproveRequest(depth));
return wrapCheckedException(res).body();
}
public GetBalancesResponse getBalances(Integer threshold, String[] addresses) {
final Call<GetBalancesResponse> res = service.getBalances(IotaGetBalancesRequest.createIotaGetBalancesRequest(threshold, addresses));
return wrapCheckedException(res).body();
}
public GetBalancesResponse getBalances(Integer threshold, List<String> addresses) {
return getBalances(threshold, addresses.toArray(new String[]{}));
}
public InterruptAttachingToTangleResponse interruptAttachingToTangle() {
final Call<InterruptAttachingToTangleResponse> res = service.interruptAttachingToTangle(IotaCommandRequest.createInterruptAttachToTangleRequest());
return wrapCheckedException(res).body();
}
public GetAttachToTangleResponse attachToTangle(String trunkTransaction, String branchTransaction, Integer minWeightMagnitude, String... trytes) throws InvalidTrytesException {
if (!InputValidator.isArrayOfTrytes(trytes)) {
throw new InvalidTrytesException();
}
final Call<GetAttachToTangleResponse> res = service.attachToTangle(IotaAttachToTangleRequest.createAttachToTangleRequest(trunkTransaction, branchTransaction, minWeightMagnitude, trytes));
return wrapCheckedException(res).body();
}
public StoreTransactionsResponse storeTransactions(String... trytes) {
final Call<StoreTransactionsResponse> res = service.storeTransactions(IotaStoreTransactionsRequest.createStoreTransactionsRequest(trytes));
return wrapCheckedException(res).body();
}
public BroadcastTransactionsResponse broadcastTransactions(String... trytes) {
final Call<BroadcastTransactionsResponse> res = service.broadcastTransactions(IotaBroadcastTransactionRequest.createBroadcastTransactionsRequest(trytes));
return wrapCheckedException(res).body();
}
@SuppressWarnings("unchecked")
public static class Builder<T extends Builder<T>> {
String protocol, host, port;
public IotaAPICore build() {
if (protocol == null || host == null || port == null) {
// check properties files.
if (!checkPropertiesFiles()) {
// last resort: best effort on enviroment variable,
// before assigning default values.
checkEnviromentVariables();
}
}
return new IotaAPICore(this);
}
/**
* @return
*/
private boolean checkPropertiesFiles() {
try {
FileReader fileReader = new FileReader("node_config.properties");
BufferedReader bufferedReader = new BufferedReader(fileReader);
final Properties nodeConfig = new Properties();
nodeConfig.load(bufferedReader);
if (nodeConfig.getProperty("iota.node.protocol") != null) {
protocol = nodeConfig.getProperty("iota.node.protocol");
}
if (nodeConfig.getProperty("iota.node.host") != null) {
host = nodeConfig.getProperty("iota.node.host");
}
if (nodeConfig.getProperty("iota.node.port") != null) {
port = nodeConfig.getProperty("iota.node.port");
}
} catch (IOException e1) {
log.debug("node_config.properties not found. Rolling back for another solution...");
}
return (port != null && protocol != null && host != null);
}
/**
*
*/
private void checkEnviromentVariables() {
protocol = env("IOTA_NODE_PROTOCOL", "http");
host = env("IOTA_NODE_HOST", "localhost");
port = env("IOTA_NODE_PORT", "14265");
}
/**
* @param host
* @return
*/
public T host(String host) {
this.host = host;
return (T) this;
}
/**
* @param port
* @return
*/
public T port(String port) {
this.port = port;
return (T) this;
}
/**
* @param protocol
* @return
*/
public T protocol(String protocol) {
this.protocol = protocol;
return (T) this;
}
}
}