97: Configure separate TEST and PROD instances of EvelynPerpsService
This commit is contained in:
@@ -41,12 +41,14 @@ public final class EvelynMissionControlImpl implements EvelynMissionControl, Nen
|
||||
public EvelynMissionControlImpl(
|
||||
@NotNull EvelynStatusService evelynStatusServiceProd,
|
||||
@NotNull EvelynStatusService evelynStatusServiceTest,
|
||||
@NotNull EvelynPerpsService evelynPerpsService,
|
||||
@NotNull EvelynPerpsService evelynPerpsServiceProd,
|
||||
@NotNull EvelynPerpsService evelynPerpsServiceTest,
|
||||
@NotNull JavaFxRuntimeService javaFxRuntimeService
|
||||
) {
|
||||
this.evelynStatusProd = Objects.requireNonNull(evelynStatusServiceProd, "evelynStatusServiceProd");
|
||||
this.evelynStatusTest = Objects.requireNonNull(evelynStatusServiceTest, "evelynStatusServiceTest");
|
||||
this.evelynPerpsService = Objects.requireNonNull(evelynPerpsService, "evelynPerpsService");
|
||||
this.evelynPerpsServiceProd = Objects.requireNonNull(evelynPerpsServiceProd, "evelynPerpsServiceProd");
|
||||
this.evelynPerpsServiceTest = Objects.requireNonNull(evelynPerpsServiceTest, "evelynPerpsServiceTest");
|
||||
this.javaFxRuntimeService = Objects.requireNonNull(
|
||||
javaFxRuntimeService,
|
||||
"javaFxRuntimeService");
|
||||
@@ -288,20 +290,28 @@ public final class EvelynMissionControlImpl implements EvelynMissionControl, Nen
|
||||
});
|
||||
perpsPolling = session;
|
||||
session.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
PerpsSnapshot snapshot = evelynPerpsService.getPositionsSnapshot();
|
||||
javaFxRuntimeService.runLater(() -> {
|
||||
if (perpsPolling == session && window.isShowing()) {
|
||||
productionPerps.update(snapshot);
|
||||
testPerps.update(snapshot);
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException exception) {
|
||||
log.warn("Unable to refresh Perps positions", exception);
|
||||
}
|
||||
pollPerps(session, evelynPerpsServiceProd, productionPerps, "PROD");
|
||||
pollPerps(session, evelynPerpsServiceTest, testPerps, "TEST");
|
||||
}, 0, PERPS_REFRESH_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void pollPerps(ScheduledExecutorService session, EvelynPerpsService service,
|
||||
PerpsTab tab, String environment) {
|
||||
if (perpsPolling != session) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
PerpsSnapshot snapshot = service.getPositionsSnapshot();
|
||||
javaFxRuntimeService.runLater(() -> {
|
||||
if (perpsPolling == session && window.isShowing()) {
|
||||
tab.update(snapshot);
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException exception) {
|
||||
log.warn("Unable to refresh {} Perps positions", environment, exception);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopPerpsPolling() {
|
||||
ScheduledExecutorService session = perpsPolling;
|
||||
perpsPolling = null;
|
||||
@@ -382,7 +392,8 @@ public final class EvelynMissionControlImpl implements EvelynMissionControl, Nen
|
||||
// region Dependencies
|
||||
private final EvelynStatusService evelynStatusProd;
|
||||
private final EvelynStatusService evelynStatusTest;
|
||||
private final EvelynPerpsService evelynPerpsService;
|
||||
private final EvelynPerpsService evelynPerpsServiceProd;
|
||||
private final EvelynPerpsService evelynPerpsServiceTest;
|
||||
private final JavaFxRuntimeService javaFxRuntimeService;
|
||||
// endregion
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.r35157.evelyn.service.perps;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/** Hub-supplied wallet identity; sample IDs are not real Solana addresses. */
|
||||
public record PerpsWalletConfiguration(String id, String name) {
|
||||
public PerpsWalletConfiguration {
|
||||
Objects.requireNonNull(id, "id");
|
||||
Objects.requireNonNull(name, "name");
|
||||
}
|
||||
}
|
||||
+40
-16
@@ -2,6 +2,7 @@ package com.r35157.evelyn.service.perps.impl.ref;
|
||||
|
||||
import com.r35157.evelyn.service.perps.EvelynPerpsService;
|
||||
import com.r35157.evelyn.service.perps.PerpsSnapshot;
|
||||
import com.r35157.evelyn.service.perps.PerpsWalletConfiguration;
|
||||
import com.r35157.evelyn.service.perps.PerpsSnapshot.Position;
|
||||
import com.r35157.evelyn.service.perps.PerpsSnapshot.Venue;
|
||||
import com.r35157.evelyn.service.perps.PerpsSnapshot.Wallet;
|
||||
@@ -10,31 +11,53 @@ import com.r35157.nenjim.process.NenjimProcess;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/** Owns the fixed examples only. No exchange clients, position management or update worker. */
|
||||
public final class EvelynPerpsServiceImpl implements EvelynPerpsService, NenjimProcess {
|
||||
public EvelynPerpsServiceImpl(@NotNull List<PerpsWalletConfiguration> wallets) {
|
||||
this.wallets = List.copyOf(wallets);
|
||||
var ids = new HashSet<String>();
|
||||
for (PerpsWalletConfiguration wallet : this.wallets) {
|
||||
if (!ids.add(wallet.id())) {
|
||||
throw new IllegalArgumentException("Duplicate Perps wallet ID: " + wallet.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void start() {
|
||||
if (snapshot != null) {
|
||||
throw new IllegalStateException("Perps service has already started");
|
||||
}
|
||||
snapshot = new PerpsSnapshot(List.of(
|
||||
new Wallet("sample-wallet-a", "Sample wallet A", List.of(
|
||||
new Venue("jupiter", "Jupiter", List.of(
|
||||
position("sol-long", "SOL-PERP", Direction.LONG, "12500.00"),
|
||||
position("btc-short", "BTC-PERP", Direction.SHORT, "8250.50"))),
|
||||
new Venue("phoenix", "Phoenix", List.of(
|
||||
position("sol-short", "SOL-PERP", Direction.SHORT, "3200.75"),
|
||||
position("eth-long", "ETH-PERP", Direction.LONG, "5400.00"))))),
|
||||
new Wallet("sample-wallet-b", "Sample wallet B", List.of(
|
||||
new Venue("jupiter", "Jupiter", List.of(
|
||||
position("eth-long", "ETH-PERP", Direction.LONG, "1875.25"),
|
||||
position("sol-short", "SOL-PERP", Direction.SHORT, "950.00"))),
|
||||
new Venue("phoenix", "Phoenix", List.of(
|
||||
position("btc-long", "BTC-PERP", Direction.LONG, "21000.00"),
|
||||
position("sol-short", "SOL-PERP", Direction.SHORT, "640.50")))))
|
||||
));
|
||||
var configuredWallets = new ArrayList<Wallet>();
|
||||
for (int index = 0; index < wallets.size(); index++) {
|
||||
PerpsWalletConfiguration wallet = wallets.get(index);
|
||||
configuredWallets.add(new Wallet(wallet.id(), wallet.name(), sampleVenues(index)));
|
||||
}
|
||||
snapshot = new PerpsSnapshot(configuredWallets);
|
||||
}
|
||||
|
||||
/** Alternate the original two sample portfolios in configured wallet order. */
|
||||
private static List<Venue> sampleVenues(int walletIndex) {
|
||||
if (walletIndex % 2 == 0) {
|
||||
return List.of(
|
||||
new Venue("jupiter", "Jupiter", List.of(
|
||||
position("sol-long", "SOL-PERP", Direction.LONG, "12500.00"),
|
||||
position("btc-short", "BTC-PERP", Direction.SHORT, "8250.50"))),
|
||||
new Venue("phoenix", "Phoenix", List.of(
|
||||
position("sol-short", "SOL-PERP", Direction.SHORT, "3200.75"),
|
||||
position("eth-long", "ETH-PERP", Direction.LONG, "5400.00"))));
|
||||
}
|
||||
return List.of(
|
||||
new Venue("jupiter", "Jupiter", List.of(
|
||||
position("eth-long", "ETH-PERP", Direction.LONG, "1875.25"),
|
||||
position("sol-short", "SOL-PERP", Direction.SHORT, "950.00"))),
|
||||
new Venue("phoenix", "Phoenix", List.of(
|
||||
position("btc-long", "BTC-PERP", Direction.LONG, "21000.00"),
|
||||
position("sol-short", "SOL-PERP", Direction.SHORT, "640.50"))));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,5 +73,6 @@ public final class EvelynPerpsServiceImpl implements EvelynPerpsService, NenjimP
|
||||
return new Position(id, instrument, direction, new ΩAmountΩ(sizeUsd));
|
||||
}
|
||||
|
||||
private final List<PerpsWalletConfiguration> wallets;
|
||||
private volatile PerpsSnapshot snapshot;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.r35157.evelyn.service.liquidity.impl.ref.EvelynLiquidityServiceImpl;
|
||||
import com.r35157.evelyn.service.status.EvelynStatusService;
|
||||
import com.r35157.evelyn.service.status.impl.ref.EvelynStatusServiceImpl;
|
||||
import com.r35157.evelyn.service.perps.EvelynPerpsService;
|
||||
import com.r35157.evelyn.service.perps.PerpsWalletConfiguration;
|
||||
import com.r35157.evelyn.service.perps.impl.ref.EvelynPerpsServiceImpl;
|
||||
import com.fanitas.evelyn.service.burner.EvelynIOUBurnerService;
|
||||
import com.fanitas.evelyn.service.burner.impl.ref.EvelynIOUBurnerServiceImpl;
|
||||
@@ -360,9 +361,15 @@ public final class NenjimHubImpl implements NenjimHub {
|
||||
solanaBlockChain, cis, liquidityConfiguration);
|
||||
}
|
||||
|
||||
private NenjimProcess constructEvelynPerpsProcess() {
|
||||
EvelynPerpsServiceImpl process = new EvelynPerpsServiceImpl();
|
||||
evelynPerpsService = process;
|
||||
private NenjimProcess constructEvelynPerpsProdProcess() {
|
||||
EvelynPerpsServiceImpl process = new EvelynPerpsServiceImpl(EVELYN_PERPS_WALLETS);
|
||||
evelynPerpsServiceProd = process;
|
||||
return process;
|
||||
}
|
||||
|
||||
private NenjimProcess constructEvelynPerpsTestProcess() {
|
||||
EvelynPerpsServiceImpl process = new EvelynPerpsServiceImpl(EVELYN_PERPS_WALLETS);
|
||||
evelynPerpsServiceTest = process;
|
||||
return process;
|
||||
}
|
||||
|
||||
@@ -383,9 +390,13 @@ public final class NenjimHubImpl implements NenjimHub {
|
||||
EVELYN_MISSION_CONTROL_ID,
|
||||
EVELYN_STATUS_TEST_ID),
|
||||
requireProcessDependency(
|
||||
evelynPerpsService,
|
||||
evelynPerpsServiceProd,
|
||||
EVELYN_MISSION_CONTROL_ID,
|
||||
EVELYN_PERPS_SERVICE_ID),
|
||||
EVELYN_PERPS_PROD_ID),
|
||||
requireProcessDependency(
|
||||
evelynPerpsServiceTest,
|
||||
EVELYN_MISSION_CONTROL_ID,
|
||||
EVELYN_PERPS_TEST_ID),
|
||||
requireProcessDependency(
|
||||
javaFxRuntimeService,
|
||||
EVELYN_MISSION_CONTROL_ID,
|
||||
@@ -433,7 +444,8 @@ public final class NenjimHubImpl implements NenjimHub {
|
||||
Map.entry(EVELYN_STATUS_TEST_ID, this::constructEvelynStatusTestProcess),
|
||||
Map.entry(EVELYN_LIQUIDITY_PROD_ID, this::constructEvelynLiquidityProdProcess),
|
||||
Map.entry(EVELYN_IOU_BURNER_PROD_ID, this::constructEvelynIOUBurnerProdProcess),
|
||||
Map.entry(EVELYN_PERPS_SERVICE_ID, this::constructEvelynPerpsProcess),
|
||||
Map.entry(EVELYN_PERPS_PROD_ID, this::constructEvelynPerpsProdProcess),
|
||||
Map.entry(EVELYN_PERPS_TEST_ID, this::constructEvelynPerpsTestProcess),
|
||||
Map.entry(JAVAFX_RUNTIME_SERVICE_ID, this::constructJavaFxRuntimeProcess),
|
||||
Map.entry(EVELYN_MISSION_CONTROL_ID, this::constructMissionControlProcess),
|
||||
Map.entry(PROCESS_MANAGER_ID, this::constructProcessManagerProcess)
|
||||
@@ -551,8 +563,13 @@ public final class NenjimHubImpl implements NenjimHub {
|
||||
new NenjimComponentId("evelyn.liquidity.prod");
|
||||
private static final NenjimComponentId EVELYN_MISSION_CONTROL_ID =
|
||||
new NenjimComponentId("evelyn.mission-control.default");
|
||||
private static final NenjimComponentId EVELYN_PERPS_SERVICE_ID =
|
||||
new NenjimComponentId("evelyn.perps.default");
|
||||
private static final NenjimComponentId EVELYN_PERPS_PROD_ID =
|
||||
new NenjimComponentId("evelyn.perps.prod");
|
||||
private static final NenjimComponentId EVELYN_PERPS_TEST_ID =
|
||||
new NenjimComponentId("evelyn.perps.test");
|
||||
private static final List<PerpsWalletConfiguration> EVELYN_PERPS_WALLETS = List.of(
|
||||
new PerpsWalletConfiguration("sample-wallet-a", "Sample wallet A"),
|
||||
new PerpsWalletConfiguration("sample-wallet-b", "Sample wallet B"));
|
||||
private static final NenjimComponentId JAVAFX_RUNTIME_SERVICE_ID =
|
||||
new NenjimComponentId("nenjim.javafx-runtime.service");
|
||||
private static final NenjimComponentId PROCESS_MANAGER_ID =
|
||||
@@ -591,7 +608,8 @@ public final class NenjimHubImpl implements NenjimHub {
|
||||
private JupiterPerpsAlarm jupiterPerpsAlarm;
|
||||
private EvelynStatusService evelynStatusServiceProd;
|
||||
private EvelynStatusService evelynStatusServiceTest;
|
||||
private EvelynPerpsService evelynPerpsService;
|
||||
private EvelynPerpsService evelynPerpsServiceProd;
|
||||
private EvelynPerpsService evelynPerpsServiceTest;
|
||||
private JupiterSwapService jupiterSwapService;
|
||||
private BoundNotificationService discordAssetAZTokenNotificationService;
|
||||
private EvelynIOUBurnerService evelynIOUBurnerServiceProd;
|
||||
|
||||
Reference in New Issue
Block a user