From cf73a03ff531d44a6aa52dea402a99332fbc4a22c2f58f359d19968d0596e128 Mon Sep 17 00:00:00 2001
From: Minimons
Date: Thu, 2 Jul 2026 20:35:25 +0200
Subject: [PATCH] Mess
---
build.gradle.kts | 1 -
.../valuetypes/WellKnownCurrencyTypes.java | 52 ++++++
.../com/r35157/libs/codec/Base58Codec.tjava | 5 +
.../jupiter/perps/JupiterPerpsPosition.tjava | 47 +++++
.../perps/JupiterPerpsPositionDirection.tjava | 9 +
.../jupiter/perps/JupiterPerpsService.tjava | 51 ++++++
.../AnchorIdlJupiterPerpsCustodyDecoder.tjava | 82 +++++----
...AnchorIdlJupiterPerpsPositionDecoder.tjava | 70 ++++++--
.../AnchorIdlJupiterPerpsServiceImpl.tjava | 68 +++++--
.../impl/anchoridl/CustodyAccountInfo.tjava | 9 +
.../impl/anchoridl/DecodingPrimitives.tjava | 31 ++++
.../anchoridl/JupiterPerpsPositionInfo.tjava | 12 ++
.../com/r35157/libs/raydium/Raydium.tjava | 7 +-
.../raydium/RaydiumConcentratedPoolInfo.tjava | 5 +-
.../RaydiumConcentratedPoolState.tjava | 5 +-
.../RaydiumConcentratedPositionState.tjava | 1 +
...RaydiumLiquidityPoolPositionStandard.tjava | 5 +-
.../raydium/RaydiumLiquidityPoolPrice.tjava | 12 +-
.../RaydiumLiquidityPoolTokenAmounts.tjava | 5 +-
.../r35157/libs/solana/SPLTokenSupply.tjava | 5 +-
.../r35157/libs/solana/SolanaBlockChain.tjava | 167 ++++++++++++++++++
.../SolanaProgramAccountMemcmpFilter.tjava | 17 ++
.../libs/valuetypes/basic/MoneyPrice.tjava | 8 +
.../r35157/nenjim/hubd/impl/ref/Main.tjava | 36 ++--
24 files changed, 618 insertions(+), 92 deletions(-)
create mode 100644 src/main/java/com/r35157/libs/solana/valuetypes/WellKnownCurrencyTypes.java
create mode 100644 src/main/tjava/com/r35157/libs/codec/Base58Codec.tjava
create mode 100644 src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPosition.tjava
create mode 100644 src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPositionDirection.tjava
create mode 100644 src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsService.tjava
create mode 100644 src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/CustodyAccountInfo.tjava
create mode 100644 src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/DecodingPrimitives.tjava
create mode 100644 src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/JupiterPerpsPositionInfo.tjava
create mode 100644 src/main/tjava/com/r35157/libs/solana/SolanaBlockChain.tjava
create mode 100644 src/main/tjava/com/r35157/libs/solana/SolanaProgramAccountMemcmpFilter.tjava
create mode 100644 src/main/tjava/com/r35157/libs/valuetypes/basic/MoneyPrice.tjava
diff --git a/build.gradle.kts b/build.gradle.kts
index c0b0f7c..ade0647 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -44,7 +44,6 @@ dependencies {
runtimeOnly("org.apache.logging.log4j:log4j-core:2.26.0")
runtimeOnly("org.apache.logging.log4j:log4j-slf4j2-impl:2.26.0")
- implementation("com.r35157.nenjim:hubd-api:0.1-dev")
implementation("com.fasterxml.jackson.core:jackson-databind:2.18.6")
implementation("com.fazecast:jSerialComm:2.11.4")
implementation("com.google.code.gson:gson:2.14.0")
diff --git a/src/main/java/com/r35157/libs/solana/valuetypes/WellKnownCurrencyTypes.java b/src/main/java/com/r35157/libs/solana/valuetypes/WellKnownCurrencyTypes.java
new file mode 100644
index 0000000..7c88278
--- /dev/null
+++ b/src/main/java/com/r35157/libs/solana/valuetypes/WellKnownCurrencyTypes.java
@@ -0,0 +1,52 @@
+package com.r35157.libs.solana.valuetypes;
+
+import com.r35157.libs.valuetypes.basic.CurrencyType;
+
+import java.util.UUID;
+
+/**
+ * Defines well-known currency types used by the Solana integration.
+ *
+ * Each enum value wraps a {@link CurrencyType} with a stable identifier and a
+ * human-readable currency name. These predefined values are intended for common
+ * currencies that the Solana-related modules need to reference consistently.
+ */
+public enum WellKnownCurrencyTypes {
+ /**
+ * Native Solana currency.
+ */
+ SOLANA(new CurrencyType(
+ UUID.fromString("019e0116-fce5-792f-a647-fa6da4dffec5"),
+ "Solana",
+ "SOL")
+ ),
+
+ /**
+ * Syrup USDC token currency.
+ */
+ SYRUPUSDC(new CurrencyType(
+ UUID.fromString("019e1d51-0600-7956-8231-f3b7058a91c2"),
+ "SyrupUSDC",
+ "SyrupUSDC")
+ );
+
+ /**
+ * Creates a well-known currency type entry.
+ *
+ * @param currencyType the currency type represented by this enum value
+ */
+ WellKnownCurrencyTypes(CurrencyType currencyType) {
+ this.currencyType = currencyType;
+ }
+
+ /**
+ * Returns the currency type represented by this enum value.
+ *
+ * @return the represented currency type
+ */
+ public CurrencyType getCurrencyType() {
+ return currencyType;
+ }
+
+ private final CurrencyType currencyType;
+}
\ No newline at end of file
diff --git a/src/main/tjava/com/r35157/libs/codec/Base58Codec.tjava b/src/main/tjava/com/r35157/libs/codec/Base58Codec.tjava
new file mode 100644
index 0000000..e3bc6ab
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/codec/Base58Codec.tjava
@@ -0,0 +1,5 @@
+package com.r35157.libs.codec;
+
+public interface Base58Codec {
+ String encode(byte[] input);
+}
diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPosition.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPosition.tjava
new file mode 100644
index 0000000..548ab0c
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPosition.tjava
@@ -0,0 +1,47 @@
+package com.r35157.libs.jupiter.perps;
+
+import java.math.BigDecimal;
+
+import com.r35157.libs.valuetypes.basic.MoneyAmount;
+
+/**
+ * Represents a Jupiter Perps position.
+ *
+ * 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.
+ *
+ * @param positionAccount the Solana account address of the Jupiter Perps position
+ * @param tradedTokenMint the mint address of the token being traded
+ * @param direction whether the position is long or short
+ * @param value the amount the position is worth if closed now
+ * @param size the leveraged amount used to open the contracts
+ * @param pnl the amount in usd in profit or loss on this position
+ * @param pnlPercent the profit and loss represented as a percentage
+ * @param leverage
+ * @param entryPrice the entry price of the position, denominated in USDC
+ * @param marketPrice the current spot price of the token
+ * @param collateral the amount of USD representing the collateral for this position
+ * @param totalFees the total amount of fees (TODO: is that including pending/due fees)
+ * @param borrowFeesDue the amount of USD that is currently outstanding
+ * @param closeFeePending the fee in USD for closing the account (TODO: multiple accounts - when adding collateral?)
+ * @param accountRent refundable amount locked for Solana account renting
+ */
+public record JupiterPerpsPosition(
+ ΩJupiterPerpsPositionAccountΩ positionAccount,
+ ΩSPLMintAddressΩ tradedTokenMint,
+ JupiterPerpsPositionDirection direction,
+ ΩUSDCAmountΩ value,
+ ΩUSDCAmountΩ size,
+ ΩUSDCAmountΩ pnl,
+ BigDecimal pnlPercent,
+ BigDecimal leverage,
+ ΩUSDCPriceΩ entryPrice,
+ ΩUSDCPriceΩ marketPrice,
+ ΩUSDCAmountΩ collateral,
+ ΩUSDCAmountΩ totalFees,
+ ΩUSDCAmountΩ borrowFeesDue,
+ ΩUSDCAmountΩ closeFeePending,
+ ΩSolanaAmountΩ accountRent
+) {
+}
\ No newline at end of file
diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPositionDirection.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPositionDirection.tjava
new file mode 100644
index 0000000..05c4066
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPositionDirection.tjava
@@ -0,0 +1,9 @@
+package com.r35157.libs.jupiter.perps;
+
+/**
+ * Direction of a Jupiter Perps position.
+ */
+public enum JupiterPerpsPositionDirection {
+ LONG,
+ SHORT
+}
\ No newline at end of file
diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsService.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsService.tjava
new file mode 100644
index 0000000..45ac671
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsService.tjava
@@ -0,0 +1,51 @@
+package com.r35157.libs.jupiter.perps;
+
+import com.r35157.libs.solana.SolanaAccountInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * Service for reading Jupiter Perps data.
+ *
+ * This service is read-only. It does not open, close, modify, or sign transactions
+ * for Jupiter Perpetual Contracts.
+ *
+ * NOTICE: The first supported operation is reading a known Jupiter Perps position account
+ * and returning its decoded position data.
+ */
+public interface JupiterPerpsService {
+ /**
+ * Reads a Jupiter Perps position from a known position account.
+ *
+ * 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.
+ *
+ * @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(@NotNull SolanaAccountInfo accountInfo)
+ throws IOException, InterruptedException
+ {
+ JupiterPerpsPosition getPosition(ΩJupiterPerpsPositionAccountΩ positionAccount)
+ throws IOException, InterruptedException;
+ */
+
+ /**
+ * Finds open Jupiter Perps positions owned by a wallet.
+ *
+ * This method returns decoded Jupiter Perps position objects. It does not return
+ * raw Solana accounts or account ids.
+ *
+ * @param owner the wallet address that owns the Jupiter Perps positions
+ * @return the open Jupiter Perps positions owned by the wallet
+ * @throws IOException if the position accounts could not be fetched or decoded
+ * @throws InterruptedException if the calling thread is interrupted while fetching positions
+ */
+ Set getOpenPositions(ΩSolanaWalletIdΩ owner)
+ throws IOException, InterruptedException;
+}
\ No newline at end of file
diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsCustodyDecoder.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsCustodyDecoder.tjava
index 04fcda1..facd83e 100644
--- a/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsCustodyDecoder.tjava
+++ b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsCustodyDecoder.tjava
@@ -4,47 +4,67 @@ import com.r35157.libs.codec.Base58Codec;
import com.r35157.libs.codec.impl.ref.Base58CodecImpl;
import com.r35157.libs.solana.SolanaAccountInfo;
+import java.math.BigInteger;
import java.util.Base64;
-class AnchorIdlJupiterPerpsCustodyDecoder {
+import static com.r35157.libs.jupiter.perps.impl.anchoridl.DecodingPrimitives.*;
- ΩSPLMintAddressΩ decodeMint(
- SolanaAccountInfo custodyAccountInfo
- ) {
- byte[] data = Base64.getDecoder().decode(custodyAccountInfo.dataBase64());
+public class AnchorIdlJupiterPerpsCustodyDecoder {
- if (data.length < MINT_OFFSET + PUBLIC_KEY_LENGTH) {
- throw new IllegalArgumentException(
- "Jupiter Perps custody account data is too short: " + data.length
- );
- }
+ public CustodyAccountInfo decode(SolanaAccountInfo custodyAccountInfo) {
+ byte[] data = decodeIdl(custodyAccountInfo);
- return readPublicKey(data, MINT_OFFSET);
- }
-
- private ΩSPLMintAddressΩ readPublicKey(
- byte[] data,
- int offset
- ) {
- byte[] publicKeyBytes = new byte[PUBLIC_KEY_LENGTH];
-
- System.arraycopy(
- data,
- offset,
- publicKeyBytes,
- 0,
- PUBLIC_KEY_LENGTH
+ CustodyAccountInfo cai = new CustodyAccountInfo(
+ decodeMintAddress(data),
+ decodeCumulativeInterestRate(data)
);
- return base58.encode(publicKeyBytes);
+ return cai;
}
- private static final int ANCHOR_DISCRIMINATOR_LENGTH = 8;
- private static final int PUBLIC_KEY_LENGTH = 32;
+ private byte[] decodeIdl(SolanaAccountInfo custodyAccountInfo) {
+ byte[] data = base64.decode(custodyAccountInfo.dataBase64());
- private static final int MINT_OFFSET =
- ANCHOR_DISCRIMINATOR_LENGTH
- + PUBLIC_KEY_LENGTH; // pool
+ if (data.length < CUMULATIVE_INTEREST_RATE_OFFSET + U128_LENGTH) {
+ String errMsg = "Jupiter Perps custody account data is too short: " + data.length;
+ throw new IllegalArgumentException(errMsg);
+ }
+
+ return data;
+ }
+
+ private ΩSPLMintAddressΩ decodeMintAddress(byte[] data) {
+ byte[] mintAddressBytes = readPublicKey(data, MINT_OFFSET);
+ ΩSPLMintAddressΩ mintAddress = base58.encode(mintAddressBytes);
+
+ return mintAddress;
+ }
+
+ private BigInteger decodeCumulativeInterestRate(byte[] data) {
+ byte[] bytes = readU128(data, CUMULATIVE_INTEREST_RATE_OFFSET);
+ BigInteger cumulativeInterestRate = new BigInteger(1, bytes);
+
+ return cumulativeInterestRate;
+ }
+
+ // Offsets:
+ // 8 discriminator
+ // +32 pool
+ // +32 mint
+ // +32 token_account
+ // +1 decimals
+ // +1 is_stable
+ // +45 oracle
+ // +48 pricing
+ // +7 permissions
+ // +8 target_ratio_bps
+ // +48 assets
+
+ private static final int ANCHOR_DISCRIMINATOR_LENGTH = 8;
+ private static final int MINT_OFFSET = ANCHOR_DISCRIMINATOR_LENGTH + PUBLIC_KEY_LENGTH;
+ private static final int FUNDING_RATE_STATE_OFFSET = 262;
+ private static final int CUMULATIVE_INTEREST_RATE_OFFSET = FUNDING_RATE_STATE_OFFSET;
private static final Base58Codec base58 = new Base58CodecImpl();
+ private static final Base64.Decoder base64 = Base64.getDecoder();
}
\ No newline at end of file
diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsPositionDecoder.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsPositionDecoder.tjava
index b4a52b5..03ae283 100644
--- a/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsPositionDecoder.tjava
+++ b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsPositionDecoder.tjava
@@ -7,17 +7,15 @@ import com.r35157.libs.jupiter.perps.JupiterPerpsPositionDirection;
import com.r35157.libs.solana.SolanaAccountInfo;
import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Base64;
-class AnchorIdlJupiterPerpsPositionDecoder {
+public class AnchorIdlJupiterPerpsPositionDecoder {
- JupiterPerpsPosition decode(
- ΩJupiterPerpsPositionAccountΩ positionAccount,
- SolanaAccountInfo accountInfo,
- ΩSPLMintAddressΩ tradedTokenMint
- ) {
+ public JupiterPerpsPositionInfo decode(SolanaAccountInfo accountInfo) {
byte[] data = Base64.getDecoder().decode(accountInfo.dataBase64());
if (data.length < PRICE_OFFSET + U64_LENGTH) {
@@ -56,19 +54,34 @@ class AnchorIdlJupiterPerpsPositionDecoder {
.valueOf(rawSizeUsd)
.movePointLeft(6);
- JupiterPerpsPosition pos = new JupiterPerpsPosition(
- positionAccount,
+ JupiterPerpsPositionInfo posInfo = new JupiterPerpsPositionInfo(
entryPrice,
direction,
- tradedTokenMint,
sizeUsd,
collateralUsd
);
- return pos;
+ return posInfo;
}
- ΩSolanaAddressΩ decodeCustodyAccount(SolanaAccountInfo accountInfo) {
+
+ public BigInteger decodeCumulativeInterestSnapshot(SolanaAccountInfo accountInfo) {
+ byte[] data = Base64.getDecoder().decode(accountInfo.dataBase64());
+
+ if (data.length < CUMULATIVE_INTEREST_SNAPSHOT_OFFSET + U128_LENGTH) {
+ throw new IllegalArgumentException(
+ "Jupiter Perps position account data is too short: " + data.length
+ );
+ }
+
+ BigInteger value = readU128(
+ data,
+ CUMULATIVE_INTEREST_SNAPSHOT_OFFSET
+ );
+ return value;
+ }
+
+ public ΩSolanaAddressΩ decodeCustodyAccount(SolanaAccountInfo accountInfo) {
byte[] data = Base64.getDecoder().decode(accountInfo.dataBase64());
if (data.length < CUSTODY_OFFSET + PUBLIC_KEY_LENGTH) {
@@ -83,6 +96,23 @@ class AnchorIdlJupiterPerpsPositionDecoder {
);
}
+ public ΩSolanaAddressΩ decodeCollateralCustodyAccount(
+ SolanaAccountInfo accountInfo
+ ) {
+ byte[] data = Base64.getDecoder().decode(accountInfo.dataBase64());
+
+ if (data.length < COLLATERAL_CUSTODY_OFFSET + PUBLIC_KEY_LENGTH) {
+ throw new IllegalArgumentException(
+ "Jupiter Perps position account data is too short: " + data.length
+ );
+ }
+
+ return readPublicKey(
+ data,
+ COLLATERAL_CUSTODY_OFFSET
+ );
+ }
+
private JupiterPerpsPositionDirection decodeDirection(
byte rawSide
) {
@@ -115,11 +145,25 @@ class AnchorIdlJupiterPerpsPositionDecoder {
return base58.encode(publicKeyBytes);
}
+ private static BigInteger readU128(
+ byte[] data,
+ int offset
+ ) {
+ byte[] bytes = new byte[U128_LENGTH];
+
+ for (int i = 0; i < U128_LENGTH; i++) {
+ bytes[i] = data[offset + U128_LENGTH - 1 - i];
+ }
+
+ return new BigInteger(1, bytes);
+ }
+
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 SIDE_ENUM_LENGTH = 1;
+ private static final int I64_LENGTH = 8;
private static final int U64_LENGTH = 8;
+ private static final int U128_LENGTH = 16;
private static final int OWNER_OFFSET = ANCHOR_DISCRIMINATOR_LENGTH;
private static final int POOL_OFFSET = OWNER_OFFSET + PUBLIC_KEY_LENGTH;
@@ -131,6 +175,8 @@ class AnchorIdlJupiterPerpsPositionDecoder {
private static final int PRICE_OFFSET = SIDE_OFFSET + SIDE_ENUM_LENGTH;
private static final int SIZE_USD_OFFSET = PRICE_OFFSET + U64_LENGTH;
private static final int COLLATERAL_USD_OFFSET = SIZE_USD_OFFSET + U64_LENGTH;
+ private static final int REALISED_PNL_USD_OFFSET = COLLATERAL_USD_OFFSET + U64_LENGTH;
+ private static final int CUMULATIVE_INTEREST_SNAPSHOT_OFFSET = REALISED_PNL_USD_OFFSET + I64_LENGTH;
private static final Base58Codec base58 = new Base58CodecImpl();
}
\ No newline at end of file
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 f3349f3..a6eb56f 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
@@ -5,8 +5,12 @@ import com.r35157.libs.jupiter.perps.JupiterPerpsService;
import com.r35157.libs.solana.SolanaAccountInfo;
import com.r35157.libs.solana.SolanaBlockChain;
import com.r35157.libs.solana.SolanaProgramAccountMemcmpFilter;
+import org.jetbrains.annotations.NotNull;
import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
import java.util.HashSet;
import java.util.Set;
@@ -20,26 +24,47 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
this.custodyDecoder = new AnchorIdlJupiterPerpsCustodyDecoder();
}
+ /*
@Override
- public JupiterPerpsPosition getPosition(ΩJupiterPerpsPositionAccountΩ positionAccount)
- throws IOException, InterruptedException {
- SolanaAccountInfo accountInfo = solanaBlockChain.getAccountInfo(positionAccount);
+ public JupiterPerpsPosition getPosition(@NotNull SolanaAccountInfo accountInfo)
+ throws IOException, InterruptedException
+ {
+ guard(accountInfo);
- if (accountInfo == null) {
- throw new IllegalArgumentException("Jupiter Perps position account does not exist: " + positionAccount);
- }
+ JupiterPerpsPositionInfo posInfo = positionDecoder.decode(accountInfo);
+ ΩUSDCAmountΩ sizeUsd = posInfo.sizeUsd();
- if (!JUPITER_PERPS_PROGRAM_ID.equals(accountInfo.owner())) {
- throw new IllegalArgumentException(
- "Account is not owned by Jupiter Perps program: " + positionAccount
- );
- }
+ CustodyAccountInfo cai = custodyDecoder.decode(custodyAccountInfo);
+ BigInteger cumulativeInterestSnapshot = positionDecoder.decodeCumulativeInterestSnapshot(positionAccountInfo);
+ ΩUSDCAmountΩ borrowFeePendingUsd = calculateBorrowFeeUsd(
+ cumulativeInterestSnapshot,
+ sizeUsd
+ );
- ΩSPLMintAddressΩ tradedTokenMint = getTradedTokenMint(accountInfo);
- JupiterPerpsPosition pos = positionDecoder.decode(positionAccount, accountInfo, tradedTokenMint);
+ JupiterPerpsPosition pos = new JupiterPerpsPosition(
+ accountInfo,
+ posInfo.entryPrice(),
+ posInfo.direction(),
+ sizeUsd,
+ posInfo.collateralUsd(),
+ cai.mintAddress(),
+ borrowFeePendingUsd
+ );
return pos;
}
+ */
+
+ private void guard(SolanaAccountInfo accountInfo) {
+ ΩSolanaProgramIdΩ owner = accountInfo.owner();
+ if (!JUPITER_PERPS_PROGRAM_ID.equals(owner)) {
+ String errorMsg = "Account '" + accountInfo.address() + "' is not owned by Jupiter Perps program ("
+ + JUPITER_PERPS_PROGRAM_ID + "), instead it is owned by '"
+ + owner
+ + "'";
+ throw new IllegalArgumentException(errorMsg);
+ }
+ }
@Override
public Set getOpenPositions(ΩSolanaWalletIdΩ owner)
@@ -73,7 +98,20 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
return Set.copyOf(positions);
}
- private ΩSPLMintAddressΩ getTradedTokenMint(SolanaAccountInfo positionAccountInfo)
+ private BigDecimal calculateBorrowFeeUsd(
+ BigInteger cumulativeInterestSnapshot,
+ ΩUSDCAmountΩ sizeUsd
+ ) {
+ BigInteger difference = currentCumulativeInterestRate.subtract(cumulativeInterestSnapshot);
+ BigDecimal borrowFeeUsd =
+ new BigDecimal(difference)
+ .multiply(sizeUsd)
+ .divide(BigDecimal.valueOf(1_000_000_000L), 6, RoundingMode.CEILING);
+
+ return borrowFeeUsd;
+ }
+
+ /*private ΩSPLMintAddressΩ getTradedTokenMint(SolanaAccountInfo positionAccountInfo)
throws IOException, InterruptedException
{
ΩSolanaAddressΩ custodyAccount = positionDecoder.decodeCustodyAccount(positionAccountInfo);
@@ -87,7 +125,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
ΩSPLMintAddressΩ mintAddress = custodyDecoder.decodeMint(custodyAccountInfo);
return mintAddress;
- }
+ }*/
private static final ΩJupiterPerpsProgramIdΩ JUPITER_PERPS_PROGRAM_ID =
"PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/CustodyAccountInfo.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/CustodyAccountInfo.tjava
new file mode 100644
index 0000000..a7913f5
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/CustodyAccountInfo.tjava
@@ -0,0 +1,9 @@
+package com.r35157.libs.jupiter.perps.impl.anchoridl;
+
+import java.math.BigInteger;
+
+public record CustodyAccountInfo(
+ ΩSPLMintAddressΩ mintAddress,
+ BigInteger currentCumulativeInterestRate
+) {
+}
diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/DecodingPrimitives.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/DecodingPrimitives.tjava
new file mode 100644
index 0000000..ee72dc7
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/DecodingPrimitives.tjava
@@ -0,0 +1,31 @@
+package com.r35157.libs.jupiter.perps.impl.anchoridl;
+
+public class DecodingPrimitives {
+
+ public static byte[] readU128(byte[] data, int offset) {
+ byte[] bytes = new byte[U128_LENGTH];
+
+ for (int i = 0; i < U128_LENGTH; i++) {
+ bytes[i] = data[offset + U128_LENGTH - 1 - i];
+ }
+
+ return bytes;
+ }
+
+ public static byte[] readPublicKey(byte[] data, int offset) {
+ byte[] publicKeyBytes = new byte[PUBLIC_KEY_LENGTH];
+
+ System.arraycopy(
+ data,
+ offset,
+ publicKeyBytes,
+ 0,
+ PUBLIC_KEY_LENGTH
+ );
+
+ return publicKeyBytes;
+ }
+
+ public static final int U128_LENGTH = 16;
+ public static final int PUBLIC_KEY_LENGTH = 32;
+}
diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/JupiterPerpsPositionInfo.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/JupiterPerpsPositionInfo.tjava
new file mode 100644
index 0000000..07c05a7
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/JupiterPerpsPositionInfo.tjava
@@ -0,0 +1,12 @@
+package com.r35157.libs.jupiter.perps.impl.anchoridl;
+
+import com.r35157.libs.jupiter.perps.JupiterPerpsPositionDirection;
+
+import java.math.BigDecimal;
+
+public record JupiterPerpsPositionInfo(
+ ΩUSDCPriceΩ entryPrice,
+ JupiterPerpsPositionDirection direction,
+ ΩUSDCAmountΩ sizeUsd,
+ ΩUSDCAmountΩ collateralUsd
+) {}
diff --git a/src/main/tjava/com/r35157/libs/raydium/Raydium.tjava b/src/main/tjava/com/r35157/libs/raydium/Raydium.tjava
index 9e56d6d..11213da 100644
--- a/src/main/tjava/com/r35157/libs/raydium/Raydium.tjava
+++ b/src/main/tjava/com/r35157/libs/raydium/Raydium.tjava
@@ -1,6 +1,5 @@
package com.r35157.libs.raydium;
-import com.r35157.libs.valuetypes.basic.AssetPrice;
import com.r35157.libs.valuetypes.basic.MoneyAmount;
import com.r35157.libs.valuetypes.basic.Range;
@@ -16,11 +15,11 @@ public interface Raydium {
* to any Raydium liquidity pool supported by the implementation.
*
* @param poolId the Raydium liquidity pool id
- * @return the current pool price
+ * @return the current pool price expressed as a Solana amount
* @throws IOException if the price could not be fetched or the response could not be parsed
* @throws InterruptedException if the calling thread is interrupted while fetching the price
*/
- AssetPrice fetchPoolPrice(ΩRaydiumLiquidityPoolIdΩ poolId) throws IOException, InterruptedException;
+ ΩSolanaAmountΩ fetchPoolPrice(ΩRaydiumLiquidityPoolIdΩ poolId) throws IOException, InterruptedException;
/**
* Fetches the Raydium liquidity pool ids where the supplied Solana owner address has positions.
@@ -184,7 +183,7 @@ public interface Raydium {
* @param decimalPlaces the number decimal places in the resulting price currency
* @return the price range represented by the concentrated liquidity position
*/
- Range calculateConcentratedPositionPriceRange(
+ Range<ΩPriceΩ> calculateConcentratedPositionPriceRange(
RaydiumConcentratedPositionState positionState,
RaydiumConcentratedPoolInfo poolInfo,
int decimalPlaces
diff --git a/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPoolInfo.tjava b/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPoolInfo.tjava
index 4f8683f..269b440 100644
--- a/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPoolInfo.tjava
+++ b/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPoolInfo.tjava
@@ -1,7 +1,5 @@
package com.r35157.libs.raydium;
-import java.math.BigDecimal;
-
/**
* Represents basic information about a Raydium concentrated liquidity pool.
*
@@ -19,6 +17,9 @@ import java.math.BigDecimal;
* @param mintBDecimals the number of decimals used by token B
* @param priceEstimate the pool price estimate as reported by Raydium
*/
+
+import java.math.BigDecimal;
+
public record RaydiumConcentratedPoolInfo(
ΩRaydiumLiquidityPoolConcentratedIdΩ poolId,
ΩSPLMintAddressΩ mintA,
diff --git a/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPoolState.tjava b/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPoolState.tjava
index 97ebca3..e9de50f 100644
--- a/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPoolState.tjava
+++ b/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPoolState.tjava
@@ -1,7 +1,5 @@
package com.r35157.libs.raydium;
-import java.math.BigInteger;
-
/**
* Represents raw on-chain state for a Raydium concentrated liquidity pool.
*
@@ -23,6 +21,9 @@ import java.math.BigInteger;
* @param sqrtPriceX64 the current square-root price in Q64.64 fixed-point format
* @param tickCurrent the current Raydium liquidity tick index
*/
+
+import java.math.BigInteger;
+
public record RaydiumConcentratedPoolState(
ΩRaydiumLiquidityPoolConcentratedIdΩ poolId,
ΩRaydiumLiquidityΩ liquidity,
diff --git a/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPositionState.tjava b/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPositionState.tjava
index ccc5496..b1f07aa 100644
--- a/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPositionState.tjava
+++ b/src/main/tjava/com/r35157/libs/raydium/RaydiumConcentratedPositionState.tjava
@@ -1,5 +1,6 @@
package com.r35157.libs.raydium;
+import java.math.BigDecimal;
import java.math.BigInteger;
public record RaydiumConcentratedPositionState(
diff --git a/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolPositionStandard.tjava b/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolPositionStandard.tjava
index 2991e8f..6cfe215 100644
--- a/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolPositionStandard.tjava
+++ b/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolPositionStandard.tjava
@@ -1,7 +1,5 @@
package com.r35157.libs.raydium;
-import java.math.BigDecimal;
-
/**
* Represents a standard Raydium liquidity pool position.
*
@@ -19,6 +17,9 @@ import java.math.BigDecimal;
* @param lpTokenAccount the SPL token account holding the liquidity pool tokens
* @param lpTokenAmount the amount of liquidity pool tokens held in the SPL token account
*/
+
+import java.math.BigDecimal;
+
public record RaydiumLiquidityPoolPositionStandard(
ΩRaydiumLiquidityPoolPositionIdΩ positionId,
ΩRaydiumLiquidityPoolPositionMintIdΩ lpMintId,
diff --git a/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolPrice.tjava b/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolPrice.tjava
index e44309e..24bd54d 100644
--- a/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolPrice.tjava
+++ b/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolPrice.tjava
@@ -1,18 +1,18 @@
package com.r35157.libs.raydium;
-import com.r35157.libs.valuetypes.basic.AssetPrice;
+import com.r35157.libs.valuetypes.basic.MoneyAmount;
/**
- * Represents the current price of the tokens in a Raydium liquidity pool.
+ * Represents the price of a Raydium liquidity pool.
*
- * The 'poolId' identifies the Raydium liquidity pool for which the current token price applies.
- * The 'price' represents the price value returned or calculated for that pool.
+ * The pool id identifies the Raydium liquidity pool for which the price applies.
+ * The amount contains the price value returned or calculated for that pool.
*
* @param poolId the Raydium liquidity pool id that the price belongs to
- * @param price the price for a token in the liquidity pool
+ * @param amount the price amount for the liquidity pool
*/
public record RaydiumLiquidityPoolPrice(
ΩRaydiumLiquidityPoolIdΩ poolId,
- AssetPrice price
+ MoneyAmount amount
) {
}
\ No newline at end of file
diff --git a/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolTokenAmounts.tjava b/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolTokenAmounts.tjava
index c229b1e..b0241aa 100644
--- a/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolTokenAmounts.tjava
+++ b/src/main/tjava/com/r35157/libs/raydium/RaydiumLiquidityPoolTokenAmounts.tjava
@@ -1,7 +1,5 @@
package com.r35157.libs.raydium;
-import java.math.BigDecimal;
-
/**
* Represents token amounts for a Raydium liquidity pool or liquidity position.
*
@@ -18,6 +16,9 @@ import java.math.BigDecimal;
* @param mintB the SPL mint address of token B
* @param amountB the amount of token B
*/
+
+import java.math.BigDecimal;
+
public record RaydiumLiquidityPoolTokenAmounts(
ΩRaydiumLiquidityPoolIdΩ poolId,
ΩSPLMintAddressΩ mintA,
diff --git a/src/main/tjava/com/r35157/libs/solana/SPLTokenSupply.tjava b/src/main/tjava/com/r35157/libs/solana/SPLTokenSupply.tjava
index f858e7d..5dcbd16 100644
--- a/src/main/tjava/com/r35157/libs/solana/SPLTokenSupply.tjava
+++ b/src/main/tjava/com/r35157/libs/solana/SPLTokenSupply.tjava
@@ -1,7 +1,5 @@
package com.r35157.libs.solana;
-import java.math.BigDecimal;
-
/**
* Represents the total supply of an SPL token mint.
*
@@ -14,6 +12,9 @@ import java.math.BigDecimal;
* @param decimals the number of decimals used by the token mint
* @param programId the SPL token program id for the mint
*/
+
+import java.math.BigDecimal;
+
public record SPLTokenSupply(
ΩSPLMintAddressΩ mintAddress,
ΩAmountΩ uiAmount,
diff --git a/src/main/tjava/com/r35157/libs/solana/SolanaBlockChain.tjava b/src/main/tjava/com/r35157/libs/solana/SolanaBlockChain.tjava
new file mode 100644
index 0000000..982aea0
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/solana/SolanaBlockChain.tjava
@@ -0,0 +1,167 @@
+package com.r35157.libs.solana;
+
+import com.r35157.libs.solana.valuetypes.SolanaProgramDerivedAddress;
+import com.r35157.libs.solana.valuetypes.economic.SolanaSPLTokenProgram;
+import com.r35157.libs.valuetypes.basic.MoneyAmount;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Provides read-oriented access to the Solana blockchain.
+ *
+ * This interface exposes the Solana operations needed by higher-level
+ * integrations. It can fetch native SOL balances, SPL token holdings, NFT-like
+ * token holding candidates, account information and program derived addresses.
+ *
+ * The interface is intentionally generic and does not contain Raydium-specific
+ * logic. Higher-level integrations are expected to interpret Solana accounts,
+ * token holdings and derived addresses according to their own domain rules.
+ */
+public interface SolanaBlockChain {
+ /**
+ * Fetches the native SOL balance for a Solana address.
+ *
+ * @param address the Solana address to inspect
+ * @return the native SOL balance for the address
+ * @throws IOException if the balance could not be fetched or parsed
+ * @throws InterruptedException if the calling thread is interrupted while fetching the balance
+ */
+ ΩSolanaAmountΩ getBalanceInSolana(ΩSolanaAddressΩ address) throws IOException, InterruptedException;
+
+ /**
+ * Fetches the native SOL balance for a Solana address in lamports.
+ *
+ * Lamports are the smallest unit of native SOL.
+ *
+ * @param address the Solana address to inspect
+ * @return the native SOL balance for the address in lamports
+ * @throws IOException if the balance could not be fetched or parsed
+ * @throws InterruptedException if the calling thread is interrupted while fetching the balance
+ */
+ ΩlamportsΩ getBalanceInLamport(ΩSolanaAddressΩ address) throws IOException, InterruptedException;
+
+ /**
+ * Fetches SPL token holdings owned by a Solana address for a specific token program.
+ *
+ * The supplied token program decides which token accounts are inspected. For example,
+ * callers may query the original SPL Token Program or the Token-2022 Program depending
+ * on which token accounts they need to discover.
+ *
+ * @param ownerAddress the Solana owner address whose token holdings should be inspected
+ * @param splProgramId the SPL token program to query
+ * @return a map of SPL mint addresses to token holding information
+ * @throws IOException if the token holdings could not be fetched or parsed
+ * @throws InterruptedException if the calling thread is interrupted while fetching token holdings
+ */
+ Map<ΩSPLMintAddressΩ, SPLTokenHolding> getSPLTokenHoldings(
+ ΩSolanaAddressΩ ownerAddress,
+ SolanaSPLTokenProgram splProgramId
+ ) throws IOException, InterruptedException;
+
+ /**
+ * Fetches NFT-like token mint address candidates owned by a Solana address for a specific token program.
+ *
+ * This method identifies token holdings that look like NFTs within the supplied token
+ * program. A returned address is only a candidate. Higher-level integrations are responsible
+ * for deciding whether the returned address has domain-specific meaning.
+ *
+ * // TODO This method currently identifies candidates from the owner's token holdings only.
+ * // A token with zero decimals and an owner balance of one is not guaranteed to be a real NFT,
+ * // because the mint's total supply may still be greater than one. A future implementation
+ * // should verify the mint supply, for example by using Solana getTokenSupply, before treating
+ * // the result as a confirmed NFT.
+ *
+ * @param ownerAddress the Solana owner address whose NFT-like holdings should be inspected
+ * @param splProgram the SPL token program to query
+ * @return the NFT-like Solana mint address candidates owned by the address
+ * @throws IOException if the NFT candidate addresses could not be fetched or parsed
+ * @throws InterruptedException if the calling thread is interrupted while fetching NFT candidate addresses
+ */
+ Set<ΩSolanaNFTAddressΩ> getSolanaNFTCandidateAddresses(
+ ΩSolanaAddressΩ ownerAddress,
+ SolanaSPLTokenProgram splProgram
+ ) throws IOException, InterruptedException;
+
+ /**
+ * Finds a Solana program derived address for a program id and a set of seeds.
+ *
+ * The seeds describe the logical inputs used to derive the address. The implementation
+ * is responsible for converting each seed into the byte representation required by Solana.
+ *
+ * @param programId the Solana program id used to derive the address
+ * @param seeds the seeds used when deriving the program address
+ * @return the derived Solana address together with its bump value
+ */
+ SolanaProgramDerivedAddress findProgramAddress(
+ ΩSolanaProgramIdΩ programId,
+ List seeds
+ );
+
+ /**
+ * Fetches account information for a Solana account address.
+ *
+ * If the account does not exist, this method returns {@code null}. If the account exists,
+ * the returned value contains the account address, the owning Solana program id and the
+ * account data encoded as Base64.
+ *
+ * @param accountAddress the Solana account address to inspect
+ * @return account information, or {@code null} if the account does not exist
+ * @throws IOException if the account information could not be fetched or parsed
+ * @throws InterruptedException if the calling thread is interrupted while fetching account information
+ */
+ SolanaAccountInfo getAccountInfo(ΩSolanaAddressΩ accountAddress)
+ throws IOException, InterruptedException;
+
+ /**
+ * Encodes a raw 32-byte Solana address into its textual Solana address representation.
+ *
+ * This method is intended for callers that have obtained raw Solana address bytes from
+ * account data and need the normal string representation used elsewhere in the API.
+ *
+ * @param addressBytes the raw 32-byte Solana address
+ * @return the encoded Solana address
+ * @throws IllegalArgumentException if the supplied byte array is not a valid Solana address length
+ */
+ ΩSolanaAddressΩ encodeSolanaAddress(byte[] addressBytes);
+
+ /**
+ * Fetches the total supply of an SPL token mint for a specific token program.
+ *
+ * The supplied token program identifies which SPL token program owns the mint,
+ * for example the original SPL Token Program or the Token-2022 Program.
+ *
+ * @param mintAddress the SPL mint address whose supply should be fetched
+ * @param splProgram the SPL token program to query
+ * @return the SPL token supply for the mint
+ * @throws IOException if the token supply could not be fetched or parsed
+ * @throws InterruptedException if the calling thread is interrupted while fetching token supply
+ */
+ SPLTokenSupply getSPLTokenSupply(
+ ΩSPLMintAddressΩ mintAddress,
+ SolanaSPLTokenProgram splProgram
+ ) throws IOException, InterruptedException;
+
+ /**
+ * Fetches accounts owned by a Solana program using server-side account data filters.
+ *
+ * This method uses Solana's {@code getProgramAccounts} RPC call. The supplied filters
+ * are sent to the RPC node, so matching is performed server-side instead of fetching all
+ * accounts owned by the program and filtering them locally.
+ *
+ * The initial supported filter type is {@link SolanaProgramAccountMemcmpFilter}, which
+ * matches bytes at a specific offset in the account data.
+ *
+ * @param programId the Solana program id that owns the accounts to search
+ * @param filters the memcmp filters to apply when searching program accounts
+ * @return the matching program accounts
+ * @throws IOException if the program accounts could not be fetched or parsed
+ * @throws InterruptedException if the calling thread is interrupted while fetching program accounts
+ */
+ Set getProgramAccounts(
+ ΩSolanaProgramIdΩ programId,
+ Set filters
+ ) throws IOException, InterruptedException;
+}
\ No newline at end of file
diff --git a/src/main/tjava/com/r35157/libs/solana/SolanaProgramAccountMemcmpFilter.tjava b/src/main/tjava/com/r35157/libs/solana/SolanaProgramAccountMemcmpFilter.tjava
new file mode 100644
index 0000000..eb523be
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/solana/SolanaProgramAccountMemcmpFilter.tjava
@@ -0,0 +1,17 @@
+package com.r35157.libs.solana;
+
+/**
+ * Filter used when fetching accounts owned by a Solana program.
+ *
+ * The initial supported filter type is {@code memcmp}, which asks the
+ * Solana RPC node to only return accounts where the account data at a specific
+ * byte offset matches a base58 encoded value.
+ *
+ * @param offset the byte offset in the account data where comparison starts
+ * @param bytes the base58 encoded bytes to match
+ */
+public record SolanaProgramAccountMemcmpFilter(
+ int offset,
+ String bytes
+) {
+}
\ No newline at end of file
diff --git a/src/main/tjava/com/r35157/libs/valuetypes/basic/MoneyPrice.tjava b/src/main/tjava/com/r35157/libs/valuetypes/basic/MoneyPrice.tjava
new file mode 100644
index 0000000..4480d0d
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/valuetypes/basic/MoneyPrice.tjava
@@ -0,0 +1,8 @@
+package com.r35157.libs.valuetypes.basic;
+
+import java.math.BigDecimal;
+
+public record MoneyPrice(
+ ΩPriceΩ price,
+ CurrencyType currencyType
+) { }
diff --git a/src/main/tjava/com/r35157/nenjim/hubd/impl/ref/Main.tjava b/src/main/tjava/com/r35157/nenjim/hubd/impl/ref/Main.tjava
index ed7957e..57f803e 100644
--- a/src/main/tjava/com/r35157/nenjim/hubd/impl/ref/Main.tjava
+++ b/src/main/tjava/com/r35157/nenjim/hubd/impl/ref/Main.tjava
@@ -5,34 +5,44 @@ import com.r35157.libs.jupiter.perps.JupiterPerpsService;
import com.r35157.libs.jupiter.perps.impl.anchoridl.AnchorIdlJupiterPerpsServiceImpl;
import com.r35157.libs.solana.SolanaBlockChain;
import com.r35157.libs.solana.impl.ref.SolanaBlockChainImpl;
-import com.r35157.nenjim.hubd.ctx.Context;
-import com.r35157.nenjim.hubd.NenjimHub;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.lang.management.ClassLoadingMXBean;
-import java.lang.management.ManagementFactory;
-import com.r35157.nenjim.hubd.ctx.ContextManager;
-import com.r35157.nenjim.hubd.journal.JournalManager;
-import com.r35157.nenjim.hubd.impl.ref.JournalManagerImpl;
-import java.nio.file.Files;
-import java.nio.file.Path;
import java.util.Set;
public class Main {
// TODO: Consider if we really need a Main class or we just need to move the main method to NenjimHubImpl?
static void main(String[] args) throws Exception {
- NenjimHubImpl nenjimHub = new NenjimHubImpl();
+ //NenjimHubImpl nenjimHub = new NenjimHubImpl();
- /*
SolanaBlockChain sbc = new SolanaBlockChainImpl();
JupiterPerpsService jupiter = new AnchorIdlJupiterPerpsServiceImpl(sbc);
ΩSolanaWalletIdΩ walletId = "vj98roDZ7744EBfxyuDFkKpEGCsKQLr7K8UFRumJNHf";
+
Set positions = jupiter.getOpenPositions(walletId);
+
+ for (JupiterPerpsPosition position : positions) {
+ System.out.println(" PositionAccount: " + position.positionAccount());
+ System.out.println(" Token mint: " + position.tradedTokenMint());
+ System.out.println(" Direction: " + position.direction());
+ System.out.println(" Value: " + position.value());
+ System.out.println(" Size $: " + position.size());
+ System.out.println(" PnL: " + position.pnl() + " " + position.pnlPercent());
+ System.out.println(" Leverage: " + position.leverage() + "x");
+ System.out.println(" Entry price: " + position.entryPrice());
+ System.out.println(" Market price: " + position.marketPrice());
+ System.out.println(" Collateral: " + position.collateral());
+ System.out.println(" Totals fees: " + position.totalFees());
+ System.out.println(" Borrow Fees Due: " + position.borrowFeesDue());
+ System.out.println(" Close Fees Pending: " + position.closeFeePending());
+ System.out.println("Amount locked for account rent (SOL): " + position.accountRent());
+
+ System.out.println();
+ }
+
int a=0;
- */
- nenjimHub.awaitShutdown();
+ //nenjimHub.awaitShutdown();
/* try {
log.info("Auto-starting 2 Nenjim application(s)...");