49: Complete wallet-bound Jupiter transaction flow

This commit is contained in:
2026-08-05 10:12:39 +02:00
parent a65a9ed043
commit 847c33000a
7 changed files with 240 additions and 76 deletions
@@ -1,5 +1,7 @@
package com.r35157.jupiterperpsalarm.impl.ref; package com.r35157.jupiterperpsalarm.impl.ref;
import com.r35157.cryptowallet.solana.SolanaWallet;
import com.r35157.cryptowallet.solana.impl.ref.SolanaWalletImpl;
import com.r35157.libs.jupiter.perps.JupiterPerpsService; import com.r35157.libs.jupiter.perps.JupiterPerpsService;
import com.r35157.libs.jupiter.perps.impl.anchoridl.AnchorIdlJupiterPerpsServiceImpl; import com.r35157.libs.jupiter.perps.impl.anchoridl.AnchorIdlJupiterPerpsServiceImpl;
import com.r35157.libs.objcache.ObjectCache; import com.r35157.libs.objcache.ObjectCache;
@@ -49,6 +51,10 @@ public final class JupiterPerpsAlarmImpl {
alarmConfiguration.variables() alarmConfiguration.variables()
); );
Path alarmConfigurationDirectory = config.alarmConfiguration()
.toAbsolutePath()
.getParent();
System.out.print("Initializing dependencies... "); System.out.print("Initializing dependencies... ");
ObjectCache objectCache = new ObjectCacheImpl(); ObjectCache objectCache = new ObjectCacheImpl();
SolanaBlockChain realSolanaBlockChain = new SolanaBlockChainImpl(); SolanaBlockChain realSolanaBlockChain = new SolanaBlockChainImpl();
@@ -57,9 +63,57 @@ public final class JupiterPerpsAlarmImpl {
objectCache objectCache
); );
JupiterPerpsService jupiterPerpsService = new AnchorIdlJupiterPerpsServiceImpl(solanaBlockChain); JupiterPerpsPositionIncreaseAlarmActionConfiguration
positionIncreaseConfiguration =
JupiterPerpsPositionIncreaseAlarmActionConfigurationParser
.parse(
alarmConfigurationDirectory.resolve(
JupiterPerpsPositionIncreaseAlarmAction
.CONFIGURATION_FILE_NAME
),
variableResolver
);
SolanaWallet positionIncreaseWallet = new SolanaWalletImpl(
positionIncreaseConfiguration.walletId(),
positionIncreaseConfiguration.signerKeyName(),
solanaBlockChain
);
JupiterPerpsService positionIncreaseJupiter =
new AnchorIdlJupiterPerpsServiceImpl(
solanaBlockChain,
positionIncreaseWallet
);
JupiterPerpsPositionDecreaseAlarmActionConfiguration
positionDecreaseConfiguration =
JupiterPerpsPositionDecreaseAlarmActionConfigurationParser
.parse(
alarmConfigurationDirectory.resolve(
JupiterPerpsPositionDecreaseAlarmAction
.CONFIGURATION_FILE_NAME
),
variableResolver
);
SolanaWallet positionDecreaseWallet = new SolanaWalletImpl(
positionDecreaseConfiguration.walletId(),
positionDecreaseConfiguration.signerKeyName(),
solanaBlockChain
);
JupiterPerpsService positionDecreaseJupiter =
new AnchorIdlJupiterPerpsServiceImpl(
solanaBlockChain,
positionDecreaseWallet
);
JupiterPerpsEntryPriceVariableRefresher entryPriceVariableRefresher = JupiterPerpsEntryPriceVariableRefresher entryPriceVariableRefresher =
new JupiterPerpsEntryPriceVariableRefresher(alarmConfiguration.variables(), jupiterPerpsService); new JupiterPerpsEntryPriceVariableRefresher(
alarmConfiguration.variables(),
positionIncreaseJupiter
);
System.out.println("Done."); System.out.println("Done.");
System.out.println("Executing first pre-run data fetch:"); System.out.println("Executing first pre-run data fetch:");
@@ -80,22 +134,18 @@ public final class JupiterPerpsAlarmImpl {
entryPriceVariableRefreshWatcher.start(); entryPriceVariableRefreshWatcher.start();
Path alarmConfigurationDirectory = config.alarmConfiguration()
.toAbsolutePath()
.getParent();
List<AlarmAction> actions = new ArrayList<>(); List<AlarmAction> actions = new ArrayList<>();
actions.add(new ConsoleAlarmAction(alarmConfigurationDirectory)); actions.add(new ConsoleAlarmAction(alarmConfigurationDirectory));
actions.add(new JupiterPerpsPositionIncreaseAlarmAction( actions.add(new JupiterPerpsPositionIncreaseAlarmAction(
alarmConfigurationDirectory, positionIncreaseConfiguration,
solanaBlockChain, positionIncreaseWallet,
jupiterPerpsService, positionIncreaseJupiter,
variableResolver variableResolver
)); ));
actions.add(new JupiterPerpsPositionDecreaseAlarmAction( actions.add(new JupiterPerpsPositionDecreaseAlarmAction(
alarmConfigurationDirectory, positionDecreaseConfiguration,
solanaBlockChain, positionDecreaseWallet,
jupiterPerpsService, positionDecreaseJupiter,
variableResolver variableResolver
)); ));
actions.add(new PushoverAlarmAction( actions.add(new PushoverAlarmAction(
@@ -1,53 +1,36 @@
package com.r35157.jupiterperpsalarm.impl.ref; package com.r35157.jupiterperpsalarm.impl.ref;
import com.r35157.cryptowallet.solana.SolanaWallet; import com.r35157.cryptowallet.solana.SolanaWallet;
import com.r35157.cryptowallet.solana.impl.ref.SolanaWalletImpl;
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition; import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
import com.r35157.libs.jupiter.perps.JupiterPerpsService; import com.r35157.libs.jupiter.perps.JupiterPerpsService;
import com.r35157.libs.solana.SolanaBlockChain;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.nio.file.Path;
import java.util.Objects; import java.util.Objects;
public final class JupiterPerpsPositionDecreaseAlarmAction public final class JupiterPerpsPositionDecreaseAlarmAction
implements ConfiguredAlarmAction { implements ConfiguredAlarmAction {
public JupiterPerpsPositionDecreaseAlarmAction( public JupiterPerpsPositionDecreaseAlarmAction(
Path configurationDirectory, JupiterPerpsPositionDecreaseAlarmActionConfiguration configuration,
SolanaBlockChain solanaBlockChain, SolanaWallet wallet,
JupiterPerpsService jupiter, JupiterPerpsService jupiter,
AlarmVariableResolver variableResolver AlarmVariableResolver variableResolver
) throws IOException { ) {
Objects.requireNonNull( this.configuration = Objects.requireNonNull(
configurationDirectory, configuration,
"configurationDirectory" "configuration"
); );
Objects.requireNonNull(solanaBlockChain, "solanaBlockChain"); this.wallet = Objects.requireNonNull(wallet, "wallet");
this.jupiter = Objects.requireNonNull(jupiter, "jupiter"); this.jupiter = Objects.requireNonNull(jupiter, "jupiter");
this.variableResolver = Objects.requireNonNull( this.variableResolver = Objects.requireNonNull(
variableResolver, variableResolver,
"variableResolver" "variableResolver"
); );
configuration =
JupiterPerpsPositionDecreaseAlarmActionConfigurationParser
.parse(
configurationDirectory.resolve(
getConfigurationFileName()
),
variableResolver
);
wallet = new SolanaWalletImpl(
configuration.walletId(),
configuration.signerKeyName(),
solanaBlockChain
);
} }
@Override @Override
public String getConfigurationFileName() { public String getConfigurationFileName() {
return "alarmaction_JupiterPerpsPositionDecreaseAlarmAction.conf"; return CONFIGURATION_FILE_NAME;
} }
@Override @Override
@@ -73,7 +56,6 @@ public final class JupiterPerpsPositionDecreaseAlarmAction
ΩSolanaTransactionSignatureΩ signature = ΩSolanaTransactionSignatureΩ signature =
jupiter.executePositionDecrease( jupiter.executePositionDecrease(
wallet,
position.positionAccount(), position.positionAccount(),
positionDecrease.receiveToken() positionDecrease.receiveToken()
.receiveTokenMint(), .receiveTokenMint(),
@@ -173,4 +155,7 @@ public final class JupiterPerpsPositionDecreaseAlarmAction
private final SolanaWallet wallet; private final SolanaWallet wallet;
private final JupiterPerpsService jupiter; private final JupiterPerpsService jupiter;
private final AlarmVariableResolver variableResolver; private final AlarmVariableResolver variableResolver;
static final String CONFIGURATION_FILE_NAME =
"alarmaction_JupiterPerpsPositionDecreaseAlarmAction.conf";
} }
@@ -1,44 +1,34 @@
package com.r35157.jupiterperpsalarm.impl.ref; package com.r35157.jupiterperpsalarm.impl.ref;
import com.r35157.cryptowallet.solana.SolanaWallet; import com.r35157.cryptowallet.solana.SolanaWallet;
import com.r35157.cryptowallet.solana.impl.ref.SolanaWalletImpl;
import com.r35157.libs.jupiter.perps.JupiterPerpsService; import com.r35157.libs.jupiter.perps.JupiterPerpsService;
import com.r35157.libs.solana.SolanaBlockChain;
import com.r35157.libs.valuetypes.basic.MoneyAmount; import com.r35157.libs.valuetypes.basic.MoneyAmount;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
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; 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, JupiterPerpsPositionIncreaseAlarmActionConfiguration configuration,
SolanaBlockChain solanaBlockChain, SolanaWallet wallet,
JupiterPerpsService jupiter, JupiterPerpsService jupiter,
AlarmVariableResolver variableResolver AlarmVariableResolver variableResolver
) throws IOException { ) {
Objects.requireNonNull(configurationDirectory, "configurationDirectory"); this.configuration = Objects.requireNonNull(
Objects.requireNonNull(solanaBlockChain, "solanaBlockChain"); configuration,
"configuration"
);
this.wallet = Objects.requireNonNull(wallet, "wallet");
this.jupiter = Objects.requireNonNull(jupiter, "jupiter"); this.jupiter = Objects.requireNonNull(jupiter, "jupiter");
this.variableResolver = Objects.requireNonNull(variableResolver, "variableResolver"); this.variableResolver = Objects.requireNonNull(variableResolver, "variableResolver");
configuration = JupiterPerpsPositionIncreaseAlarmActionConfigurationParser.parse(
configurationDirectory.resolve(getConfigurationFileName()),
variableResolver
);
wallet = new SolanaWalletImpl(
configuration.walletId(),
configuration.signerKeyName(),
solanaBlockChain
);
} }
@Override @Override
public String getConfigurationFileName() { public String getConfigurationFileName() {
return "alarmaction_JupiterPerpsPositionIncreaseAlarmAction.conf"; return CONFIGURATION_FILE_NAME;
} }
@Override @Override
@@ -59,7 +49,6 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured
ΩSolanaTransactionSignatureΩ signature = ΩSolanaTransactionSignatureΩ signature =
jupiter.executePositionIncrease( jupiter.executePositionIncrease(
wallet,
positionIncrease.asset().tradedTokenMint(), positionIncrease.asset().tradedTokenMint(),
positionIncrease.direction(), positionIncrease.direction(),
positionIncrease.collateralUsd(), positionIncrease.collateralUsd(),
@@ -116,4 +105,7 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured
private final SolanaWallet wallet; private final SolanaWallet wallet;
private final JupiterPerpsService jupiter; private final JupiterPerpsService jupiter;
private final AlarmVariableResolver variableResolver; private final AlarmVariableResolver variableResolver;
static final String CONFIGURATION_FILE_NAME =
"alarmaction_JupiterPerpsPositionIncreaseAlarmAction.conf";
} }
@@ -1,6 +1,5 @@
package com.r35157.libs.jupiter.perps; package com.r35157.libs.jupiter.perps;
import com.r35157.cryptowallet.solana.SolanaWallet;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -10,10 +9,10 @@ import java.util.Set;
/** /**
* Service for reading Jupiter Perps data and executing complete position * Service for reading Jupiter Perps data and executing complete position
* operations. * operations for its configured wallet.
* *
* <p>For position mutations, the service constructs the required transaction * <p>The service constructs and submits Jupiter transactions, while its
* and delegates signing and submission to the supplied wallet.</p> * configured wallet is responsible for signing them.</p>
*/ */
public interface JupiterPerpsService { public interface JupiterPerpsService {
/** /**
@@ -49,10 +48,9 @@ public interface JupiterPerpsService {
/** /**
* Opens or increases a Jupiter Perps position. * Opens or increases a Jupiter Perps position.
* *
* <p>The service constructs the transaction and asks the supplied wallet * <p>The service constructs the transaction, asks its configured wallet
* to sign and submit it.</p> * to sign it, and submits it to Jupiter.</p>
* *
* @param wallet the wallet that owns or will own the position
* @param tradedTokenMint the mint address of the asset being traded * @param tradedTokenMint the mint address of the asset being traded
* @param direction whether the position is long or short * @param direction whether the position is long or short
* @param inputTokenAmount the amount of USDC to supply as collateral * @param inputTokenAmount the amount of USDC to supply as collateral
@@ -65,7 +63,6 @@ public interface JupiterPerpsService {
*/ */
@NotNull @NotNull
ΩSolanaTransactionSignatureΩ executePositionIncrease( ΩSolanaTransactionSignatureΩ executePositionIncrease(
@NotNull SolanaWallet wallet,
@NotNull ΩSPLMintAddressΩ tradedTokenMint, @NotNull ΩSPLMintAddressΩ tradedTokenMint,
@NotNull JupiterPerpsPositionDirection direction, @NotNull JupiterPerpsPositionDirection direction,
@NotNull ΩUSDCAmountΩ inputTokenAmount, @NotNull ΩUSDCAmountΩ inputTokenAmount,
@@ -76,10 +73,9 @@ public interface JupiterPerpsService {
/** /**
* Decreases an existing Jupiter Perps position. * Decreases an existing Jupiter Perps position.
* *
* <p>The service constructs the transaction and asks the supplied wallet * <p>The service constructs the transaction, asks its configured wallet
* to sign and submit it.</p> * to sign it, and submits it to Jupiter.</p>
* *
* @param wallet the wallet that owns the position
* @param positionAccount the Jupiter Perps position to decrease * @param positionAccount the Jupiter Perps position to decrease
* @param receiveTokenMint the mint address of the token to receive * @param receiveTokenMint the mint address of the token to receive
* @param sizeUsdDelta the requested decrease in position size, denominated in USD * @param sizeUsdDelta the requested decrease in position size, denominated in USD
@@ -91,7 +87,6 @@ public interface JupiterPerpsService {
*/ */
@NotNull @NotNull
ΩSolanaTransactionSignatureΩ executePositionDecrease( ΩSolanaTransactionSignatureΩ executePositionDecrease(
@NotNull SolanaWallet wallet,
@NotNull ΩJupiterPerpsPositionAccountΩ positionAccount, @NotNull ΩJupiterPerpsPositionAccountΩ positionAccount,
@NotNull ΩSPLMintAddressΩ receiveTokenMint, @NotNull ΩSPLMintAddressΩ receiveTokenMint,
@NotNull ΩUSDCAmountΩ sizeUsdDelta, @NotNull ΩUSDCAmountΩ sizeUsdDelta,
@@ -7,12 +7,15 @@ import com.r35157.libs.jupiter.perps.JupiterPerpsPositionDirection;
import com.r35157.libs.jupiter.perps.JupiterPerpsService; import com.r35157.libs.jupiter.perps.JupiterPerpsService;
import com.r35157.libs.jupiter.perps.protocol.DecreasePositionRequest; import com.r35157.libs.jupiter.perps.protocol.DecreasePositionRequest;
import com.r35157.libs.jupiter.perps.protocol.DecreasePositionResponse; import com.r35157.libs.jupiter.perps.protocol.DecreasePositionResponse;
import com.r35157.libs.jupiter.perps.protocol.ExecuteTransactionRequest;
import com.r35157.libs.jupiter.perps.protocol.ExecuteTransactionResponse;
import com.r35157.libs.jupiter.perps.protocol.IncreasePositionRequest; import com.r35157.libs.jupiter.perps.protocol.IncreasePositionRequest;
import com.r35157.libs.jupiter.perps.protocol.IncreasePositionResponse; import com.r35157.libs.jupiter.perps.protocol.IncreasePositionResponse;
import com.r35157.libs.jupiter.perps.protocol.TransactionMetadata; import com.r35157.libs.jupiter.perps.protocol.TransactionMetadata;
import com.r35157.libs.solana.SolanaAccountInfo; import com.r35157.libs.solana.SolanaAccountInfo;
import com.r35157.libs.solana.SolanaBlockChain; import com.r35157.libs.solana.SolanaBlockChain;
import com.r35157.libs.solana.SolanaProgramAccountMemcmpFilter; import com.r35157.libs.solana.SolanaProgramAccountMemcmpFilter;
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 com.r35157.libs.valuetypes.basic.MoneyAmount;
import com.r35157.libs.valuetypes.basic.WellKnownCurrencyTypes; import com.r35157.libs.valuetypes.basic.WellKnownCurrencyTypes;
@@ -28,6 +31,7 @@ import java.net.http.HttpClient;
import java.net.http.HttpRequest; import java.net.http.HttpRequest;
import java.net.http.HttpResponse; import java.net.http.HttpResponse;
import java.util.HashSet; import java.util.HashSet;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import static java.math.BigDecimal.ZERO; import static java.math.BigDecimal.ZERO;
@@ -35,9 +39,14 @@ import static java.math.BigDecimal.ZERO;
public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService { public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
public AnchorIdlJupiterPerpsServiceImpl( public AnchorIdlJupiterPerpsServiceImpl(
SolanaBlockChain solanaBlockChain SolanaBlockChain solanaBlockChain,
SolanaWallet wallet
) { ) {
this.solanaBlockChain = solanaBlockChain; this.solanaBlockChain = Objects.requireNonNull(
solanaBlockChain,
"solanaBlockChain"
);
this.wallet = Objects.requireNonNull(wallet, "wallet");
this.positionDecoder = new AnchorIdlJupiterPerpsPositionDecoder(); this.positionDecoder = new AnchorIdlJupiterPerpsPositionDecoder();
this.custodyDecoder = new AnchorIdlJupiterPerpsCustodyDecoder(); this.custodyDecoder = new AnchorIdlJupiterPerpsCustodyDecoder();
} }
@@ -113,7 +122,6 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
@Override @Override
public @NotNull ΩSolanaTransactionSignatureΩ executePositionIncrease( public @NotNull ΩSolanaTransactionSignatureΩ executePositionIncrease(
@NotNull SolanaWallet wallet,
@NotNull ΩSPLMintAddressΩ tradedTokenMint, @NotNull ΩSPLMintAddressΩ tradedTokenMint,
@NotNull JupiterPerpsPositionDirection direction, @NotNull JupiterPerpsPositionDirection direction,
@NotNull ΩUSDCAmountΩ inputTokenAmount, @NotNull ΩUSDCAmountΩ inputTokenAmount,
@@ -130,7 +138,10 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
maxSlippageBps maxSlippageBps
); );
return wallet.signAndSendTransaction(unsignedTransaction); SolanaSignedTransaction signedTransaction =
wallet.signTransaction(unsignedTransaction);
return executePositionIncreaseTransaction(signedTransaction);
} }
private @NotNull SolanaUnsignedTransaction buildPositionIncreaseTransaction( private @NotNull SolanaUnsignedTransaction buildPositionIncreaseTransaction(
@@ -183,9 +194,38 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
} }
} }
private @NotNull ΩSolanaTransactionSignatureΩ
executePositionIncreaseTransaction(
@NotNull SolanaSignedTransaction transaction
) throws IOException, InterruptedException {
if (transaction.serializedTransaction() == null
|| transaction.serializedTransaction().isBlank()) {
throw new IllegalArgumentException(
"Signed transaction must not be blank"
);
}
ExecuteTransactionRequest request =
new ExecuteTransactionRequest(
"increase-position",
transaction.serializedTransaction()
);
ExecuteTransactionResponse response =
requestTransactionExecution(request);
if (response.txid() == null || response.txid().isBlank()) {
throw new IOException(
"Jupiter transaction execution response did not "
+ "contain a transaction signature"
);
}
return response.txid();
}
@Override @Override
public @NotNull ΩSolanaTransactionSignatureΩ executePositionDecrease( public @NotNull ΩSolanaTransactionSignatureΩ executePositionDecrease(
@NotNull SolanaWallet wallet,
@NotNull ΩJupiterPerpsPositionAccountΩ positionAccount, @NotNull ΩJupiterPerpsPositionAccountΩ positionAccount,
@NotNull ΩSPLMintAddressΩ receiveTokenMint, @NotNull ΩSPLMintAddressΩ receiveTokenMint,
@NotNull ΩUSDCAmountΩ sizeUsdDelta, @NotNull ΩUSDCAmountΩ sizeUsdDelta,
@@ -199,7 +239,10 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
maxSlippageBps maxSlippageBps
); );
return wallet.signAndSendTransaction(unsignedTransaction); SolanaSignedTransaction signedTransaction =
wallet.signTransaction(unsignedTransaction);
return executePositionDecreaseTransaction(signedTransaction);
} }
private @NotNull SolanaUnsignedTransaction buildPositionDecreaseTransaction( private @NotNull SolanaUnsignedTransaction buildPositionDecreaseTransaction(
@@ -248,6 +291,36 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
} }
} }
private @NotNull ΩSolanaTransactionSignatureΩ
executePositionDecreaseTransaction(
@NotNull SolanaSignedTransaction transaction
) throws IOException, InterruptedException {
if (transaction.serializedTransaction() == null
|| transaction.serializedTransaction().isBlank()) {
throw new IllegalArgumentException(
"Signed transaction must not be blank"
);
}
ExecuteTransactionRequest request =
new ExecuteTransactionRequest(
"decrease-position",
transaction.serializedTransaction()
);
ExecuteTransactionResponse response =
requestTransactionExecution(request);
if (response.txid() == null || response.txid().isBlank()) {
throw new IOException(
"Jupiter transaction execution response did not "
+ "contain a transaction signature"
);
}
return response.txid();
}
private static DecreasePositionRequest buildDecreasePositionRequest( private static DecreasePositionRequest buildDecreasePositionRequest(
ΩJupiterPerpsPositionAccountΩ positionAccount, ΩJupiterPerpsPositionAccountΩ positionAccount,
ΩSPLMintAddressΩ receiveTokenMint, ΩSPLMintAddressΩ receiveTokenMint,
@@ -674,11 +747,51 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
return response; return response;
} }
private static ExecuteTransactionResponse requestTransactionExecution(
ExecuteTransactionRequest request
) throws IOException, InterruptedException {
String requestJson =
OBJECT_MAPPER.writeValueAsString(request);
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(EXECUTE_TRANSACTION_ENDPOINT)
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.header("x-client-platform", "nenjim-hub")
.POST(HttpRequest.BodyPublishers.ofString(requestJson))
.build();
HttpResponse<String> httpResponse = HTTP_CLIENT.send(
httpRequest,
HttpResponse.BodyHandlers.ofString()
);
if (httpResponse.statusCode() < 200
|| httpResponse.statusCode() >= 300) {
throw new IOException(
"Jupiter transaction execution failed with HTTP "
+ httpResponse.statusCode()
+ ": "
+ httpResponse.body()
);
}
return OBJECT_MAPPER.readValue(
httpResponse.body(),
ExecuteTransactionResponse.class
);
}
private static final ΩSPLMintAddressΩ BTC_MINT = "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh"; private static final ΩSPLMintAddressΩ BTC_MINT = "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh";
private static final ΩSPLMintAddressΩ ETH_MINT = "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs"; private static final ΩSPLMintAddressΩ ETH_MINT = "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs";
private static final ΩSPLMintAddressΩ SOL_MINT = "So11111111111111111111111111111111111111112"; private static final ΩSPLMintAddressΩ SOL_MINT = "So11111111111111111111111111111111111111112";
private static final ΩSPLMintAddressΩ USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"; private static final ΩSPLMintAddressΩ USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
private static final URI EXECUTE_TRANSACTION_ENDPOINT =
URI.create(
"https://perps-api.jup.ag/v2/transaction/execute"
);
private static final URI DECREASE_POSITION_ENDPOINT = private static final URI DECREASE_POSITION_ENDPOINT =
URI.create( URI.create(
"https://perps-api.jup.ag/v2/positions/decrease" "https://perps-api.jup.ag/v2/positions/decrease"
@@ -697,6 +810,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
private static final int USDC_DECIMALS = 6; private static final int USDC_DECIMALS = 6;
private final SolanaBlockChain solanaBlockChain; private final SolanaBlockChain solanaBlockChain;
private final SolanaWallet wallet;
private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder; private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder;
private final AnchorIdlJupiterPerpsCustodyDecoder custodyDecoder; private final AnchorIdlJupiterPerpsCustodyDecoder custodyDecoder;
} }
@@ -0,0 +1,14 @@
package com.r35157.libs.jupiter.perps.protocol;
/**
* Jupiter Perps protocol request for executing a signed transaction.
*
* @param action the Jupiter transaction action
* @param serializedTxBase64 the complete signed Solana transaction,
* encoded as Base64
*/
public record ExecuteTransactionRequest(
String action,
String serializedTxBase64
) {
}
@@ -0,0 +1,14 @@
package com.r35157.libs.jupiter.perps.protocol;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* Relevant fields returned by Jupiter after executing a transaction.
*
* @param txid the Solana transaction signature
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public record ExecuteTransactionResponse(
String txid
) {
}