49: Complete wallet-bound Jupiter transaction flow
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package com.r35157.jupiterperpsalarm.impl.ref;
|
package com.r35157.jupiterperpsalarm.impl.ref;
|
||||||
|
|
||||||
|
import com.r35157.cryptowallet.solana.SolanaWallet;
|
||||||
|
import com.r35157.cryptowallet.solana.impl.ref.SolanaWalletImpl;
|
||||||
import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
||||||
import com.r35157.libs.jupiter.perps.impl.anchoridl.AnchorIdlJupiterPerpsServiceImpl;
|
import com.r35157.libs.jupiter.perps.impl.anchoridl.AnchorIdlJupiterPerpsServiceImpl;
|
||||||
import com.r35157.libs.objcache.ObjectCache;
|
import com.r35157.libs.objcache.ObjectCache;
|
||||||
@@ -49,6 +51,10 @@ public final class JupiterPerpsAlarmImpl {
|
|||||||
alarmConfiguration.variables()
|
alarmConfiguration.variables()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Path alarmConfigurationDirectory = config.alarmConfiguration()
|
||||||
|
.toAbsolutePath()
|
||||||
|
.getParent();
|
||||||
|
|
||||||
System.out.print("Initializing dependencies... ");
|
System.out.print("Initializing dependencies... ");
|
||||||
ObjectCache objectCache = new ObjectCacheImpl();
|
ObjectCache objectCache = new ObjectCacheImpl();
|
||||||
SolanaBlockChain realSolanaBlockChain = new SolanaBlockChainImpl();
|
SolanaBlockChain realSolanaBlockChain = new SolanaBlockChainImpl();
|
||||||
@@ -57,9 +63,57 @@ public final class JupiterPerpsAlarmImpl {
|
|||||||
objectCache
|
objectCache
|
||||||
);
|
);
|
||||||
|
|
||||||
JupiterPerpsService jupiterPerpsService = new AnchorIdlJupiterPerpsServiceImpl(solanaBlockChain);
|
JupiterPerpsPositionIncreaseAlarmActionConfiguration
|
||||||
|
positionIncreaseConfiguration =
|
||||||
|
JupiterPerpsPositionIncreaseAlarmActionConfigurationParser
|
||||||
|
.parse(
|
||||||
|
alarmConfigurationDirectory.resolve(
|
||||||
|
JupiterPerpsPositionIncreaseAlarmAction
|
||||||
|
.CONFIGURATION_FILE_NAME
|
||||||
|
),
|
||||||
|
variableResolver
|
||||||
|
);
|
||||||
|
|
||||||
|
SolanaWallet positionIncreaseWallet = new SolanaWalletImpl(
|
||||||
|
positionIncreaseConfiguration.walletId(),
|
||||||
|
positionIncreaseConfiguration.signerKeyName(),
|
||||||
|
solanaBlockChain
|
||||||
|
);
|
||||||
|
|
||||||
|
JupiterPerpsService positionIncreaseJupiter =
|
||||||
|
new AnchorIdlJupiterPerpsServiceImpl(
|
||||||
|
solanaBlockChain,
|
||||||
|
positionIncreaseWallet
|
||||||
|
);
|
||||||
|
|
||||||
|
JupiterPerpsPositionDecreaseAlarmActionConfiguration
|
||||||
|
positionDecreaseConfiguration =
|
||||||
|
JupiterPerpsPositionDecreaseAlarmActionConfigurationParser
|
||||||
|
.parse(
|
||||||
|
alarmConfigurationDirectory.resolve(
|
||||||
|
JupiterPerpsPositionDecreaseAlarmAction
|
||||||
|
.CONFIGURATION_FILE_NAME
|
||||||
|
),
|
||||||
|
variableResolver
|
||||||
|
);
|
||||||
|
|
||||||
|
SolanaWallet positionDecreaseWallet = new SolanaWalletImpl(
|
||||||
|
positionDecreaseConfiguration.walletId(),
|
||||||
|
positionDecreaseConfiguration.signerKeyName(),
|
||||||
|
solanaBlockChain
|
||||||
|
);
|
||||||
|
|
||||||
|
JupiterPerpsService positionDecreaseJupiter =
|
||||||
|
new AnchorIdlJupiterPerpsServiceImpl(
|
||||||
|
solanaBlockChain,
|
||||||
|
positionDecreaseWallet
|
||||||
|
);
|
||||||
|
|
||||||
JupiterPerpsEntryPriceVariableRefresher entryPriceVariableRefresher =
|
JupiterPerpsEntryPriceVariableRefresher entryPriceVariableRefresher =
|
||||||
new JupiterPerpsEntryPriceVariableRefresher(alarmConfiguration.variables(), jupiterPerpsService);
|
new JupiterPerpsEntryPriceVariableRefresher(
|
||||||
|
alarmConfiguration.variables(),
|
||||||
|
positionIncreaseJupiter
|
||||||
|
);
|
||||||
System.out.println("Done.");
|
System.out.println("Done.");
|
||||||
|
|
||||||
System.out.println("Executing first pre-run data fetch:");
|
System.out.println("Executing first pre-run data fetch:");
|
||||||
@@ -80,22 +134,18 @@ public final class JupiterPerpsAlarmImpl {
|
|||||||
|
|
||||||
entryPriceVariableRefreshWatcher.start();
|
entryPriceVariableRefreshWatcher.start();
|
||||||
|
|
||||||
Path alarmConfigurationDirectory = config.alarmConfiguration()
|
|
||||||
.toAbsolutePath()
|
|
||||||
.getParent();
|
|
||||||
|
|
||||||
List<AlarmAction> actions = new ArrayList<>();
|
List<AlarmAction> actions = new ArrayList<>();
|
||||||
actions.add(new ConsoleAlarmAction(alarmConfigurationDirectory));
|
actions.add(new ConsoleAlarmAction(alarmConfigurationDirectory));
|
||||||
actions.add(new JupiterPerpsPositionIncreaseAlarmAction(
|
actions.add(new JupiterPerpsPositionIncreaseAlarmAction(
|
||||||
alarmConfigurationDirectory,
|
positionIncreaseConfiguration,
|
||||||
solanaBlockChain,
|
positionIncreaseWallet,
|
||||||
jupiterPerpsService,
|
positionIncreaseJupiter,
|
||||||
variableResolver
|
variableResolver
|
||||||
));
|
));
|
||||||
actions.add(new JupiterPerpsPositionDecreaseAlarmAction(
|
actions.add(new JupiterPerpsPositionDecreaseAlarmAction(
|
||||||
alarmConfigurationDirectory,
|
positionDecreaseConfiguration,
|
||||||
solanaBlockChain,
|
positionDecreaseWallet,
|
||||||
jupiterPerpsService,
|
positionDecreaseJupiter,
|
||||||
variableResolver
|
variableResolver
|
||||||
));
|
));
|
||||||
actions.add(new PushoverAlarmAction(
|
actions.add(new PushoverAlarmAction(
|
||||||
|
|||||||
+11
-26
@@ -1,53 +1,36 @@
|
|||||||
package com.r35157.jupiterperpsalarm.impl.ref;
|
package com.r35157.jupiterperpsalarm.impl.ref;
|
||||||
|
|
||||||
import com.r35157.cryptowallet.solana.SolanaWallet;
|
import com.r35157.cryptowallet.solana.SolanaWallet;
|
||||||
import com.r35157.cryptowallet.solana.impl.ref.SolanaWalletImpl;
|
|
||||||
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.JupiterPerpsService;
|
||||||
import com.r35157.libs.solana.SolanaBlockChain;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public final class JupiterPerpsPositionDecreaseAlarmAction
|
public final class JupiterPerpsPositionDecreaseAlarmAction
|
||||||
implements ConfiguredAlarmAction {
|
implements ConfiguredAlarmAction {
|
||||||
public JupiterPerpsPositionDecreaseAlarmAction(
|
public JupiterPerpsPositionDecreaseAlarmAction(
|
||||||
Path configurationDirectory,
|
JupiterPerpsPositionDecreaseAlarmActionConfiguration configuration,
|
||||||
SolanaBlockChain solanaBlockChain,
|
SolanaWallet wallet,
|
||||||
JupiterPerpsService jupiter,
|
JupiterPerpsService jupiter,
|
||||||
AlarmVariableResolver variableResolver
|
AlarmVariableResolver variableResolver
|
||||||
) throws IOException {
|
) {
|
||||||
Objects.requireNonNull(
|
this.configuration = Objects.requireNonNull(
|
||||||
configurationDirectory,
|
configuration,
|
||||||
"configurationDirectory"
|
"configuration"
|
||||||
);
|
);
|
||||||
Objects.requireNonNull(solanaBlockChain, "solanaBlockChain");
|
this.wallet = Objects.requireNonNull(wallet, "wallet");
|
||||||
this.jupiter = Objects.requireNonNull(jupiter, "jupiter");
|
this.jupiter = Objects.requireNonNull(jupiter, "jupiter");
|
||||||
this.variableResolver = Objects.requireNonNull(
|
this.variableResolver = Objects.requireNonNull(
|
||||||
variableResolver,
|
variableResolver,
|
||||||
"variableResolver"
|
"variableResolver"
|
||||||
);
|
);
|
||||||
|
|
||||||
configuration =
|
|
||||||
JupiterPerpsPositionDecreaseAlarmActionConfigurationParser
|
|
||||||
.parse(
|
|
||||||
configurationDirectory.resolve(
|
|
||||||
getConfigurationFileName()
|
|
||||||
),
|
|
||||||
variableResolver
|
|
||||||
);
|
|
||||||
wallet = new SolanaWalletImpl(
|
|
||||||
configuration.walletId(),
|
|
||||||
configuration.signerKeyName(),
|
|
||||||
solanaBlockChain
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getConfigurationFileName() {
|
public String getConfigurationFileName() {
|
||||||
return "alarmaction_JupiterPerpsPositionDecreaseAlarmAction.conf";
|
return CONFIGURATION_FILE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -73,7 +56,6 @@ public final class JupiterPerpsPositionDecreaseAlarmAction
|
|||||||
|
|
||||||
ΩSolanaTransactionSignatureΩ signature =
|
ΩSolanaTransactionSignatureΩ signature =
|
||||||
jupiter.executePositionDecrease(
|
jupiter.executePositionDecrease(
|
||||||
wallet,
|
|
||||||
position.positionAccount(),
|
position.positionAccount(),
|
||||||
positionDecrease.receiveToken()
|
positionDecrease.receiveToken()
|
||||||
.receiveTokenMint(),
|
.receiveTokenMint(),
|
||||||
@@ -173,4 +155,7 @@ public final class JupiterPerpsPositionDecreaseAlarmAction
|
|||||||
private final SolanaWallet wallet;
|
private final SolanaWallet wallet;
|
||||||
private final JupiterPerpsService jupiter;
|
private final JupiterPerpsService jupiter;
|
||||||
private final AlarmVariableResolver variableResolver;
|
private final AlarmVariableResolver variableResolver;
|
||||||
|
|
||||||
|
static final String CONFIGURATION_FILE_NAME =
|
||||||
|
"alarmaction_JupiterPerpsPositionDecreaseAlarmAction.conf";
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-20
@@ -1,44 +1,34 @@
|
|||||||
package com.r35157.jupiterperpsalarm.impl.ref;
|
package com.r35157.jupiterperpsalarm.impl.ref;
|
||||||
|
|
||||||
import com.r35157.cryptowallet.solana.SolanaWallet;
|
import com.r35157.cryptowallet.solana.SolanaWallet;
|
||||||
import com.r35157.cryptowallet.solana.impl.ref.SolanaWalletImpl;
|
|
||||||
import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
import com.r35157.libs.jupiter.perps.JupiterPerpsService;
|
||||||
import com.r35157.libs.solana.SolanaBlockChain;
|
|
||||||
import com.r35157.libs.valuetypes.basic.MoneyAmount;
|
import com.r35157.libs.valuetypes.basic.MoneyAmount;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static com.r35157.libs.solana.valuetypes.economic.SolanaSPLTokenProgram.SPL_TOKEN_PROGRAM;
|
import static com.r35157.libs.solana.valuetypes.economic.SolanaSPLTokenProgram.SPL_TOKEN_PROGRAM;
|
||||||
|
|
||||||
public final class JupiterPerpsPositionIncreaseAlarmAction implements ConfiguredAlarmAction {
|
public final class JupiterPerpsPositionIncreaseAlarmAction implements ConfiguredAlarmAction {
|
||||||
public JupiterPerpsPositionIncreaseAlarmAction(
|
public JupiterPerpsPositionIncreaseAlarmAction(
|
||||||
Path configurationDirectory,
|
JupiterPerpsPositionIncreaseAlarmActionConfiguration configuration,
|
||||||
SolanaBlockChain solanaBlockChain,
|
SolanaWallet wallet,
|
||||||
JupiterPerpsService jupiter,
|
JupiterPerpsService jupiter,
|
||||||
AlarmVariableResolver variableResolver
|
AlarmVariableResolver variableResolver
|
||||||
) throws IOException {
|
) {
|
||||||
Objects.requireNonNull(configurationDirectory, "configurationDirectory");
|
this.configuration = Objects.requireNonNull(
|
||||||
Objects.requireNonNull(solanaBlockChain, "solanaBlockChain");
|
configuration,
|
||||||
|
"configuration"
|
||||||
|
);
|
||||||
|
this.wallet = Objects.requireNonNull(wallet, "wallet");
|
||||||
this.jupiter = Objects.requireNonNull(jupiter, "jupiter");
|
this.jupiter = Objects.requireNonNull(jupiter, "jupiter");
|
||||||
this.variableResolver = Objects.requireNonNull(variableResolver, "variableResolver");
|
this.variableResolver = Objects.requireNonNull(variableResolver, "variableResolver");
|
||||||
|
|
||||||
configuration = JupiterPerpsPositionIncreaseAlarmActionConfigurationParser.parse(
|
|
||||||
configurationDirectory.resolve(getConfigurationFileName()),
|
|
||||||
variableResolver
|
|
||||||
);
|
|
||||||
wallet = new SolanaWalletImpl(
|
|
||||||
configuration.walletId(),
|
|
||||||
configuration.signerKeyName(),
|
|
||||||
solanaBlockChain
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getConfigurationFileName() {
|
public String getConfigurationFileName() {
|
||||||
return "alarmaction_JupiterPerpsPositionIncreaseAlarmAction.conf";
|
return CONFIGURATION_FILE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -59,7 +49,6 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured
|
|||||||
|
|
||||||
ΩSolanaTransactionSignatureΩ signature =
|
ΩSolanaTransactionSignatureΩ signature =
|
||||||
jupiter.executePositionIncrease(
|
jupiter.executePositionIncrease(
|
||||||
wallet,
|
|
||||||
positionIncrease.asset().tradedTokenMint(),
|
positionIncrease.asset().tradedTokenMint(),
|
||||||
positionIncrease.direction(),
|
positionIncrease.direction(),
|
||||||
positionIncrease.collateralUsd(),
|
positionIncrease.collateralUsd(),
|
||||||
@@ -116,4 +105,7 @@ public final class JupiterPerpsPositionIncreaseAlarmAction implements Configured
|
|||||||
private final SolanaWallet wallet;
|
private final SolanaWallet wallet;
|
||||||
private final JupiterPerpsService jupiter;
|
private final JupiterPerpsService jupiter;
|
||||||
private final AlarmVariableResolver variableResolver;
|
private final AlarmVariableResolver variableResolver;
|
||||||
|
|
||||||
|
static final String CONFIGURATION_FILE_NAME =
|
||||||
|
"alarmaction_JupiterPerpsPositionIncreaseAlarmAction.conf";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.r35157.libs.jupiter.perps;
|
package com.r35157.libs.jupiter.perps;
|
||||||
|
|
||||||
import com.r35157.cryptowallet.solana.SolanaWallet;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -10,10 +9,10 @@ import java.util.Set;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for reading Jupiter Perps data and executing complete position
|
* Service for reading Jupiter Perps data and executing complete position
|
||||||
* operations.
|
* operations for its configured wallet.
|
||||||
*
|
*
|
||||||
* <p>For position mutations, the service constructs the required transaction
|
* <p>The service constructs and submits Jupiter transactions, while its
|
||||||
* and delegates signing and submission to the supplied wallet.</p>
|
* configured wallet is responsible for signing them.</p>
|
||||||
*/
|
*/
|
||||||
public interface JupiterPerpsService {
|
public interface JupiterPerpsService {
|
||||||
/**
|
/**
|
||||||
@@ -49,10 +48,9 @@ public interface JupiterPerpsService {
|
|||||||
/**
|
/**
|
||||||
* Opens or increases a Jupiter Perps position.
|
* Opens or increases a Jupiter Perps position.
|
||||||
*
|
*
|
||||||
* <p>The service constructs the transaction and asks the supplied wallet
|
* <p>The service constructs the transaction, asks its configured wallet
|
||||||
* to sign and submit it.</p>
|
* to sign it, and submits it to Jupiter.</p>
|
||||||
*
|
*
|
||||||
* @param wallet the wallet that owns or will own the position
|
|
||||||
* @param tradedTokenMint the mint address of the asset being traded
|
* @param tradedTokenMint the mint address of the asset being traded
|
||||||
* @param direction whether the position is long or short
|
* @param direction whether the position is long or short
|
||||||
* @param inputTokenAmount the amount of USDC to supply as collateral
|
* @param inputTokenAmount the amount of USDC to supply as collateral
|
||||||
@@ -65,7 +63,6 @@ public interface JupiterPerpsService {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
ΩSolanaTransactionSignatureΩ executePositionIncrease(
|
ΩSolanaTransactionSignatureΩ executePositionIncrease(
|
||||||
@NotNull SolanaWallet wallet,
|
|
||||||
@NotNull ΩSPLMintAddressΩ tradedTokenMint,
|
@NotNull ΩSPLMintAddressΩ tradedTokenMint,
|
||||||
@NotNull JupiterPerpsPositionDirection direction,
|
@NotNull JupiterPerpsPositionDirection direction,
|
||||||
@NotNull ΩUSDCAmountΩ inputTokenAmount,
|
@NotNull ΩUSDCAmountΩ inputTokenAmount,
|
||||||
@@ -76,10 +73,9 @@ public interface JupiterPerpsService {
|
|||||||
/**
|
/**
|
||||||
* Decreases an existing Jupiter Perps position.
|
* Decreases an existing Jupiter Perps position.
|
||||||
*
|
*
|
||||||
* <p>The service constructs the transaction and asks the supplied wallet
|
* <p>The service constructs the transaction, asks its configured wallet
|
||||||
* to sign and submit it.</p>
|
* to sign it, and submits it to Jupiter.</p>
|
||||||
*
|
*
|
||||||
* @param wallet the wallet that owns the position
|
|
||||||
* @param positionAccount the Jupiter Perps position to decrease
|
* @param positionAccount the Jupiter Perps position to decrease
|
||||||
* @param receiveTokenMint the mint address of the token to receive
|
* @param receiveTokenMint the mint address of the token to receive
|
||||||
* @param sizeUsdDelta the requested decrease in position size, denominated in USD
|
* @param sizeUsdDelta the requested decrease in position size, denominated in USD
|
||||||
@@ -91,7 +87,6 @@ public interface JupiterPerpsService {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
ΩSolanaTransactionSignatureΩ executePositionDecrease(
|
ΩSolanaTransactionSignatureΩ executePositionDecrease(
|
||||||
@NotNull SolanaWallet wallet,
|
|
||||||
@NotNull ΩJupiterPerpsPositionAccountΩ positionAccount,
|
@NotNull ΩJupiterPerpsPositionAccountΩ positionAccount,
|
||||||
@NotNull ΩSPLMintAddressΩ receiveTokenMint,
|
@NotNull ΩSPLMintAddressΩ receiveTokenMint,
|
||||||
@NotNull ΩUSDCAmountΩ sizeUsdDelta,
|
@NotNull ΩUSDCAmountΩ sizeUsdDelta,
|
||||||
|
|||||||
+120
-6
@@ -7,12 +7,15 @@ 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.DecreasePositionRequest;
|
import com.r35157.libs.jupiter.perps.protocol.DecreasePositionRequest;
|
||||||
import com.r35157.libs.jupiter.perps.protocol.DecreasePositionResponse;
|
import com.r35157.libs.jupiter.perps.protocol.DecreasePositionResponse;
|
||||||
|
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.IncreasePositionRequest;
|
||||||
import com.r35157.libs.jupiter.perps.protocol.IncreasePositionResponse;
|
import com.r35157.libs.jupiter.perps.protocol.IncreasePositionResponse;
|
||||||
import com.r35157.libs.jupiter.perps.protocol.TransactionMetadata;
|
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.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;
|
||||||
@@ -28,6 +31,7 @@ import java.net.http.HttpClient;
|
|||||||
import java.net.http.HttpRequest;
|
import java.net.http.HttpRequest;
|
||||||
import java.net.http.HttpResponse;
|
import java.net.http.HttpResponse;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static java.math.BigDecimal.ZERO;
|
import static java.math.BigDecimal.ZERO;
|
||||||
@@ -35,9 +39,14 @@ import static java.math.BigDecimal.ZERO;
|
|||||||
public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
||||||
|
|
||||||
public AnchorIdlJupiterPerpsServiceImpl(
|
public AnchorIdlJupiterPerpsServiceImpl(
|
||||||
SolanaBlockChain solanaBlockChain
|
SolanaBlockChain solanaBlockChain,
|
||||||
|
SolanaWallet wallet
|
||||||
) {
|
) {
|
||||||
this.solanaBlockChain = solanaBlockChain;
|
this.solanaBlockChain = Objects.requireNonNull(
|
||||||
|
solanaBlockChain,
|
||||||
|
"solanaBlockChain"
|
||||||
|
);
|
||||||
|
this.wallet = Objects.requireNonNull(wallet, "wallet");
|
||||||
this.positionDecoder = new AnchorIdlJupiterPerpsPositionDecoder();
|
this.positionDecoder = new AnchorIdlJupiterPerpsPositionDecoder();
|
||||||
this.custodyDecoder = new AnchorIdlJupiterPerpsCustodyDecoder();
|
this.custodyDecoder = new AnchorIdlJupiterPerpsCustodyDecoder();
|
||||||
}
|
}
|
||||||
@@ -113,7 +122,6 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ΩSolanaTransactionSignatureΩ executePositionIncrease(
|
public @NotNull ΩSolanaTransactionSignatureΩ executePositionIncrease(
|
||||||
@NotNull SolanaWallet wallet,
|
|
||||||
@NotNull ΩSPLMintAddressΩ tradedTokenMint,
|
@NotNull ΩSPLMintAddressΩ tradedTokenMint,
|
||||||
@NotNull JupiterPerpsPositionDirection direction,
|
@NotNull JupiterPerpsPositionDirection direction,
|
||||||
@NotNull ΩUSDCAmountΩ inputTokenAmount,
|
@NotNull ΩUSDCAmountΩ inputTokenAmount,
|
||||||
@@ -130,7 +138,10 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
maxSlippageBps
|
maxSlippageBps
|
||||||
);
|
);
|
||||||
|
|
||||||
return wallet.signAndSendTransaction(unsignedTransaction);
|
SolanaSignedTransaction signedTransaction =
|
||||||
|
wallet.signTransaction(unsignedTransaction);
|
||||||
|
|
||||||
|
return executePositionIncreaseTransaction(signedTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull SolanaUnsignedTransaction buildPositionIncreaseTransaction(
|
private @NotNull SolanaUnsignedTransaction buildPositionIncreaseTransaction(
|
||||||
@@ -183,9 +194,38 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @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();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ΩSolanaTransactionSignatureΩ executePositionDecrease(
|
public @NotNull ΩSolanaTransactionSignatureΩ executePositionDecrease(
|
||||||
@NotNull SolanaWallet wallet,
|
|
||||||
@NotNull ΩJupiterPerpsPositionAccountΩ positionAccount,
|
@NotNull ΩJupiterPerpsPositionAccountΩ positionAccount,
|
||||||
@NotNull ΩSPLMintAddressΩ receiveTokenMint,
|
@NotNull ΩSPLMintAddressΩ receiveTokenMint,
|
||||||
@NotNull ΩUSDCAmountΩ sizeUsdDelta,
|
@NotNull ΩUSDCAmountΩ sizeUsdDelta,
|
||||||
@@ -199,7 +239,10 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
maxSlippageBps
|
maxSlippageBps
|
||||||
);
|
);
|
||||||
|
|
||||||
return wallet.signAndSendTransaction(unsignedTransaction);
|
SolanaSignedTransaction signedTransaction =
|
||||||
|
wallet.signTransaction(unsignedTransaction);
|
||||||
|
|
||||||
|
return executePositionDecreaseTransaction(signedTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NotNull SolanaUnsignedTransaction buildPositionDecreaseTransaction(
|
private @NotNull SolanaUnsignedTransaction buildPositionDecreaseTransaction(
|
||||||
@@ -248,6 +291,36 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @NotNull ΩSolanaTransactionSignatureΩ
|
||||||
|
executePositionDecreaseTransaction(
|
||||||
|
@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(
|
||||||
|
"decrease-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 static DecreasePositionRequest buildDecreasePositionRequest(
|
private static DecreasePositionRequest buildDecreasePositionRequest(
|
||||||
ΩJupiterPerpsPositionAccountΩ positionAccount,
|
ΩJupiterPerpsPositionAccountΩ positionAccount,
|
||||||
ΩSPLMintAddressΩ receiveTokenMint,
|
ΩSPLMintAddressΩ receiveTokenMint,
|
||||||
@@ -674,11 +747,51 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
return response;
|
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Ω BTC_MINT = "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh";
|
private static final ΩSPLMintAddressΩ BTC_MINT = "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh";
|
||||||
private static final ΩSPLMintAddressΩ ETH_MINT = "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs";
|
private static final ΩSPLMintAddressΩ ETH_MINT = "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs";
|
||||||
private static final ΩSPLMintAddressΩ SOL_MINT = "So11111111111111111111111111111111111111112";
|
private static final ΩSPLMintAddressΩ SOL_MINT = "So11111111111111111111111111111111111111112";
|
||||||
private static final ΩSPLMintAddressΩ USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
private static final ΩSPLMintAddressΩ USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
||||||
|
|
||||||
|
private static final URI EXECUTE_TRANSACTION_ENDPOINT =
|
||||||
|
URI.create(
|
||||||
|
"https://perps-api.jup.ag/v2/transaction/execute"
|
||||||
|
);
|
||||||
|
|
||||||
private static final URI DECREASE_POSITION_ENDPOINT =
|
private static final URI DECREASE_POSITION_ENDPOINT =
|
||||||
URI.create(
|
URI.create(
|
||||||
"https://perps-api.jup.ag/v2/positions/decrease"
|
"https://perps-api.jup.ag/v2/positions/decrease"
|
||||||
@@ -697,6 +810,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
|
|||||||
private static final int USDC_DECIMALS = 6;
|
private static final int USDC_DECIMALS = 6;
|
||||||
|
|
||||||
private final SolanaBlockChain solanaBlockChain;
|
private final SolanaBlockChain solanaBlockChain;
|
||||||
|
private final SolanaWallet wallet;
|
||||||
private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder;
|
private final AnchorIdlJupiterPerpsPositionDecoder positionDecoder;
|
||||||
private final AnchorIdlJupiterPerpsCustodyDecoder custodyDecoder;
|
private final AnchorIdlJupiterPerpsCustodyDecoder custodyDecoder;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
) {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user