X: Clean-up and documentation updates
This commit is contained in:
@@ -47,27 +47,17 @@ import static com.r35157.libs.solana.valuetypes.economic.SolanaSPLTokenProgram.T
|
||||
|
||||
public class EvelynImpl implements Evelyn {
|
||||
|
||||
/*public EvelynImpl(
|
||||
State state,
|
||||
DesiredPositionCalculator desiredPositionCalculator,
|
||||
Raydium raydium,
|
||||
SolanaBlockChain solanaChain
|
||||
) {
|
||||
this.state = state;
|
||||
this.desiredPositionCalculator = desiredPositionCalculator;
|
||||
this.raydium = raydium;
|
||||
this.solanaChain = solanaChain;
|
||||
}*/
|
||||
public EvelynImpl(
|
||||
@NotNull String instanceName,
|
||||
@NotNull TickerService tickerService,
|
||||
@NotNull TradingPair eveUsdtTradingPair
|
||||
@NotNull TradingPair eveUsdtTradingPair,
|
||||
@NotNull Clock clock
|
||||
) {
|
||||
this(
|
||||
instanceName,
|
||||
tickerService,
|
||||
eveUsdtTradingPair,
|
||||
Clock.systemUTC(),
|
||||
clock,
|
||||
SAMPLE_DELAY_MINUTES,
|
||||
TimeUnit.MINUTES,
|
||||
DATA_ROOT
|
||||
@@ -131,6 +121,8 @@ public class EvelynImpl implements Evelyn {
|
||||
this.clock = validatedClock;
|
||||
this.sampleDelay = sampleDelay;
|
||||
this.sampleDelayUnit = validatedDelayUnit;
|
||||
|
||||
statusIndexHistory = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -766,7 +758,7 @@ public class EvelynImpl implements Evelyn {
|
||||
private final Clock clock;
|
||||
private final long sampleDelay;
|
||||
private final TimeUnit sampleDelayUnit;
|
||||
private final List<EvelynStatusIndexPoint> statusIndexHistory = new ArrayList<>();
|
||||
private final List<EvelynStatusIndexPoint> statusIndexHistory;
|
||||
|
||||
private ScheduledExecutorService statusIndexScheduler;
|
||||
private Instant lastPersistedTimestamp;
|
||||
|
||||
+4
-1
@@ -44,7 +44,10 @@ public final class HardcodedPriceSource implements PriceSource {
|
||||
currencyIdentityService,
|
||||
"currencyIdentityService"
|
||||
);
|
||||
this.clock = Objects.requireNonNull(clock, "clock");
|
||||
this.clock = Objects.requireNonNull(
|
||||
clock,
|
||||
"clock"
|
||||
);
|
||||
if (observationDelay <= 0) {
|
||||
throw new IllegalArgumentException("observationDelay must be positive");
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ import java.util.function.Function;
|
||||
|
||||
public final class EvelynMissionControlImpl implements EvelynMissionControl {
|
||||
|
||||
public EvelynMissionControlImpl(Evelyn evelynProd, Evelyn evelynTest) {
|
||||
this.evelynProd = Objects.requireNonNull(evelynProd);
|
||||
this.evelynTest = Objects.requireNonNull(evelynTest);
|
||||
public EvelynMissionControlImpl(Evelyn evelynServiceProd, Evelyn evelynServiceTest) {
|
||||
this.evelynProd = Objects.requireNonNull(evelynServiceProd, "evelynServiceProd");
|
||||
this.evelynTest = Objects.requireNonNull(evelynServiceTest, "evelynServiceTest");
|
||||
refreshTimeline.setCycleCount(Timeline.INDEFINITE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,19 @@
|
||||
package com.r35157.jupiterperpsalarm;
|
||||
|
||||
public class JupiterPerpsAlarm {
|
||||
/**
|
||||
* Monitors configured Jupiter Perps prices and dispatches matching alarm
|
||||
* actions.
|
||||
*
|
||||
* <p>An instance is expected to be fully configured with its wallet and
|
||||
* Jupiter service before it is started. Those dependencies determine which
|
||||
* wallet is observed and used for transaction actions; alarm action files do
|
||||
* not select them.</p>
|
||||
*/
|
||||
public interface JupiterPerpsAlarm {
|
||||
/**
|
||||
* Starts alarm monitoring asynchronously.
|
||||
*
|
||||
* <p>Each instance must be started at most once.</p>
|
||||
*/
|
||||
void start();
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ public final class AlarmConfigurationParser {
|
||||
|
||||
private static final Pattern PERSISTENT_GRACE_PERIOD_PATTERN =
|
||||
Pattern.compile("(\\d+)(ms|s|m|h|d|w|M|y)");
|
||||
private static final int SUPPORTED_FORMAT_VERSION = 1;
|
||||
private static final int SUPPORTED_FORMAT_VERSION = 2;
|
||||
|
||||
private AlarmConfigurationParser() {
|
||||
}
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
package com.r35157.jupiterperpsalarm.impl.ref;
|
||||
|
||||
import com.r35157.assetaz.services.cis.CurrencyIdentityService;
|
||||
import com.r35157.cryptowallet.solana.SolanaWallet;
|
||||
import com.r35157.cryptowallet.solana.impl.ref.SolanaWalletImpl;
|
||||
import com.r35157.jupiterperpsalarm.JupiterPerpsAlarm;
|
||||
import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
||||
import com.r35157.libs.jupiter.perps.impl.anchoridl.AnchorIdlJupiterPerpsServiceImpl;
|
||||
import com.r35157.libs.objcache.ObjectCache;
|
||||
import com.r35157.libs.objcache.impl.ref.ObjectCacheImpl;
|
||||
import com.r35157.libs.solana.SolanaBlockChain;
|
||||
import com.r35157.libs.solana.impl.cached.CachedSolanaBlockChain;
|
||||
import com.r35157.libs.solana.impl.ref.SolanaBlockChainImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
@@ -18,19 +12,52 @@ import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public final class JupiterPerpsAlarmImpl {
|
||||
public final class JupiterPerpsAlarmImpl implements JupiterPerpsAlarm {
|
||||
|
||||
public static void start(
|
||||
String[] args,
|
||||
CurrencyIdentityService currencyIdentityService
|
||||
) throws Exception {
|
||||
public JupiterPerpsAlarmImpl(
|
||||
@NotNull SolanaWallet solanaWallet,
|
||||
@NotNull JupiterPerpsService jupiterServicePerps,
|
||||
@NotNull String configFilename
|
||||
) {
|
||||
this.solanaWallet = Objects.requireNonNull(
|
||||
solanaWallet,
|
||||
"solanaWallet"
|
||||
);
|
||||
|
||||
this.jupiterServicePerps = Objects.requireNonNull(
|
||||
jupiterServicePerps,
|
||||
"jupiterServicePerps"
|
||||
);
|
||||
|
||||
this.configFilename = Objects.requireNonNull(
|
||||
configFilename,
|
||||
"configFilename"
|
||||
);
|
||||
|
||||
this.thread = new Thread(() -> {
|
||||
try {
|
||||
run();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace(System.err);
|
||||
}
|
||||
}, "Nenjim Plugin - JupiterPerpsAlarm");
|
||||
this.thread.setDaemon(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private void run() throws Exception {
|
||||
Config config;
|
||||
System.out.println("Starting Jupiter Perps Alarms...");
|
||||
try {
|
||||
System.out.print("Parsing commandline parameters... ");
|
||||
config = Config.parse(args, System.getenv());
|
||||
config = Config.parse(new String[] { configFilename }, System.getenv());
|
||||
System.out.println("Done.");
|
||||
} catch (IllegalArgumentException exception) {
|
||||
printUsage();
|
||||
@@ -60,14 +87,6 @@ public final class JupiterPerpsAlarmImpl {
|
||||
.getParent();
|
||||
|
||||
System.out.print("Initializing dependencies... ");
|
||||
ObjectCache objectCache = new ObjectCacheImpl();
|
||||
SolanaBlockChain realSolanaBlockChain = new SolanaBlockChainImpl(
|
||||
currencyIdentityService
|
||||
);
|
||||
SolanaBlockChain solanaBlockChain = new CachedSolanaBlockChain(
|
||||
realSolanaBlockChain,
|
||||
objectCache
|
||||
);
|
||||
|
||||
JupiterPerpsPositionIncreaseAlarmActionConfiguration
|
||||
positionIncreaseConfiguration =
|
||||
@@ -80,19 +99,6 @@ public final class JupiterPerpsAlarmImpl {
|
||||
variableResolver
|
||||
);
|
||||
|
||||
SolanaWallet positionIncreaseWallet = new SolanaWalletImpl(
|
||||
positionIncreaseConfiguration.walletId(),
|
||||
positionIncreaseConfiguration.signerKeyName(),
|
||||
solanaBlockChain
|
||||
);
|
||||
|
||||
JupiterPerpsService positionIncreaseJupiter =
|
||||
new AnchorIdlJupiterPerpsServiceImpl(
|
||||
solanaBlockChain,
|
||||
positionIncreaseWallet,
|
||||
currencyIdentityService
|
||||
);
|
||||
|
||||
JupiterPerpsPositionDecreaseAlarmActionConfiguration
|
||||
positionDecreaseConfiguration =
|
||||
JupiterPerpsPositionDecreaseAlarmActionConfigurationParser
|
||||
@@ -104,23 +110,11 @@ public final class JupiterPerpsAlarmImpl {
|
||||
variableResolver
|
||||
);
|
||||
|
||||
SolanaWallet positionDecreaseWallet = new SolanaWalletImpl(
|
||||
positionDecreaseConfiguration.walletId(),
|
||||
positionDecreaseConfiguration.signerKeyName(),
|
||||
solanaBlockChain
|
||||
);
|
||||
|
||||
JupiterPerpsService positionDecreaseJupiter =
|
||||
new AnchorIdlJupiterPerpsServiceImpl(
|
||||
solanaBlockChain,
|
||||
positionDecreaseWallet,
|
||||
currencyIdentityService
|
||||
);
|
||||
|
||||
JupiterPerpsEntryPriceVariableRefresher entryPriceVariableRefresher =
|
||||
new JupiterPerpsEntryPriceVariableRefresher(
|
||||
alarmConfiguration.variables(),
|
||||
positionIncreaseJupiter
|
||||
jupiterServicePerps,
|
||||
solanaWallet.getAddress()
|
||||
);
|
||||
System.out.println("Done.");
|
||||
|
||||
@@ -146,14 +140,14 @@ public final class JupiterPerpsAlarmImpl {
|
||||
actions.add(new ConsoleAlarmAction(alarmConfigurationDirectory));
|
||||
actions.add(new JupiterPerpsPositionIncreaseAlarmAction(
|
||||
positionIncreaseConfiguration,
|
||||
positionIncreaseWallet,
|
||||
positionIncreaseJupiter,
|
||||
solanaWallet,
|
||||
jupiterServicePerps,
|
||||
variableResolver
|
||||
));
|
||||
actions.add(new JupiterPerpsPositionDecreaseAlarmAction(
|
||||
positionDecreaseConfiguration,
|
||||
positionDecreaseWallet,
|
||||
positionDecreaseJupiter,
|
||||
solanaWallet,
|
||||
jupiterServicePerps,
|
||||
variableResolver
|
||||
));
|
||||
actions.add(new PushoverAlarmAction(
|
||||
@@ -215,7 +209,7 @@ public final class JupiterPerpsAlarmImpl {
|
||||
new CountDownLatch(1).await();
|
||||
}
|
||||
|
||||
private static void validateAlarmConditions(
|
||||
private void validateAlarmConditions(
|
||||
List<PriceAlarmDefinition> definitions,
|
||||
AlarmVariableResolver variableResolver
|
||||
) {
|
||||
@@ -244,7 +238,7 @@ public final class JupiterPerpsAlarmImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<JupiterPerpsAsset, List<PriceAlarmDefinition>> groupByAsset(
|
||||
private Map<JupiterPerpsAsset, List<PriceAlarmDefinition>> groupByAsset(
|
||||
List<PriceAlarmDefinition> definitions
|
||||
) {
|
||||
Map<JupiterPerpsAsset, List<PriceAlarmDefinition>> result = new EnumMap<>(
|
||||
@@ -258,19 +252,16 @@ public final class JupiterPerpsAlarmImpl {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void printUsage() {
|
||||
private void printUsage() {
|
||||
System.err.println("""
|
||||
Usage:
|
||||
gradle run
|
||||
gradle run --args='--config=/path/to/price-alarms.conf'
|
||||
JupiterPerpsAlarmImpl is constructed and started by NenjimHubImpl.
|
||||
|
||||
Options:
|
||||
--config=<path> Default: price-alarms.conf
|
||||
--ws=<url1,url2,...> Default: wss://api.mainnet-beta.solana.com
|
||||
Current Hub configuration:
|
||||
--config=conf/alarms.conf
|
||||
|
||||
Environment:
|
||||
PRICE_ALARMS_CONFIG Alternative default configuration path
|
||||
SOLANA_WS_URLS Comma-separated RPC WebSocket endpoints
|
||||
Default: wss://api.mainnet-beta.solana.com
|
||||
""");
|
||||
}
|
||||
|
||||
@@ -321,6 +312,9 @@ public final class JupiterPerpsAlarmImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private JupiterPerpsAlarmImpl() {
|
||||
}
|
||||
private final SolanaWallet solanaWallet;
|
||||
private final JupiterPerpsService jupiterServicePerps;
|
||||
private final String configFilename;
|
||||
|
||||
private final Thread thread;
|
||||
}
|
||||
|
||||
+6
-10
@@ -16,10 +16,12 @@ public final class JupiterPerpsEntryPriceVariableRefresher
|
||||
|
||||
public JupiterPerpsEntryPriceVariableRefresher(
|
||||
Map<String, String> variables,
|
||||
JupiterPerpsService jupiterPerpsService
|
||||
JupiterPerpsService jupiterPerpsService,
|
||||
ΩSolanaWalletIdΩ walletAddress
|
||||
) {
|
||||
this.variables = Objects.requireNonNull(variables, "variables");
|
||||
this.jupiterPerpsService = Objects.requireNonNull(jupiterPerpsService, "jupiterPerpsService");
|
||||
this.walletAddress = Objects.requireNonNull(walletAddress, "walletAddress");
|
||||
|
||||
scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> {
|
||||
Thread thread = new Thread(
|
||||
@@ -56,20 +58,13 @@ public final class JupiterPerpsEntryPriceVariableRefresher
|
||||
public synchronized void refresh() {
|
||||
System.out.println("Executing refresh now...");
|
||||
|
||||
ΩSolanaWalletIdΩ wallet = variables.get("JUPITER_PERPS_WALLET");
|
||||
|
||||
if (wallet == null || wallet.isBlank()) {
|
||||
System.err.println("Cannot refresh Jupiter Perps price variables: JUPITER_PERPS_WALLET is not configured");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
System.out.println(" Fetching 'Open Positions':");
|
||||
Set<JupiterPerpsPosition> positions = jupiterPerpsService.getOpenPositions(wallet);
|
||||
Set<JupiterPerpsPosition> positions = jupiterPerpsService.getOpenPositions(walletAddress);
|
||||
|
||||
System.out.println(
|
||||
"Fetched " + positions.size()
|
||||
+ " open Jupiter Perps positions for wallet: " + wallet
|
||||
+ " open Jupiter Perps positions for wallet: " + walletAddress
|
||||
);
|
||||
|
||||
|
||||
@@ -208,4 +203,5 @@ public final class JupiterPerpsEntryPriceVariableRefresher
|
||||
private final ScheduledExecutorService scheduler;
|
||||
private final Map<String, String> variables;
|
||||
private final JupiterPerpsService jupiterPerpsService;
|
||||
private final ΩSolanaWalletIdΩ walletAddress;
|
||||
}
|
||||
-14
@@ -8,14 +8,10 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public record JupiterPerpsPositionDecreaseAlarmActionConfiguration(
|
||||
ΩSolanaWalletIdΩ walletId,
|
||||
String signerKeyName,
|
||||
ΩUSDCAmountΩ reservePositionSizeUsdLimit,
|
||||
Map<Integer, PositionDecrease> positionDecreases
|
||||
) {
|
||||
public JupiterPerpsPositionDecreaseAlarmActionConfiguration {
|
||||
Objects.requireNonNull(walletId, "walletId");
|
||||
Objects.requireNonNull(signerKeyName, "signerKeyName");
|
||||
Objects.requireNonNull(reservePositionSizeUsdLimit, "reservePositionSizeUsdLimit");
|
||||
|
||||
if (reservePositionSizeUsdLimit.signum() < 0) {
|
||||
@@ -26,16 +22,6 @@ public record JupiterPerpsPositionDecreaseAlarmActionConfiguration(
|
||||
}
|
||||
|
||||
positionDecreases = Map.copyOf(positionDecreases);
|
||||
|
||||
if (walletId.isBlank()) {
|
||||
throw new IllegalArgumentException("Wallet id cannot be blank");
|
||||
}
|
||||
|
||||
if (signerKeyName.isBlank()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Signer key name cannot be blank"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public record PositionDecrease(
|
||||
|
||||
+2
-37
@@ -26,8 +26,6 @@ public final class JupiterPerpsPositionDecreaseAlarmActionConfigurationParser {
|
||||
);
|
||||
Map<Integer, JupiterPerpsPositionDecreaseAlarmActionConfiguration.PositionDecrease>
|
||||
positionDecreases = new LinkedHashMap<>();
|
||||
ΩSolanaWalletIdΩ walletId = null;
|
||||
String signerKeyName = null;
|
||||
ΩUSDCAmountΩ reservePositionSizeUsdLimit = null;
|
||||
|
||||
for (int lineNumber = 1; lineNumber <= lines.size(); lineNumber++) {
|
||||
@@ -44,27 +42,7 @@ public final class JupiterPerpsPositionDecreaseAlarmActionConfigurationParser {
|
||||
String[] columns = line.split("\\s+");
|
||||
String firstColumn = columns[0].toUpperCase(Locale.ROOT);
|
||||
|
||||
if (firstColumn.equals("WALLET_ID")) {
|
||||
requireColumnCount(columns, 2, "WALLET_ID value");
|
||||
if (walletId != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Duplicate WALLET_ID"
|
||||
);
|
||||
}
|
||||
walletId = variableResolver.resolve(columns[1]);
|
||||
} else if (firstColumn.equals("SIGNER_KEY_NAME")) {
|
||||
requireColumnCount(
|
||||
columns,
|
||||
2,
|
||||
"SIGNER_KEY_NAME value"
|
||||
);
|
||||
if (signerKeyName != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Duplicate SIGNER_KEY_NAME"
|
||||
);
|
||||
}
|
||||
signerKeyName = variableResolver.resolve(columns[1]);
|
||||
} else if (firstColumn.equals("RESERVE_POSITION_SIZE_USD_LIMIT")) {
|
||||
if (firstColumn.equals("RESERVE_POSITION_SIZE_USD_LIMIT")) {
|
||||
requireColumnCount(
|
||||
columns,
|
||||
2,
|
||||
@@ -94,17 +72,6 @@ public final class JupiterPerpsPositionDecreaseAlarmActionConfigurationParser {
|
||||
}
|
||||
}
|
||||
|
||||
if (walletId == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Missing WALLET_ID in " + path
|
||||
);
|
||||
}
|
||||
if (signerKeyName == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Missing SIGNER_KEY_NAME in " + path
|
||||
);
|
||||
}
|
||||
|
||||
if (reservePositionSizeUsdLimit == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Missing RESERVE_POSITION_SIZE_USD_LIMIT in " + path
|
||||
@@ -112,8 +79,6 @@ public final class JupiterPerpsPositionDecreaseAlarmActionConfigurationParser {
|
||||
}
|
||||
|
||||
return new JupiterPerpsPositionDecreaseAlarmActionConfiguration(
|
||||
walletId,
|
||||
signerKeyName,
|
||||
reservePositionSizeUsdLimit,
|
||||
positionDecreases
|
||||
);
|
||||
@@ -173,7 +138,7 @@ public final class JupiterPerpsPositionDecreaseAlarmActionConfigurationParser {
|
||||
: line.substring(0, commentStart);
|
||||
}
|
||||
|
||||
private static final int SUPPORTED_FORMAT_VERSION = 1;
|
||||
private static final int SUPPORTED_FORMAT_VERSION = 2;
|
||||
|
||||
private JupiterPerpsPositionDecreaseAlarmActionConfigurationParser() {
|
||||
}
|
||||
|
||||
-10
@@ -8,23 +8,13 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public record JupiterPerpsPositionIncreaseAlarmActionConfiguration(
|
||||
ΩSolanaWalletIdΩ walletId,
|
||||
String signerKeyName,
|
||||
ΩUSDCAmountΩ reserveUsdcLimit,
|
||||
Map<Integer, PositionIncrease> positionIncreases
|
||||
) {
|
||||
public JupiterPerpsPositionIncreaseAlarmActionConfiguration {
|
||||
Objects.requireNonNull(walletId, "walletId");
|
||||
Objects.requireNonNull(signerKeyName, "signerKeyName");
|
||||
Objects.requireNonNull(reserveUsdcLimit, "reserveUsdcLimit");
|
||||
positionIncreases = Map.copyOf(positionIncreases);
|
||||
|
||||
if (walletId.isBlank()) {
|
||||
throw new IllegalArgumentException("Wallet id cannot be blank");
|
||||
}
|
||||
if (signerKeyName.isBlank()) {
|
||||
throw new IllegalArgumentException("Signer key name cannot be blank");
|
||||
}
|
||||
if (reserveUsdcLimit.signum() < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"USDC reserve limit cannot be negative: " + reserveUsdcLimit
|
||||
|
||||
+2
-26
@@ -26,8 +26,6 @@ public final class JupiterPerpsPositionIncreaseAlarmActionConfigurationParser {
|
||||
);
|
||||
Map<Integer, JupiterPerpsPositionIncreaseAlarmActionConfiguration.PositionIncrease>
|
||||
positionIncreases = new LinkedHashMap<>();
|
||||
ΩSolanaWalletIdΩ walletId = null;
|
||||
String signerKeyName = null;
|
||||
ΩUSDCAmountΩ reserveUsdcLimit = null;
|
||||
|
||||
for (int lineNumber = 1; lineNumber <= lines.size(); lineNumber++) {
|
||||
@@ -44,19 +42,7 @@ public final class JupiterPerpsPositionIncreaseAlarmActionConfigurationParser {
|
||||
String[] columns = line.split("\\s+");
|
||||
String firstColumn = columns[0].toUpperCase(Locale.ROOT);
|
||||
|
||||
if (firstColumn.equals("WALLET_ID")) {
|
||||
requireColumnCount(columns, 2, "WALLET_ID value");
|
||||
if (walletId != null) {
|
||||
throw new IllegalArgumentException("Duplicate WALLET_ID");
|
||||
}
|
||||
walletId = variableResolver.resolve(columns[1]);
|
||||
} else if (firstColumn.equals("SIGNER_KEY_NAME")) {
|
||||
requireColumnCount(columns, 2, "SIGNER_KEY_NAME value");
|
||||
if (signerKeyName != null) {
|
||||
throw new IllegalArgumentException("Duplicate SIGNER_KEY_NAME");
|
||||
}
|
||||
signerKeyName = variableResolver.resolve(columns[1]);
|
||||
} else if (firstColumn.equals("RESERVE_USDC_LIMIT")) {
|
||||
if (firstColumn.equals("RESERVE_USDC_LIMIT")) {
|
||||
requireColumnCount(columns, 2, "RESERVE_USDC_LIMIT value");
|
||||
if (reserveUsdcLimit != null) {
|
||||
throw new IllegalArgumentException(
|
||||
@@ -81,14 +67,6 @@ public final class JupiterPerpsPositionIncreaseAlarmActionConfigurationParser {
|
||||
}
|
||||
}
|
||||
|
||||
if (walletId == null) {
|
||||
throw new IllegalArgumentException("Missing WALLET_ID in " + path);
|
||||
}
|
||||
|
||||
if (signerKeyName == null) {
|
||||
throw new IllegalArgumentException("Missing SIGNER_KEY_NAME in " + path);
|
||||
}
|
||||
|
||||
if (reserveUsdcLimit == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Missing RESERVE_USDC_LIMIT in " + path
|
||||
@@ -96,8 +74,6 @@ public final class JupiterPerpsPositionIncreaseAlarmActionConfigurationParser {
|
||||
}
|
||||
|
||||
return new JupiterPerpsPositionIncreaseAlarmActionConfiguration(
|
||||
walletId,
|
||||
signerKeyName,
|
||||
reserveUsdcLimit,
|
||||
positionIncreases
|
||||
);
|
||||
@@ -150,7 +126,7 @@ public final class JupiterPerpsPositionIncreaseAlarmActionConfigurationParser {
|
||||
return commentStart < 0 ? line : line.substring(0, commentStart);
|
||||
}
|
||||
|
||||
private static final int SUPPORTED_FORMAT_VERSION = 1;
|
||||
private static final int SUPPORTED_FORMAT_VERSION = 2;
|
||||
|
||||
private JupiterPerpsPositionIncreaseAlarmActionConfigurationParser() {
|
||||
}
|
||||
|
||||
@@ -1,24 +1,56 @@
|
||||
package com.r35157.libs.objcache;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Stores objects under structured keys for a caller-supplied time to live.
|
||||
*/
|
||||
public interface ObjectCache {
|
||||
|
||||
/**
|
||||
* Stores or replaces an object.
|
||||
*
|
||||
* <p>A time to live of zero makes the entry immediately expired.</p>
|
||||
*
|
||||
* @param key cache key
|
||||
* @param object object to cache
|
||||
* @param ttlMillis time to live in milliseconds
|
||||
* @throws NullPointerException if {@code key} or {@code object} is null
|
||||
* @throws IllegalArgumentException if {@code ttlMillis} is negative
|
||||
*/
|
||||
void put(
|
||||
ObjectCacheKey key,
|
||||
Object object,
|
||||
@NotNull ObjectCacheKey key,
|
||||
@NotNull Object object,
|
||||
long ttlMillis
|
||||
);
|
||||
|
||||
@Nullable
|
||||
Object get(
|
||||
ObjectCacheKey key
|
||||
/**
|
||||
* Returns the cached object when it exists and has not expired.
|
||||
*
|
||||
* <p>An expired entry is treated as absent and is removed lazily by
|
||||
* this operation.</p>
|
||||
*
|
||||
* @param key cache key
|
||||
* @return cached object, or {@code null} when absent or expired
|
||||
* @throws NullPointerException if {@code key} is null
|
||||
*/
|
||||
@Nullable Object get(
|
||||
@NotNull ObjectCacheKey key
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes an entry when present.
|
||||
*
|
||||
* @param key cache key
|
||||
* @throws NullPointerException if {@code key} is null
|
||||
*/
|
||||
void remove(
|
||||
ObjectCacheKey key
|
||||
@NotNull ObjectCacheKey key
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes all entries.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.r35157.libs.objcache.impl.ref;
|
||||
|
||||
import com.r35157.libs.objcache.ObjectCache;
|
||||
import com.r35157.libs.objcache.ObjectCacheKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
@@ -10,10 +11,14 @@ import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public final class ObjectCacheImpl implements ObjectCache {
|
||||
|
||||
public ObjectCacheImpl() {
|
||||
objects = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(
|
||||
ObjectCacheKey key,
|
||||
Object object,
|
||||
@NotNull ObjectCacheKey key,
|
||||
@NotNull Object object,
|
||||
long ttlMillis
|
||||
) {
|
||||
Objects.requireNonNull(key);
|
||||
@@ -37,7 +42,7 @@ public final class ObjectCacheImpl implements ObjectCache {
|
||||
|
||||
@Override
|
||||
public @Nullable Object get(
|
||||
ObjectCacheKey key
|
||||
@NotNull ObjectCacheKey key
|
||||
) {
|
||||
Objects.requireNonNull(key);
|
||||
|
||||
@@ -57,7 +62,7 @@ public final class ObjectCacheImpl implements ObjectCache {
|
||||
|
||||
@Override
|
||||
public void remove(
|
||||
ObjectCacheKey key
|
||||
@NotNull ObjectCacheKey key
|
||||
) {
|
||||
Objects.requireNonNull(key);
|
||||
objects.remove(key);
|
||||
@@ -68,9 +73,6 @@ public final class ObjectCacheImpl implements ObjectCache {
|
||||
objects.clear();
|
||||
}
|
||||
|
||||
private final ConcurrentMap<
|
||||
ObjectCacheKey,
|
||||
ObjectCacheEntry
|
||||
> objects = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<ObjectCacheKey, ObjectCacheEntry> objects;
|
||||
|
||||
}
|
||||
@@ -41,16 +41,27 @@ import static com.r35157.libs.solana.valuetypes.economic.SolanaSPLTokenProgram.T
|
||||
public class RaydiumImpl implements Raydium {
|
||||
|
||||
public RaydiumImpl(
|
||||
HttpClient httpClient,
|
||||
ObjectMapper objectMapper,
|
||||
SolanaBlockChain solanaBlockChain,
|
||||
CurrencyIdentityService currencyIdentityService
|
||||
) {
|
||||
this.solanaBlockChain = Objects.requireNonNull(solanaBlockChain, "solanaBlockChain");
|
||||
this.httpClient = Objects.requireNonNull(
|
||||
httpClient,
|
||||
"httpClient"
|
||||
);
|
||||
this.objectMapper = Objects.requireNonNull(
|
||||
objectMapper,
|
||||
"objectMapper"
|
||||
);
|
||||
this.solanaBlockChain = Objects.requireNonNull(
|
||||
solanaBlockChain,
|
||||
"solanaBlockChain"
|
||||
);
|
||||
this.currencyIdentityService = Objects.requireNonNull(
|
||||
currencyIdentityService,
|
||||
"currencyIdentityService"
|
||||
);
|
||||
this.httpClient = HttpClient.newHttpClient();
|
||||
this.objectMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.r35157.libs.solana.*;
|
||||
import com.r35157.libs.solana.valuetypes.SolanaProgramDerivedAddress;
|
||||
import com.r35157.libs.solana.valuetypes.economic.SolanaSPLTokenProgram;
|
||||
import com.r35157.libs.valuetypes.basic.MoneyAmount;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -37,13 +38,23 @@ import static com.r35157.libs.solana.SolanaConstants.RPC_URL;
|
||||
|
||||
public class SolanaBlockChainImpl implements SolanaBlockChain {
|
||||
|
||||
public SolanaBlockChainImpl(CurrencyIdentityService currencyIdentityService) {
|
||||
public SolanaBlockChainImpl(
|
||||
@NotNull HttpClient httpClient,
|
||||
@NotNull ObjectMapper objectMapper,
|
||||
@NotNull CurrencyIdentityService currencyIdentityService
|
||||
) {
|
||||
this.httpClient = Objects.requireNonNull(
|
||||
httpClient,
|
||||
"httpClient"
|
||||
);
|
||||
this.objectMapper = Objects.requireNonNull(
|
||||
objectMapper,
|
||||
"objectMapper"
|
||||
);
|
||||
this.currencyIdentityService = Objects.requireNonNull(
|
||||
currencyIdentityService,
|
||||
"currencyIdentityService"
|
||||
);
|
||||
this.httpClient = HttpClient.newHttpClient();
|
||||
this.objectMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,7 +12,6 @@ public final class NenjimComposerImpl implements NenjimComposer {
|
||||
}
|
||||
|
||||
private void showWindow() {
|
||||
|
||||
var window = new Stage();
|
||||
window.setTitle("Nenjim Composer");
|
||||
window.show();
|
||||
|
||||
@@ -6,17 +6,27 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Coordinates the lifecycle of Nenjim services and applications.
|
||||
*/
|
||||
public interface NenjimHub {
|
||||
/**
|
||||
* Start the NenjimHub - This is the first thing to do
|
||||
* Starts all initialized services and applications in dependency order,
|
||||
* then blocks while the Hub remains online.
|
||||
*
|
||||
* @throws Exception if startup or shutdown waiting fails
|
||||
*/
|
||||
void start() throws Exception;
|
||||
|
||||
/**
|
||||
* Starts a process based on the provided fully qualified interface name.
|
||||
* The actual implementation that is run is binded according to the Context.
|
||||
* Requests startup of the implementation bound to a fully qualified process
|
||||
* interface name in the active context.
|
||||
*
|
||||
* @param fqInterfaceName the fully qualified interface name of the process to start. The interface must extend the {@code NenjimProcess} interface.
|
||||
* <p>Dynamic binding through this method is not yet implemented by the
|
||||
* reference Hub.</p>
|
||||
*
|
||||
* @param fqInterfaceName fully qualified interface name; the interface must
|
||||
* extend {@link NenjimProcess}
|
||||
*/
|
||||
void startProcess(String fqInterfaceName);
|
||||
|
||||
@@ -28,8 +38,7 @@ public interface NenjimHub {
|
||||
HashMap<Integer, NenjimProcess> getRunningProcesses();
|
||||
|
||||
/**
|
||||
* A no-operation (noop). This method is suppoted to do nothing.
|
||||
* Performs no operation.
|
||||
*/
|
||||
void noop();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,87 +1,12 @@
|
||||
package com.r35157.nenjim.hubd.impl.ref;
|
||||
|
||||
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
||||
import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
||||
import com.r35157.libs.jupiter.perps.impl.anchoridl.AnchorIdlJupiterPerpsServiceImpl;
|
||||
import com.r35157.libs.solana.SolanaBlockChain;
|
||||
import com.r35157.libs.solana.impl.ref.SolanaBlockChainImpl;
|
||||
import com.r35157.nenjim.hubd.ctx.Context;
|
||||
import com.r35157.nenjim.hubd.NenjimHub;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.lang.management.ClassLoadingMXBean;
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
import com.r35157.nenjim.hubd.ctx.ContextManager;
|
||||
import com.r35157.nenjim.hubd.journal.JournalManager;
|
||||
import com.r35157.nenjim.hubd.impl.ref.JournalManagerImpl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
|
||||
public class Main {
|
||||
|
||||
// TODO: Consider if we really need a Main class or we just need to move the main method to NenjimHubImpl?
|
||||
static void main(String[] args) throws Exception {
|
||||
static void main() throws Exception {
|
||||
NenjimHub nenjimHub = new NenjimHubImpl();
|
||||
nenjimHub.start();
|
||||
|
||||
/*SolanaBlockChain sbc = new SolanaBlockChainImpl();
|
||||
JupiterPerpsService jupiter = new AnchorIdlJupiterPerpsServiceImpl(sbc);
|
||||
ΩSolanaWalletIdΩ walletId = "vj98roDZ7744EBfxyuDFkKpEGCsKQLr7K8UFRumJNHf";
|
||||
Set<JupiterPerpsPosition> positions = jupiter.getOpenPositions(walletId);
|
||||
*/
|
||||
|
||||
/*while(true) {
|
||||
String addr = "31eu4pNE2vb8ErASGoJDHZXvjezhuE2PxjdnuQcCbUv7";
|
||||
JupiterPerpsPosition pos = jupiter.getPosition(addr);
|
||||
ΩUSDCAmountΩ a = pos.borrowFeesDue();
|
||||
}*/
|
||||
//int i = 0;
|
||||
|
||||
/* try {
|
||||
log.info("Auto-starting 2 Nenjim application(s)...");
|
||||
log.info(" Starting AssetAZCore...");
|
||||
//com.r35157.;
|
||||
|
||||
log.info(" Starting jupiterperpsalarm...");
|
||||
String[] params = new String[] {
|
||||
"--config=/home/minimons/projects/com_r35157_nenjim-hubd-impl_ref/conf/alarms.conf"
|
||||
};
|
||||
com.r35157.jupiterperpsalarm.Main.main(params);
|
||||
*/
|
||||
//hub = new NenjimHubImpl();
|
||||
|
||||
/*
|
||||
String classesCacheDirRaw = "~/.config/nenjim/cache/classes";
|
||||
String classesCacheDir = (classesCacheDirRaw.startsWith("~/"))
|
||||
? System.getProperty("user.home") + classesCacheDirRaw.substring(1)
|
||||
: classesCacheDirRaw;
|
||||
Path pathToClassesCache = Path.of(classesCacheDir);
|
||||
|
||||
if(Files.exists(pathToClassesCache) == false) {
|
||||
System.err.println("Cannot find '" + classesCacheDirRaw + "'");
|
||||
System.exit(-1);
|
||||
}*/
|
||||
|
||||
//System.out.println("Initializing initial NenjimClassLoader with default context...");
|
||||
//JournalManager journalManager = new JournalManagerImpl();
|
||||
//ContextManager contextManager = new ContextManagerImpl();
|
||||
//Context defaultContext = contextManager.getDefault();
|
||||
|
||||
//NenjimClassLoader nenjimClassLoader = new NenjimClassLoader(journalManager, defaultContext);
|
||||
//Class<?> clazz = nenjimClassLoader.findClass("com.r35157.nenjim.hubd.impl.ref.NenjimHubImpl");
|
||||
|
||||
/*NenjimHub nenjimHub = null;
|
||||
Context defaultContext = new Context();
|
||||
|
||||
Object instance = clazz.getDeclaredConstructor().newInstance();
|
||||
NenjimKicker kicker = (NenjimKicker)instance;
|
||||
*/
|
||||
//int a = 0;
|
||||
}
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Main.class);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.r35157.nenjim.hubd.impl.ref;
|
||||
|
||||
import com.fanitas.evelyn.core.Evelyn;
|
||||
import com.fanitas.evelyn.core.impl.ref.EvelynImpl;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.r35157.assetaz.services.ticker.plugins.pricesource.PriceSource;
|
||||
import com.r35157.assetaz.services.ticker.TickerService;
|
||||
import com.r35157.assetaz.services.ticker.plugins.pricesource.impl.hardcoded.HardcodedPriceSource;
|
||||
@@ -9,9 +10,17 @@ import com.r35157.assetaz.services.ticker.plugins.pricesource.impl.raydiumpool.R
|
||||
import com.r35157.assetaz.services.ticker.impl.ref.TickerServiceImpl;
|
||||
import com.r35157.assetaz.services.cis.CurrencyIdentityService;
|
||||
import com.r35157.assetaz.services.cis.impl.hc.HardcodedCurrencyIdentityService;
|
||||
import com.r35157.cryptowallet.solana.SolanaWallet;
|
||||
import com.r35157.cryptowallet.solana.impl.ref.SolanaWalletImpl;
|
||||
import com.r35157.evelyn.emc.EvelynMissionControl;
|
||||
import com.r35157.evelyn.emc.impl.ref.EvelynMissionControlImpl;
|
||||
import com.r35157.jupiterperpsalarm.JupiterPerpsAlarm;
|
||||
import com.r35157.jupiterperpsalarm.impl.ref.JupiterPerpsAlarmImpl;
|
||||
import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
||||
import com.r35157.libs.jupiter.perps.impl.anchoridl.AnchorIdlJupiterPerpsServiceImpl;
|
||||
import com.r35157.libs.objcache.ObjectCache;
|
||||
import com.r35157.libs.objcache.impl.ref.ObjectCacheImpl;
|
||||
import com.r35157.libs.solana.impl.cached.CachedSolanaBlockChain;
|
||||
import com.r35157.nenjim.composer.NenjimComposer;
|
||||
import com.r35157.nenjim.composer.impl.ref.NenjimComposerImpl;
|
||||
import com.r35157.nenjim.hubd.NenjimHub;
|
||||
@@ -32,6 +41,8 @@ import crypto.r35157.nenjim.NenjimProcess;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.http.HttpClient;
|
||||
import java.time.Clock;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
@@ -39,9 +50,11 @@ import static com.r35157.assetaz.services.cis.CurrencyTypeIds.EVE_ID;
|
||||
import static com.r35157.assetaz.services.cis.CurrencyTypeIds.USDT_ID;
|
||||
|
||||
public class NenjimHubImpl implements NenjimHub {
|
||||
public NenjimHubImpl() throws Exception {
|
||||
public NenjimHubImpl() {
|
||||
log.info("Initializing NenjimHub...");
|
||||
|
||||
initializeAll();
|
||||
|
||||
nextProcessId = 1;
|
||||
//processesScope = new StructuredTaskScope.ShutdownOnFailure();
|
||||
processes = new HashMap<>();
|
||||
@@ -49,85 +62,35 @@ public class NenjimHubImpl implements NenjimHub {
|
||||
|
||||
@Override
|
||||
public void start() throws Exception {
|
||||
log.info("Starting autorun processes:");
|
||||
startAutoRunProcesses();
|
||||
|
||||
log.info("Starting:");
|
||||
log.info(" Services...");
|
||||
tickerService.start();
|
||||
jupiterPerpsAlarm.start();
|
||||
evelynServiceProd.start();
|
||||
evelynServiceTest.start();
|
||||
|
||||
log.info(" Applications...");
|
||||
missionControl.start();
|
||||
nenjimComposer.start();
|
||||
processManager.start();
|
||||
testTool.start();
|
||||
sodaTaskManager.start();
|
||||
suwimoClient.start();
|
||||
|
||||
System.out.println("Done - Now online!");
|
||||
|
||||
waitForAndShutdown();
|
||||
}
|
||||
|
||||
private void waitForAndShutdown() throws InterruptedException {
|
||||
System.out.println("Done - Now online!");
|
||||
|
||||
/*
|
||||
try {
|
||||
processesScope.join();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
processesScope.close();
|
||||
*/
|
||||
|
||||
awaitShutdown();
|
||||
|
||||
System.out.println("Nenjim is now shutdown (stopped all processes)!");
|
||||
@Override
|
||||
public HashMap<Integer, NenjimProcess> getRunningProcesses() {
|
||||
return processes;
|
||||
}
|
||||
|
||||
private void startAutoRunProcesses() {
|
||||
CurrencyIdentityService cis = new HardcodedCurrencyIdentityService();
|
||||
SolanaBlockChain solanaBlockChain = new SolanaBlockChainImpl(cis);
|
||||
Raydium raydium = new RaydiumImpl(solanaBlockChain, cis);
|
||||
|
||||
//PriceSource hardcodedPriceSource = new HardcodedPriceSource(cis);
|
||||
PriceSource raydiumPoolPriceSource = createEVEUSDTPriceSource(cis, raydium);
|
||||
|
||||
TickerService tickerService = startAssetAZTickerService(raydiumPoolPriceSource);
|
||||
|
||||
//startJupiterPerpsAlarm(cis);
|
||||
|
||||
TradingPair eveUsdt = createEVEUSDTTradingPair(cis);
|
||||
Evelyn evelynProd = new EvelynImpl("Production", tickerService, eveUsdt);
|
||||
Evelyn evelynTest = new EvelynImpl("Test", tickerService, eveUsdt);
|
||||
evelynProd.start();
|
||||
evelynTest.start();
|
||||
startEvelynMissionControl(evelynProd, evelynTest);
|
||||
//startNenjimComposer();
|
||||
//startNenjimProcessManager();
|
||||
//startNenjimTestTool();
|
||||
//startSodaTaskManager();
|
||||
//startSuwimoClient();
|
||||
|
||||
// TODO: Old but more correct way to auto start plugins - but it is currently broken.
|
||||
/*
|
||||
String[] processesToAutoStart = {
|
||||
//"com.r35157.jupiterperpsalarm.impl.ref.JupiterPerpsAlarmImpl"
|
||||
//"crypto.r35157.nenjim.NenjimHubSocketAdminAdapter",
|
||||
//"crypto.r35157.nenjim.NenjimHubRestAdminAdapter",
|
||||
//"crypto.r35157.nenjim.NenjimHubRPCAdminAdapter",
|
||||
//"crypto.r35157.nenjim.SuwimoHub",
|
||||
//"crypto.r35157.nenjim.SodaTaskManager",
|
||||
//"crypto.r35157.assetaz.hub.AssetAZHub"
|
||||
};
|
||||
|
||||
for (String processInterfaceName : processesToAutoStart) {
|
||||
startProcess(processInterfaceName);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private PriceSource createEVEUSDTPriceSource(CurrencyIdentityService cis, Raydium raydium) {
|
||||
TradingPair eveUsdt = createEVEUSDTTradingPair(cis);
|
||||
PriceSource priceSource = new RaydiumPoolPriceSource(raydium, EVE_USDT_RAYDIUM_POOL_ID, eveUsdt);
|
||||
|
||||
return priceSource;
|
||||
}
|
||||
|
||||
private TradingPair createEVEUSDTTradingPair(CurrencyIdentityService cis) {
|
||||
return new TradingPair(cis.resolve(EVE_ID), cis.resolve(USDT_ID));
|
||||
}
|
||||
|
||||
private TickerService startAssetAZTickerService(PriceSource... priceSources) {
|
||||
TickerService tickerService = new TickerServiceImpl(priceSources);
|
||||
tickerService.start();
|
||||
return tickerService;
|
||||
@Override
|
||||
public void noop() {
|
||||
System.out.println("NenjimHub command: 'noop'");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,126 +120,115 @@ public class NenjimHubImpl implements NenjimHub {
|
||||
});*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<Integer, NenjimProcess> getRunningProcesses() {
|
||||
return processes;
|
||||
private void initializeAll() {
|
||||
log.info(" Initializing building blocks...");
|
||||
initializeBuildingBlocks();
|
||||
|
||||
log.info(" Initializing plugins...");
|
||||
initializePlugins();
|
||||
|
||||
log.info(" Initializing services...");
|
||||
initializeServices();
|
||||
|
||||
log.info(" Initializing applications...");
|
||||
initializeApplications();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noop() {
|
||||
System.out.println("NenjimHub command: 'noop'");
|
||||
private void initializeBuildingBlocks() {
|
||||
objectCache = new ObjectCacheImpl();
|
||||
clockUTC = Clock.systemUTC();
|
||||
cis = new HardcodedCurrencyIdentityService();
|
||||
httpClient = HttpClient.newHttpClient();
|
||||
objectMapper = new ObjectMapper();
|
||||
solanaBlockChain = new SolanaBlockChainImpl(httpClient, objectMapper, cis);
|
||||
cachedSolanaBlockChain = new CachedSolanaBlockChain(solanaBlockChain, objectCache);
|
||||
raydium = new RaydiumImpl(httpClient, objectMapper, cachedSolanaBlockChain, cis);
|
||||
eveUSDT = new TradingPair(cis.resolve(EVE_ID), cis.resolve(USDT_ID));
|
||||
solanaWalletEvelynPerpsTest = new SolanaWalletImpl(
|
||||
"6NyYEoXmJyBXvU4pvv9aoxZNdyqqtkmPBZFEDkRDHcqp",
|
||||
"evelyn_perps_test",
|
||||
solanaBlockChain
|
||||
);
|
||||
solanaWalletEvelynPerpsProd = new SolanaWalletImpl(
|
||||
"H5Yrdm7B4FHhTxhPw9SVwFzQyTEL6bAPptZuTyRxcepq",
|
||||
"evelyn_perps_prod",
|
||||
solanaBlockChain
|
||||
);
|
||||
}
|
||||
|
||||
private void awaitShutdown() throws InterruptedException {
|
||||
private void initializePlugins() {
|
||||
hardcodedPriceSource = new HardcodedPriceSource(cis);
|
||||
raydiumPoolPriceSource = new RaydiumPoolPriceSource(raydium, EVE_USDT_RAYDIUM_POOL_ID, eveUSDT);
|
||||
}
|
||||
|
||||
private void initializeServices() {
|
||||
tickerService = new TickerServiceImpl(
|
||||
//hardcodedPriceSource, // Activating this could be dangerous as other services rely on these prices
|
||||
raydiumPoolPriceSource
|
||||
);
|
||||
|
||||
jupiterServicePerpsProd = new AnchorIdlJupiterPerpsServiceImpl(
|
||||
cachedSolanaBlockChain,
|
||||
solanaWalletEvelynPerpsProd,
|
||||
cis
|
||||
);
|
||||
|
||||
jupiterServicePerpsTest = new AnchorIdlJupiterPerpsServiceImpl(
|
||||
cachedSolanaBlockChain,
|
||||
solanaWalletEvelynPerpsTest,
|
||||
cis
|
||||
);
|
||||
|
||||
jupiterPerpsAlarm = new JupiterPerpsAlarmImpl(
|
||||
solanaWalletEvelynPerpsTest,
|
||||
jupiterServicePerpsTest,
|
||||
"--config=conf/alarms.conf"
|
||||
);
|
||||
|
||||
evelynServiceProd = new EvelynImpl("Production", tickerService, eveUSDT, clockUTC);
|
||||
|
||||
evelynServiceTest = new EvelynImpl("Test", tickerService, eveUSDT, clockUTC);
|
||||
|
||||
// TODO: Old but more correct way to auto start plugins - but it is currently broken.
|
||||
/*
|
||||
String[] processesToAutoStart = {
|
||||
//"com.r35157.jupiterperpsalarm.impl.ref.JupiterPerpsAlarmImpl"
|
||||
//"crypto.r35157.nenjim.NenjimHubSocketAdminAdapter",
|
||||
//"crypto.r35157.nenjim.NenjimHubRestAdminAdapter",
|
||||
//"crypto.r35157.nenjim.NenjimHubRPCAdminAdapter",
|
||||
//"crypto.r35157.nenjim.SuwimoHub",
|
||||
//"crypto.r35157.nenjim.SodaTaskManager",
|
||||
//"crypto.r35157.assetaz.hub.AssetAZHub"
|
||||
};
|
||||
|
||||
for (String processInterfaceName : processesToAutoStart) {
|
||||
startProcess(processInterfaceName);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private void initializeApplications() {
|
||||
nenjimComposer = new NenjimComposerImpl();
|
||||
processManager = new NenjimProcessManagerImpl();
|
||||
testTool = new NenjimTestToolImpl();
|
||||
sodaTaskManager = new SodaTaskManagerImpl();
|
||||
missionControl = new EvelynMissionControlImpl(evelynServiceProd, evelynServiceTest);
|
||||
suwimoClient = new SuwimoClientImpl();
|
||||
}
|
||||
|
||||
private void waitForAndShutdown() throws InterruptedException {
|
||||
/*
|
||||
try {
|
||||
processesScope.join();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
processesScope.close();
|
||||
*/
|
||||
|
||||
shutdownLatch.await();
|
||||
}
|
||||
|
||||
private void startJupiterPerpsAlarm(
|
||||
CurrencyIdentityService currencyIdentityService
|
||||
) {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
JupiterPerpsAlarmImpl.start(
|
||||
new String[] {"--config=conf/alarms.conf"},
|
||||
currencyIdentityService
|
||||
);
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}, "Nenjim Plugin - JupiterPerpsAlarm");
|
||||
|
||||
thread.setDaemon(false);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private void startEvelynMissionControl(Evelyn evelynProd, Evelyn evelynTest) {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
EvelynMissionControl emc = new EvelynMissionControlImpl(evelynProd, evelynTest);
|
||||
emc.start();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}, "Nenjim Plugin - Evelyn Mission Control");
|
||||
|
||||
thread.setDaemon(false);
|
||||
thread.start();
|
||||
|
||||
}
|
||||
|
||||
private void startNenjimComposer() {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
NenjimComposer nc = new NenjimComposerImpl();
|
||||
nc.start();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}, "Nenjim Plugin - Nenjim Composer");
|
||||
|
||||
thread.setDaemon(false);
|
||||
thread.start();
|
||||
|
||||
}
|
||||
|
||||
private void startNenjimProcessManager() {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
NenjimProcessManager npm = new NenjimProcessManagerImpl();
|
||||
npm.start();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}, "Nenjim Plugin - Nenjim Process Manager");
|
||||
|
||||
thread.setDaemon(false);
|
||||
thread.start();
|
||||
|
||||
}
|
||||
|
||||
private void startNenjimTestTool() {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
NenjimTestTool ntt = new NenjimTestToolImpl();
|
||||
ntt.start();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}, "Nenjim Plugin - Nenjim Test Tool");
|
||||
|
||||
thread.setDaemon(false);
|
||||
thread.start();
|
||||
|
||||
}
|
||||
|
||||
private void startSodaTaskManager() {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
SodaTaskManager stm = new SodaTaskManagerImpl();
|
||||
stm.start();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}, "Nenjim Plugin - Soda Task Manager");
|
||||
|
||||
thread.setDaemon(false);
|
||||
thread.start();
|
||||
|
||||
}
|
||||
|
||||
private void startSuwimoClient() {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
SuwimoClient client = new SuwimoClientImpl();
|
||||
client.start();
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}, "Nenjim Plugin - Suwimo Client");
|
||||
|
||||
thread.setDaemon(false);
|
||||
thread.start();
|
||||
|
||||
System.out.println("Nenjim is now shutdown (stopped all processes)!");
|
||||
}
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(NenjimHubImpl.class);
|
||||
@@ -287,4 +239,38 @@ public class NenjimHubImpl implements NenjimHub {
|
||||
private HashMap<Integer, NenjimProcess> processes;
|
||||
//private StructuredTaskScope.ShutdownOnFailure processesScope;
|
||||
private int nextProcessId;
|
||||
|
||||
// Dependency components
|
||||
private ObjectCache objectCache;
|
||||
private Clock clockUTC;
|
||||
private CurrencyIdentityService cis;
|
||||
private SolanaBlockChain solanaBlockChain;
|
||||
private SolanaBlockChain cachedSolanaBlockChain;
|
||||
private Raydium raydium;
|
||||
private TradingPair eveUSDT;
|
||||
private HttpClient httpClient;
|
||||
private ObjectMapper objectMapper;
|
||||
private SolanaWallet evelynPerpsProd;
|
||||
private SolanaWallet solanaWalletEvelynPerpsProd;
|
||||
private SolanaWallet solanaWalletEvelynPerpsTest;
|
||||
private JupiterPerpsService jupiterServicePerpsProd;
|
||||
private JupiterPerpsService jupiterServicePerpsTest;
|
||||
|
||||
// Plugins
|
||||
private PriceSource hardcodedPriceSource;
|
||||
private PriceSource raydiumPoolPriceSource;
|
||||
|
||||
// Services
|
||||
private TickerService tickerService;
|
||||
private JupiterPerpsAlarm jupiterPerpsAlarm;
|
||||
private Evelyn evelynServiceProd;
|
||||
private Evelyn evelynServiceTest;
|
||||
|
||||
// Applications
|
||||
private EvelynMissionControl missionControl;
|
||||
private NenjimComposer nenjimComposer;
|
||||
private NenjimProcessManager processManager;
|
||||
private NenjimTestTool testTool;
|
||||
private SodaTaskManager sodaTaskManager;
|
||||
private SuwimoClient suwimoClient;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.r35157.libs.solana.impl.ref;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.r35157.assetaz.services.cis.CurrencyIdentityService;
|
||||
import com.r35157.assetaz.services.cis.ExternalCurrencyReference;
|
||||
import com.r35157.assetaz.valuetypes.CurrencyType;
|
||||
@@ -10,6 +11,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.net.http.HttpClient;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
@@ -154,7 +156,11 @@ class SolanaBlockChainImplTest {
|
||||
long fee,
|
||||
AtomicReference<String> feeMessage
|
||||
) {
|
||||
return new SolanaBlockChainImpl(CURRENCY_IDENTITIES) {
|
||||
return new SolanaBlockChainImpl(
|
||||
HTTP_CLIENT,
|
||||
OBJECT_MAPPER,
|
||||
CURRENCY_IDENTITIES
|
||||
) {
|
||||
@Override
|
||||
public long getBalanceInLamport(String address) {
|
||||
return balance;
|
||||
@@ -215,6 +221,8 @@ class SolanaBlockChainImplTest {
|
||||
return Set.of();
|
||||
}
|
||||
};
|
||||
private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
private static final String SENDER =
|
||||
"So11111111111111111111111111111111111111112";
|
||||
private static final String RECIPIENT =
|
||||
|
||||
Reference in New Issue
Block a user