41: Skip Jupiter Perps position increase when USDC balance is insufficient
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
# Wallet and signer used for position-increase transactions
|
# Wallet and signer used for position-increase transactions
|
||||||
################################################################
|
################################################################
|
||||||
WALLET_ID {{JUPITER_PERPS_WALLET}}
|
WALLET_ID {{JUPITER_PERPS_WALLET}}
|
||||||
SIGNER_KEY_NAME <SIGNER>
|
SIGNER_KEY_NAME <SIGNER>
|
||||||
|
RESERVE_USDC_LIMIT 10
|
||||||
|
|
||||||
# Id Asset Direction CollateralUSDC SizeDeltaUSD MaxSlippageBPS
|
# 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.SolanaBlockChain;
|
||||||
import com.r35157.libs.solana.SolanaSignedTransaction;
|
import com.r35157.libs.solana.SolanaSignedTransaction;
|
||||||
import com.r35157.libs.solana.SolanaUnsignedTransaction;
|
import com.r35157.libs.solana.SolanaUnsignedTransaction;
|
||||||
|
import com.r35157.libs.valuetypes.basic.MoneyAmount;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static com.r35157.libs.solana.valuetypes.economic.SolanaSPLTokenProgram.SPL_TOKEN_PROGRAM;
|
||||||
|
|
||||||
public final class JupiterPerpsPositionIncreaseAlarmAction implements ConfiguredAlarmAction {
|
public final class JupiterPerpsPositionIncreaseAlarmAction implements ConfiguredAlarmAction {
|
||||||
public JupiterPerpsPositionIncreaseAlarmAction(
|
public JupiterPerpsPositionIncreaseAlarmAction(
|
||||||
Path configurationDirectory,
|
Path configurationDirectory,
|
||||||
@@ -51,6 +55,10 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured
|
|||||||
JupiterPerpsPositionIncreaseAlarmActionConfiguration.ResolvedPositionIncrease
|
JupiterPerpsPositionIncreaseAlarmActionConfiguration.ResolvedPositionIncrease
|
||||||
positionIncrease = definition.resolve(variableResolver);
|
positionIncrease = definition.resolve(variableResolver);
|
||||||
|
|
||||||
|
if (!isUSDCBalanceOk(positionIncrease)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SolanaUnsignedTransaction utrans =
|
SolanaUnsignedTransaction utrans =
|
||||||
jupiter.buildPositionIncreaseTransaction(
|
jupiter.buildPositionIncreaseTransaction(
|
||||||
wallet.getAddress(),
|
wallet.getAddress(),
|
||||||
@@ -60,6 +68,7 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured
|
|||||||
positionIncrease.sizeUsdDelta(),
|
positionIncrease.sizeUsdDelta(),
|
||||||
positionIncrease.maxSlippageBps()
|
positionIncrease.maxSlippageBps()
|
||||||
);
|
);
|
||||||
|
|
||||||
SolanaSignedTransaction strans = wallet.signTransaction(utrans);
|
SolanaSignedTransaction strans = wallet.signTransaction(utrans);
|
||||||
ΩSolanaTransactionSignatureΩ signature = jupiter.executePositionIncreaseTransaction(strans);
|
ΩSolanaTransactionSignatureΩ signature = jupiter.executePositionIncreaseTransaction(strans);
|
||||||
System.out.println("Position Increase Signature: " + signature);
|
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 JupiterPerpsPositionIncreaseAlarmActionConfiguration configuration;
|
||||||
private final SolanaWallet wallet;
|
private final SolanaWallet wallet;
|
||||||
private final JupiterPerpsService jupiter;
|
private final JupiterPerpsService jupiter;
|
||||||
|
|||||||
+7
@@ -10,11 +10,13 @@ import java.util.Objects;
|
|||||||
public record JupiterPerpsPositionIncreaseAlarmActionConfiguration(
|
public record JupiterPerpsPositionIncreaseAlarmActionConfiguration(
|
||||||
ΩSolanaWalletIdΩ walletId,
|
ΩSolanaWalletIdΩ walletId,
|
||||||
String signerKeyName,
|
String signerKeyName,
|
||||||
|
ΩUSDCAmountΩ reserveUsdcLimit,
|
||||||
Map<Integer, PositionIncrease> positionIncreases
|
Map<Integer, PositionIncrease> positionIncreases
|
||||||
) {
|
) {
|
||||||
public JupiterPerpsPositionIncreaseAlarmActionConfiguration {
|
public JupiterPerpsPositionIncreaseAlarmActionConfiguration {
|
||||||
Objects.requireNonNull(walletId, "walletId");
|
Objects.requireNonNull(walletId, "walletId");
|
||||||
Objects.requireNonNull(signerKeyName, "signerKeyName");
|
Objects.requireNonNull(signerKeyName, "signerKeyName");
|
||||||
|
Objects.requireNonNull(reserveUsdcLimit, "reserveUsdcLimit");
|
||||||
positionIncreases = Map.copyOf(positionIncreases);
|
positionIncreases = Map.copyOf(positionIncreases);
|
||||||
|
|
||||||
if (walletId.isBlank()) {
|
if (walletId.isBlank()) {
|
||||||
@@ -23,6 +25,11 @@ public record JupiterPerpsPositionIncreaseAlarmActionConfiguration(
|
|||||||
if (signerKeyName.isBlank()) {
|
if (signerKeyName.isBlank()) {
|
||||||
throw new IllegalArgumentException("Signer key name cannot be blank");
|
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(
|
public record PositionIncrease(
|
||||||
|
|||||||
+20
@@ -1,6 +1,7 @@
|
|||||||
package com.r35157.jupiterperpsalarm.impl.ref;
|
package com.r35157.jupiterperpsalarm.impl.ref;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@@ -20,6 +21,7 @@ public final class JupiterPerpsPositionIncreaseAlarmActionConfigurationParser {
|
|||||||
positionIncreases = new LinkedHashMap<>();
|
positionIncreases = new LinkedHashMap<>();
|
||||||
ΩSolanaWalletIdΩ walletId = null;
|
ΩSolanaWalletIdΩ walletId = null;
|
||||||
String signerKeyName = null;
|
String signerKeyName = null;
|
||||||
|
ΩUSDCAmountΩ reserveUsdcLimit = null;
|
||||||
|
|
||||||
for (int lineNumber = 1; lineNumber <= lines.size(); lineNumber++) {
|
for (int lineNumber = 1; lineNumber <= lines.size(); lineNumber++) {
|
||||||
String line = removeComment(lines.get(lineNumber - 1)).trim();
|
String line = removeComment(lines.get(lineNumber - 1)).trim();
|
||||||
@@ -43,6 +45,16 @@ public final class JupiterPerpsPositionIncreaseAlarmActionConfigurationParser {
|
|||||||
throw new IllegalArgumentException("Duplicate SIGNER_KEY_NAME");
|
throw new IllegalArgumentException("Duplicate SIGNER_KEY_NAME");
|
||||||
}
|
}
|
||||||
signerKeyName = variableResolver.resolve(columns[1]);
|
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 {
|
} else {
|
||||||
parsePositionIncrease(
|
parsePositionIncrease(
|
||||||
columns,
|
columns,
|
||||||
@@ -61,13 +73,21 @@ public final class JupiterPerpsPositionIncreaseAlarmActionConfigurationParser {
|
|||||||
if (walletId == null) {
|
if (walletId == null) {
|
||||||
throw new IllegalArgumentException("Missing WALLET_ID in " + path);
|
throw new IllegalArgumentException("Missing WALLET_ID in " + path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signerKeyName == null) {
|
if (signerKeyName == null) {
|
||||||
throw new IllegalArgumentException("Missing SIGNER_KEY_NAME in " + path);
|
throw new IllegalArgumentException("Missing SIGNER_KEY_NAME in " + path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reserveUsdcLimit == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Missing RESERVE_USDC_LIMIT in " + path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return new JupiterPerpsPositionIncreaseAlarmActionConfiguration(
|
return new JupiterPerpsPositionIncreaseAlarmActionConfiguration(
|
||||||
walletId,
|
walletId,
|
||||||
signerKeyName,
|
signerKeyName,
|
||||||
|
reserveUsdcLimit,
|
||||||
positionIncreases
|
positionIncreases
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user