22: Investigate and expose borrowFeeUsd in JupiterPerpsPosition

This commit is contained in:
2026-08-05 10:12:38 +02:00
parent f6afbd322b
commit 27c161bb6b
8 changed files with 123 additions and 36 deletions
@@ -31,8 +31,8 @@ public record JupiterPerpsPosition(
ΩJupiterPerpsPositionAccountΩ positionAccount, ΩJupiterPerpsPositionAccountΩ positionAccount,
ΩSPLMintAddressΩ tradedTokenMint, ΩSPLMintAddressΩ tradedTokenMint,
JupiterPerpsPositionDirection direction, JupiterPerpsPositionDirection direction,
ΩUSDCAmountΩ value, ΩUSDCAmountΩ positionValue,
ΩUSDCAmountΩ size, ΩUSDCAmountΩ positionSize,
ΩUSDCAmountΩ pnl, ΩUSDCAmountΩ pnl,
BigDecimal pnlPercent, BigDecimal pnlPercent,
BigDecimal leverage, BigDecimal leverage,
@@ -17,7 +17,7 @@ class AnchorIdlJupiterPerpsCustodyDecoder {
ΩJupiterPerpsPostionIdlΩ idl = decodeIdl(encodedCustodyAccountInfo); ΩJupiterPerpsPostionIdlΩ idl = decodeIdl(encodedCustodyAccountInfo);
JupiterCustodyAccountInfo cai = new JupiterCustodyAccountInfo( JupiterCustodyAccountInfo cai = new JupiterCustodyAccountInfo(
readPublicKey(idl, MINT_OFFSET), decodePublicKey(idl, MINT_OFFSET),
decodeCumulativeInterestRate(idl) decodeCumulativeInterestRate(idl)
); );
@@ -35,15 +35,15 @@ class AnchorIdlJupiterPerpsCustodyDecoder {
return idl; return idl;
} }
private BigInteger decodeCumulativeInterestRate(byte[] data) { private @NotNull ΩJupiterCumulativeInterestRateΩ decodeCumulativeInterestRate(ΩJupiterPerpsCustodyAccountIdlΩ idl) {
byte[] bytes = readU128(data, CUMULATIVE_INTEREST_RATE_OFFSET); byte[] bytes = readU128(idl, CUMULATIVE_INTEREST_RATE_OFFSET);
BigInteger cumulativeInterestRate = new BigInteger(1, bytes); ΩJupiterCumulativeInterestRateΩ cumulativeInterestRate = new ΩJupiterCumulativeInterestRateΩ(1, bytes);
return cumulativeInterestRate; return cumulativeInterestRate;
} }
// Offsets: // Offsets:
// 8 discriminator // 8 discriminator
// +32 pool // +32 pool
// +32 mint // +32 mint
// +32 token_account // +32 token_account
@@ -55,8 +55,8 @@ class AnchorIdlJupiterPerpsCustodyDecoder {
// +8 target_ratio_bps // +8 target_ratio_bps
// +48 assets // +48 assets
private static final int ANCHOR_DISCRIMINATOR_LENGTH = 8; private static final int DISCRIMINATOR_LENGTH = 8;
private static final int MINT_OFFSET = ANCHOR_DISCRIMINATOR_LENGTH + PUBLIC_KEY_LENGTH; private static final int MINT_OFFSET = DISCRIMINATOR_LENGTH + PUBLIC_KEY_LENGTH;
private static final int FUNDING_RATE_STATE_OFFSET = 262; private static final int FUNDING_RATE_STATE_OFFSET = 262;
private static final int CUMULATIVE_INTEREST_RATE_OFFSET = FUNDING_RATE_STATE_OFFSET; private static final int CUMULATIVE_INTEREST_RATE_OFFSET = FUNDING_RATE_STATE_OFFSET;
@@ -6,6 +6,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.Base64; import java.util.Base64;
@@ -21,47 +22,63 @@ class AnchorIdlJupiterPerpsPositionDecoder {
JupiterPerpsPositionDirection direction = decodeDirection(idl); JupiterPerpsPositionDirection direction = decodeDirection(idl);
long rawEntryPrice = ByteBuffer ΩjupiterRawEntryPriceUsdΩ rawEntryPrice = ByteBuffer
.wrap(idl, PRICE_OFFSET, U64_LENGTH) .wrap(idl, PRICE_OFFSET, U64_LENGTH)
.order(ByteOrder.LITTLE_ENDIAN) .order(ByteOrder.LITTLE_ENDIAN)
.getLong(); .getLong();
ΩUSDCPriceΩ entryPrice = BigDecimal ΩUSDCPriceΩ entryPrice = ΩUSDCPriceΩ
.valueOf(rawEntryPrice) .valueOf(rawEntryPrice)
.movePointLeft(6); .movePointLeft(6);
long rawCollateralUsd = ByteBuffer ΩjupiterRawCollateralUsdΩ rawCollateralUsd = ByteBuffer
.wrap(idl, COLLATERAL_USD_OFFSET, U64_LENGTH) .wrap(idl, COLLATERAL_USD_OFFSET, U64_LENGTH)
.order(ByteOrder.LITTLE_ENDIAN) .order(ByteOrder.LITTLE_ENDIAN)
.getLong(); .getLong();
ΩUSDCAmountΩ collateralUsd = BigDecimal ΩUSDCAmountΩ collateral = ΩUSDCAmountΩ
.valueOf(rawCollateralUsd) .valueOf(rawCollateralUsd)
.movePointLeft(6); .movePointLeft(6);
long rawSizeUsd = ByteBuffer ΩjupiterRawSizeUsdΩ rawSizeUsd = ByteBuffer
.wrap(idl, SIZE_USD_OFFSET, U64_LENGTH) .wrap(idl, SIZE_USD_OFFSET, U64_LENGTH)
.order(ByteOrder.LITTLE_ENDIAN) .order(ByteOrder.LITTLE_ENDIAN)
.getLong(); .getLong();
ΩUSDCAmountΩ sizeUsd = BigDecimal ΩUSDCAmountΩ positionSize = ΩUSDCAmountΩ
.valueOf(rawSizeUsd) .valueOf(rawSizeUsd)
.movePointLeft(6); .movePointLeft(6);
ΩJupiterCustodyAccountAddressΩ custodyAccountAddress = readPublicKey(idl, CUSTODY_OFFSET); ΩJupiterPerpsCustodyAccountAddressΩ custodyAccountAddress =
decodePublicKey(idl, CUSTODY_OFFSET);
ΩJupiterPerpsCollateralCustodyAccountAddressΩ collateralCustodyAccountAddress =
decodePublicKey(idl, COLLATERAL_CUSTODY_OFFSET);
ΩJupiterCumulativeInterestSnapshotΩ cumulativeInterestSnapshot = decodeCumulativeInterestSnapshot(idl);
JupiterPerpsPositionInfo posInfo = new JupiterPerpsPositionInfo( JupiterPerpsPositionInfo posInfo = new JupiterPerpsPositionInfo(
entryPrice, entryPrice,
direction, direction,
sizeUsd, positionSize,
collateralUsd, collateral,
custodyAccountAddress custodyAccountAddress,
collateralCustodyAccountAddress,
cumulativeInterestSnapshot
); );
return posInfo; return posInfo;
} }
ΩJupiterCustodyAccountAddressΩ decodeCustodyAccountAddress(SolanaAccountInfo accountInfo) { private @NotNull ΩJupiterCumulativeInterestSnapshotΩ decodeCumulativeInterestSnapshot(ΩJupiterPerpsPostionIdlΩ idl) {
byte[] bytes = readU128(idl, CUMULATIVE_INTEREST_SNAPSHOT_OFFSET);
ΩJupiterCumulativeInterestSnapshotΩ cumulativeInterestSnapshot
= new ΩJupiterCumulativeInterestSnapshotΩ(1, bytes);
return cumulativeInterestSnapshot;
}
ΩJupiterPerpsCustodyAccountAddressΩ decodeCustodyAccountAddress(SolanaAccountInfo accountInfo) {
byte[] data = base64.decode(accountInfo.data()); byte[] data = base64.decode(accountInfo.data());
if (data.length < CUSTODY_OFFSET + PUBLIC_KEY_LENGTH) { if (data.length < CUSTODY_OFFSET + PUBLIC_KEY_LENGTH) {
@@ -69,7 +86,7 @@ class AnchorIdlJupiterPerpsPositionDecoder {
throw new IllegalArgumentException(errorMsg); throw new IllegalArgumentException(errorMsg);
} }
ΩJupiterCustodyAccountAddressΩ addr = readPublicKey(data, CUSTODY_OFFSET); ΩJupiterPerpsCustodyAccountAddressΩ addr = decodePublicKey(data, CUSTODY_OFFSET);
return addr; return addr;
} }
@@ -117,6 +134,8 @@ class AnchorIdlJupiterPerpsPositionDecoder {
private static final int PRICE_OFFSET = SIDE_OFFSET + SIDE_ENUM_LENGTH; 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 SIZE_USD_OFFSET = PRICE_OFFSET + U64_LENGTH;
private static final int COLLATERAL_USD_OFFSET = SIZE_USD_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 Base64.Decoder base64 = Base64.getDecoder(); private static final Base64.Decoder base64 = Base64.getDecoder();
} }
@@ -12,6 +12,8 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@@ -48,7 +50,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
if(perpsPositionInfo == null) { if(perpsPositionInfo == null) {
pos = null; pos = null;
} else { } else {
ΩJupiterCustodyAccountAddressΩ custodyAccountAddress = positionDecoder.decodeCustodyAccountAddress(accountInfo); ΩJupiterPerpsCustodyAccountAddressΩ custodyAccountAddress = positionDecoder.decodeCustodyAccountAddress(accountInfo);
ΩJupiterCustodyAccountInfoEncodedΩ encodedCustodyAccountInfo = solanaBlockChain.getAccountInfo(custodyAccountAddress); ΩJupiterCustodyAccountInfoEncodedΩ encodedCustodyAccountInfo = solanaBlockChain.getAccountInfo(custodyAccountAddress);
if (encodedCustodyAccountInfo == null) { if (encodedCustodyAccountInfo == null) {
@@ -59,13 +61,31 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
JupiterCustodyAccountInfo custodyAccountInfo = custodyDecoder.decode(encodedCustodyAccountInfo); JupiterCustodyAccountInfo custodyAccountInfo = custodyDecoder.decode(encodedCustodyAccountInfo);
ΩSPLMintAddressΩ mintAddress = custodyAccountInfo.mintAddress(); ΩSPLMintAddressΩ mintAddress = custodyAccountInfo.mintAddress();
ΩJupiterPerpsCollateralCustodyAccountAddressΩ collateralCustodyAccountAddress =
perpsPositionInfo.collateralCustodyAccountAddress();
ΩJupiterCustodyAccountInfoEncodedΩ encodedCollateralCustodyAccountInfo =
solanaBlockChain.getAccountInfo(collateralCustodyAccountAddress);
JupiterCustodyAccountInfo collateralCustodyAccountInfo =
custodyDecoder.decode(encodedCollateralCustodyAccountInfo);
ΩJupiterPostionInterestΩ positionInterest =
collateralCustodyAccountInfo.currentCumulativeInterestRate()
.subtract(perpsPositionInfo.cumulativeInterestSnapshot());
ΩUSDCAmountΩ borrowFeesDue =
calculateBorrowFeesDue(
positionInterest,
perpsPositionInfo.positionSize()
);
ΩUSDCAmountΩ value = ZERO; // TODO - Dummy ΩUSDCAmountΩ value = ZERO; // TODO - Dummy
ΩUSDCAmountΩ pnl = ZERO; // TODO - Dummy ΩUSDCAmountΩ pnl = ZERO; // TODO - Dummy
BigDecimal pnlPercent = ZERO; // TODO - Dummy BigDecimal pnlPercent = ZERO; // TODO - Dummy
BigDecimal leverage = ZERO; // TODO - Dummy BigDecimal leverage = ZERO; // TODO - Dummy
ΩUSDCPriceΩ marketPrice = ZERO; // TODO - Dummy ΩUSDCPriceΩ marketPrice = ZERO; // TODO - Dummy
ΩUSDCAmountΩ totalFees = ZERO; // TODO - Dummy ΩUSDCAmountΩ totalFees = ZERO; // TODO - Dummy
ΩUSDCAmountΩ borrowFeesDue = ZERO; // TODO - Dummy
ΩUSDCAmountΩ closeFeePending = ZERO; // TODO - Dummy ΩUSDCAmountΩ closeFeePending = ZERO; // TODO - Dummy
ΩSolanaAmountΩ accountRent = new MoneyAmount(ZERO, WellKnownCurrencyTypes.SOLANA.getCurrencyType()); // TODO - Dummy ΩSolanaAmountΩ accountRent = new MoneyAmount(ZERO, WellKnownCurrencyTypes.SOLANA.getCurrencyType()); // TODO - Dummy
@@ -74,7 +94,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
mintAddress, mintAddress,
perpsPositionInfo.direction(), perpsPositionInfo.direction(),
value, value,
perpsPositionInfo.size(), perpsPositionInfo.positionSize(),
pnl, pnl,
pnlPercent, pnlPercent,
leverage, leverage,
@@ -115,12 +135,13 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
} }
JupiterPerpsPositionInfo perpsPositionInfo = positionDecoder.decode(accountInfo); JupiterPerpsPositionInfo perpsPositionInfo = positionDecoder.decode(accountInfo);
if(perpsPositionInfo == null || perpsPositionInfo.size().compareTo(ZERO) == 0) { if(perpsPositionInfo == null || perpsPositionInfo.positionSize().compareTo(ZERO) == 0) {
continue; continue;
} }
ΩJupiterCustodyAccountAddressΩ custodyAccountAddress = perpsPositionInfo.custodyAccountAddress(); ΩJupiterPerpsCustodyAccountAddressΩ custodyAccountAddress = perpsPositionInfo.custodyAccountAddress();
ΩJupiterCustodyAccountInfoEncodedΩ encodedCustodyAccountInfo = solanaBlockChain.getAccountInfo(custodyAccountAddress); ΩJupiterCustodyAccountInfoEncodedΩ encodedCustodyAccountInfo
= solanaBlockChain.getAccountInfo(custodyAccountAddress);
if (encodedCustodyAccountInfo == null) { if (encodedCustodyAccountInfo == null) {
String errorMsg = "Jupiter Perps custody account does not exist: " + custodyAccountAddress; String errorMsg = "Jupiter Perps custody account does not exist: " + custodyAccountAddress;
@@ -130,13 +151,31 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
JupiterCustodyAccountInfo custodyAccountInfo = custodyDecoder.decode(encodedCustodyAccountInfo); JupiterCustodyAccountInfo custodyAccountInfo = custodyDecoder.decode(encodedCustodyAccountInfo);
ΩSPLMintAddressΩ mintAddress = custodyAccountInfo.mintAddress(); ΩSPLMintAddressΩ mintAddress = custodyAccountInfo.mintAddress();
ΩJupiterPerpsCollateralCustodyAccountAddressΩ collateralCustodyAccountAddress =
perpsPositionInfo.collateralCustodyAccountAddress();
ΩJupiterCustodyAccountInfoEncodedΩ encodedCollateralCustodyAccountInfo =
solanaBlockChain.getAccountInfo(collateralCustodyAccountAddress);
JupiterCustodyAccountInfo collateralCustodyAccountInfo =
custodyDecoder.decode(encodedCollateralCustodyAccountInfo);
ΩJupiterPostionInterestΩ positionInterest =
collateralCustodyAccountInfo.currentCumulativeInterestRate()
.subtract(perpsPositionInfo.cumulativeInterestSnapshot());
ΩUSDCAmountΩ borrowFeesDue =
calculateBorrowFeesDue(
positionInterest,
perpsPositionInfo.positionSize()
);
ΩUSDCAmountΩ value = ZERO; // TODO - Dummy ΩUSDCAmountΩ value = ZERO; // TODO - Dummy
ΩUSDCAmountΩ pnl = ZERO; // TODO - Dummy ΩUSDCAmountΩ pnl = ZERO; // TODO - Dummy
BigDecimal pnlPercent = ZERO; // TODO - Dummy BigDecimal pnlPercent = ZERO; // TODO - Dummy
BigDecimal leverage = ZERO; // TODO - Dummy BigDecimal leverage = ZERO; // TODO - Dummy
ΩUSDCPriceΩ marketPrice = ZERO; // TODO - Dummy ΩUSDCPriceΩ marketPrice = ZERO; // TODO - Dummy
ΩUSDCAmountΩ totalFees = ZERO; // TODO - Dummy ΩUSDCAmountΩ totalFees = ZERO; // TODO - Dummy
ΩUSDCAmountΩ borrowFeesDue = ZERO; // TODO - Dummy
ΩUSDCAmountΩ closeFeePending = ZERO; // TODO - Dummy ΩUSDCAmountΩ closeFeePending = ZERO; // TODO - Dummy
ΩSolanaAmountΩ accountRent = new MoneyAmount(ZERO, WellKnownCurrencyTypes.SOLANA.getCurrencyType()); // TODO - Dummy ΩSolanaAmountΩ accountRent = new MoneyAmount(ZERO, WellKnownCurrencyTypes.SOLANA.getCurrencyType()); // TODO - Dummy
@@ -145,7 +184,7 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
mintAddress, mintAddress,
perpsPositionInfo.direction(), perpsPositionInfo.direction(),
value, value,
perpsPositionInfo.size(), perpsPositionInfo.positionSize(),
pnl, pnl,
pnlPercent, pnlPercent,
leverage, leverage,
@@ -164,6 +203,21 @@ public class AnchorIdlJupiterPerpsServiceImpl implements JupiterPerpsService {
return Set.copyOf(positions); return Set.copyOf(positions);
} }
private static ΩUSDCAmountΩ calculateBorrowFeesDue(
ΩJupiterPostionInterestΩ positionInterest,
ΩUSDCAmountΩ size
) {
ΩUSDCAmountΩ fees = new BigDecimal(positionInterest)
.multiply(size)
.divide(
BigDecimal.valueOf(RATE_POWER),
6,
RoundingMode.CEILING
);
return fees;
}
private static final long RATE_POWER = 1_000_000_000L;
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;
@@ -2,6 +2,9 @@ package com.r35157.libs.jupiter.perps.impl.anchoridl;
import com.r35157.libs.codec.Base58Codec; import com.r35157.libs.codec.Base58Codec;
import com.r35157.libs.codec.impl.ref.Base58CodecImpl; import com.r35157.libs.codec.impl.ref.Base58CodecImpl;
import org.jetbrains.annotations.NotNull;
import java.math.BigInteger;
public class DecodingPrimitives { public class DecodingPrimitives {
@@ -15,7 +18,7 @@ public class DecodingPrimitives {
return bytes; return bytes;
} }
public static ΩSolanaAddressΩ readPublicKey(byte[] data, int offset) { public static @NotNull ΩSolanaAddressΩ decodePublicKey(ΩJupiterPerpsPostionIdlΩ data, int offset) {
byte[] bytes = new byte[PUBLIC_KEY_LENGTH]; byte[] bytes = new byte[PUBLIC_KEY_LENGTH];
System.arraycopy( System.arraycopy(
@@ -4,6 +4,6 @@ import java.math.BigInteger;
public record JupiterCustodyAccountInfo( public record JupiterCustodyAccountInfo(
ΩSPLMintAddressΩ mintAddress, ΩSPLMintAddressΩ mintAddress,
BigInteger currentCumulativeInterestRate ΩJupiterCumulativeInterestRateΩ currentCumulativeInterestRate
) { ) {
} }
@@ -3,12 +3,15 @@ package com.r35157.libs.jupiter.perps.impl.anchoridl;
import com.r35157.libs.jupiter.perps.JupiterPerpsPositionDirection; import com.r35157.libs.jupiter.perps.JupiterPerpsPositionDirection;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger;
public record JupiterPerpsPositionInfo( public record JupiterPerpsPositionInfo(
ΩUSDCPriceΩ entryPrice, ΩUSDCPriceΩ entryPrice,
JupiterPerpsPositionDirection direction, JupiterPerpsPositionDirection direction,
ΩUSDCAmountΩ size, ΩUSDCAmountΩ positionSize,
ΩUSDCAmountΩ collateral, ΩUSDCAmountΩ collateral,
ΩJupiterCustodyAccountAddressΩ custodyAccountAddress ΩJupiterPerpsCustodyAccountAddressΩ custodyAccountAddress,
ΩJupiterPerpsCollateralCustodyAccountAddressΩ collateralCustodyAccountAddress,
ΩJupiterCumulativeInterestSnapshotΩ cumulativeInterestSnapshot
) { ) {
} }
@@ -15,6 +15,8 @@ import java.lang.management.ManagementFactory;
import com.r35157.nenjim.hubd.ctx.ContextManager; import com.r35157.nenjim.hubd.ctx.ContextManager;
import com.r35157.nenjim.hubd.journal.JournalManager; import com.r35157.nenjim.hubd.journal.JournalManager;
import com.r35157.nenjim.hubd.impl.ref.JournalManagerImpl; import com.r35157.nenjim.hubd.impl.ref.JournalManagerImpl;
import java.math.BigDecimal;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Set; import java.util.Set;
@@ -28,10 +30,16 @@ public class Main {
SolanaBlockChain sbc = new SolanaBlockChainImpl(); SolanaBlockChain sbc = new SolanaBlockChainImpl();
JupiterPerpsService jupiter = new AnchorIdlJupiterPerpsServiceImpl(sbc); JupiterPerpsService jupiter = new AnchorIdlJupiterPerpsServiceImpl(sbc);
ΩSolanaWalletIdΩ walletId = "vj98roDZ7744EBfxyuDFkKpEGCsKQLr7K8UFRumJNHf"; ΩSolanaWalletIdΩ walletId = "vj98roDZ7744EBfxyuDFkKpEGCsKQLr7K8UFRumJNHf";
Set<JupiterPerpsPosition> positions = jupiter.getOpenPositions(walletId); //Set<JupiterPerpsPosition> positions = jupiter.getOpenPositions(walletId);
int a=0;
nenjimHub.awaitShutdown(); while(true) {
String addr = "2z2oExdggoRPCcojntHrGbRiDWeJgVSRbasfMbPfprQi";
JupiterPerpsPosition pos = jupiter.getPosition(addr);
ΩUSDCAmountΩ a = pos.borrowFeesDue();
int i = 0;
}
// nenjimHub.awaitShutdown();
/* try { /* try {
log.info("Auto-starting 2 Nenjim application(s)..."); log.info("Auto-starting 2 Nenjim application(s)...");