exchange popup menu mostly implemented
This commit is contained in:
parent
25cbf1615f
commit
ad636a445c
|
|
@ -4,7 +4,7 @@
|
||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2024-12-19T12:29:08.104137914Z">
|
<DropdownSelection timestamp="2024-12-23T10:34:33.165240137Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="LocalEmulator" identifier="path=/home/nicolas/.android/avd/Pixel_6_Pro_API_34.avd" />
|
<DeviceId pluginId="LocalEmulator" identifier="path=/home/nicolas/.android/avd/Pixel_6_Pro_API_34.avd" />
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package com.example.dcav2gui;
|
||||||
|
|
||||||
import static com.example.dcav2gui.MainActivity.globalSettings;
|
import static com.example.dcav2gui.MainActivity.globalSettings;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.example.dcav2gui.ui.exchanges.WorkerData;
|
import com.example.dcav2gui.ui.exchanges.WorkerData;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
|
@ -129,6 +131,40 @@ public class InstanceInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double getServerTime(String exchange, boolean retry) throws IOException {
|
||||||
|
Request serverTimeRequest = new Request.Builder()
|
||||||
|
.url(API_BASE_URL + "/" + exchange + "/server_time")
|
||||||
|
.header("X-API-KEY", API_KEY)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try (Response serverTimeResponse = httpClient.newCall(serverTimeRequest).execute()) {
|
||||||
|
if (!serverTimeResponse.isSuccessful()) {
|
||||||
|
if (serverTimeResponse.code() == 503 && retry) {
|
||||||
|
return getServerTime(exchange,false);
|
||||||
|
}
|
||||||
|
throw new IOException("Unexpected code " + serverTimeResponse);
|
||||||
|
}
|
||||||
|
String serverTimeResponseBody = serverTimeResponse.body().string();
|
||||||
|
|
||||||
|
try {
|
||||||
|
JsonElement jsonElement = JsonParser.parseString(serverTimeResponseBody);
|
||||||
|
if (!jsonElement.isJsonObject()) {
|
||||||
|
System.err.println("The parsed JSON response is not a JsonObject.");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
||||||
|
if (jsonObject.has("Time")) {
|
||||||
|
return jsonObject.get("Time").getAsDouble();
|
||||||
|
} else {
|
||||||
|
System.err.println("The parsed JSON response does not contain a 'Time' entry.");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Error querying server time: " + e.getMessage());
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static List<DealData> getAllTrades() throws IOException {
|
public static List<DealData> getAllTrades() throws IOException {
|
||||||
|
|
||||||
|
|
@ -374,6 +410,45 @@ public class InstanceInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<String> getMissingPairs(String exchange, boolean retry) throws IOException {
|
||||||
|
List<String> valueToReturn = new ArrayList<>();
|
||||||
|
|
||||||
|
Request missingPairsRequest = new Request.Builder()
|
||||||
|
.url(API_BASE_URL + "/" + exchange + "/missing_pairs")
|
||||||
|
.header("X-API-KEY", API_KEY)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try (Response missingPairsResponse = httpClient.newCall(missingPairsRequest).execute()) {
|
||||||
|
if (!missingPairsResponse.isSuccessful()) {
|
||||||
|
if (missingPairsResponse.code() == 503 && retry) {
|
||||||
|
return getMissingPairs(exchange, false);
|
||||||
|
}
|
||||||
|
throw new IOException("Unexpected code " + missingPairsResponse);
|
||||||
|
}
|
||||||
|
String missingPairsResponseBody = missingPairsResponse.body().string();
|
||||||
|
JsonElement jsonElement = JsonParser.parseString(missingPairsResponseBody);
|
||||||
|
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 an Error field");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonObject.has("MissingPairs")) {
|
||||||
|
//Parse the string as a Json array and add it to response
|
||||||
|
JsonArray jsonArray = jsonObject.getAsJsonArray("MissingPairs");
|
||||||
|
for (JsonElement jsonElement1 : jsonArray) {
|
||||||
|
String missingPair = jsonElement1.getAsString();
|
||||||
|
valueToReturn.add(missingPair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return valueToReturn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static List<WorkerStatsData> getAllWorkersStats(String exchange, boolean retry) throws IOException {
|
public static List<WorkerStatsData> getAllWorkersStats(String exchange, boolean retry) throws IOException {
|
||||||
List<WorkerStatsData> valueToReturn = new ArrayList<>();
|
List<WorkerStatsData> valueToReturn = new ArrayList<>();
|
||||||
|
|
@ -510,15 +585,12 @@ public class InstanceInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static InstanceGlobalStatsData getInstanceGlobalStatus(String exchange, boolean retry) throws IOException {
|
public static InstanceGlobalStatsData getInstanceGlobalStatus(String exchange, boolean retry) throws IOException {
|
||||||
List<WorkerStatsData> valueToReturn = new ArrayList<>();
|
|
||||||
|
|
||||||
Request globalStatsRequest = new Request.Builder()
|
Request globalStatsRequest = new Request.Builder()
|
||||||
.url(API_BASE_URL + "/" + exchange + "/global_status")
|
.url(API_BASE_URL + "/" + exchange + "/global_status")
|
||||||
.header("X-API-KEY", API_KEY)
|
.header("X-API-KEY", API_KEY)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
||||||
try (Response globalStatsResponse = httpClient.newCall(globalStatsRequest).execute()) {
|
try (Response globalStatsResponse = httpClient.newCall(globalStatsRequest).execute()) {
|
||||||
if (!globalStatsResponse.isSuccessful()) {
|
if (!globalStatsResponse.isSuccessful()) {
|
||||||
if (globalStatsResponse.code() == 503 && retry) {
|
if (globalStatsResponse.code() == 503 && retry) {
|
||||||
|
|
@ -539,7 +611,6 @@ public class InstanceInterface {
|
||||||
|
|
||||||
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
||||||
|
|
||||||
|
|
||||||
// Extracting online_workers and paused_traders from the response
|
// Extracting online_workers and paused_traders from the response
|
||||||
JsonArray onlineWorkersJsonArray = jsonObject.get("online_workers").getAsJsonArray();
|
JsonArray onlineWorkersJsonArray = jsonObject.get("online_workers").getAsJsonArray();
|
||||||
List<String> onlineWorkers = new ArrayList<>();
|
List<String> onlineWorkers = new ArrayList<>();
|
||||||
|
|
@ -620,7 +691,6 @@ public class InstanceInterface {
|
||||||
workerStatsData.getIsShort(),
|
workerStatsData.getIsShort(),
|
||||||
workerStatsData.getIsBoosted(),
|
workerStatsData.getIsBoosted(),
|
||||||
workerStatsData.getAutoSwitchEnabled(),
|
workerStatsData.getAutoSwitchEnabled(),
|
||||||
//Let's deal with this later
|
|
||||||
workerStatsData.getIsPaused(),
|
workerStatsData.getIsPaused(),
|
||||||
workerStatsData.getStopWhenProfit(),
|
workerStatsData.getStopWhenProfit(),
|
||||||
workerStatsData.getOldLongDictionary());
|
workerStatsData.getOldLongDictionary());
|
||||||
|
|
@ -732,6 +802,22 @@ public class InstanceInterface {
|
||||||
public Boolean getAttemptToRestart() { return attemptToRestart; }
|
public Boolean getAttemptToRestart() { return attemptToRestart; }
|
||||||
public double getDefaultOrderSize() { return defaultOrderSize; }
|
public double getDefaultOrderSize() { return defaultOrderSize; }
|
||||||
public Boolean getUnifiedOrderQuery() { return unifiedOrderQuery; }
|
public Boolean getUnifiedOrderQuery() { return unifiedOrderQuery; }
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Name: " + brokerName + "\n" +
|
||||||
|
"Testnet: " + isSandbox.toString() + "\n" +
|
||||||
|
"Simulate market orders: " + simulateMarketOrders.toString() + "\n" +
|
||||||
|
"Pairs: " + pairs + "\n" +
|
||||||
|
"Lap time: " + laptime + " seconds \n" +
|
||||||
|
"Cooldown multiplier: " + cooldownMultiplier + "\n" +
|
||||||
|
"Wait time before a new safety order: " + waitBeforeNewSafetyOrder + "\n" +
|
||||||
|
"Telegram: " + sendTelegram.toString() + "\n" +
|
||||||
|
"Restart: " + attemptToRestart.toString() + "\n" +
|
||||||
|
"Default order size: " + defaultOrderSize + "\n" +
|
||||||
|
"Unified order query: " + unifiedOrderQuery;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ public class BinanceViewModel extends AndroidViewModel {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule the next execution
|
// Schedule the next execution
|
||||||
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
package com.example.dcav2gui.ui.home;
|
package com.example.dcav2gui.ui.home;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
|
|
@ -31,6 +33,7 @@ import com.example.dcav2gui.MainActivity;
|
||||||
import com.example.dcav2gui.R;
|
import com.example.dcav2gui.R;
|
||||||
import com.example.dcav2gui.TickerTracker;
|
import com.example.dcav2gui.TickerTracker;
|
||||||
import com.example.dcav2gui.databinding.FragmentHomeBinding;
|
import com.example.dcav2gui.databinding.FragmentHomeBinding;
|
||||||
|
import com.example.dcav2gui.ui.exchanges.adapters.WorkerCardAdapter;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -327,22 +330,22 @@ public class HomeFragment extends Fragment {
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
if (item.getItemId() == R.id.exchangeMenuGlobalStatus) {
|
if (item.getItemId() == R.id.exchangeMenuGlobalStatus) {
|
||||||
// Handle the "Details..." option
|
fetchExchangeDetails(exchange);
|
||||||
// For example, navigate to a details fragment
|
|
||||||
return true;
|
return true;
|
||||||
} else if (item.getItemId() == R.id.exchangeMenuMissingPairs) {
|
} else if (item.getItemId() == R.id.exchangeMenuMissingPairs) {
|
||||||
|
fetchMissingPairs(exchange);
|
||||||
return true;
|
return true;
|
||||||
} else if (item.getItemId() == R.id.exchangeMenuServerTime) {
|
} else if (item.getItemId() == R.id.exchangeMenuServerTime) {
|
||||||
|
fetchServerTime(exchange);
|
||||||
return true;
|
return true;
|
||||||
} else if (item.getItemId() == R.id.exchangeMenuTraderTime) {
|
} else if (item.getItemId() == R.id.exchangeMenuTraderTime) {
|
||||||
|
fetchTraderTime(exchange);
|
||||||
return true;
|
return true;
|
||||||
} else if (item.getItemId() == R.id.exchangeMenuPausedTraders) {
|
} else if (item.getItemId() == R.id.exchangeMenuPausedTraders) {
|
||||||
|
fetchPausedTraders(exchange);
|
||||||
return true;
|
return true;
|
||||||
} else if (item.getItemId() == R.id.exchangeMenuConfigFile) {
|
} else if (item.getItemId() == R.id.exchangeMenuConfigFile) {
|
||||||
return true;
|
fetchExchangeConfig(exchange);
|
||||||
} else if (item.getItemId() == R.id.exchangeMenuBacktests) {
|
|
||||||
return true;
|
|
||||||
} else if (item.getItemId() == R.id.exchangeMenuGetBalance) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -408,6 +411,135 @@ public class HomeFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fetchExchangeDetails(String exchange) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
InstanceInterface.InstanceGlobalStatsData result = InstanceInterface.getInstanceGlobalStatus(exchange, true);
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> showInstanceDetailsDialog(result));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(getContext(), "Failed to fetch details", Toast.LENGTH_SHORT).show());
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchPausedTraders(String exchange) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
InstanceInterface.InstanceGlobalStatsData result = InstanceInterface.getInstanceGlobalStatus(exchange, true);
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> showPausedTradersDialog(result));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(getContext(), "Failed to fetch details", Toast.LENGTH_SHORT).show());
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchMissingPairs(String exchange) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
List<String> result = InstanceInterface.getMissingPairs(exchange, true);
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> showMissingPairsDialog(result));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(getContext(), "Failed to fetch missing pairs", Toast.LENGTH_SHORT).show());
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchServerTime(String exchange) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
double result = InstanceInterface.getServerTime(exchange, true);
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> showServerTimeDialog(result));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(getContext(), "Failed to fetch missing pairs", Toast.LENGTH_SHORT).show());
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchTraderTime(String exchange) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
double result = InstanceInterface.getTraderTime(exchange, true);
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> showTraderTimeDialog(result));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(getContext(), "Failed to fetch missing pairs", Toast.LENGTH_SHORT).show());
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchExchangeConfig(String exchange) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
InstanceInterface.InstanceGlobalStatsData result = InstanceInterface.getInstanceGlobalStatus(exchange, true);
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> showInstanceConfigDialog(result));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(getContext(), "Failed to fetch details", Toast.LENGTH_SHORT).show());
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showInstanceDetailsDialog(InstanceInterface.InstanceGlobalStatsData result) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
|
builder.setTitle(result.getName() + " details");
|
||||||
|
builder.setMessage("Instance uptime: " + WorkerCardAdapter.formatSeconds(result.getUptime()) + "\n" +
|
||||||
|
"Online traders: " + result.getOnlineWorkers().size() + "\n" +
|
||||||
|
"Paused traders: " + result.getPausedTraders().size() + "\n" +
|
||||||
|
"DCAv2 version: " + result.getVersion() + "\n" +
|
||||||
|
"CCXT version: " + result.getCcxtVersion());
|
||||||
|
builder.setPositiveButton("OK", null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showPausedTradersDialog(InstanceInterface.InstanceGlobalStatsData result) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
|
builder.setTitle("Paused traders:");
|
||||||
|
builder.setMessage(result.getPausedTraders().toString());
|
||||||
|
builder.setPositiveButton("OK", null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showInstanceConfigDialog(InstanceInterface.InstanceGlobalStatsData result) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
|
builder.setTitle(result.getName() + " config:");
|
||||||
|
builder.setMessage(result.getConfig().toString());
|
||||||
|
builder.setPositiveButton("OK", null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showMissingPairsDialog(List<String> missingPairs) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
|
builder.setTitle("Missing pairs");
|
||||||
|
if (missingPairs.isEmpty()) {
|
||||||
|
builder.setMessage("No missing traders");
|
||||||
|
} else {
|
||||||
|
builder.setMessage(String.valueOf(missingPairs));
|
||||||
|
}
|
||||||
|
builder.setPositiveButton("OK", null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showServerTimeDialog(double serverTime) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
|
builder.setTitle("Server time");
|
||||||
|
builder.setMessage(timeStampConverter(serverTime));
|
||||||
|
builder.setPositiveButton("OK", null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showTraderTimeDialog(double traderTime) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
|
builder.setTitle("Trader time");
|
||||||
|
builder.setMessage(timeStampConverter(traderTime));
|
||||||
|
builder.setPositiveButton("OK", null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void fetchAndDisplayData() {
|
private void fetchAndDisplayData() {
|
||||||
// For the cache
|
// For the cache
|
||||||
MainActivity mainActivity = (MainActivity) requireActivity();
|
MainActivity mainActivity = (MainActivity) requireActivity();
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,4 @@
|
||||||
android:title="View paused traders" />
|
android:title="View paused traders" />
|
||||||
<item android:id="@+id/exchangeMenuConfigFile"
|
<item android:id="@+id/exchangeMenuConfigFile"
|
||||||
android:title="View config file" />
|
android:title="View config file" />
|
||||||
<item android:id="@+id/exchangeMenuBacktests"
|
|
||||||
android:title="Backtests" />
|
|
||||||
<item android:id="@+id/exchangeMenuGetBalance"
|
|
||||||
android:title="Get balance" />
|
|
||||||
</menu>
|
</menu>
|
||||||
Loading…
Reference in New Issue