diff --git a/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPositionService.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPositionService.tjava
index 2f47ad3..533cad7 100644
--- a/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPositionService.tjava
+++ b/src/main/tjava/com/r35157/libs/jupiter/perps/JupiterPerpsPositionService.tjava
@@ -1,6 +1,7 @@
package com.r35157.libs.jupiter.perps;
import java.io.IOException;
+import java.util.Set;
/**
* Service for reading Jupiter Perps positions.
@@ -27,4 +28,18 @@ public interface JupiterPerpsPositionService {
*/
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/AnchorIdlJupiterPerpsPositionServiceImpl.tjava b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsPositionServiceImpl.tjava
index 79d4cbf..259d9e7 100644
--- a/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsPositionServiceImpl.tjava
+++ b/src/main/tjava/com/r35157/libs/jupiter/perps/impl/anchoridl/AnchorIdlJupiterPerpsPositionServiceImpl.tjava
@@ -4,8 +4,11 @@ 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 com.r35157.libs.solana.SolanaProgramAccountMemcmpFilter;
import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
public class AnchorIdlJupiterPerpsPositionServiceImpl implements JupiterPerpsPositionService {
@@ -35,8 +38,42 @@ public class AnchorIdlJupiterPerpsPositionServiceImpl implements JupiterPerpsPos
return pos;
}
+ @Override
+ public Set getOpenPositions(ΩSolanaWalletIdΩ owner)
+ throws IOException, InterruptedException {
+ Set accountInfos = solanaBlockChain.getProgramAccounts(
+ JUPITER_PERPS_PROGRAM_ID,
+ Set.of(new SolanaProgramAccountMemcmpFilter(
+ POSITION_OWNER_OFFSET,
+ owner
+ ))
+ );
+
+ Set positions = new HashSet<>();
+
+ for (SolanaAccountInfo accountInfo : accountInfos) {
+ ΩSolanaAddressΩ address = accountInfo.address();
+ ΩSolanaProgramIdΩ programId = accountInfo.owner();
+
+ if (!JUPITER_PERPS_PROGRAM_ID.equals(programId)) {
+ String errorMsg = "Account '" + address + "' is not owned by Jupiter Perps program '" +
+ programId + "'";
+ throw new IllegalArgumentException(errorMsg);
+ }
+
+ JupiterPerpsPosition position = positionDecoder.decode(
+ address,
+ accountInfo
+ );
+ positions.add(position);
+ }
+
+ return Set.copyOf(positions);
+ }
+
private static final ΩJupiterPerpsProgramIdΩ JUPITER_PERPS_PROGRAM_ID =
"PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
+ private static final int POSITION_OWNER_OFFSET = 8;
private final SolanaBlockChain solanaBlockChain;
private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder;