DCAv2GUI/app/src/main/java/com/example/dcav2gui/WorkerInterface.java

1169 lines
56 KiB
Java

package com.example.dcav2gui;
import static android.app.PendingIntent.getActivity;
import static com.example.dcav2gui.MainActivity.globalSettings;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Looper;
import android.text.InputType;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.Toast;
import java.io.IOException;
import java.util.Locale;
import com.example.dcav2gui.ui.exchanges.adapters.WorkerCardAdapter;
import com.example.dcav2gui.ui.home.HomeFragment;
import com.google.android.material.materialswitch.MaterialSwitch;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class WorkerInterface {
private static final String API_BASE_URL = globalSettings.apiUrl;
private static final String API_KEY = globalSettings.apiKey;
private static final OkHttpClient httpClient = new OkHttpClient();
public static InstanceInterface.WorkerStatsData getWorkerDetails(String exchange, String pair, boolean retry) throws IOException {
InstanceInterface.WorkerStatsData valueToReturn = null;
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Request workerStatsRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/worker_status?base="+base+"&quote="+quote)
.header("X-API-KEY", API_KEY)
.build();
try (Response workerStatsResponse = httpClient.newCall(workerStatsRequest).execute()) {
if (!workerStatsResponse.isSuccessful()) {
if (workerStatsResponse.code() == 503 && retry) {
return getWorkerDetails(exchange, pair,false);
}
throw new IOException("Unexpected code " + workerStatsResponse);
}
String workersStatsResponseBody = workerStatsResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(workersStatsResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return null;
}
JsonObject value = jsonObject.getAsJsonObject();
try {
boolean isShort = value.has("is_short") && value.get("is_short").isJsonPrimitive() && value.get("is_short").getAsBoolean();
boolean isBoosted = value.has("is_boosted") && value.get("is_boosted").isJsonPrimitive() && value.get("is_boosted").getAsBoolean();
boolean isPaused = value.has("is_paused") && value.get("is_paused").isJsonPrimitive() && value.get("is_paused").getAsBoolean();
boolean isAutoSwitchEnabled = value.has("autoswitch") && value.get("autoswitch").isJsonPrimitive() && value.get("autoswitch").getAsBoolean();
boolean stopWhenProfit = value.has("stop_when_profit") && value.get("stop_when_profit").isJsonPrimitive() && value.get("stop_when_profit").getAsBoolean();
double orderSize = value.has("order_size") && value.get("order_size").isJsonPrimitive() ? value.get("order_size").getAsDouble() : 0.0;
double quoteSpent = value.has("quote_spent") && value.get("quote_spent").isJsonPrimitive() ? value.get("quote_spent").getAsDouble() : 0.0;
double baseBought = value.has("base_bought") && value.get("base_bought").isJsonPrimitive() ? value.get("base_bought").getAsDouble() : 0.0;
int soAmount = value.has("so_amount") && value.get("so_amount").isJsonPrimitive() ? value.get("so_amount").getAsInt() : 0;
int numberOfSafetyOrders = value.has("no_of_safety_orders") && value.get("no_of_safety_orders").isJsonPrimitive() ? value.get("no_of_safety_orders").getAsInt() : 0;
int tpMode = value.has("tp_mode") && value.get("tp_mode").isJsonPrimitive() ? value.get("tp_mode").getAsInt() : 0;
String profitTable = value.has("profit_table") && value.get("profit_table").isJsonPrimitive() ? value.get("profit_table").getAsString() : null;
double startTime = value.has("start_time") && value.get("start_time").isJsonPrimitive() ? value.get("start_time").getAsDouble() : 0.0;
double startPrice = value.has("start_price") && value.get("start_price").isJsonPrimitive() ? value.get("start_price").getAsDouble() : 0.0;
double dealStartTime = value.has("deal_start_time") && value.get("deal_start_time").isJsonPrimitive() ? value.get("deal_start_time").getAsDouble() : 0.0;
double dealUptime = value.has("deal_uptime") && value.get("deal_uptime").isJsonPrimitive() ? value.get("deal_uptime").getAsDouble() : 0.0;
double totalUptime = value.has("total_uptime") && value.get("total_uptime").isJsonPrimitive() ? value.get("total_uptime").getAsDouble() : 0.0;
double price = value.has("price") && value.get("price").isJsonPrimitive() ? value.get("price").getAsDouble() : 0.0;
double takeProfitPrice = value.has("take_profit_price") && value.get("take_profit_price").isJsonPrimitive() ? value.get("take_profit_price").getAsDouble() : 0.0;
double nextSoPrice = value.has("next_so_price") && value.get("next_so_price").isJsonPrimitive() ? value.get("next_so_price").getAsDouble() : 0.0;
JsonObject takeProfitOrder = value.get("take_profit_order").getAsJsonObject();
JsonObject safetyOrder = value.get("safety_order").getAsJsonObject();
String tpOrderId = takeProfitOrder.has("id") && takeProfitOrder.get("id").isJsonPrimitive() ? takeProfitOrder.get("id").getAsString() : null;
String safetyOrderId = safetyOrder.has("id") && safetyOrder.get("id").isJsonPrimitive() ? safetyOrder.get("id").getAsString() : null;
double feesPaidInBase = value.has("fees_paid_in_base") && value.get("fees_paid_in_base").isJsonPrimitive() ? value.get("fees_paid_in_base").getAsDouble() : 0.0;
double feesPaidInQuote = value.has("fees_paid_in_quote") && value.get("fees_paid_in_quote").isJsonPrimitive() ? value.get("fees_paid_in_quote").getAsDouble() : 0.0;
double partialProfit = value.has("partial_profit") && value.get("partial_profit").isJsonPrimitive() ? value.get("partial_profit").getAsDouble() : 0.0;
String safetyPriceTable = value.has("safety_price_table") && value.get("safety_price_table").isJsonPrimitive() ? value.get("safety_price_table").getAsString() : null;
String dealOrderHistory = value.has("deal_order_history") && value.get("deal_order_history").isJsonPrimitive() ? value.get("deal_order_history").getAsString() : null;
String pauseReason = value.has("pause_reason") && value.get("pause_reason").isJsonPrimitive() ? value.get("pause_reason").getAsString() : null;
String statusString = value.has("status_string") && value.get("status_string").isJsonPrimitive() ? value.get("status_string").getAsString() : null;
JsonObject oldLong;
InstanceInterface.OldLongDictionary oldLongDictionary = null;
if (value.has("old_long")) {
oldLong = value.get("old_long").getAsJsonObject();
if (!oldLong.entrySet().isEmpty()) {
oldLongDictionary = new InstanceInterface.OldLongDictionary(
oldLong.get("datetime").getAsString(),
oldLong.get("fees_paid_in_quote").getAsDouble(),
oldLong.get("quote_spent").getAsDouble(),
oldLong.get("tp_amount").getAsDouble(),
oldLong.get("tp_price").getAsDouble()
);
}
}
valueToReturn = new InstanceInterface.WorkerStatsData(
pair,
isShort,
isBoosted,
isPaused,
isAutoSwitchEnabled,
stopWhenProfit,
orderSize,
quoteSpent,
baseBought,
soAmount,
numberOfSafetyOrders,
tpMode,
profitTable,
startTime,
startPrice,
dealStartTime,
dealUptime,
totalUptime,
price,
takeProfitPrice,
nextSoPrice,
tpOrderId,
takeProfitOrder,
safetyOrderId,
safetyOrder,
feesPaidInBase,
feesPaidInQuote,
partialProfit,
safetyPriceTable,
dealOrderHistory,
pauseReason,
oldLongDictionary,
statusString);
} catch (Exception e) {
System.err.println("Error processing JSON for key '" + pair + "': " + e.getMessage());
}
}
return valueToReturn;
}
public static JsonObject addTrader(String exchange, String pair, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request addTraderRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/add_pair")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response addTraderResponse = httpClient.newCall(addTraderRequest).execute()) {
if (!addTraderResponse.isSuccessful()) {
if (addTraderResponse.code() == 503 && retry) {
return addTrader(exchange, pair, false);
}
throw new IOException("Unexpected code " + addTraderResponse);
}
String addTraderResponseBody = addTraderResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(addTraderResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Pair added"}
return jsonObject;
}
}
public static JsonObject removeTrader(String exchange, String pair, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request removeTraderRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/remove_pair")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response removeTraderResponse = httpClient.newCall(removeTraderRequest).execute()) {
if (!removeTraderResponse.isSuccessful()) {
if (removeTraderResponse.code() == 503 && retry) {
return removeTrader(exchange, pair, false);
}
throw new IOException("Unexpected code " + removeTraderResponse);
}
String removeTraderResponseBody = removeTraderResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(removeTraderResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Pair to be removed"}
return jsonObject;
}
}
public static JsonObject restartTrader(String exchange, String pair, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request restartTraderRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/restart_pair")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response restartTraderResponse = httpClient.newCall(restartTraderRequest).execute()) {
if (!restartTraderResponse.isSuccessful()) {
if (restartTraderResponse.code() == 503 && retry) {
return restartTrader(exchange, pair, false);
}
throw new IOException("Unexpected code " + restartTraderResponse);
}
String restartTraderResponseBody = restartTraderResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(restartTraderResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Pair restarted"}
return jsonObject;
}
}
public static JsonObject importTrader(String exchange, String pair, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request importTraderRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/import_pair")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response importTraderResponse = httpClient.newCall(importTraderRequest).execute()) {
if (!importTraderResponse.isSuccessful()) {
if (importTraderResponse.code() == 503 && retry) {
return importTrader(exchange, pair, false);
}
throw new IOException("Unexpected code " + importTraderResponse);
}
String importTraderResponseBody = importTraderResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(importTraderResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Pair imported successfully"}
return jsonObject;
}
}
public static JsonObject togglePause(String exchange, String pair, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request togglePauseRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/toggle_pause")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response togglePauseResponse = httpClient.newCall(togglePauseRequest).execute()) {
if (!togglePauseResponse.isSuccessful()) {
if (togglePauseResponse.code() == 503 && retry) {
return togglePause(exchange, pair, false);
}
throw new IOException("Unexpected code " + togglePauseResponse);
}
String togglePauseResponseBody = togglePauseResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(togglePauseResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Trader will be paused"} or {"Success":"Trader will be resumed"}
return jsonObject;
}
}
public static JsonObject toggleAutoswitch(String exchange, String pair, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request toggleAutoswitchRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/toggle_autoswitch")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response toggleAutoswitchResponse = httpClient.newCall(toggleAutoswitchRequest).execute()) {
if (!toggleAutoswitchResponse.isSuccessful()) {
if (toggleAutoswitchResponse.code() == 503 && retry) {
return toggleAutoswitch(exchange, pair, false);
}
throw new IOException("Unexpected code " + toggleAutoswitchResponse);
}
String toggleAutoswitchResponseBody = toggleAutoswitchResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(toggleAutoswitchResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Autoswitch is now ON"} or {"Success":"Autoswitch is now OFF"}
return jsonObject;
}
}
public static JsonObject toggleCleanup(String exchange, String pair, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request toggleCleanupRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/toggle_cleanup")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response toggleCleanupResponse = httpClient.newCall(toggleCleanupRequest).execute()) {
if (!toggleCleanupResponse.isSuccessful()) {
if (toggleCleanupResponse.code() == 503 && retry) {
return toggleCleanup(exchange, pair, false);
}
throw new IOException("Unexpected code " + toggleCleanupResponse);
}
String toggleCleanupResponseBody = toggleCleanupResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(toggleCleanupResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Cleanup turned ON"} or {"Success":"Cleanup turned OFF"}
return jsonObject;
}
}
public static JsonObject toggleLastCall(String exchange, String pair, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request toggleLastCallRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/last_call")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response toggleLastCallResponse = httpClient.newCall(toggleLastCallRequest).execute()) {
if (!toggleLastCallResponse.isSuccessful()) {
if (toggleLastCallResponse.code() == 503 && retry) {
return toggleLastCall(exchange, pair, false);
}
throw new IOException("Unexpected code " + toggleLastCallResponse);
}
String toggleLastCallResponseBody = toggleLastCallResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(toggleLastCallResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Trader scheduled to go offline when profit is reached"} or {"Success":"Last call cancelled"}
return jsonObject;
}
}
public static JsonObject switchToLong(String exchange, String pair, boolean calculateProfits, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
String profits = "0";
if (calculateProfits) {
profits = "1";
}
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
jsonPayload.addProperty("calculate_profits", profits);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request switchToLongRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/switch_to_long")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response switchToLongResponse = httpClient.newCall(switchToLongRequest).execute()) {
if (!switchToLongResponse.isSuccessful()) {
if (switchToLongResponse.code() == 503 && retry) {
return switchToLong(exchange, pair, calculateProfits,false);
}
throw new IOException("Unexpected code " + switchToLongResponse);
}
String switchToLongResponseBody = switchToLongResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(switchToLongResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Pair switched to long mode"}
return jsonObject;
}
}
public static JsonObject switchToShort(String exchange, String pair, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request switchToShortRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/switch_to_short")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response switchToShortResponse = httpClient.newCall(switchToShortRequest).execute()) {
if (!switchToShortResponse.isSuccessful()) {
if (switchToShortResponse.code() == 503 && retry) {
return switchToShort(exchange, pair, false);
}
throw new IOException("Unexpected code " + switchToShortResponse);
}
String switchToShortResponseBody = switchToShortResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(switchToShortResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Pair switched to short mode"}
return jsonObject;
}
}
public static JsonObject switchQuoteCurrency(String exchange, String pair, String targetQuoteCurrency, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
jsonPayload.addProperty("new_quote", targetQuoteCurrency);
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request switchQuoteCurrencyRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/switch_quote_currency")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response switchQuoteCurrencyResponse = httpClient.newCall(switchQuoteCurrencyRequest).execute()) {
if (!switchQuoteCurrencyResponse.isSuccessful()) {
if (switchQuoteCurrencyResponse.code() == 503 && retry) {
return switchQuoteCurrency(exchange, pair, targetQuoteCurrency,false);
}
throw new IOException("Unexpected code " + switchQuoteCurrencyResponse);
}
String switchQuoteCurrencyResponseBody = switchQuoteCurrencyResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(switchQuoteCurrencyResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Mission successful"}
return jsonObject;
}
}
public static JsonObject addSafetyOrders(String exchange, String pair, int amount, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
jsonPayload.addProperty("amount", String.valueOf(amount));
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request addSafetyOrdersRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/add_so")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response addSafetyOrdersResponse = httpClient.newCall(addSafetyOrdersRequest).execute()) {
if (!addSafetyOrdersResponse.isSuccessful()) {
if (addSafetyOrdersResponse.code() == 503 && retry) {
return addSafetyOrders(exchange, pair, amount,false);
}
throw new IOException("Unexpected code " + addSafetyOrdersResponse);
}
String addSafetyOrdersResponseBody = addSafetyOrdersResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(addSafetyOrdersResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Added $amount safety orders"}
return jsonObject;
}
}
public static JsonObject addQuote(String exchange, String pair, double amount, boolean retry) throws IOException {
String[] pairBaseAndQuote = pair.split("/");
String base = pairBaseAndQuote[0];
String quote = pairBaseAndQuote[1];
Gson gson = new Gson();
JsonObject jsonPayload = new JsonObject();
jsonPayload.addProperty("base", base);
jsonPayload.addProperty("quote", quote);
jsonPayload.addProperty("amount", String.valueOf(amount));
String jsonPayloadString = gson.toJson(jsonPayload);
RequestBody requestBody = RequestBody.create(jsonPayloadString, MediaType.get("application/json; charset=utf-8"));
Request addQuoteRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/add_quote")
.header("X-API-KEY", API_KEY)
.post(requestBody)
.build();
try (Response addQuoteResponse = httpClient.newCall(addQuoteRequest).execute()) {
if (!addQuoteResponse.isSuccessful()) {
if (addQuoteResponse.code() == 503 && retry) {
return addQuote(exchange, pair, amount,false);
}
throw new IOException("Unexpected code " + addQuoteResponse);
}
String addQuoteResponseBody = addQuoteResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(addQuoteResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return null;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("Error")) {
System.err.println("The parsed JSON response contains Error");
return jsonObject;
}
//If no error, the response is {"Success":"Quote added successfully"}
return jsonObject;
}
}
public static void showToggleDialog(JsonObject result, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
for (String key: result.keySet()) {
builder.setTitle(key);
builder.setMessage(result.get(key).getAsString());
}
builder.setPositiveButton("OK", null);
builder.show();
}
public static void sendTogglePause(String exchange, String pair, Context context) {
new Thread(() -> {
try {
JsonObject result = togglePause(exchange, pair, true);
new Handler(Looper.getMainLooper()).post(() -> WorkerInterface.showToggleDialog(result, context));
} catch (IOException e) {
e.printStackTrace();
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context, "Failed to toggle pause", Toast.LENGTH_SHORT).show());
}
}).start();
}
public static void sendToggleAutoswitch(String exchange, String pair, Context context) {
new Thread(() -> {
try {
JsonObject result = toggleAutoswitch(exchange, pair, true);
new Handler(Looper.getMainLooper()).post(() -> WorkerInterface.showToggleDialog(result, context));
} catch (IOException e) {
e.printStackTrace();
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context, "Failed to toggle autoswitch", Toast.LENGTH_SHORT).show());
}
}).start();
}
public static void sendToggleCleanup(String exchange, String pair, Context context) {
new Thread(() -> {
try {
JsonObject result = toggleCleanup(exchange, pair, true);
new Handler(Looper.getMainLooper()).post(() -> WorkerInterface.showToggleDialog(result, context));
} catch (IOException e) {
e.printStackTrace();
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context, "Failed to toggle cleanup", Toast.LENGTH_SHORT).show());
}
}).start();
}
public static void sendToggleLastCall(String exchange, String pair, Context context) {
new Thread(() -> {
try {
JsonObject result = toggleLastCall(exchange, pair, true);
new Handler(Looper.getMainLooper()).post(() -> WorkerInterface.showToggleDialog(result, context));
} catch (IOException e) {
e.printStackTrace();
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context, "Failed to toggle last call", Toast.LENGTH_SHORT).show());
}
}).start();
}
public static void sendSwitchToLongCall(String exchange, String pair, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Switch "+ pair + " to long mode?");
builder.setPositiveButton("Switch to long", (dialog, which) -> {
new Thread(() -> {
try {
JsonObject response = WorkerInterface.switchToLong(exchange, pair, true,true);
new Handler(Looper.getMainLooper()).post(() -> {
showToggleDialog(response, context);
});
} catch (IOException e) {
e.printStackTrace();
// Show an error dialog on the main thread
new Handler(Looper.getMainLooper()).post(() -> {
AlertDialog.Builder errorBuilder = new AlertDialog.Builder(context);
errorBuilder.setTitle("Error");
errorBuilder.setMessage("Failed to switch to long: " + e.getMessage());
errorBuilder.setPositiveButton("OK", null);
errorBuilder.show();
});
}
}).start();
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
public static void sendSwitchToShortCall(String exchange, String pair, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Switch "+ pair + " to short mode?");
builder.setPositiveButton("Switch to short", (dialog, which) -> {
new Thread(() -> {
try {
JsonObject response = WorkerInterface.switchToShort(exchange, pair, true);
new Handler(Looper.getMainLooper()).post(() -> {
showToggleDialog(response, context);
});
} catch (IOException e) {
e.printStackTrace();
// Show an error dialog on the main thread
new Handler(Looper.getMainLooper()).post(() -> {
AlertDialog.Builder errorBuilder = new AlertDialog.Builder(context);
errorBuilder.setTitle("Error");
errorBuilder.setMessage("Failed to switch to short: " + e.getMessage());
errorBuilder.setPositiveButton("OK", null);
errorBuilder.show();
});
}
}).start();
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
public static void sendAddTraderCall(String exchange, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Enter pair to add to "+ exchange);
final EditText input = new EditText(context);
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
builder.setView(input);
builder.setPositiveButton("Add", (dialog, which) -> {
final String pair = input.getText().toString();
new Thread(() -> {
try {
JsonObject response = WorkerInterface.addTrader(exchange, pair, true);
new Handler(Looper.getMainLooper()).post(() -> {
showToggleDialog(response, context);
});
} catch (IOException e) {
e.printStackTrace();
// Show an error dialog on the main thread
new Handler(Looper.getMainLooper()).post(() -> {
AlertDialog.Builder errorBuilder = new AlertDialog.Builder(context);
errorBuilder.setTitle("Error");
errorBuilder.setMessage("Failed to add trader: " + e.getMessage());
errorBuilder.setPositiveButton("OK", null);
errorBuilder.show();
});
}
}).start();
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
public static void sendRemoveTraderCall(String exchange, String pair, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Remove "+ pair + " from instance?");
builder.setPositiveButton("Remove trader", (dialog, which) -> {
new Thread(() -> {
try {
JsonObject response = WorkerInterface.removeTrader(exchange, pair, true);
new Handler(Looper.getMainLooper()).post(() -> {
showToggleDialog(response, context);
});
} catch (IOException e) {
e.printStackTrace();
// Show an error dialog on the main thread
new Handler(Looper.getMainLooper()).post(() -> {
AlertDialog.Builder errorBuilder = new AlertDialog.Builder(context);
errorBuilder.setTitle("Error");
errorBuilder.setMessage("Failed to remove trader: " + e.getMessage());
errorBuilder.setPositiveButton("OK", null);
errorBuilder.show();
});
}
}).start();
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
public static void sendRestartTraderCall(String exchange, String pair, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Restart "+ pair + "?");
builder.setPositiveButton("Restart trader", (dialog, which) -> {
new Thread(() -> {
try {
JsonObject response = WorkerInterface.restartTrader(exchange, pair, true);
new Handler(Looper.getMainLooper()).post(() -> {
showToggleDialog(response, context);
});
} catch (IOException e) {
e.printStackTrace();
// Show an error dialog on the main thread
new Handler(Looper.getMainLooper()).post(() -> {
AlertDialog.Builder errorBuilder = new AlertDialog.Builder(context);
errorBuilder.setTitle("Error");
errorBuilder.setMessage("Failed to restart trader: " + e.getMessage());
errorBuilder.setPositiveButton("OK", null);
errorBuilder.show();
});
}
}).start();
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
public static void sendImportTraderCall(String exchange, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Enter pair to import to "+ exchange);
final EditText input = new EditText(context);
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
builder.setView(input);
builder.setPositiveButton("Import", (dialog, which) -> {
final String pair = input.getText().toString();
new Thread(() -> {
try {
JsonObject response = WorkerInterface.importTrader(exchange, pair, true);
new Handler(Looper.getMainLooper()).post(() -> {
showToggleDialog(response, context);
});
} catch (IOException e) {
e.printStackTrace();
// Show an error dialog on the main thread
new Handler(Looper.getMainLooper()).post(() -> {
AlertDialog.Builder errorBuilder = new AlertDialog.Builder(context);
errorBuilder.setTitle("Error");
errorBuilder.setMessage("Failed to import trader: " + e.getMessage());
errorBuilder.setPositiveButton("OK", null);
errorBuilder.show();
});
}
}).start();
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
public static void sendSwitchQuoteCurrencyCall(String exchange, String pair, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Enter new quote currency of"+ pair);
final EditText input = new EditText(context);
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
builder.setView(input);
builder.setPositiveButton("Change quote currency", (dialog, which) -> {
final String newQuoteCurrency = input.getText().toString();
new Thread(() -> {
try {
JsonObject response = WorkerInterface.switchQuoteCurrency(exchange, pair, newQuoteCurrency,true);
new Handler(Looper.getMainLooper()).post(() -> {
showToggleDialog(response, context);
});
} catch (IOException e) {
e.printStackTrace();
// Show an error dialog on the main thread
new Handler(Looper.getMainLooper()).post(() -> {
AlertDialog.Builder errorBuilder = new AlertDialog.Builder(context);
errorBuilder.setTitle("Error");
errorBuilder.setMessage("Failed to switch quote currency: " + e.getMessage());
errorBuilder.setPositiveButton("OK", null);
errorBuilder.show();
});
}
}).start();
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
public static void sendAddSafetyOrdersCall(String exchange, String pair, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Add safety orders to "+ pair);
final EditText input = new EditText(context);
input.setInputType(InputType.TYPE_CLASS_NUMBER);
input.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
builder.setView(input);
builder.setPositiveButton("Add safety orders", (dialog, which) -> {
final int amountToAdd = Integer.parseInt(input.getText().toString());
new Thread(() -> {
try {
JsonObject response = WorkerInterface.addSafetyOrders(exchange, pair, amountToAdd,true);
new Handler(Looper.getMainLooper()).post(() -> {
showToggleDialog(response, context);
});
} catch (IOException e) {
e.printStackTrace();
// Show an error dialog on the main thread
new Handler(Looper.getMainLooper()).post(() -> {
AlertDialog.Builder errorBuilder = new AlertDialog.Builder(context);
errorBuilder.setTitle("Error");
errorBuilder.setMessage("Failed to add safety orders: " + e.getMessage());
errorBuilder.setPositiveButton("OK", null);
errorBuilder.show();
});
}
}).start();
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
public static void sendAddQuoteCall(String exchange, String pair, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Add quote currency to "+ pair);
final EditText input = new EditText(context);
input.setInputType(InputType.TYPE_CLASS_NUMBER);
input.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
builder.setView(input);
builder.setPositiveButton("Add quote", (dialog, which) -> {
final double amountToAdd = Double.parseDouble(input.getText().toString());
new Thread(() -> {
try {
JsonObject response = WorkerInterface.addQuote(exchange, pair, amountToAdd,true);
new Handler(Looper.getMainLooper()).post(() -> {
showToggleDialog(response, context);
});
} catch (IOException e) {
e.printStackTrace();
// Show an error dialog on the main thread
new Handler(Looper.getMainLooper()).post(() -> {
AlertDialog.Builder errorBuilder = new AlertDialog.Builder(context);
errorBuilder.setTitle("Error");
errorBuilder.setMessage("Failed to add quote currency: " + e.getMessage());
errorBuilder.setPositiveButton("OK", null);
errorBuilder.show();
});
}
}).start();
});
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
builder.show();
}
public static void fetchWorkerStats(String exchange, String pair, Context context) {
new Thread(() -> {
try {
InstanceInterface.WorkerStatsData result = WorkerInterface.getWorkerDetails(exchange, pair, true);
new Handler(Looper.getMainLooper()).post(() -> WorkerInterface.showWorkerDetailsDialog(result, context));
} catch (IOException e) {
e.printStackTrace();
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context, "Failed to fetch exchange config", Toast.LENGTH_SHORT).show());
}
}).start();
}
public static void showWorkerDetailsDialog(InstanceInterface.WorkerStatsData result, Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
int priceDecimals = countDecimalPlaces(result.getPrice());
String numberFormat = "%." + priceDecimals + "f";
builder.setTitle(result.getPair() + " status");
String isPausedExtraString = "";
if (result.getIsPaused()) {
isPausedExtraString = "Pause reason: " + result.getPauseReason() + "\n";
}
String oldLongExtraString = "";
if (result.getIsShort() && result.getOldLongDictionary()!=null) {
double oldTarget = result.getOldLongDictionary().getTpAmount() * result.getOldLongDictionary().getTpPrice();
double baseLeft = result.getOldLongDictionary().getTpAmount() - result.getBaseBought();
double minSwitchPrice = (oldTarget - result.getQuoteSpent()) / baseLeft;
oldLongExtraString = "\nOLD LONG:\n" +
"Switch date: " + result.getOldLongDictionary().getDatetime() + "\n" +
"Amount of base in the deal: " + result.getOldLongDictionary().getTpAmount() + "\n" +
"Take profit price: " + String.format(Locale.ROOT, numberFormat,result.getOldLongDictionary().getTpPrice()) + "\n" +
"Switch price: " + String.format(Locale.ROOT, numberFormat, minSwitchPrice) + "\n" +
"Quote spent: " + result.getOldLongDictionary().getQuoteSpent() + "\n" +
"Fees paid in quote: " + result.getOldLongDictionary().getFeesPaidInQuote();
}
builder.setMessage("Price: " + result.getPrice() + "\n" +
"Take profit price: " + String.format(Locale.ROOT, numberFormat,result.getTakeProfitPrice()) + "\n" +
"Next safety order price: " + String.format(Locale.ROOT, numberFormat,result.getNextSoPrice()) + "\n" +
"Take profit order ID: " + result.getTpOrderId() + "\n" +
"Safety order ID: " + result.getSoOrderId() + "\n" +
"Short: " + result.getIsShort() + "\n" +
"Boosted: " + result.getIsBoosted() + "\n" +
"Paused: " + result.getIsPaused() + "\n" + isPausedExtraString +
"Autoswitch: " + result.getAutoSwitchEnabled() + "\n" +
"Last call: " + result.getStopWhenProfit() + "\n" +
"Order size: " + result.getOrderSize() + "\n" +
"Quote in deal: " + result.getQuoteSpent() + "\n" +
"Base in deal: " + result.getBaseBought() + "\n" +
"Safety orders sent: " + (result.getSoAmount()-1) + "\n" +
"Max safety orders: " + result.getNumberOfSafetyOrders() + "\n" +
"Start time: " + HomeFragment.timeStampConverter(result.getStartTime(), false) + "\n" +
"Total uptime: " + WorkerCardAdapter.formatSeconds(result.getTotalUptime()) + "\n" +
"Start price: " + String.format(Locale.ROOT, numberFormat,result.getStartPrice()) + "\n" +
"Deal start time: " + HomeFragment.timeStampConverter(result.getDealStartTime(), false) + "\n" +
"Deal uptime: " + WorkerCardAdapter.formatSeconds(result.getDealUptime()) + "\n" +
"Fees paid in base: " + result.getFeesPaidInBase() + "\n" +
"Fees paid in quote: " + result.getFeesPaidInQuote() + "\n" +
"Partial profit: " + result.getPartialProfit() + "\n" +
oldLongExtraString);
builder.setPositiveButton("OK", null);
builder.show();
}
public static int countDecimalPlaces(double number) {
String numberStr = String.valueOf(number);
int decimalIndex = numberStr.indexOf('.');
// If there are no decimals, return 0
if (decimalIndex == -1) {
return 0;
}
return numberStr.length() - decimalIndex - 1;
}
}