Compare commits
5 Commits
| Author | SHA256 | Date | |
|---|---|---|---|
| ba9a167a57 | |||
| 0c2f00f791 | |||
| 8f0f4061ee | |||
| 3f47f9a895 | |||
| a52dbec41a |
@@ -1,70 +0,0 @@
|
|||||||
package com.r35157.libs.codec.impl.ref;
|
|
||||||
|
|
||||||
import com.r35157.libs.codec.Base58Codec;
|
|
||||||
|
|
||||||
public class Base58CodecImpl implements Base58Codec {
|
|
||||||
|
|
||||||
public String encode(byte[] input) {
|
|
||||||
if (input.length == 0) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] copy = input.clone();
|
|
||||||
|
|
||||||
int zeros = 0;
|
|
||||||
while (zeros < copy.length && copy[zeros] == 0) {
|
|
||||||
zeros++;
|
|
||||||
}
|
|
||||||
|
|
||||||
char[] encoded = new char[copy.length * 2];
|
|
||||||
int outputStart = encoded.length;
|
|
||||||
|
|
||||||
int inputStart = zeros;
|
|
||||||
while (inputStart < copy.length) {
|
|
||||||
int remainder = divmod58(
|
|
||||||
copy,
|
|
||||||
inputStart
|
|
||||||
);
|
|
||||||
|
|
||||||
if (copy[inputStart] == 0) {
|
|
||||||
inputStart++;
|
|
||||||
}
|
|
||||||
|
|
||||||
encoded[--outputStart] = ALPHABET[remainder];
|
|
||||||
}
|
|
||||||
|
|
||||||
while (outputStart < encoded.length && encoded[outputStart] == ENCODED_ZERO) {
|
|
||||||
outputStart++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (zeros-- > 0) {
|
|
||||||
encoded[--outputStart] = ENCODED_ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new String(
|
|
||||||
encoded,
|
|
||||||
outputStart,
|
|
||||||
encoded.length - outputStart
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int divmod58(byte[] number, int startAt) {
|
|
||||||
int remainder = 0;
|
|
||||||
|
|
||||||
for (int i = startAt; i < number.length; i++) {
|
|
||||||
int digit = number[i] & 0xff;
|
|
||||||
int temp = remainder * 256 + digit;
|
|
||||||
|
|
||||||
number[i] = (byte) (temp / 58);
|
|
||||||
remainder = temp % 58;
|
|
||||||
}
|
|
||||||
|
|
||||||
return remainder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final char[] ALPHABET =
|
|
||||||
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
|
|
||||||
|
|
||||||
private static final char ENCODED_ZERO =
|
|
||||||
ALPHABET[0];
|
|
||||||
}
|
|
||||||
@@ -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,45 @@
|
|||||||
|
package com.r35157.libs.jupiter.perps;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds open Jupiter Perps positions owned by a wallet.
|
||||||
|
*
|
||||||
|
* <p>This method returns decoded Jupiter Perps position objects. It does not return
|
||||||
|
* raw Solana accounts or account ids.</p>
|
||||||
|
*
|
||||||
|
* @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<JupiterPerpsPosition> getOpenPositions(ΩSolanaWalletIdΩ owner)
|
||||||
|
throws IOException, InterruptedException;
|
||||||
|
}
|
||||||
-50
@@ -1,50 +0,0 @@
|
|||||||
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
|
||||||
|
|
||||||
import com.r35157.libs.codec.Base58Codec;
|
|
||||||
import com.r35157.libs.codec.impl.ref.Base58CodecImpl;
|
|
||||||
import com.r35157.libs.solana.SolanaAccountInfo;
|
|
||||||
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
class AnchorIdlJupiterPerpsCustodyDecoder {
|
|
||||||
|
|
||||||
ΩSPLMintAddressΩ decodeMint(
|
|
||||||
SolanaAccountInfo custodyAccountInfo
|
|
||||||
) {
|
|
||||||
byte[] data = Base64.getDecoder().decode(custodyAccountInfo.dataBase64());
|
|
||||||
|
|
||||||
if (data.length < MINT_OFFSET + PUBLIC_KEY_LENGTH) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Jupiter Perps custody account data is too short: " + data.length
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
return base58.encode(publicKeyBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int ANCHOR_DISCRIMINATOR_LENGTH = 8;
|
|
||||||
private static final int PUBLIC_KEY_LENGTH = 32;
|
|
||||||
|
|
||||||
private static final int MINT_OFFSET =
|
|
||||||
ANCHOR_DISCRIMINATOR_LENGTH
|
|
||||||
+ PUBLIC_KEY_LENGTH; // pool
|
|
||||||
|
|
||||||
private static final Base58Codec base58 = new Base58CodecImpl();
|
|
||||||
}
|
|
||||||
+12
-69
@@ -1,9 +1,6 @@
|
|||||||
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
||||||
|
|
||||||
import com.r35157.libs.codec.Base58Codec;
|
|
||||||
import com.r35157.libs.codec.impl.ref.Base58CodecImpl;
|
|
||||||
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.solana.SolanaAccountInfo;
|
import com.r35157.libs.solana.SolanaAccountInfo;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -15,8 +12,7 @@ class AnchorIdlJupiterPerpsPositionDecoder {
|
|||||||
|
|
||||||
JupiterPerpsPosition decode(
|
JupiterPerpsPosition decode(
|
||||||
ΩJupiterPerpsPositionAccountΩ positionAccount,
|
ΩJupiterPerpsPositionAccountΩ positionAccount,
|
||||||
SolanaAccountInfo accountInfo,
|
SolanaAccountInfo accountInfo
|
||||||
ΩSPLMintAddressΩ tradedTokenMint
|
|
||||||
) {
|
) {
|
||||||
byte[] data = Base64.getDecoder().decode(accountInfo.dataBase64());
|
byte[] data = Base64.getDecoder().decode(accountInfo.dataBase64());
|
||||||
|
|
||||||
@@ -26,9 +22,6 @@ class AnchorIdlJupiterPerpsPositionDecoder {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
JupiterPerpsPositionDirection direction =
|
|
||||||
decodeDirection(data[SIDE_OFFSET]);
|
|
||||||
|
|
||||||
long rawEntryPrice = ByteBuffer
|
long rawEntryPrice = ByteBuffer
|
||||||
.wrap(data, PRICE_OFFSET, U64_LENGTH)
|
.wrap(data, PRICE_OFFSET, U64_LENGTH)
|
||||||
.order(ByteOrder.LITTLE_ENDIAN)
|
.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
@@ -40,75 +33,25 @@ class AnchorIdlJupiterPerpsPositionDecoder {
|
|||||||
|
|
||||||
JupiterPerpsPosition pos = new JupiterPerpsPosition(
|
JupiterPerpsPosition pos = new JupiterPerpsPosition(
|
||||||
positionAccount,
|
positionAccount,
|
||||||
entryPrice,
|
entryPrice
|
||||||
direction,
|
|
||||||
tradedTokenMint
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
ΩSolanaAddressΩ decodeCustodyAccount(SolanaAccountInfo accountInfo) {
|
|
||||||
byte[] data = Base64.getDecoder().decode(accountInfo.dataBase64());
|
|
||||||
|
|
||||||
if (data.length < CUSTODY_OFFSET + PUBLIC_KEY_LENGTH) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Jupiter Perps position account data is too short: " + data.length
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return readPublicKey(
|
|
||||||
data,
|
|
||||||
CUSTODY_OFFSET
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private JupiterPerpsPositionDirection decodeDirection(
|
|
||||||
byte rawSide
|
|
||||||
) {
|
|
||||||
// Jupiter Perps position side values are encoded as 1 = LONG, 2 = SHORT.
|
|
||||||
JupiterPerpsPositionDirection direction = switch (rawSide) {
|
|
||||||
case 1 -> JupiterPerpsPositionDirection.LONG;
|
|
||||||
case 2 -> JupiterPerpsPositionDirection.SHORT;
|
|
||||||
default -> throw new IllegalArgumentException(
|
|
||||||
"Unknown Jupiter Perps position side: " + rawSide
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ΩSolanaAddressΩ readPublicKey(
|
|
||||||
byte[] data,
|
|
||||||
int offset
|
|
||||||
) {
|
|
||||||
byte[] publicKeyBytes = new byte[PUBLIC_KEY_LENGTH];
|
|
||||||
|
|
||||||
System.arraycopy(
|
|
||||||
data,
|
|
||||||
offset,
|
|
||||||
publicKeyBytes,
|
|
||||||
0,
|
|
||||||
PUBLIC_KEY_LENGTH
|
|
||||||
);
|
|
||||||
|
|
||||||
return base58.encode(publicKeyBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final int ANCHOR_DISCRIMINATOR_LENGTH = 8;
|
private static final int ANCHOR_DISCRIMINATOR_LENGTH = 8;
|
||||||
private static final int PUBLIC_KEY_LENGTH = 32;
|
private static final int PUBLIC_KEY_LENGTH = 32;
|
||||||
private static final int I64_LENGTH = 8;
|
private static final int I64_LENGTH = 8;
|
||||||
private static final int SIDE_ENUM_LENGTH = 1;
|
|
||||||
private static final int U64_LENGTH = 8;
|
private static final int U64_LENGTH = 8;
|
||||||
|
private static final int SIDE_ENUM_LENGTH = 1;
|
||||||
|
|
||||||
private static final int OWNER_OFFSET = ANCHOR_DISCRIMINATOR_LENGTH;
|
private static final int PRICE_OFFSET =
|
||||||
private static final int POOL_OFFSET = OWNER_OFFSET + PUBLIC_KEY_LENGTH;
|
ANCHOR_DISCRIMINATOR_LENGTH
|
||||||
private static final int CUSTODY_OFFSET = POOL_OFFSET + PUBLIC_KEY_LENGTH;
|
+ PUBLIC_KEY_LENGTH // owner
|
||||||
private static final int COLLATERAL_CUSTODY_OFFSET = CUSTODY_OFFSET + PUBLIC_KEY_LENGTH; // custody
|
+ PUBLIC_KEY_LENGTH // pool
|
||||||
private static final int OPEN_TIME_OFFSET = COLLATERAL_CUSTODY_OFFSET + PUBLIC_KEY_LENGTH;
|
+ PUBLIC_KEY_LENGTH // custody
|
||||||
private static final int UPDATE_TIME_OFFSET = OPEN_TIME_OFFSET + I64_LENGTH; // openTime
|
+ PUBLIC_KEY_LENGTH // collateralCustody
|
||||||
private static final int SIDE_OFFSET = UPDATE_TIME_OFFSET + I64_LENGTH;
|
+ I64_LENGTH // openTime
|
||||||
private static final int PRICE_OFFSET = SIDE_OFFSET + SIDE_ENUM_LENGTH;
|
+ I64_LENGTH // updateTime
|
||||||
|
+ SIDE_ENUM_LENGTH; // side
|
||||||
private static final Base58Codec base58 = new Base58CodecImpl();
|
|
||||||
}
|
}
|
||||||
+8
-27
@@ -1,7 +1,7 @@
|
|||||||
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
package com.r35157.libs.jupiter.perps.impl.anchoridl;
|
||||||
|
|
||||||
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
||||||
import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
import com.r35157.libs.jupiter.perps.JupiterPerpsPositionService;
|
||||||
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;
|
||||||
@@ -10,14 +10,13 @@ import java.io.IOException;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
public class AnchorIdlJupiterPerpsPositionServiceImpl implements JupiterPerpsPositionService {
|
||||||
|
|
||||||
public AnchorIdlJupiterPerpsServiceImpl(
|
public AnchorIdlJupiterPerpsPositionServiceImpl(
|
||||||
SolanaBlockChain solanaBlockChain
|
SolanaBlockChain solanaBlockChain
|
||||||
) {
|
) {
|
||||||
this.solanaBlockChain = solanaBlockChain;
|
this.solanaBlockChain = solanaBlockChain;
|
||||||
this.positionDecoder = new AnchorIdlJupiterPerpsPositionDecoder();
|
this.positionDecoder = new AnchorIdlJupiterPerpsPositionDecoder();
|
||||||
this.custodyDecoder = new AnchorIdlJupiterPerpsCustodyDecoder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -35,9 +34,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ΩSPLMintAddressΩ tradedTokenMint = getTradedTokenMint(accountInfo);
|
JupiterPerpsPosition pos = positionDecoder.decode(positionAccount, accountInfo);
|
||||||
JupiterPerpsPosition pos = positionDecoder.decode(positionAccount, accountInfo, tradedTokenMint);
|
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,36 +61,20 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
throw new IllegalArgumentException(errorMsg);
|
throw new IllegalArgumentException(errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
ΩSPLMintAddressΩ tradedTokenMint = getTradedTokenMint(accountInfo);
|
JupiterPerpsPosition position = positionDecoder.decode(
|
||||||
|
address,
|
||||||
JupiterPerpsPosition position = positionDecoder.decode(address, accountInfo, tradedTokenMint);
|
accountInfo
|
||||||
|
);
|
||||||
positions.add(position);
|
positions.add(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Set.copyOf(positions);
|
return Set.copyOf(positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ΩSPLMintAddressΩ getTradedTokenMint(SolanaAccountInfo positionAccountInfo)
|
|
||||||
throws IOException, InterruptedException
|
|
||||||
{
|
|
||||||
ΩSolanaAddressΩ custodyAccount = positionDecoder.decodeCustodyAccount(positionAccountInfo);
|
|
||||||
SolanaAccountInfo custodyAccountInfo = solanaBlockChain.getAccountInfo(custodyAccount);
|
|
||||||
|
|
||||||
if (custodyAccountInfo == null) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Jupiter Perps custody account does not exist: " + custodyAccount
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ΩSPLMintAddressΩ mintAddress = custodyDecoder.decodeMint(custodyAccountInfo);
|
|
||||||
return mintAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final ΩJupiterPerpsProgramIdΩ JUPITER_PERPS_PROGRAM_ID =
|
private static final ΩJupiterPerpsProgramIdΩ JUPITER_PERPS_PROGRAM_ID =
|
||||||
"PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
|
"PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
|
||||||
private static final int POSITION_OWNER_OFFSET = 8;
|
private static final int POSITION_OWNER_OFFSET = 8;
|
||||||
|
|
||||||
private final SolanaBlockChain solanaBlockChain;
|
private final SolanaBlockChain solanaBlockChain;
|
||||||
private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder;
|
private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder;
|
||||||
private final AnchorIdlJupiterPerpsCustodyDecoder custodyDecoder;
|
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.r35157.nenjim.hubd.impl.ref;
|
package com.r35157.nenjim.hubd.impl.ref;
|
||||||
|
|
||||||
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
import com.r35157.libs.jupiter.perps.JupiterPerpsPosition;
|
||||||
import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
import com.r35157.libs.jupiter.perps.JupiterPerpsPositionService;
|
||||||
import com.r35157.libs.jupiter.perps.impl.anchoridl.AnchorIdlJupiterPerpsServiceImpl;
|
import com.r35157.libs.jupiter.perps.impl.anchoridl.AnchorIdlJupiterPerpsPositionServiceImpl;
|
||||||
import com.r35157.libs.solana.SolanaBlockChain;
|
import com.r35157.libs.solana.SolanaBlockChain;
|
||||||
import com.r35157.libs.solana.impl.ref.SolanaBlockChainImpl;
|
import com.r35157.libs.solana.impl.ref.SolanaBlockChainImpl;
|
||||||
import com.r35157.nenjim.hubd.ctx.Context;
|
import com.r35157.nenjim.hubd.ctx.Context;
|
||||||
@@ -24,10 +24,9 @@ public class Main {
|
|||||||
// TODO: Consider if we really need a Main class or we just need to move the main method to NenjimHubImpl?
|
// 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 {
|
static void main(String[] args) throws Exception {
|
||||||
NenjimHubImpl nenjimHub = new NenjimHubImpl();
|
NenjimHubImpl nenjimHub = new NenjimHubImpl();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SolanaBlockChain sbc = new SolanaBlockChainImpl();
|
SolanaBlockChain sbc = new SolanaBlockChainImpl();
|
||||||
JupiterPerpsService jupiter = new AnchorIdlJupiterPerpsServiceImpl(sbc);
|
JupiterPerpsPositionService jupiter = new AnchorIdlJupiterPerpsPositionServiceImpl(sbc);
|
||||||
ΩSolanaWalletIdΩ walletId = "vj98roDZ7744EBfxyuDFkKpEGCsKQLr7K8UFRumJNHf";
|
ΩSolanaWalletIdΩ walletId = "vj98roDZ7744EBfxyuDFkKpEGCsKQLr7K8UFRumJNHf";
|
||||||
Set<JupiterPerpsPosition> positions = jupiter.getOpenPositions(walletId);
|
Set<JupiterPerpsPosition> positions = jupiter.getOpenPositions(walletId);
|
||||||
int a=0;
|
int a=0;
|
||||||
|
|||||||
Reference in New Issue
Block a user