13: Create initial Jupiter Perps position API
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
package com.r35157.libs.jupiter.perps;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Jupiter Perps position.
|
||||||
|
*
|
||||||
|
* <p>A Jupiter Perps position is represented on-chain by a Solana account owned by
|
||||||
|
* the Jupiter Perps program. This record contains the public API view of such a
|
||||||
|
* position.</p>
|
||||||
|
*
|
||||||
|
* <p>The initial version of this API only exposes the position account and the entry
|
||||||
|
* price. More position fields may be added later as the Jupiter Perps API matures.</p>
|
||||||
|
*
|
||||||
|
* @param positionAccount the Solana account address of the Jupiter Perps position
|
||||||
|
* @param entryPrice the entry price of the position, denominated in USDC
|
||||||
|
*/
|
||||||
|
public record JupiterPerpsPosition(
|
||||||
|
ΩJupiterPerpsPositionAccountΩ positionAccount,
|
||||||
|
ΩUSDCPriceΩ entryPrice
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.r35157.libs.jupiter.perps;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for reading Jupiter Perps positions.
|
||||||
|
*
|
||||||
|
* <p>This service is read-only. It does not open, close, modify, or sign transactions
|
||||||
|
* for Jupiter Perps positions.</p>
|
||||||
|
*
|
||||||
|
* <p>The first supported operation is reading a known Jupiter Perps position account
|
||||||
|
* and returning its decoded position data.</p>
|
||||||
|
*/
|
||||||
|
public interface JupiterPerpsPositionService {
|
||||||
|
/**
|
||||||
|
* Reads a Jupiter Perps position from a known position account.
|
||||||
|
*
|
||||||
|
* <p>The supplied account must be the Solana account that stores the Jupiter Perps
|
||||||
|
* position state. It is not the wallet address, token account, custody account, pool
|
||||||
|
* account, or position request account.</p>
|
||||||
|
*
|
||||||
|
* @param positionAccount the Solana account address of the Jupiter Perps position
|
||||||
|
* @return the decoded Jupiter Perps position
|
||||||
|
* @throws IOException if the position account could not be fetched or decoded
|
||||||
|
* @throws InterruptedException if the calling thread is interrupted while fetching
|
||||||
|
* the position account
|
||||||
|
*/
|
||||||
|
JupiterPerpsPosition getPosition(ΩJupiterPerpsPositionAccountΩ positionAccount)
|
||||||
|
throws IOException, InterruptedException;
|
||||||
|
}
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
||||||
|
|
||||||
|
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
||||||
|
import com.r35157.libs.solana.SolanaAccountInfo;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
class AnchorIdlJupiterPerpsPositionDecoder {
|
||||||
|
|
||||||
|
JupiterPerpsPosition decode(
|
||||||
|
ΩJupiterPerpsPositionAccountΩ positionAccount,
|
||||||
|
SolanaAccountInfo accountInfo
|
||||||
|
) {
|
||||||
|
byte[] data = Base64.getDecoder().decode(accountInfo.dataBase64());
|
||||||
|
|
||||||
|
if (data.length < PRICE_OFFSET + U64_LENGTH) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Jupiter Perps position account data is too short: " + data.length
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
long rawEntryPrice = ByteBuffer
|
||||||
|
.wrap(data, PRICE_OFFSET, U64_LENGTH)
|
||||||
|
.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
.getLong();
|
||||||
|
|
||||||
|
ΩUSDCPriceΩ entryPrice = BigDecimal
|
||||||
|
.valueOf(rawEntryPrice)
|
||||||
|
.movePointLeft(6);
|
||||||
|
|
||||||
|
JupiterPerpsPosition pos = new JupiterPerpsPosition(
|
||||||
|
positionAccount,
|
||||||
|
entryPrice
|
||||||
|
);
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int ANCHOR_DISCRIMINATOR_LENGTH = 8;
|
||||||
|
private static final int PUBLIC_KEY_LENGTH = 32;
|
||||||
|
private static final int I64_LENGTH = 8;
|
||||||
|
private static final int U64_LENGTH = 8;
|
||||||
|
private static final int SIDE_ENUM_LENGTH = 1;
|
||||||
|
|
||||||
|
private static final int PRICE_OFFSET =
|
||||||
|
ANCHOR_DISCRIMINATOR_LENGTH
|
||||||
|
+ PUBLIC_KEY_LENGTH // owner
|
||||||
|
+ PUBLIC_KEY_LENGTH // pool
|
||||||
|
+ PUBLIC_KEY_LENGTH // custody
|
||||||
|
+ PUBLIC_KEY_LENGTH // collateralCustody
|
||||||
|
+ I64_LENGTH // openTime
|
||||||
|
+ I64_LENGTH // updateTime
|
||||||
|
+ SIDE_ENUM_LENGTH; // side
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
||||||
|
|
||||||
|
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
||||||
|
import com.r35157.libs.jupiter.perps.JupiterPerpsPositionService;
|
||||||
|
import com.r35157.libs.solana.SolanaAccountInfo;
|
||||||
|
import com.r35157.libs.solana.SolanaBlockChain;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class AnchorIdlJupiterPerpsPositionServiceImpl implements JupiterPerpsPositionService {
|
||||||
|
|
||||||
|
public AnchorIdlJupiterPerpsPositionServiceImpl(
|
||||||
|
SolanaBlockChain solanaBlockChain
|
||||||
|
) {
|
||||||
|
this.solanaBlockChain = solanaBlockChain;
|
||||||
|
this.positionDecoder = new AnchorIdlJupiterPerpsPositionDecoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JupiterPerpsPosition getPosition(ΩJupiterPerpsPositionAccountΩ positionAccount)
|
||||||
|
throws IOException, InterruptedException {
|
||||||
|
SolanaAccountInfo accountInfo = solanaBlockChain.getAccountInfo(positionAccount);
|
||||||
|
|
||||||
|
if (accountInfo == null) {
|
||||||
|
throw new IllegalArgumentException("Jupiter Perps position account does not exist: " + positionAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!JUPITER_PERPS_PROGRAM_ID.equals(accountInfo.owner())) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Account is not owned by Jupiter Perps program: " + positionAccount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
JupiterPerpsPosition pos = positionDecoder.decode(positionAccount, accountInfo);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final ΩJupiterPerpsProgramIdΩ JUPITER_PERPS_PROGRAM_ID =
|
||||||
|
"PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
|
||||||
|
|
||||||
|
private final SolanaBlockChain solanaBlockChain;
|
||||||
|
private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user