@drift-labs/sdk 2.41.0-beta.0 → 2.41.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/VERSION +1 -1
- package/bun.lockb +0 -0
- package/lib/accounts/types.d.ts +5 -1
- package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -1
- package/lib/accounts/webSocketAccountSubscriber.js +28 -2
- package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +2 -1
- package/lib/accounts/webSocketDriftClientAccountSubscriber.js +6 -5
- package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +32 -0
- package/lib/accounts/webSocketProgramAccountSubscriber.js +99 -0
- package/lib/accounts/webSocketUserAccountSubscriber.d.ts +2 -1
- package/lib/accounts/webSocketUserAccountSubscriber.js +3 -2
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +2 -1
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +3 -2
- package/lib/addresses/pda.d.ts +1 -0
- package/lib/addresses/pda.js +5 -1
- package/lib/adminClient.d.ts +2 -0
- package/lib/adminClient.js +20 -0
- package/lib/auctionSubscriber/auctionSubscriber.d.ts +3 -2
- package/lib/auctionSubscriber/auctionSubscriber.js +15 -7
- package/lib/auctionSubscriber/types.d.ts +1 -0
- package/lib/dlob/DLOB.d.ts +2 -6
- package/lib/dlob/DLOB.js +9 -11
- package/lib/dlob/DLOBSubscriber.js +4 -7
- package/lib/dlob/orderBookLevels.d.ts +4 -2
- package/lib/dlob/orderBookLevels.js +79 -16
- package/lib/driftClient.d.ts +2 -1
- package/lib/driftClient.js +13 -14
- package/lib/driftClientConfig.d.ts +1 -0
- package/lib/factory/bigNum.js +4 -2
- package/lib/idl/drift.json +222 -2
- package/lib/jupiter/jupiterClient.d.ts +4 -1
- package/lib/jupiter/jupiterClient.js +4 -1
- package/lib/math/amm.js +7 -2
- package/lib/math/auction.d.ts +12 -1
- package/lib/math/auction.js +22 -1
- package/lib/math/market.js +2 -4
- package/lib/math/superStake.d.ts +51 -4
- package/lib/math/superStake.js +173 -21
- package/lib/math/trade.js +2 -4
- package/lib/math/utils.d.ts +1 -0
- package/lib/math/utils.js +10 -1
- package/lib/orderSubscriber/OrderSubscriber.d.ts +1 -3
- package/lib/orderSubscriber/OrderSubscriber.js +4 -3
- package/lib/orderSubscriber/WebsocketSubscription.d.ts +4 -2
- package/lib/orderSubscriber/WebsocketSubscription.js +15 -12
- package/lib/orderSubscriber/types.d.ts +1 -0
- package/lib/user.d.ts +2 -2
- package/lib/user.js +5 -5
- package/package.json +2 -1
- package/src/accounts/types.ts +8 -1
- package/src/accounts/webSocketAccountSubscriber.ts +36 -2
- package/src/accounts/webSocketDriftClientAccountSubscriber.ts +15 -5
- package/src/accounts/webSocketProgramAccountSubscriber.ts +152 -0
- package/src/accounts/webSocketUserAccountSubscriber.ts +10 -2
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +10 -2
- package/src/addresses/pda.ts +9 -0
- package/src/adminClient.ts +32 -0
- package/src/auctionSubscriber/auctionSubscriber.ts +30 -21
- package/src/auctionSubscriber/types.ts +1 -0
- package/src/dlob/DLOB.ts +9 -32
- package/src/dlob/DLOBSubscriber.ts +8 -7
- package/src/dlob/orderBookLevels.ts +133 -32
- package/src/driftClient.ts +14 -16
- package/src/driftClientConfig.ts +1 -0
- package/src/factory/bigNum.ts +2 -0
- package/src/idl/drift.json +222 -2
- package/src/jupiter/jupiterClient.ts +6 -0
- package/src/math/amm.ts +9 -2
- package/src/math/auction.ts +36 -2
- package/src/math/market.ts +4 -9
- package/src/math/superStake.ts +247 -23
- package/src/math/trade.ts +3 -11
- package/src/math/utils.ts +12 -0
- package/src/orderSubscriber/OrderSubscriber.ts +12 -7
- package/src/orderSubscriber/WebsocketSubscription.ts +34 -23
- package/src/orderSubscriber/types.ts +1 -0
- package/src/user.ts +7 -5
- package/tests/amm/test.ts +402 -0
- package/tests/auctions/test.ts +66 -0
- package/tests/dlob/test.ts +1 -73
package/lib/math/amm.js
CHANGED
|
@@ -253,8 +253,13 @@ function calculateVolSpreadBN(lastOracleConfPct, reservePrice, markStd, oracleSt
|
|
|
253
253
|
const clampMax = numericConstants_1.PERCENTAGE_PRECISION.mul(new anchor_1.BN(16)).div(new anchor_1.BN(10));
|
|
254
254
|
const longVolSpreadFactor = (0, __1.clampBN)(longIntensity.mul(numericConstants_1.PERCENTAGE_PRECISION).div(anchor_1.BN.max(numericConstants_1.ONE, volume24H)), clampMin, clampMax);
|
|
255
255
|
const shortVolSpreadFactor = (0, __1.clampBN)(shortIntensity.mul(numericConstants_1.PERCENTAGE_PRECISION).div(anchor_1.BN.max(numericConstants_1.ONE, volume24H)), clampMin, clampMax);
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
// only consider confidence interval at full value when above 25 bps
|
|
257
|
+
let confComponent = lastOracleConfPct;
|
|
258
|
+
if (lastOracleConfPct.lte(numericConstants_1.PRICE_PRECISION.div(new anchor_1.BN(400)))) {
|
|
259
|
+
confComponent = lastOracleConfPct.div(new anchor_1.BN(10));
|
|
260
|
+
}
|
|
261
|
+
const longVolSpread = anchor_1.BN.max(confComponent, volSpread.mul(longVolSpreadFactor).div(numericConstants_1.PERCENTAGE_PRECISION));
|
|
262
|
+
const shortVolSpread = anchor_1.BN.max(confComponent, volSpread.mul(shortVolSpreadFactor).div(numericConstants_1.PERCENTAGE_PRECISION));
|
|
258
263
|
return [longVolSpread, shortVolSpread];
|
|
259
264
|
}
|
|
260
265
|
exports.calculateVolSpreadBN = calculateVolSpreadBN;
|
package/lib/math/auction.d.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
import { Order } from '../types';
|
|
1
|
+
import { Order, PositionDirection } from '../types';
|
|
2
2
|
import { BN } from '../.';
|
|
3
3
|
export declare function isAuctionComplete(order: Order, slot: number): boolean;
|
|
4
4
|
export declare function isFallbackAvailableLiquiditySource(order: Order, minAuctionDuration: number, slot: number): boolean;
|
|
5
5
|
export declare function getAuctionPrice(order: Order, slot: number, oraclePrice: BN): BN;
|
|
6
6
|
export declare function getAuctionPriceForFixedAuction(order: Order, slot: number): BN;
|
|
7
7
|
export declare function getAuctionPriceForOracleOffsetAuction(order: Order, slot: number, oraclePrice: BN): BN;
|
|
8
|
+
export declare function deriveOracleAuctionParams({ direction, oraclePrice, auctionStartPrice, auctionEndPrice, limitPrice, }: {
|
|
9
|
+
direction: PositionDirection;
|
|
10
|
+
oraclePrice: BN;
|
|
11
|
+
auctionStartPrice: BN;
|
|
12
|
+
auctionEndPrice: BN;
|
|
13
|
+
limitPrice: BN;
|
|
14
|
+
}): {
|
|
15
|
+
auctionStartPrice: BN;
|
|
16
|
+
auctionEndPrice: BN;
|
|
17
|
+
oraclePriceOffset: number;
|
|
18
|
+
};
|
package/lib/math/auction.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAuctionPriceForOracleOffsetAuction = exports.getAuctionPriceForFixedAuction = exports.getAuctionPrice = exports.isFallbackAvailableLiquiditySource = exports.isAuctionComplete = void 0;
|
|
3
|
+
exports.deriveOracleAuctionParams = exports.getAuctionPriceForOracleOffsetAuction = exports.getAuctionPriceForFixedAuction = exports.getAuctionPrice = exports.isFallbackAvailableLiquiditySource = exports.isAuctionComplete = void 0;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const _1 = require("../.");
|
|
6
6
|
function isAuctionComplete(order, slot) {
|
|
@@ -89,3 +89,24 @@ function getAuctionPriceForOracleOffsetAuction(order, slot, oraclePrice) {
|
|
|
89
89
|
return oraclePrice.add(priceOffset);
|
|
90
90
|
}
|
|
91
91
|
exports.getAuctionPriceForOracleOffsetAuction = getAuctionPriceForOracleOffsetAuction;
|
|
92
|
+
function deriveOracleAuctionParams({ direction, oraclePrice, auctionStartPrice, auctionEndPrice, limitPrice, }) {
|
|
93
|
+
let oraclePriceOffset = limitPrice.sub(oraclePrice);
|
|
94
|
+
if (oraclePriceOffset.eq(_1.ZERO)) {
|
|
95
|
+
oraclePriceOffset = (0, types_1.isVariant)(direction, 'long')
|
|
96
|
+
? auctionEndPrice.sub(oraclePrice).add(_1.ONE)
|
|
97
|
+
: auctionEndPrice.sub(oraclePrice).sub(_1.ONE);
|
|
98
|
+
}
|
|
99
|
+
let oraclePriceOffsetNum;
|
|
100
|
+
try {
|
|
101
|
+
oraclePriceOffsetNum = oraclePriceOffset.toNumber();
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
oraclePriceOffsetNum = 0;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
auctionStartPrice: auctionStartPrice.sub(oraclePrice),
|
|
108
|
+
auctionEndPrice: auctionEndPrice.sub(oraclePrice),
|
|
109
|
+
oraclePriceOffset: oraclePriceOffsetNum,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
exports.deriveOracleAuctionParams = deriveOracleAuctionParams;
|
package/lib/math/market.js
CHANGED
|
@@ -130,12 +130,10 @@ exports.calculateNetUserPnlImbalance = calculateNetUserPnlImbalance;
|
|
|
130
130
|
function calculateAvailablePerpLiquidity(market, oraclePriceData, dlob, slot) {
|
|
131
131
|
let [bids, asks] = (0, amm_1.calculateMarketOpenBidAsk)(market.amm.baseAssetReserve, market.amm.minBaseAssetReserve, market.amm.maxBaseAssetReserve, market.amm.orderStepSize);
|
|
132
132
|
asks = asks.abs();
|
|
133
|
-
const
|
|
134
|
-
const askPrice = calculateAskPrice(market, oraclePriceData);
|
|
135
|
-
for (const bid of dlob.getMakerLimitBids(market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData, askPrice)) {
|
|
133
|
+
for (const bid of dlob.getRestingLimitBids(market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData)) {
|
|
136
134
|
bids = bids.add(bid.order.baseAssetAmount.sub(bid.order.baseAssetAmountFilled));
|
|
137
135
|
}
|
|
138
|
-
for (const ask of dlob.
|
|
136
|
+
for (const ask of dlob.getRestingLimitAsks(market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData)) {
|
|
139
137
|
asks = asks.add(ask.order.baseAssetAmount.sub(ask.order.baseAssetAmountFilled));
|
|
140
138
|
}
|
|
141
139
|
return {
|
package/lib/math/superStake.d.ts
CHANGED
|
@@ -4,11 +4,12 @@ import { DriftClient } from '../driftClient';
|
|
|
4
4
|
import { BN } from '@coral-xyz/anchor';
|
|
5
5
|
import { User } from '../user';
|
|
6
6
|
import { DepositRecord } from '../types';
|
|
7
|
-
export declare function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey,
|
|
7
|
+
export declare function findBestSuperStakeIxs({ marketIndex, amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, }: {
|
|
8
|
+
marketIndex: number;
|
|
8
9
|
amount: BN;
|
|
9
10
|
jupiterClient: JupiterClient;
|
|
10
11
|
driftClient: DriftClient;
|
|
11
|
-
|
|
12
|
+
price?: number;
|
|
12
13
|
userAccountPublicKey?: PublicKey;
|
|
13
14
|
forceMarinade?: boolean;
|
|
14
15
|
onlyDirectRoutes?: boolean;
|
|
@@ -18,8 +19,54 @@ export declare function findBestSuperStakeIxs({ amount, jupiterClient, driftClie
|
|
|
18
19
|
method: 'jupiter' | 'marinade';
|
|
19
20
|
price: number;
|
|
20
21
|
}>;
|
|
21
|
-
export declare function
|
|
22
|
+
export declare function findBestMSolSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, }: {
|
|
23
|
+
amount: BN;
|
|
24
|
+
jupiterClient: JupiterClient;
|
|
25
|
+
driftClient: DriftClient;
|
|
26
|
+
price?: number;
|
|
27
|
+
userAccountPublicKey?: PublicKey;
|
|
28
|
+
forceMarinade?: boolean;
|
|
29
|
+
onlyDirectRoutes?: boolean;
|
|
30
|
+
}): Promise<{
|
|
31
|
+
ixs: TransactionInstruction[];
|
|
32
|
+
lookupTables: AddressLookupTableAccount[];
|
|
33
|
+
method: 'jupiter' | 'marinade';
|
|
34
|
+
price: number;
|
|
35
|
+
}>;
|
|
36
|
+
export declare function findBestJitoSolSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, onlyDirectRoutes, }: {
|
|
37
|
+
amount: BN;
|
|
38
|
+
jupiterClient: JupiterClient;
|
|
39
|
+
driftClient: DriftClient;
|
|
40
|
+
userAccountPublicKey?: PublicKey;
|
|
41
|
+
onlyDirectRoutes?: boolean;
|
|
42
|
+
}): Promise<{
|
|
43
|
+
ixs: TransactionInstruction[];
|
|
44
|
+
lookupTables: AddressLookupTableAccount[];
|
|
45
|
+
method: 'jupiter' | 'marinade';
|
|
46
|
+
price: number;
|
|
47
|
+
}>;
|
|
48
|
+
export type JITO_SOL_METRICS_ENDPOINT_RESPONSE = {
|
|
49
|
+
data: {
|
|
50
|
+
getStakePoolStats: {
|
|
51
|
+
tvl: {
|
|
52
|
+
data: number;
|
|
53
|
+
date: string;
|
|
54
|
+
}[];
|
|
55
|
+
supply: {
|
|
56
|
+
data: number;
|
|
57
|
+
date: string;
|
|
58
|
+
}[];
|
|
59
|
+
apy: {
|
|
60
|
+
data: number;
|
|
61
|
+
date: string;
|
|
62
|
+
}[];
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
export declare function fetchJitoSolMetrics(): Promise<JITO_SOL_METRICS_ENDPOINT_RESPONSE>;
|
|
67
|
+
export declare function calculateSolEarned({ marketIndex, user, depositRecords, }: {
|
|
68
|
+
marketIndex: number;
|
|
22
69
|
user: User;
|
|
23
70
|
depositRecords: DepositRecord[];
|
|
24
71
|
}): Promise<BN>;
|
|
25
|
-
export declare function calculateEstimatedSuperStakeLiquidationPrice(
|
|
72
|
+
export declare function calculateEstimatedSuperStakeLiquidationPrice(lstDepositAmount: number, lstMaintenanceAssetWeight: number, solBorrowAmount: number, solMaintenanceLiabilityWeight: number, lstPriceRatio: number): number;
|
package/lib/math/superStake.js
CHANGED
|
@@ -3,17 +3,44 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.calculateEstimatedSuperStakeLiquidationPrice = exports.calculateSolEarned = exports.findBestSuperStakeIxs = void 0;
|
|
6
|
+
exports.calculateEstimatedSuperStakeLiquidationPrice = exports.calculateSolEarned = exports.fetchJitoSolMetrics = exports.findBestJitoSolSuperStakeIxs = exports.findBestMSolSuperStakeIxs = exports.findBestSuperStakeIxs = void 0;
|
|
7
7
|
const web3_js_1 = require("@solana/web3.js");
|
|
8
8
|
const marinade_1 = require("../marinade");
|
|
9
9
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
10
10
|
const types_1 = require("../types");
|
|
11
11
|
const numericConstants_1 = require("../constants/numericConstants");
|
|
12
12
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const utils_1 = require("./utils");
|
|
14
|
+
async function findBestSuperStakeIxs({ marketIndex, amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, }) {
|
|
15
|
+
if (marketIndex === 2) {
|
|
16
|
+
return findBestMSolSuperStakeIxs({
|
|
17
|
+
amount,
|
|
18
|
+
jupiterClient,
|
|
19
|
+
driftClient,
|
|
20
|
+
userAccountPublicKey,
|
|
21
|
+
price,
|
|
22
|
+
forceMarinade,
|
|
23
|
+
onlyDirectRoutes,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
else if (marketIndex === 6) {
|
|
27
|
+
return findBestJitoSolSuperStakeIxs({
|
|
28
|
+
amount,
|
|
29
|
+
jupiterClient,
|
|
30
|
+
driftClient,
|
|
31
|
+
userAccountPublicKey,
|
|
32
|
+
onlyDirectRoutes,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
throw new Error(`Unsupported superstake market index: ${marketIndex}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.findBestSuperStakeIxs = findBestSuperStakeIxs;
|
|
40
|
+
async function findBestMSolSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, }) {
|
|
41
|
+
if (!price) {
|
|
15
42
|
const marinadeProgram = (0, marinade_1.getMarinadeFinanceProgram)(driftClient.provider);
|
|
16
|
-
|
|
43
|
+
price = await (0, marinade_1.getMarinadeMSolPrice)(marinadeProgram);
|
|
17
44
|
}
|
|
18
45
|
const solMint = driftClient.getSpotMarketAccount(1).mint;
|
|
19
46
|
const mSOLMint = driftClient.getSpotMarketAccount(2).mint;
|
|
@@ -32,7 +59,7 @@ async function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userA
|
|
|
32
59
|
catch (e) {
|
|
33
60
|
console.error('Error getting jupiter price', e);
|
|
34
61
|
}
|
|
35
|
-
if (!jupiterPrice ||
|
|
62
|
+
if (!jupiterPrice || price <= jupiterPrice || forceMarinade) {
|
|
36
63
|
const ixs = await driftClient.getStakeForMSOLIx({
|
|
37
64
|
amount,
|
|
38
65
|
userAccountPublicKey,
|
|
@@ -41,7 +68,7 @@ async function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userA
|
|
|
41
68
|
method: 'marinade',
|
|
42
69
|
ixs,
|
|
43
70
|
lookupTables: [],
|
|
44
|
-
price:
|
|
71
|
+
price: price,
|
|
45
72
|
};
|
|
46
73
|
}
|
|
47
74
|
else {
|
|
@@ -61,25 +88,137 @@ async function findBestSuperStakeIxs({ amount, jupiterClient, driftClient, userA
|
|
|
61
88
|
};
|
|
62
89
|
}
|
|
63
90
|
}
|
|
64
|
-
exports.
|
|
65
|
-
async function
|
|
91
|
+
exports.findBestMSolSuperStakeIxs = findBestMSolSuperStakeIxs;
|
|
92
|
+
async function findBestJitoSolSuperStakeIxs({ amount, jupiterClient, driftClient, userAccountPublicKey, onlyDirectRoutes, }) {
|
|
93
|
+
const solMint = driftClient.getSpotMarketAccount(1).mint;
|
|
94
|
+
const JitoSolMint = driftClient.getSpotMarketAccount(6).mint;
|
|
95
|
+
let jupiterPrice;
|
|
96
|
+
let bestRoute;
|
|
97
|
+
try {
|
|
98
|
+
const jupiterRoutes = await jupiterClient.getRoutes({
|
|
99
|
+
inputMint: solMint,
|
|
100
|
+
outputMint: JitoSolMint,
|
|
101
|
+
amount,
|
|
102
|
+
onlyDirectRoutes,
|
|
103
|
+
});
|
|
104
|
+
bestRoute = jupiterRoutes[0];
|
|
105
|
+
jupiterPrice = bestRoute.inAmount / bestRoute.outAmount;
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
console.error('Error getting jupiter price', e);
|
|
109
|
+
throw e;
|
|
110
|
+
}
|
|
111
|
+
const { ixs, lookupTables } = await driftClient.getJupiterSwapIx({
|
|
112
|
+
inMarketIndex: 1,
|
|
113
|
+
outMarketIndex: 6,
|
|
114
|
+
route: bestRoute,
|
|
115
|
+
jupiterClient,
|
|
116
|
+
amount,
|
|
117
|
+
userAccountPublicKey,
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
method: 'jupiter',
|
|
121
|
+
ixs,
|
|
122
|
+
lookupTables,
|
|
123
|
+
price: jupiterPrice,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
exports.findBestJitoSolSuperStakeIxs = findBestJitoSolSuperStakeIxs;
|
|
127
|
+
const JITO_SOL_START_DATE = '2022-10-31T00:00:00Z';
|
|
128
|
+
async function fetchJitoSolMetrics() {
|
|
129
|
+
const res = await (0, node_fetch_1.default)('https://kobe.mainnet.jito.network/', {
|
|
130
|
+
body: JSON.stringify({
|
|
131
|
+
operationName: 'QueryRoot',
|
|
132
|
+
variables: {
|
|
133
|
+
request: {
|
|
134
|
+
bucketType: 'DAILY',
|
|
135
|
+
rangeFilter: {
|
|
136
|
+
start: JITO_SOL_START_DATE,
|
|
137
|
+
end: new Date().toISOString(),
|
|
138
|
+
},
|
|
139
|
+
sortBy: {
|
|
140
|
+
order: 'ASC',
|
|
141
|
+
field: 'BLOCK_TIME',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
query: `
|
|
146
|
+
query QueryRoot($request: GetStakePoolStatsRequest!) {
|
|
147
|
+
getStakePoolStats(req: $request) {
|
|
148
|
+
tvl {
|
|
149
|
+
data
|
|
150
|
+
date
|
|
151
|
+
}
|
|
152
|
+
apy {
|
|
153
|
+
data
|
|
154
|
+
date
|
|
155
|
+
}
|
|
156
|
+
supply {
|
|
157
|
+
data
|
|
158
|
+
date
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
`,
|
|
163
|
+
}),
|
|
164
|
+
method: 'POST',
|
|
165
|
+
});
|
|
166
|
+
const data = await res.json();
|
|
167
|
+
return data;
|
|
168
|
+
}
|
|
169
|
+
exports.fetchJitoSolMetrics = fetchJitoSolMetrics;
|
|
170
|
+
const getJitoSolHistoricalPriceMap = async (timestamps) => {
|
|
171
|
+
try {
|
|
172
|
+
const data = await fetchJitoSolMetrics();
|
|
173
|
+
const jitoSolHistoricalPriceMap = new Map();
|
|
174
|
+
const jitoSolHistoricalPriceInSol = [];
|
|
175
|
+
for (let i = 0; i < data.data.getStakePoolStats.supply.length; i++) {
|
|
176
|
+
const priceInSol = data.data.getStakePoolStats.tvl[i].data /
|
|
177
|
+
10 ** 9 /
|
|
178
|
+
data.data.getStakePoolStats.supply[i].data;
|
|
179
|
+
jitoSolHistoricalPriceInSol.push({
|
|
180
|
+
price: priceInSol,
|
|
181
|
+
ts: data.data.getStakePoolStats.tvl[i].date,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
for (const timestamp of timestamps) {
|
|
185
|
+
const date = new Date(timestamp * 1000);
|
|
186
|
+
const dateString = date.toISOString();
|
|
187
|
+
const price = jitoSolHistoricalPriceInSol.find((p) => (0, utils_1.checkSameDate)(p.ts, dateString));
|
|
188
|
+
if (price) {
|
|
189
|
+
jitoSolHistoricalPriceMap.set(timestamp, price.price);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return jitoSolHistoricalPriceMap;
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
console.error(err);
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
async function calculateSolEarned({ marketIndex, user, depositRecords, }) {
|
|
66
200
|
const now = Date.now() / 1000;
|
|
67
201
|
const timestamps = [
|
|
68
202
|
now,
|
|
69
203
|
...depositRecords.map((r) => r.ts.toNumber()),
|
|
70
204
|
];
|
|
71
|
-
|
|
72
|
-
const
|
|
205
|
+
let lstRatios = new Map();
|
|
206
|
+
const getMsolPrice = async (timestamp) => {
|
|
73
207
|
const date = new Date(timestamp * 1000); // Convert Unix timestamp to milliseconds
|
|
74
208
|
const swaggerApiDateTime = date.toISOString(); // Format date as swagger API date-time
|
|
75
209
|
const url = `https://api.marinade.finance/msol/price_sol?time=${swaggerApiDateTime}`;
|
|
76
210
|
const response = await (0, node_fetch_1.default)(url);
|
|
77
211
|
if (response.status === 200) {
|
|
78
212
|
const data = await response.json();
|
|
79
|
-
|
|
213
|
+
lstRatios.set(timestamp, data);
|
|
80
214
|
}
|
|
81
215
|
};
|
|
82
|
-
|
|
216
|
+
if (marketIndex === 2) {
|
|
217
|
+
await Promise.all(timestamps.map(getMsolPrice));
|
|
218
|
+
}
|
|
219
|
+
else if (marketIndex === 6) {
|
|
220
|
+
lstRatios = await getJitoSolHistoricalPriceMap(timestamps);
|
|
221
|
+
}
|
|
83
222
|
let solEarned = numericConstants_1.ZERO;
|
|
84
223
|
for (const record of depositRecords) {
|
|
85
224
|
if (record.marketIndex === 1) {
|
|
@@ -91,7 +230,7 @@ async function calculateSolEarned({ user, depositRecords, }) {
|
|
|
91
230
|
}
|
|
92
231
|
}
|
|
93
232
|
else if (record.marketIndex === 2) {
|
|
94
|
-
const msolRatio =
|
|
233
|
+
const msolRatio = lstRatios.get(record.ts.toNumber());
|
|
95
234
|
const msolRatioBN = new anchor_1.BN(msolRatio * web3_js_1.LAMPORTS_PER_SOL);
|
|
96
235
|
const solAmount = record.amount.mul(msolRatioBN).div(numericConstants_1.LAMPORTS_PRECISION);
|
|
97
236
|
if ((0, types_1.isVariant)(record.direction, 'deposit')) {
|
|
@@ -101,21 +240,34 @@ async function calculateSolEarned({ user, depositRecords, }) {
|
|
|
101
240
|
solEarned = solEarned.add(solAmount);
|
|
102
241
|
}
|
|
103
242
|
}
|
|
243
|
+
else if (record.marketIndex === 6) {
|
|
244
|
+
const jitoSolRatio = lstRatios.get(record.ts.toNumber());
|
|
245
|
+
const jitoSolRatioBN = new anchor_1.BN(jitoSolRatio * web3_js_1.LAMPORTS_PER_SOL);
|
|
246
|
+
const solAmount = record.amount
|
|
247
|
+
.mul(jitoSolRatioBN)
|
|
248
|
+
.div(numericConstants_1.LAMPORTS_PRECISION);
|
|
249
|
+
if ((0, types_1.isVariant)(record.direction, 'deposit')) {
|
|
250
|
+
solEarned = solEarned.sub(solAmount);
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
solEarned = solEarned.add(solAmount);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
104
256
|
}
|
|
105
|
-
const
|
|
257
|
+
const currentLstTokenAmount = await user.getTokenAmount(marketIndex);
|
|
258
|
+
const currentLstRatio = lstRatios.get(now);
|
|
259
|
+
const currentLstRatioBN = new anchor_1.BN(currentLstRatio * web3_js_1.LAMPORTS_PER_SOL);
|
|
260
|
+
solEarned = solEarned.add(currentLstTokenAmount.mul(currentLstRatioBN).div(numericConstants_1.LAMPORTS_PRECISION));
|
|
106
261
|
const currentSOLTokenAmount = await user.getTokenAmount(1);
|
|
107
|
-
const currentMSOLRatio = msolRatios.get(now);
|
|
108
|
-
const currentMSOLRatioBN = new anchor_1.BN(currentMSOLRatio * web3_js_1.LAMPORTS_PER_SOL);
|
|
109
|
-
solEarned = solEarned.add(currentMSOLTokenAmount.mul(currentMSOLRatioBN).div(numericConstants_1.LAMPORTS_PRECISION));
|
|
110
262
|
solEarned = solEarned.add(currentSOLTokenAmount);
|
|
111
263
|
return solEarned;
|
|
112
264
|
}
|
|
113
265
|
exports.calculateSolEarned = calculateSolEarned;
|
|
114
|
-
// calculate estimated liquidation price (in
|
|
115
|
-
function calculateEstimatedSuperStakeLiquidationPrice(
|
|
266
|
+
// calculate estimated liquidation price (in LST/SOL) based on target amounts
|
|
267
|
+
function calculateEstimatedSuperStakeLiquidationPrice(lstDepositAmount, lstMaintenanceAssetWeight, solBorrowAmount, solMaintenanceLiabilityWeight, lstPriceRatio) {
|
|
116
268
|
const liquidationDivergence = (solMaintenanceLiabilityWeight * solBorrowAmount) /
|
|
117
|
-
(
|
|
118
|
-
const liquidationPrice =
|
|
269
|
+
(lstMaintenanceAssetWeight * lstDepositAmount * lstPriceRatio);
|
|
270
|
+
const liquidationPrice = lstPriceRatio * liquidationDivergence;
|
|
119
271
|
return liquidationPrice;
|
|
120
272
|
}
|
|
121
273
|
exports.calculateEstimatedSuperStakeLiquidationPrice = calculateEstimatedSuperStakeLiquidationPrice;
|
package/lib/math/trade.js
CHANGED
|
@@ -278,9 +278,7 @@ function calculateEstimatedPerpEntryPrice(assetType, amount, direction, market,
|
|
|
278
278
|
};
|
|
279
279
|
}
|
|
280
280
|
const takerIsLong = (0, types_2.isVariant)(direction, 'long');
|
|
281
|
-
const limitOrders = dlob[takerIsLong ? '
|
|
282
|
-
? (0, market_1.calculateBidPrice)(market, oraclePriceData)
|
|
283
|
-
: (0, market_1.calculateAskPrice)(market, oraclePriceData));
|
|
281
|
+
const limitOrders = dlob[takerIsLong ? 'getRestingLimitAsks' : 'getRestingLimitBids'](market.marketIndex, slot, types_1.MarketType.PERP, oraclePriceData);
|
|
284
282
|
const swapDirection = (0, amm_1.getSwapDirection)(assetType, direction);
|
|
285
283
|
const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, direction, oraclePriceData);
|
|
286
284
|
const amm = {
|
|
@@ -463,7 +461,7 @@ function calculateEstimatedSpotEntryPrice(assetType, amount, direction, market,
|
|
|
463
461
|
}
|
|
464
462
|
const basePrecision = new anchor_1.BN(Math.pow(10, market.decimals));
|
|
465
463
|
const takerIsLong = (0, types_2.isVariant)(direction, 'long');
|
|
466
|
-
const dlobLimitOrders = dlob[takerIsLong ? '
|
|
464
|
+
const dlobLimitOrders = dlob[takerIsLong ? 'getRestingLimitAsks' : 'getRestingLimitBids'](market.marketIndex, slot, types_1.MarketType.SPOT, oraclePriceData);
|
|
467
465
|
const serumLimitOrders = takerIsLong
|
|
468
466
|
? serumAsks.getL2(100)
|
|
469
467
|
: serumBids.getL2(100);
|
package/lib/math/utils.d.ts
CHANGED
|
@@ -12,3 +12,4 @@ export declare const sigNum: (x: BN) => BN;
|
|
|
12
12
|
* @returns: timeRemainingUntilUpdate (in seconds)
|
|
13
13
|
*/
|
|
14
14
|
export declare function timeRemainingUntilUpdate(now: BN, lastUpdateTs: BN, updatePeriod: BN): BN;
|
|
15
|
+
export declare const checkSameDate: (dateString1: string, dateString2: string) => boolean;
|
package/lib/math/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.timeRemainingUntilUpdate = exports.sigNum = exports.divCeil = exports.squareRootBN = exports.clampBN = void 0;
|
|
3
|
+
exports.checkSameDate = exports.timeRemainingUntilUpdate = exports.sigNum = exports.divCeil = exports.squareRootBN = exports.clampBN = void 0;
|
|
4
4
|
const __1 = require("../");
|
|
5
5
|
function clampBN(x, min, max) {
|
|
6
6
|
return __1.BN.max(min, __1.BN.min(x, max));
|
|
@@ -76,3 +76,12 @@ function timeRemainingUntilUpdate(now, lastUpdateTs, updatePeriod) {
|
|
|
76
76
|
return timeRemainingUntilUpdate;
|
|
77
77
|
}
|
|
78
78
|
exports.timeRemainingUntilUpdate = timeRemainingUntilUpdate;
|
|
79
|
+
const checkSameDate = (dateString1, dateString2) => {
|
|
80
|
+
const date1 = new Date(dateString1);
|
|
81
|
+
const date2 = new Date(dateString2);
|
|
82
|
+
const isSameDate = date1.getDate() === date2.getDate() &&
|
|
83
|
+
date1.getMonth() === date2.getMonth() &&
|
|
84
|
+
date1.getFullYear() === date2.getFullYear();
|
|
85
|
+
return isSameDate;
|
|
86
|
+
};
|
|
87
|
+
exports.checkSameDate = checkSameDate;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
3
2
|
import { DriftClient } from '../driftClient';
|
|
4
3
|
import { UserAccount } from '../types';
|
|
5
|
-
import { Buffer } from 'buffer';
|
|
6
4
|
import { DLOB } from '../dlob/DLOB';
|
|
7
5
|
import { OrderSubscriberConfig, OrderSubscriberEvents } from './types';
|
|
8
6
|
import { PollingSubscription } from './PollingSubscription';
|
|
@@ -22,7 +20,7 @@ export declare class OrderSubscriber {
|
|
|
22
20
|
constructor(config: OrderSubscriberConfig);
|
|
23
21
|
subscribe(): Promise<void>;
|
|
24
22
|
fetch(): Promise<void>;
|
|
25
|
-
tryUpdateUserAccount(key: string,
|
|
23
|
+
tryUpdateUserAccount(key: string, userAccount: UserAccount, slot: number): void;
|
|
26
24
|
getDLOB(slot: number): Promise<DLOB>;
|
|
27
25
|
unsubscribe(): Promise<void>;
|
|
28
26
|
}
|
|
@@ -22,6 +22,7 @@ class OrderSubscriber {
|
|
|
22
22
|
this.subscription = new WebsocketSubscription_1.WebsocketSubscription({
|
|
23
23
|
orderSubscriber: this,
|
|
24
24
|
skipInitialLoad: config.subscriptionConfig.skipInitialLoad,
|
|
25
|
+
resubTimeoutMs: config.subscriptionConfig.resubTimeoutMs,
|
|
25
26
|
});
|
|
26
27
|
}
|
|
27
28
|
this.eventEmitter = new events_1.EventEmitter();
|
|
@@ -57,7 +58,8 @@ class OrderSubscriber {
|
|
|
57
58
|
// @ts-ignore
|
|
58
59
|
const buffer = buffer_1.Buffer.from(programAccount.account.data[0], programAccount.account.data[1]);
|
|
59
60
|
programAccountSet.add(key);
|
|
60
|
-
this.
|
|
61
|
+
const userAccount = this.driftClient.program.account.user.coder.accounts.decode('User', buffer);
|
|
62
|
+
this.tryUpdateUserAccount(key, userAccount, slot);
|
|
61
63
|
}
|
|
62
64
|
for (const key of this.usersAccounts.keys()) {
|
|
63
65
|
if (!programAccountSet.has(key)) {
|
|
@@ -73,10 +75,9 @@ class OrderSubscriber {
|
|
|
73
75
|
this.fetchPromise = undefined;
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
|
-
tryUpdateUserAccount(key,
|
|
78
|
+
tryUpdateUserAccount(key, userAccount, slot) {
|
|
77
79
|
const slotAndUserAccount = this.usersAccounts.get(key);
|
|
78
80
|
if (!slotAndUserAccount || slotAndUserAccount.slot < slot) {
|
|
79
|
-
const userAccount = this.driftClient.program.account.user.coder.accounts.decode('User', buffer);
|
|
80
81
|
const newOrders = userAccount.orders.filter((order) => {
|
|
81
82
|
var _a;
|
|
82
83
|
return order.slot.toNumber() > ((_a = slotAndUserAccount === null || slotAndUserAccount === void 0 ? void 0 : slotAndUserAccount.slot) !== null && _a !== void 0 ? _a : 0) &&
|
|
@@ -2,10 +2,12 @@ import { OrderSubscriber } from './OrderSubscriber';
|
|
|
2
2
|
export declare class WebsocketSubscription {
|
|
3
3
|
private orderSubscriber;
|
|
4
4
|
private skipInitialLoad;
|
|
5
|
-
private
|
|
6
|
-
|
|
5
|
+
private resubTimeoutMs?;
|
|
6
|
+
private subscriber;
|
|
7
|
+
constructor({ orderSubscriber, skipInitialLoad, resubTimeoutMs, }: {
|
|
7
8
|
orderSubscriber: OrderSubscriber;
|
|
8
9
|
skipInitialLoad?: boolean;
|
|
10
|
+
resubTimeoutMs?: number;
|
|
9
11
|
});
|
|
10
12
|
subscribe(): Promise<void>;
|
|
11
13
|
unsubscribe(): Promise<void>;
|
|
@@ -2,29 +2,32 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WebsocketSubscription = void 0;
|
|
4
4
|
const memcmp_1 = require("../memcmp");
|
|
5
|
+
const webSocketProgramAccountSubscriber_1 = require("../accounts/webSocketProgramAccountSubscriber");
|
|
5
6
|
class WebsocketSubscription {
|
|
6
|
-
constructor({ orderSubscriber, skipInitialLoad = false, }) {
|
|
7
|
+
constructor({ orderSubscriber, skipInitialLoad = false, resubTimeoutMs, }) {
|
|
7
8
|
this.orderSubscriber = orderSubscriber;
|
|
8
9
|
this.skipInitialLoad = skipInitialLoad;
|
|
10
|
+
this.resubTimeoutMs = resubTimeoutMs;
|
|
9
11
|
}
|
|
10
12
|
async subscribe() {
|
|
11
|
-
if (this.
|
|
12
|
-
|
|
13
|
+
if (!this.subscriber) {
|
|
14
|
+
this.subscriber = new webSocketProgramAccountSubscriber_1.WebSocketProgramAccountSubscriber('OrderSubscriber', 'User', this.orderSubscriber.driftClient.program, this.orderSubscriber.driftClient.program.account.user.coder.accounts.decode.bind(this.orderSubscriber.driftClient.program.account.user.coder.accounts), {
|
|
15
|
+
filters: [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getNonIdleUserFilter)()],
|
|
16
|
+
commitment: this.orderSubscriber.driftClient.opts.commitment,
|
|
17
|
+
}, this.resubTimeoutMs);
|
|
13
18
|
}
|
|
14
|
-
this.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}, this.orderSubscriber.driftClient.opts.commitment, [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getNonIdleUserFilter)()]);
|
|
19
|
+
await this.subscriber.subscribe((accountId, account, context) => {
|
|
20
|
+
const userKey = accountId.toBase58();
|
|
21
|
+
this.orderSubscriber.tryUpdateUserAccount(userKey, account, context.slot);
|
|
22
|
+
});
|
|
19
23
|
if (!this.skipInitialLoad) {
|
|
20
24
|
await this.orderSubscriber.fetch();
|
|
21
25
|
}
|
|
22
26
|
}
|
|
23
27
|
async unsubscribe() {
|
|
24
|
-
if (this.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
+
if (!this.subscriber)
|
|
29
|
+
return;
|
|
30
|
+
this.subscriber.unsubscribe();
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
exports.WebsocketSubscription = WebsocketSubscription;
|
package/lib/user.d.ts
CHANGED
|
@@ -180,14 +180,14 @@ export declare class User {
|
|
|
180
180
|
* calculates current user leverage which is (total liability size) / (net asset value)
|
|
181
181
|
* @returns : Precision TEN_THOUSAND
|
|
182
182
|
*/
|
|
183
|
-
getLeverage(): BN;
|
|
183
|
+
getLeverage(includeOpenOrders?: boolean): BN;
|
|
184
184
|
calculateLeverageFromComponents({ perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue, }: {
|
|
185
185
|
perpLiabilityValue: BN;
|
|
186
186
|
perpPnl: BN;
|
|
187
187
|
spotAssetValue: BN;
|
|
188
188
|
spotLiabilityValue: BN;
|
|
189
189
|
}): BN;
|
|
190
|
-
getLeverageComponents(): {
|
|
190
|
+
getLeverageComponents(includeOpenOrders?: boolean): {
|
|
191
191
|
perpLiabilityValue: BN;
|
|
192
192
|
perpPnl: BN;
|
|
193
193
|
spotAssetValue: BN;
|
package/lib/user.js
CHANGED
|
@@ -822,8 +822,8 @@ class User {
|
|
|
822
822
|
* calculates current user leverage which is (total liability size) / (net asset value)
|
|
823
823
|
* @returns : Precision TEN_THOUSAND
|
|
824
824
|
*/
|
|
825
|
-
getLeverage() {
|
|
826
|
-
return this.calculateLeverageFromComponents(this.getLeverageComponents());
|
|
825
|
+
getLeverage(includeOpenOrders = true) {
|
|
826
|
+
return this.calculateLeverageFromComponents(this.getLeverageComponents(includeOpenOrders));
|
|
827
827
|
}
|
|
828
828
|
calculateLeverageFromComponents({ perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue, }) {
|
|
829
829
|
const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
|
|
@@ -834,10 +834,10 @@ class User {
|
|
|
834
834
|
}
|
|
835
835
|
return totalLiabilityValue.mul(numericConstants_1.TEN_THOUSAND).div(netAssetValue);
|
|
836
836
|
}
|
|
837
|
-
getLeverageComponents() {
|
|
838
|
-
const perpLiability = this.getTotalPerpPositionValue(undefined, undefined,
|
|
837
|
+
getLeverageComponents(includeOpenOrders = true) {
|
|
838
|
+
const perpLiability = this.getTotalPerpPositionValue(undefined, undefined, includeOpenOrders);
|
|
839
839
|
const perpPnl = this.getUnrealizedPNL(true);
|
|
840
|
-
const { totalAssetValue: spotAssetValue, totalLiabilityValue: spotLiabilityValue, } = this.getSpotMarketAssetAndLiabilityValue(undefined, undefined, undefined,
|
|
840
|
+
const { totalAssetValue: spotAssetValue, totalLiabilityValue: spotLiabilityValue, } = this.getSpotMarketAssetAndLiabilityValue(undefined, undefined, undefined, includeOpenOrders);
|
|
841
841
|
return {
|
|
842
842
|
perpLiabilityValue: perpLiability,
|
|
843
843
|
perpPnl,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.41.0-beta.
|
|
3
|
+
"version": "2.41.0-beta.2",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"uuid": "^8.3.2"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
+
"@types/big.js": "^6.2.0",
|
|
47
48
|
"@types/chai": "^4.3.1",
|
|
48
49
|
"@types/jest": "^28.1.3",
|
|
49
50
|
"@types/mocha": "^9.1.1",
|