From 847c33000a35cc43a404ab88661c7ff1f6ca2725 Mon Sep 17 00:00:00 2001 From: Minimons Date: Wed, 29 Jul 2026 08:56:40 +0200 Subject: [PATCH] 49: Complete wallet-bound Jupiter transaction flow --- .../impl/ref/JupiterPerpsAlarmImpl.tjava | 74 ++++++++-- ...iterPerpsPositionDecreaseAlarmAction.tjava | 37 ++--- ...iterPerpsPositionIncreaseAlarmAction.tjava | 32 ++--- .../jupiter/perps/JupiterPerpsService.tjava | 19 +-- .../AnchorIdlJupiterPerpsServiceImpl.tjava | 126 +++++++++++++++++- .../protocol/ExecuteTransactionRequest.tjava | 14 ++ .../protocol/ExecuteTransactionResponse.tjava | 14 ++ 7 files changed, 240 insertions(+), 76 deletions(-) create mode 100644 src/main/tjava/com/r35157/libs/jupiter/perps/protocol/ExecuteTransactionRequest.tjava create mode 100644 src/main/tjava/com/r35157/libs/jupiter/perps/protocol/ExecuteTransactionResponse.tjava diff --git a/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsAlarmImpl.tjava b/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsAlarmImpl.tjava index e3bc2db..1b63c9f 100644 --- a/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsAlarmImpl.tjava +++ b/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsAlarmImpl.tjava @@ -1,5 +1,7 @@ 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.impl.anchoridl.AnchorIdlJupiterPerpsServiceImpl; import com.r35157.libs.objcache.ObjectCache; @@ -49,6 +51,10 @@ public final class JupiterPerpsAlarmImpl { alarmConfiguration.variables() ); + Path alarmConfigurationDirectory = config.alarmConfiguration() + .toAbsolutePath() + .getParent(); + System.out.print("Initializing dependencies... "); ObjectCache objectCache = new ObjectCacheImpl(); SolanaBlockChain realSolanaBlockChain = new SolanaBlockChainImpl(); @@ -57,9 +63,57 @@ public final class JupiterPerpsAlarmImpl { 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 = - new JupiterPerpsEntryPriceVariableRefresher(alarmConfiguration.variables(), jupiterPerpsService); + new JupiterPerpsEntryPriceVariableRefresher( + alarmConfiguration.variables(), + positionIncreaseJupiter + ); System.out.println("Done."); System.out.println("Executing first pre-run data fetch:"); @@ -80,22 +134,18 @@ public final class JupiterPerpsAlarmImpl { entryPriceVariableRefreshWatcher.start(); - Path alarmConfigurationDirectory = config.alarmConfiguration() - .toAbsolutePath() - .getParent(); - List actions = new ArrayList<>(); actions.add(new ConsoleAlarmAction(alarmConfigurationDirectory)); actions.add(new JupiterPerpsPositionIncreaseAlarmAction( - alarmConfigurationDirectory, - solanaBlockChain, - jupiterPerpsService, + positionIncreaseConfiguration, + positionIncreaseWallet, + positionIncreaseJupiter, variableResolver )); actions.add(new JupiterPerpsPositionDecreaseAlarmAction( - alarmConfigurationDirectory, - solanaBlockChain, - jupiterPerpsService, + positionDecreaseConfiguration, + positionDecreaseWallet, + positionDecreaseJupiter, variableResolver )); actions.add(new PushoverAlarmAction( diff --git a/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsPositionDecreaseAlarmAction.tjava b/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsPositionDecreaseAlarmAction.tjava index acfd9af..58c5875 100644 --- a/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsPositionDecreaseAlarmAction.tjava +++ b/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsPositionDecreaseAlarmAction.tjava @@ -1,53 +1,36 @@ 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.JupiterPerpsPosition; import com.r35157.libs.jupiter.perps.JupiterPerpsService; -import com.r35157.libs.solana.SolanaBlockChain; import java.io.IOException; import java.math.BigDecimal; -import java.nio.file.Path; import java.util.Objects; public final class JupiterPerpsPositionDecreaseAlarmAction implements ConfiguredAlarmAction { public JupiterPerpsPositionDecreaseAlarmAction( - Path configurationDirectory, - SolanaBlockChain solanaBlockChain, + JupiterPerpsPositionDecreaseAlarmActionConfiguration configuration, + SolanaWallet wallet, JupiterPerpsService jupiter, AlarmVariableResolver variableResolver - ) throws IOException { - Objects.requireNonNull( - configurationDirectory, - "configurationDirectory" + ) { + this.configuration = Objects.requireNonNull( + configuration, + "configuration" ); - Objects.requireNonNull(solanaBlockChain, "solanaBlockChain"); + this.wallet = Objects.requireNonNull(wallet, "wallet"); this.jupiter = Objects.requireNonNull(jupiter, "jupiter"); this.variableResolver = Objects.requireNonNull( variableResolver, "variableResolver" ); - - configuration = - JupiterPerpsPositionDecreaseAlarmActionConfigurationParser - .parse( - configurationDirectory.resolve( - getConfigurationFileName() - ), - variableResolver - ); - wallet = new SolanaWalletImpl( - configuration.walletId(), - configuration.signerKeyName(), - solanaBlockChain - ); } @Override public String getConfigurationFileName() { - return "alarmaction_JupiterPerpsPositionDecreaseAlarmAction.conf"; + return CONFIGURATION_FILE_NAME; } @Override @@ -73,7 +56,6 @@ public final class JupiterPerpsPositionDecreaseAlarmAction ΩSolanaTransactionSignatureΩ signature = jupiter.executePositionDecrease( - wallet, position.positionAccount(), positionDecrease.receiveToken() .receiveTokenMint(), @@ -173,4 +155,7 @@ public final class JupiterPerpsPositionDecreaseAlarmAction private final SolanaWallet wallet; private final JupiterPerpsService jupiter; private final AlarmVariableResolver variableResolver; + + static final String CONFIGURATION_FILE_NAME = + "alarmaction_JupiterPerpsPositionDecreaseAlarmAction.conf"; } diff --git a/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsPositionIncreaseAlarmAction.tjava b/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsPositionIncreaseAlarmAction.tjava index 85020d3..7612e5d 100644 --- a/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsPositionIncreaseAlarmAction.tjava +++ b/src/main/tjava/com/r35157/jupiterperpsalarm/impl/ref/JupiterPerpsPositionIncreaseAlarmAction.tjava @@ -1,44 +1,34 @@ 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.solana.SolanaBlockChain; 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, - SolanaBlockChain solanaBlockChain, + JupiterPerpsPositionIncreaseAlarmActionConfiguration configuration, + SolanaWallet wallet, JupiterPerpsService jupiter, AlarmVariableResolver variableResolver - ) throws IOException { - Objects.requireNonNull(configurationDirectory, "configurationDirectory"); - Objects.requireNonNull(solanaBlockChain, "solanaBlockChain"); + ) { + this.configuration = Objects.requireNonNull( + configuration, + "configuration" + ); + this.wallet = Objects.requireNonNull(wallet, "wallet"); this.jupiter = Objects.requireNonNull(jupiter, "jupiter"); this.variableResolver = Objects.requireNonNull(variableResolver, "variableResolver"); - - configuration = JupiterPerpsPositionIncreaseAlarmActionConfigurationParser.parse( - configurationDirectory.resolve(getConfigurationFileName()), - variableResolver - ); - wallet = new SolanaWalletImpl( - configuration.walletId(), - configuration.signerKeyName(), - solanaBlockChain - ); } @Override public String getConfigurationFileName() { - return "alarmaction_JupiterPerpsPositionIncreaseAlarmAction.conf"; + return CONFIGURATION_FILE_NAME; } @Override @@ -59,7 +49,6 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured ΩSolanaTransactionSignatureΩ signature = jupiter.executePositionIncrease( - wallet, positionIncrease.asset().tradedTokenMint(), positionIncrease.direction(), positionIncrease.collateralUsd(), @@ -116,4 +105,7 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured private final SolanaWallet wallet; private final JupiterPerpsService jupiter; private final AlarmVariableResolver variableResolver; + + static final String CONFIGURATION_FILE_NAME = + "alarmaction_JupiterPerpsPositionIncreaseAlarmAction.conf"; } diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsService.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsService.tjava index 917ae12..80fe61b 100644 --- a/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsService.tjava +++ b/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsService.tjava @@ -1,6 +1,5 @@ package com.r35157.libs.jupiter.perps; -import com.r35157.cryptowallet.solana.SolanaWallet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -10,10 +9,10 @@ import java.util.Set; /** * Service for reading Jupiter Perps data and executing complete position - * operations. + * operations for its configured wallet. * - *

For position mutations, the service constructs the required transaction - * and delegates signing and submission to the supplied wallet.

+ *

The service constructs and submits Jupiter transactions, while its + * configured wallet is responsible for signing them.

*/ public interface JupiterPerpsService { /** @@ -49,10 +48,9 @@ public interface JupiterPerpsService { /** * Opens or increases a Jupiter Perps position. * - *

The service constructs the transaction and asks the supplied wallet - * to sign and submit it.

+ *

The service constructs the transaction, asks its configured wallet + * to sign it, and submits it to Jupiter.

* - * @param wallet the wallet that owns or will own the position * @param tradedTokenMint the mint address of the asset being traded * @param direction whether the position is long or short * @param inputTokenAmount the amount of USDC to supply as collateral @@ -65,7 +63,6 @@ public interface JupiterPerpsService { */ @NotNull ΩSolanaTransactionSignatureΩ executePositionIncrease( - @NotNull SolanaWallet wallet, @NotNull ΩSPLMintAddressΩ tradedTokenMint, @NotNull JupiterPerpsPositionDirection direction, @NotNull ΩUSDCAmountΩ inputTokenAmount, @@ -76,10 +73,9 @@ public interface JupiterPerpsService { /** * Decreases an existing Jupiter Perps position. * - *

The service constructs the transaction and asks the supplied wallet - * to sign and submit it.

+ *

The service constructs the transaction, asks its configured wallet + * to sign it, and submits it to Jupiter.

* - * @param wallet the wallet that owns the position * @param positionAccount the Jupiter Perps position to decrease * @param receiveTokenMint the mint address of the token to receive * @param sizeUsdDelta the requested decrease in position size, denominated in USD @@ -91,7 +87,6 @@ public interface JupiterPerpsService { */ @NotNull ΩSolanaTransactionSignatureΩ executePositionDecrease( - @NotNull SolanaWallet wallet, @NotNull ΩJupiterPerpsPositionAccountΩ positionAccount, @NotNull ΩSPLMintAddressΩ receiveTokenMint, @NotNull ΩUSDCAmountΩ sizeUsdDelta, diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsServiceImpl.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsServiceImpl.tjava index 3e74b44..c32ca55 100644 --- a/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsServiceImpl.tjava +++ b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsServiceImpl.tjava @@ -7,12 +7,15 @@ import com.r35157.libs.jupiter.perps.JupiterPerpsPositionDirection; import com.r35157.libs.jupiter.perps.JupiterPerpsService; import com.r35157.libs.jupiter.perps.protocol.DecreasePositionRequest; 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.IncreasePositionResponse; import com.r35157.libs.jupiter.perps.protocol.TransactionMetadata; import com.r35157.libs.solana.SolanaAccountInfo; import com.r35157.libs.solana.SolanaBlockChain; import com.r35157.libs.solana.SolanaProgramAccountMemcmpFilter; +import com.r35157.libs.solana.SolanaSignedTransaction; import com.r35157.libs.solana.SolanaUnsignedTransaction; import com.r35157.libs.valuetypes.basic.MoneyAmount; 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.HttpResponse; import java.util.HashSet; +import java.util.Objects; import java.util.Set; import static java.math.BigDecimal.ZERO; @@ -35,9 +39,14 @@ import static java.math.BigDecimal.ZERO; public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService { 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.custodyDecoder = new AnchorIdlJupiterPerpsCustodyDecoder(); } @@ -113,7 +122,6 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService { @Override public @NotNull ΩSolanaTransactionSignatureΩ executePositionIncrease( - @NotNull SolanaWallet wallet, @NotNull ΩSPLMintAddressΩ tradedTokenMint, @NotNull JupiterPerpsPositionDirection direction, @NotNull ΩUSDCAmountΩ inputTokenAmount, @@ -130,7 +138,10 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService { maxSlippageBps ); - return wallet.signAndSendTransaction(unsignedTransaction); + SolanaSignedTransaction signedTransaction = + wallet.signTransaction(unsignedTransaction); + + return executePositionIncreaseTransaction(signedTransaction); } 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 public @NotNull ΩSolanaTransactionSignatureΩ executePositionDecrease( - @NotNull SolanaWallet wallet, @NotNull ΩJupiterPerpsPositionAccountΩ positionAccount, @NotNull ΩSPLMintAddressΩ receiveTokenMint, @NotNull ΩUSDCAmountΩ sizeUsdDelta, @@ -199,7 +239,10 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService { maxSlippageBps ); - return wallet.signAndSendTransaction(unsignedTransaction); + SolanaSignedTransaction signedTransaction = + wallet.signTransaction(unsignedTransaction); + + return executePositionDecreaseTransaction(signedTransaction); } 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( ΩJupiterPerpsPositionAccountΩ positionAccount, ΩSPLMintAddressΩ receiveTokenMint, @@ -674,11 +747,51 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService { 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 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Ω ETH_MINT = "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs"; private static final ΩSPLMintAddressΩ SOL_MINT = "So11111111111111111111111111111111111111112"; 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 = URI.create( "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 final SolanaBlockChain solanaBlockChain; + private final SolanaWallet wallet; private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder; private final AnchorIdlJupiterPerpsCustodyDecoder custodyDecoder; } diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/protocol/ExecuteTransactionRequest.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/protocol/ExecuteTransactionRequest.tjava new file mode 100644 index 0000000..84ad3b8 --- /dev/null +++ b/src/main/tjava/com/r35157/libs/jupiter/perps/protocol/ExecuteTransactionRequest.tjava @@ -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 +) { +} diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/protocol/ExecuteTransactionResponse.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/protocol/ExecuteTransactionResponse.tjava new file mode 100644 index 0000000..6c43865 --- /dev/null +++ b/src/main/tjava/com/r35157/libs/jupiter/perps/protocol/ExecuteTransactionResponse.tjava @@ -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 +) { +}