29: Generate an unsigned transaction for increasing a Jupiter Perps position
This commit is contained in:
@@ -1,19 +1,20 @@
|
|||||||
package com.r35157.libs.jupiter.perps;
|
package com.r35157.libs.jupiter.perps;
|
||||||
|
|
||||||
|
import com.r35157.libs.solana.SolanaSignedTransaction;
|
||||||
|
import com.r35157.libs.solana.SolanaUnsignedTransaction;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for reading Jupiter Perps data.
|
* Service for reading Jupiter Perps data and constructing and executing
|
||||||
|
* Jupiter Perps transactions.
|
||||||
*
|
*
|
||||||
* <p>This service is read-only. It does not open, close, modify, or sign transactions
|
* <p>This service does not sign transactions. A compatible wallet is
|
||||||
* for Jupiter Perpetual Contracts.</p>
|
* required to sign a constructed transaction before it can be executed.</p>
|
||||||
*
|
|
||||||
* <p>NOTICE: The first supported operation is reading a known Jupiter Perps position account
|
|
||||||
* and returning its decoded position data.</p>
|
|
||||||
*/
|
*/
|
||||||
public interface JupiterPerpsService {
|
public interface JupiterPerpsService {
|
||||||
/**
|
/**
|
||||||
@@ -45,4 +46,61 @@ public interface JupiterPerpsService {
|
|||||||
*/
|
*/
|
||||||
@NotNull Set<JupiterPerpsPosition> getOpenPositions(@NotNull ΩSolanaWalletIdΩ owner)
|
@NotNull Set<JupiterPerpsPosition> getOpenPositions(@NotNull ΩSolanaWalletIdΩ owner)
|
||||||
throws IOException, InterruptedException;
|
throws IOException, InterruptedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an unsigned Solana transaction for opening or increasing
|
||||||
|
* a Jupiter Perps position.
|
||||||
|
*
|
||||||
|
* <p>The transaction is constructed for the supplied wallet, traded asset,
|
||||||
|
* position direction, USDC collateral amount, position-size delta, and
|
||||||
|
* slippage limit.</p>
|
||||||
|
*
|
||||||
|
* <p>This method does not sign or submit the transaction and therefore does
|
||||||
|
* not modify blockchain state. The returned transaction must be signed by
|
||||||
|
* the supplied wallet and submitted separately.</p>
|
||||||
|
*
|
||||||
|
* @param owner 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
|
||||||
|
* @param sizeUsdDelta the requested increase in position size, denominated in USD
|
||||||
|
* @param maxSlippageBps the maximum accepted slippage, in basis points
|
||||||
|
* @return the complete unsigned Solana transaction
|
||||||
|
* @throws IllegalArgumentException if an amount, mint, or slippage value is invalid
|
||||||
|
* @throws IOException if Jupiter cannot construct the transaction or its response
|
||||||
|
* cannot be decoded
|
||||||
|
* @throws InterruptedException if the calling thread is interrupted while
|
||||||
|
* communicating with Jupiter
|
||||||
|
*/
|
||||||
|
@NotNull SolanaUnsignedTransaction buildPositionIncreaseTransaction(
|
||||||
|
@NotNull ΩSolanaWalletIdΩ owner,
|
||||||
|
@NotNull ΩSPLMintAddressΩ tradedTokenMint,
|
||||||
|
@NotNull JupiterPerpsPositionDirection direction,
|
||||||
|
@NotNull ΩUSDCAmountΩ inputTokenAmount,
|
||||||
|
@NotNull ΩUSDCAmountΩ sizeUsdDelta,
|
||||||
|
int maxSlippageBps
|
||||||
|
) throws IOException, InterruptedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a signed Jupiter Perps position-increase transaction.
|
||||||
|
*
|
||||||
|
* <p>The supplied transaction must previously have been constructed by
|
||||||
|
* {@link #buildPositionIncreaseTransaction} and signed by its required
|
||||||
|
* Solana wallet.</p>
|
||||||
|
*
|
||||||
|
* <p>Unlike the build method, this operation submits the transaction and
|
||||||
|
* may therefore modify blockchain state.</p>
|
||||||
|
*
|
||||||
|
* @param transaction the complete signed position-increase transaction
|
||||||
|
* @return the Solana transaction signature
|
||||||
|
* @throws IllegalArgumentException if the transaction is missing or blank
|
||||||
|
* @throws IOException if Jupiter rejects the transaction or its response
|
||||||
|
* cannot be decoded
|
||||||
|
* @throws InterruptedException if the calling thread is interrupted while
|
||||||
|
* communicating with Jupiter
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
ΩSolanaTransactionSignatureΩ executePositionIncreaseTransaction(
|
||||||
|
@NotNull SolanaSignedTransaction transaction
|
||||||
|
) throws IOException, InterruptedException;
|
||||||
}
|
}
|
||||||
+276
-2
@@ -1,11 +1,19 @@
|
|||||||
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
||||||
import com.r35157.libs.jupiter.perps.JupiterPerpsPositionDirection;
|
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.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.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.valuetypes.basic.MoneyAmount;
|
import com.r35157.libs.valuetypes.basic.MoneyAmount;
|
||||||
import com.r35157.libs.valuetypes.basic.WellKnownCurrencyTypes;
|
import com.r35157.libs.valuetypes.basic.WellKnownCurrencyTypes;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -15,6 +23,10 @@ import java.io.IOException;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -99,6 +111,88 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
return Set.copyOf(positions);
|
return Set.copyOf(positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull SolanaUnsignedTransaction buildPositionIncreaseTransaction(
|
||||||
|
@NotNull ΩSolanaWalletIdΩ owner,
|
||||||
|
@NotNull ΩSPLMintAddressΩ tradedTokenMint,
|
||||||
|
@NotNull JupiterPerpsPositionDirection direction,
|
||||||
|
@NotNull ΩUSDCAmountΩ inputTokenAmount,
|
||||||
|
@NotNull ΩUSDCAmountΩ sizeUsdDelta,
|
||||||
|
int maxSlippageBps
|
||||||
|
) throws IOException, InterruptedException {
|
||||||
|
IncreasePositionRequest request = buildIncreasePositionRequest(
|
||||||
|
owner,
|
||||||
|
tradedTokenMint,
|
||||||
|
direction,
|
||||||
|
inputTokenAmount,
|
||||||
|
sizeUsdDelta,
|
||||||
|
maxSlippageBps
|
||||||
|
);
|
||||||
|
|
||||||
|
IncreasePositionResponse response = requestPositionIncrease(request);
|
||||||
|
TransactionMetadata metadata = response.txMetadata();
|
||||||
|
|
||||||
|
if (response.serializedTxBase64() == null
|
||||||
|
|| response.serializedTxBase64().isBlank()) {
|
||||||
|
throw new IOException(
|
||||||
|
"Jupiter Perps response did not contain a serialized transaction"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metadata == null) {
|
||||||
|
throw new IOException(
|
||||||
|
"Jupiter Perps response did not contain transaction metadata"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
SolanaUnsignedTransaction utx = new SolanaUnsignedTransaction(
|
||||||
|
response.serializedTxBase64(),
|
||||||
|
metadata.blockhash(),
|
||||||
|
Long.parseLong(metadata.lastValidBlockHeight())
|
||||||
|
);
|
||||||
|
|
||||||
|
return utx;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new IOException(
|
||||||
|
"Invalid lastValidBlockHeight returned by Jupiter: "
|
||||||
|
+ metadata.lastValidBlockHeight(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @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();
|
||||||
|
}
|
||||||
|
|
||||||
private JupiterPerpsPosition buildPosition(
|
private JupiterPerpsPosition buildPosition(
|
||||||
ΩJupiterPerpsPositionAccountΩ positionAccount,
|
ΩJupiterPerpsPositionAccountΩ positionAccount,
|
||||||
JupiterPerpsPositionInfo perpsPositionInfo
|
JupiterPerpsPositionInfo perpsPositionInfo
|
||||||
@@ -261,11 +355,191 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
throw new IllegalArgumentException("Unsupported Jupiter Perps position direction: " + direction);
|
throw new IllegalArgumentException("Unsupported Jupiter Perps position direction: " + direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IncreasePositionRequest buildIncreasePositionRequest(
|
||||||
|
ΩSolanaWalletIdΩ owner,
|
||||||
|
ΩSPLMintAddressΩ tradedTokenMint,
|
||||||
|
JupiterPerpsPositionDirection direction,
|
||||||
|
ΩUSDCAmountΩ inputTokenAmount,
|
||||||
|
ΩUSDCAmountΩ sizeUsdDelta,
|
||||||
|
int maxSlippageBps
|
||||||
|
) {
|
||||||
|
if (inputTokenAmount.signum() <= 0) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Input token amount must be greater than zero: " + inputTokenAmount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeUsdDelta.signum() < 0) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Position size delta must not be negative: " + sizeUsdDelta
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxSlippageBps < 0 || maxSlippageBps > BASIS_POINTS_DIVISOR) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Maximum slippage must be between 0 and "
|
||||||
|
+ BASIS_POINTS_DIVISOR
|
||||||
|
+ " basis points: "
|
||||||
|
+ maxSlippageBps
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IncreasePositionRequest request = new IncreasePositionRequest(
|
||||||
|
toProtocolAsset(tradedTokenMint),
|
||||||
|
"USDC",
|
||||||
|
toMicroAmount(inputTokenAmount),
|
||||||
|
toProtocolSide(direction),
|
||||||
|
Integer.toString(maxSlippageBps),
|
||||||
|
toMicroAmount(sizeUsdDelta),
|
||||||
|
owner
|
||||||
|
);
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String toProtocolAsset(ΩSPLMintAddressΩ tradedTokenMint) {
|
||||||
|
if (SOL_MINT.equals(tradedTokenMint)) {
|
||||||
|
return "SOL";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BTC_MINT.equals(tradedTokenMint)) {
|
||||||
|
return "BTC";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ETH_MINT.equals(tradedTokenMint)) {
|
||||||
|
return "ETH";
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unsupported Jupiter Perps traded-token mint: " + tradedTokenMint
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String toProtocolSide(
|
||||||
|
JupiterPerpsPositionDirection direction
|
||||||
|
) {
|
||||||
|
return switch (direction) {
|
||||||
|
case LONG -> "long";
|
||||||
|
case SHORT -> "short";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String toMicroAmount(BigDecimal amount) {
|
||||||
|
return amount
|
||||||
|
.movePointRight(USDC_DECIMALS)
|
||||||
|
.toBigIntegerExact()
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IncreasePositionResponse requestPositionIncrease(
|
||||||
|
IncreasePositionRequest request
|
||||||
|
) throws IOException, InterruptedException {
|
||||||
|
String requestJson = OBJECT_MAPPER.writeValueAsString(request);
|
||||||
|
|
||||||
|
HttpRequest httpRequest = HttpRequest.newBuilder()
|
||||||
|
.uri(INCREASE_POSITION_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 Perps increase-position request failed with HTTP "
|
||||||
|
+ httpResponse.statusCode()
|
||||||
|
+ ": "
|
||||||
|
+ httpResponse.body()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IncreasePositionResponse response = OBJECT_MAPPER.readValue(
|
||||||
|
httpResponse.body(),
|
||||||
|
IncreasePositionResponse.class
|
||||||
|
);
|
||||||
|
|
||||||
|
TransactionMetadata metadata = response.txMetadata();
|
||||||
|
|
||||||
|
if (metadata.blockhash() == null || metadata.blockhash().isBlank()) {
|
||||||
|
String errorMsg = "Jupiter Perps response did not contain a blockhash";
|
||||||
|
throw new IOException(errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
long lastValidBlockHeight;
|
||||||
|
|
||||||
|
try {
|
||||||
|
lastValidBlockHeight =
|
||||||
|
Long.parseLong(metadata.lastValidBlockHeight());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
String errorMsg = "Invalid lastValidBlockHeight returned by Jupiter: " + metadata.lastValidBlockHeight();
|
||||||
|
throw new IOException(errorMsg, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastValidBlockHeight <= 0) {
|
||||||
|
String errorMsg = "Invalid lastValidBlockHeight returned by Jupiter: " + lastValidBlockHeight;
|
||||||
|
throw new IOException(errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
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Ω SOL_MINT = "So11111111111111111111111111111111111111112";
|
||||||
|
private static final ΩSPLMintAddressΩ BTC_MINT = "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh";
|
||||||
|
private static final ΩSPLMintAddressΩ ETH_MINT = "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs";
|
||||||
|
|
||||||
|
private static final URI EXECUTE_TRANSACTION_ENDPOINT =
|
||||||
|
URI.create(
|
||||||
|
"https://perps-api.jup.ag/v2/transaction/execute"
|
||||||
|
);
|
||||||
|
|
||||||
|
private static final ΩJupiterPerpsProgramIdΩ JUPITER_PERPS_PROGRAM_ID = "PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
|
||||||
|
|
||||||
|
private static final URI INCREASE_POSITION_ENDPOINT = URI.create("https://perps-api.jup.ag/v2/positions/increase");
|
||||||
|
private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();
|
||||||
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
private static final long RATE_POWER = 1_000_000_000L;
|
private static final long RATE_POWER = 1_000_000_000L;
|
||||||
private static final int CLOSE_FEE_BPS = 6;
|
private static final int CLOSE_FEE_BPS = 6;
|
||||||
private static final int BASIS_POINTS_DIVISOR = 10_000;
|
private static final int BASIS_POINTS_DIVISOR = 10_000;
|
||||||
private static final ΩJupiterPerpsProgramIdΩ JUPITER_PERPS_PROGRAM_ID =
|
|
||||||
"PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
|
|
||||||
private static final int POSITION_OWNER_OFFSET = 8;
|
private static final int POSITION_OWNER_OFFSET = 8;
|
||||||
private static final int MAX_LEVERAGE = 500;
|
private static final int MAX_LEVERAGE = 500;
|
||||||
private static final int USDC_DECIMALS = 6;
|
private static final int USDC_DECIMALS = 6;
|
||||||
|
|||||||
@@ -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
|
||||||
|
) {
|
||||||
|
}
|
||||||
+14
@@ -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
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.r35157.libs.jupiter.perps.protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jupiter Perps protocol request for constructing an unsigned
|
||||||
|
* position-increase transaction.
|
||||||
|
*
|
||||||
|
* @param asset the Jupiter Perps market symbol, such as {@code SOL},
|
||||||
|
* {@code BTC}, or {@code ETH}
|
||||||
|
* @param inputToken the symbol of the token supplied as collateral,
|
||||||
|
* currently {@code USDC}
|
||||||
|
* @param inputTokenAmount the input-token amount in raw chain units,
|
||||||
|
* encoded as a decimal string
|
||||||
|
* @param side the position direction in Jupiter protocol format:
|
||||||
|
* {@code long} or {@code short}
|
||||||
|
* @param maxSlippageBps the maximum accepted slippage in basis points,
|
||||||
|
* encoded as a decimal string
|
||||||
|
* @param sizeUsdDelta the requested position-size increase in micro-USD,
|
||||||
|
* encoded as a decimal string
|
||||||
|
* @param walletAddress the Solana wallet that owns or will own the position
|
||||||
|
*/
|
||||||
|
public record IncreasePositionRequest(
|
||||||
|
String asset,
|
||||||
|
String inputToken,
|
||||||
|
String inputTokenAmount,
|
||||||
|
String side,
|
||||||
|
String maxSlippageBps,
|
||||||
|
String sizeUsdDelta,
|
||||||
|
String walletAddress
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.r35157.libs.jupiter.perps.protocol;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relevant fields returned by Jupiter after constructing an unsigned
|
||||||
|
* position-increase transaction.
|
||||||
|
*
|
||||||
|
* <p>Additional response fields that are not required by the current
|
||||||
|
* implementation are ignored during decoding.</p>
|
||||||
|
*
|
||||||
|
* @param positionPubkey the Solana account address of the position that
|
||||||
|
* will be opened or increased
|
||||||
|
* @param serializedTxBase64 the complete unsigned Solana transaction,
|
||||||
|
* encoded as Base64
|
||||||
|
* @param txMetadata metadata describing the transaction's blockhash
|
||||||
|
* and validity period
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public record IncreasePositionResponse(
|
||||||
|
String positionPubkey,
|
||||||
|
String serializedTxBase64,
|
||||||
|
TransactionMetadata txMetadata
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.r35157.libs.jupiter.perps.protocol;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validity metadata for a Solana transaction constructed by Jupiter.
|
||||||
|
*
|
||||||
|
* @param blockhash the recent Solana blockhash embedded in the transaction
|
||||||
|
* @param lastValidBlockHeight the last block height at which the transaction
|
||||||
|
* may be processed, encoded as a decimal string
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public record TransactionMetadata(
|
||||||
|
String blockhash,
|
||||||
|
String lastValidBlockHeight
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.r35157.libs.solana;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A serialized Solana transaction that has not yet been signed or submitted.
|
||||||
|
*
|
||||||
|
* @param serializedTransaction the complete Base64 encoded Solana transaction
|
||||||
|
* @param blockhash the recent blockhash used by the transaction
|
||||||
|
* @param lastValidBlockHeight the last block height at which the transaction is valid
|
||||||
|
*/
|
||||||
|
public record SolanaUnsignedTransaction(
|
||||||
|
ΩBase64StringΩ serializedTransaction,
|
||||||
|
ΩSolanaBlockhashΩ blockhash,
|
||||||
|
long lastValidBlockHeight
|
||||||
|
) {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user