Compare commits

...

10 Commits

11 changed files with 123 additions and 17 deletions

View File

@ -16,6 +16,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import okhttp3.OkHttpClient;
@ -26,6 +27,7 @@ import okhttp3.Response;
public class InstanceInterface {
private static final String API_BASE_URL = globalSettings.apiUrl;
private static final String API_KEY = globalSettings.apiKey;
private static final String EARN_API_KEY = globalSettings.earnApiKey;
private static final OkHttpClient httpClient = new OkHttpClient();
public static ProfitStatsData getProfitStatsData(boolean retry) throws IOException {
@ -443,7 +445,11 @@ public class InstanceInterface {
});
CompletableFuture<Double> fundsAvailableFuture = CompletableFuture.supplyAsync(() -> {
try {
if (globalSettings.useEarn) {
return getFundsAvailableWithEarn(exchange,"USDT", true);
} else {
return getFundsAvailable(exchange,"USDT", true);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -491,6 +497,40 @@ public class InstanceInterface {
}
private static double getFundsAvailableWithEarn(String exchange, String coin, boolean retry) throws IOException {
String parsedBroker = exchange;
if (Objects.equals(parsedBroker, "okex")) {
parsedBroker = "okx";
}
Request fundsRequest = new Request.Builder()
.url(API_BASE_URL + "/earn/get_total_balance?broker=" + parsedBroker)
.header("X-API-KEY", EARN_API_KEY)
.build();
try (Response fundsResponse = httpClient.newCall(fundsRequest).execute()) {
if (!fundsResponse.isSuccessful()) {
if (fundsResponse.code() == 503 && retry) {
return getFundsAvailableWithEarn(exchange, coin, false);
}
throw new IOException("Unexpected code " + fundsResponse);
}
String fundsResponseBody = fundsResponse.body().string();
JsonElement jsonElement = JsonParser.parseString(fundsResponseBody);
if (!jsonElement.isJsonObject()) {
System.err.println("The parsed JSON response is not a JsonObject.");
return 0.0;
}
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (!jsonObject.has("trading_balance")) {
System.err.println("The parsed JSON response does not contain the balances requested.");
return 0.0;
}
return jsonObject.get("trading_balance").getAsDouble() + jsonObject.get("earning_balance").getAsDouble();
}
}
private static double getFundsAvailable(String exchange, String coin, boolean retry) throws IOException {
Request fundsRequest = new Request.Builder()
.url(API_BASE_URL + "/" + exchange + "/get_balance?coin=" + coin)

View File

@ -70,10 +70,10 @@ public class GateioFragment extends Fragment implements WorkerCardAdapter.OnCard
WorkerInterface.sendAddTraderCall("gateio",getContext());
return true;
} else if (item.getItemId() == R.id.removeTrader) {
System.err.println(pair + " Remove trader option clicked");
WorkerInterface.sendRemoveTraderCall("gateio",pair, getContext());
return true;
} else if (item.getItemId() == R.id.restartTrader) {
System.err.println(pair + " Restart option clicked");
WorkerInterface.sendRestartTraderCall("gateio",pair, getContext());
return true;
} else if (item.getItemId() == R.id.importTrader) {
WorkerInterface.sendImportTraderCall("gateio",getContext());

View File

@ -70,10 +70,10 @@ public class KucoinFragment extends Fragment implements WorkerCardAdapter.OnCard
WorkerInterface.sendAddTraderCall("kucoin",getContext());
return true;
} else if (item.getItemId() == R.id.removeTrader) {
System.err.println(pair + " Remove trader option clicked");
WorkerInterface.sendRemoveTraderCall("kucoin",pair,getContext());
return true;
} else if (item.getItemId() == R.id.restartTrader) {
System.err.println(pair + " Restart option clicked");
WorkerInterface.sendRestartTraderCall("kucoin",pair,getContext());
return true;
} else if (item.getItemId() == R.id.importTrader) {
WorkerInterface.sendImportTraderCall("kucoin",getContext());

View File

@ -70,10 +70,10 @@ public class OkxFragment extends Fragment implements WorkerCardAdapter.OnCardLon
WorkerInterface.sendAddTraderCall("okex",getContext());
return true;
} else if (item.getItemId() == R.id.removeTrader) {
System.err.println(pair + " Remove trader option clicked");
WorkerInterface.sendRemoveTraderCall("okex",pair,getContext());
return true;
} else if (item.getItemId() == R.id.restartTrader) {
System.err.println(pair + " Restart option clicked");
WorkerInterface.sendRestartTraderCall("okex", pair, getContext());
return true;
} else if (item.getItemId() == R.id.importTrader) {
WorkerInterface.sendImportTraderCall("okex",getContext());

View File

@ -81,8 +81,13 @@ public class WorkerCardAdapter{
}
price.setText(String.format(Locale.ROOT, "%.8f", worker.getPrice()));
if (worker.isShort()
&& worker.getOldLongDictionary()!=null
&& worker.getPrice()>worker.getOldLongDictionary().getTpPrice()) {
price.setTextColor(Color.parseColor("#00FF00"));
}
//TODO: If short and old_long and next_so_price<switch_price, set color to green
nextSoPrice.setText(String.format(Locale.ROOT, "%.8f", worker.getNextSoPrice()));
if (worker.isShort() &&
worker.getOldLongDictionary()!=null &&
@ -145,7 +150,14 @@ public class WorkerCardAdapter{
cardLayout.setBackgroundColor(Color.parseColor("#C5C281"));
workerStatusString.setVisibility(View.INVISIBLE);
} else if (worker.isAuto()) {
workerStatusString.setText(R.string.autoswitch_notice);
String stringToDisplay = "AUTO";
if (worker.getPrice()!=0) {
int multiplier = (int) (worker.getOldLongDictionary().getTpPrice() / worker.getPrice());
if (multiplier>1) {
stringToDisplay = stringToDisplay + " x" + multiplier;
}
}
workerStatusString.setText(stringToDisplay);
workerStatusString.setVisibility(View.VISIBLE);
} else {
workerStatusString.setText("");

View File

@ -1021,7 +1021,11 @@ public class HomeFragment extends Fragment {
if (binanceData.getFundsNeeded() != 0) {
binanceFundsPercentage = 100 - (binanceData.getFundsNeeded() - binanceData.getFundsAvailable()) / binanceData.getFundsNeeded() * 100;
}
String binanceFundsPercentageString = String.format(Locale.ROOT, "%.2f", binanceFundsPercentage) + "%";
String percentageFormat = "%.2f";
if (binanceFundsPercentage>=100) {
percentageFormat = "%.1f";
}
String binanceFundsPercentageString = String.format(Locale.ROOT, percentageFormat, binanceFundsPercentage) + "%";
exchange1Funds.setText(binanceFunds);
exchange1FundsPercentage.setText(binanceFundsPercentageString);
}
@ -1034,7 +1038,11 @@ public class HomeFragment extends Fragment {
if (gateioData.getFundsNeeded() != 0) {
gateioFundsPercentage = 100 - (gateioData.getFundsNeeded() - gateioData.getFundsAvailable()) / gateioData.getFundsNeeded() * 100;
}
String gateioFundsPercentageString = String.format(Locale.ROOT, "%.2f", gateioFundsPercentage) + "%";
String percentageFormat = "%.2f";
if (gateioFundsPercentage>=100) {
percentageFormat = "%.1f";
}
String gateioFundsPercentageString = String.format(Locale.ROOT, percentageFormat, gateioFundsPercentage) + "%";
exchange2Funds.setText(gateioFunds);
exchange2FundsPercentage.setText(gateioFundsPercentageString);
}
@ -1047,7 +1055,11 @@ public class HomeFragment extends Fragment {
if (kucoinData.getFundsNeeded() != 0) {
kucoinFundsPercentage = 100 - (kucoinData.getFundsNeeded() - kucoinData.getFundsAvailable()) / kucoinData.getFundsNeeded() * 100;
}
String kucoinFundsPercentageString = String.format(Locale.ROOT, "%.2f", kucoinFundsPercentage) + "%";
String percentageFormat = "%.2f";
if (kucoinFundsPercentage>=100) {
percentageFormat = "%.1f";
}
String kucoinFundsPercentageString = String.format(Locale.ROOT, percentageFormat, kucoinFundsPercentage) + "%";
exchange3Funds.setText(kucoinFunds);
exchange3FundsPercentage.setText(kucoinFundsPercentageString);
}
@ -1060,7 +1072,11 @@ public class HomeFragment extends Fragment {
if (okexData.getFundsNeeded() != 0) {
okexFundsPercentage = 100 - (okexData.getFundsNeeded() - okexData.getFundsAvailable()) / okexData.getFundsNeeded() * 100;
}
String okexFundsPercentageString = String.format(Locale.ROOT, "%.2f", okexFundsPercentage) + "%";
String percentageFormat = "%.2f";
if (okexFundsPercentage>=100) {
percentageFormat = "%.1f";
}
String okexFundsPercentageString = String.format(Locale.ROOT, percentageFormat, okexFundsPercentage) + "%";
exchange4Funds.setText(okexFunds);
exchange4FundsPercentage.setText(okexFundsPercentageString);
}

View File

@ -5,6 +5,8 @@ public class SettingsData {
public String profileName;
public String apiUrl;
public String apiKey;
public boolean useEarn;
public String earnApiKey;
public boolean useTelegram;
public String botToken;
public String chatId;
@ -16,6 +18,8 @@ public class SettingsData {
String profileName,
String apiUrl,
String apiKey,
boolean useEarn,
String earnApiKey,
boolean useTelegram,
String botToken,
String chatId,
@ -26,6 +30,8 @@ public class SettingsData {
this.profileName = profileName;
this.apiUrl = apiUrl;
this.apiKey = apiKey;
this.useEarn = useEarn;
this.earnApiKey = earnApiKey;
this.useTelegram = useTelegram;
this.botToken = botToken;
this.chatId = chatId;

View File

@ -30,6 +30,8 @@ public class SettingsFragment extends Fragment {
EditText editProfileName = root.findViewById(R.id.editProfileName);
EditText editApiUrl = root.findViewById(R.id.editApiUrl);
EditText editApiKey = root.findViewById(R.id.editApiKey);
CheckBox checkUseEarn = root.findViewById(R.id.useEarn);
EditText editEarnApiKey = root.findViewById(R.id.earnApiKey);
CheckBox checkBox = root.findViewById(R.id.useTelegram);
EditText editBotToken = root.findViewById(R.id.editBotToken);
EditText editChatId = root.findViewById(R.id.editChatId);
@ -37,6 +39,7 @@ public class SettingsFragment extends Fragment {
EditText editAmountOfLogLines = root.findViewById(R.id.editAmountOfLogLines);
EditText editAmountOfLastTrades = root.findViewById(R.id.editAmountOfLastTrades);
Button buttonSaveSettings = root.findViewById(R.id.buttonSaveSettings);
//Load settings if settings.json exists
@ -46,6 +49,8 @@ public class SettingsFragment extends Fragment {
editProfileName.setText(settingsData.profileName);
editApiUrl.setText(settingsData.apiUrl);
editApiKey.setText(settingsData.apiKey);
checkUseEarn.setChecked(settingsData.useEarn);
editEarnApiKey.setText(settingsData.earnApiKey);
checkBox.setChecked(settingsData.useTelegram);
editBotToken.setText(settingsData.botToken);
editChatId.setText(settingsData.chatId);
@ -72,6 +77,8 @@ public class SettingsFragment extends Fragment {
String profileName = editProfileName.getText().toString();
String apiUrl = editApiUrl.getText().toString();
String apiKey = editApiKey.getText().toString();
boolean useEarn = checkUseEarn.isChecked();
String earnApiKey = editEarnApiKey.getText().toString();
boolean useTelegram = checkBox.isChecked();
String botToken = editBotToken.getText().toString();
String chatId = editChatId.getText().toString();
@ -119,6 +126,8 @@ public class SettingsFragment extends Fragment {
profileName,
apiUrl,
apiKey,
useEarn,
earnApiKey,
useTelegram,
botToken,
chatId,

View File

@ -17,6 +17,8 @@ public class SettingsViewModel extends ViewModel {
public String profileName;
public String apiUrl;
public String apiKey;
public boolean useEarn;
public String earnApiKey;
public boolean useTelegram;
public String botToken;
public String chatId;
@ -29,6 +31,8 @@ public class SettingsViewModel extends ViewModel {
String profileName,
String apiUrl,
String apiKey,
boolean useEarn,
String earnApiKey,
boolean useTelegram,
String botToken,
String chatId,
@ -41,6 +45,8 @@ public class SettingsViewModel extends ViewModel {
this.profileName = profileName;
this.apiUrl = apiUrl;
this.apiKey = apiKey;
this.useEarn = useEarn;
this.earnApiKey = earnApiKey;
this.useTelegram = useTelegram;
this.botToken = botToken;
this.chatId = chatId;
@ -54,6 +60,8 @@ public class SettingsViewModel extends ViewModel {
profileName,
apiUrl,
apiKey,
useEarn,
earnApiKey,
useTelegram,
botToken,
chatId,

View File

@ -69,6 +69,20 @@
android:inputType="text"
android:textSize="16sp"/>
<CheckBox
android:id="@+id/useEarn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Earn" />
<EditText
android:id="@+id/earnApiKey"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/earn_key_hint"
android:textStyle="italic"
android:inputType="text"
android:textSize="16sp"/>
<CheckBox
android:id="@+id/useTelegram"

View File

@ -1,9 +1,9 @@
<resources>
<string name="app_name" translatable="false">DCAv2GUI</string>
<string name="nav_header_title" translatable="false">DCAv2</string>
<string name="nav_header_subtitle">Version 2025.01.08</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title" translatable="false">DCAv2</string>
<string name="nav_header_subtitle">nicolassanchez@tutanota.com</string>
<string name="nav_header_desc">Navigation header</string>
<string name="action_settings">Settings</string>
@ -15,7 +15,8 @@
<string name="profile_name_hint">Enter the profile name</string>
<string name="api_url_hint">Enter the API URL</string>
<string name="api_key_hint">Enter the API Key</string>
<string name="api_key_hint">Enter the API key</string>
<string name="earn_key_hint">Enter the Earn API key</string>
<string name="use_telegram">Use Telegram</string>
<string name="bot_token_hint">Enter the bot token</string>
<string name="chat_id_hint">Enter the chat ID</string>