41: Skip Jupiter Perps position increase when USDC balance is insufficient
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
################################################################
|
||||
WALLET_ID {{JUPITER_PERPS_WALLET}}
|
||||
SIGNER_KEY_NAME <SIGNER>
|
||||
|
||||
RESERVE_USDC_LIMIT 10
|
||||
|
||||
# Id Asset Direction CollateralUSDC SizeDeltaUSD MaxSlippageBPS
|
||||
############################################################################
|
||||
|
||||
+48
@@ -6,11 +6,15 @@ import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
||||
import com.r35157.libs.solana.SolanaBlockChain;
|
||||
import com.r35157.libs.solana.SolanaSignedTransaction;
|
||||
import com.r35157.libs.solana.SolanaUnsignedTransaction;
|
||||
import com.r35157.libs.valuetypes.basic.MoneyAmount;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.r35157.libs.solana.valuetypes.economic.SolanaSPLTokenProgram.SPL_TOKEN_PROGRAM;
|
||||
|
||||
public final class JupiterPerpsPositionIncreaseAlarmAction implements ConfiguredAlarmAction {
|
||||
public JupiterPerpsPositionIncreaseAlarmAction(
|
||||
Path configurationDirectory,
|
||||
@@ -51,6 +55,10 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured
|
||||
JupiterPerpsPositionIncreaseAlarmActionConfiguration.ResolvedPositionIncrease
|
||||
positionIncrease = definition.resolve(variableResolver);
|
||||
|
||||
if (!isUSDCBalanceOk(positionIncrease)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SolanaUnsignedTransaction utrans =
|
||||
jupiter.buildPositionIncreaseTransaction(
|
||||
wallet.getAddress(),
|
||||
@@ -60,6 +68,7 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured
|
||||
positionIncrease.sizeUsdDelta(),
|
||||
positionIncrease.maxSlippageBps()
|
||||
);
|
||||
|
||||
SolanaSignedTransaction strans = wallet.signTransaction(utrans);
|
||||
ΩSolanaTransactionSignatureΩ signature = jupiter.executePositionIncreaseTransaction(strans);
|
||||
System.out.println("Position Increase Signature: " + signature);
|
||||
@@ -68,6 +77,45 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isUSDCBalanceOk(JupiterPerpsPositionIncreaseAlarmActionConfiguration.ResolvedPositionIncrease positionIncrease)
|
||||
throws IOException, InterruptedException {
|
||||
ΩAmountΩ usdcBalance = wallet.getSPLTokenBalance(
|
||||
JupiterPerpsReceiveToken.USDC.receiveTokenMint(),
|
||||
SPL_TOKEN_PROGRAM
|
||||
);
|
||||
|
||||
if (usdcBalance == null) {
|
||||
System.err.println("Position Increase of "
|
||||
+ positionIncrease.collateralUsd()
|
||||
+ " USDC skipped: Wallet has no USDC token account!"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
ΩUSDCAmountΩ collateralUsd = positionIncrease.collateralUsd();
|
||||
ΩUSDCAmountΩ reserveUsdcLimit = configuration.reserveUsdcLimit();
|
||||
ΩUSDCAmountΩ requiredUsdcBalance = collateralUsd.add(reserveUsdcLimit);
|
||||
|
||||
if (usdcBalance.compareTo(requiredUsdcBalance) < 0) {
|
||||
System.err.println(
|
||||
"Position Increase of "
|
||||
+ positionIncrease.collateralUsd()
|
||||
+ " USDC skipped: Wallet has "
|
||||
+ usdcBalance
|
||||
+ " USDC, but "
|
||||
+ requiredUsdcBalance
|
||||
+ " USDC is required ("
|
||||
+ collateralUsd
|
||||
+ " collateral + "
|
||||
+ reserveUsdcLimit
|
||||
+ " reserve)."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private final JupiterPerpsPositionIncreaseAlarmActionConfiguration configuration;
|
||||
private final SolanaWallet wallet;
|
||||
private final JupiterPerpsService jupiter;
|
||||
|
||||
+7
@@ -10,11 +10,13 @@ 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()) {
|
||||
@@ -23,6 +25,11 @@ public record JupiterPerpsPositionIncreaseAlarmActionConfiguration(
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public record PositionIncrease(
|
||||
|
||||
+20
@@ -1,6 +1,7 @@
|
||||
package com.r35157.jupiterperpsalarm.impl.ref;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -20,6 +21,7 @@ public final class JupiterPerpsPositionIncreaseAlarmActionConfigurationParser {
|
||||
positionIncreases = new LinkedHashMap<>();
|
||||
ΩSolanaWalletIdΩ walletId = null;
|
||||
String signerKeyName = null;
|
||||
ΩUSDCAmountΩ reserveUsdcLimit = null;
|
||||
|
||||
for (int lineNumber = 1; lineNumber <= lines.size(); lineNumber++) {
|
||||
String line = removeComment(lines.get(lineNumber - 1)).trim();
|
||||
@@ -43,6 +45,16 @@ public final class JupiterPerpsPositionIncreaseAlarmActionConfigurationParser {
|
||||
throw new IllegalArgumentException("Duplicate SIGNER_KEY_NAME");
|
||||
}
|
||||
signerKeyName = variableResolver.resolve(columns[1]);
|
||||
} else if (firstColumn.equals("RESERVE_USDC_LIMIT")) {
|
||||
requireColumnCount(columns, 2, "RESERVE_USDC_LIMIT value");
|
||||
if (reserveUsdcLimit != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Duplicate RESERVE_USDC_LIMIT"
|
||||
);
|
||||
}
|
||||
reserveUsdcLimit = new ΩUSDCAmountΩ(
|
||||
variableResolver.resolve(columns[1])
|
||||
);
|
||||
} else {
|
||||
parsePositionIncrease(
|
||||
columns,
|
||||
@@ -61,13 +73,21 @@ 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
|
||||
);
|
||||
}
|
||||
|
||||
return new JupiterPerpsPositionIncreaseAlarmActionConfiguration(
|
||||
walletId,
|
||||
signerKeyName,
|
||||
reserveUsdcLimit,
|
||||
positionIncreases
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user