@drift-labs/sdk 2.38.1-beta.8 → 2.38.1-beta.9

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.
@@ -1,22 +1,38 @@
1
- import { SpotMarketAccount, SpotPosition } from '../types';
2
- import { ZERO } from '../constants/numericConstants';
1
+ import { MarginCategory, SpotMarketAccount, SpotPosition } from '../types';
2
+ import {
3
+ SPOT_MARKET_WEIGHT_PRECISION,
4
+ ZERO,
5
+ } from '../constants/numericConstants';
3
6
  import { BN } from '@coral-xyz/anchor';
4
7
  import {
8
+ calculateAssetWeight,
9
+ calculateLiabilityWeight,
5
10
  getSignedTokenAmount,
11
+ getStrictTokenValue,
6
12
  getTokenAmount,
7
13
  getTokenValue,
8
14
  } from './spotBalance';
9
- import { OraclePriceData } from '../oracles/types';
15
+ import { StrictOraclePrice } from '../oracles/strictOraclePrice';
10
16
 
11
17
  export function isSpotPositionAvailable(position: SpotPosition): boolean {
12
18
  return position.scaledBalance.eq(ZERO) && position.openOrders === 0;
13
19
  }
14
20
 
21
+ export type OrderFillSimulation = {
22
+ tokenAmount: BN;
23
+ ordersValue: BN;
24
+ tokenValue: BN;
25
+ weight: BN;
26
+ weightedTokenValue: BN;
27
+ freeCollateralContribution;
28
+ };
29
+
15
30
  export function getWorstCaseTokenAmounts(
16
31
  spotPosition: SpotPosition,
17
32
  spotMarketAccount: SpotMarketAccount,
18
- oraclePriceData: OraclePriceData
19
- ): [BN, BN] {
33
+ strictOraclePrice: StrictOraclePrice,
34
+ marginCategory: MarginCategory
35
+ ): OrderFillSimulation {
20
36
  const tokenAmount = getSignedTokenAmount(
21
37
  getTokenAmount(
22
38
  spotPosition.scaledBalance,
@@ -26,22 +42,121 @@ export function getWorstCaseTokenAmounts(
26
42
  spotPosition.balanceType
27
43
  );
28
44
 
29
- const tokenAmountAllBidsFill = tokenAmount.add(spotPosition.openBids);
30
- const tokenAmountAllAsksFill = tokenAmount.add(spotPosition.openAsks);
45
+ const tokenValue = getStrictTokenValue(
46
+ tokenAmount,
47
+ spotMarketAccount.decimals,
48
+ strictOraclePrice
49
+ );
31
50
 
32
- if (tokenAmountAllBidsFill.abs().gt(tokenAmountAllAsksFill.abs())) {
33
- const worstCaseQuoteTokenAmount = getTokenValue(
34
- spotPosition.openBids.neg(),
35
- spotMarketAccount.decimals,
36
- oraclePriceData
51
+ if (spotPosition.openBids.eq(ZERO) && spotPosition.openAsks.eq(ZERO)) {
52
+ const { weight, weightedTokenValue } = calculateWeightedTokenValue(
53
+ tokenAmount,
54
+ tokenValue,
55
+ strictOraclePrice.current,
56
+ spotMarketAccount,
57
+ marginCategory
37
58
  );
38
- return [tokenAmountAllBidsFill, worstCaseQuoteTokenAmount];
59
+ return {
60
+ tokenAmount,
61
+ ordersValue: ZERO,
62
+ tokenValue,
63
+ weight,
64
+ weightedTokenValue,
65
+ freeCollateralContribution: weightedTokenValue,
66
+ };
67
+ }
68
+
69
+ const bidsSimulation = simulateOrderFill(
70
+ tokenAmount,
71
+ tokenValue,
72
+ spotPosition.openBids,
73
+ strictOraclePrice,
74
+ spotMarketAccount,
75
+ marginCategory
76
+ );
77
+ const asksSimulation = simulateOrderFill(
78
+ tokenAmount,
79
+ tokenValue,
80
+ spotPosition.openAsks,
81
+ strictOraclePrice,
82
+ spotMarketAccount,
83
+ marginCategory
84
+ );
85
+
86
+ if (
87
+ asksSimulation.freeCollateralContribution.lt(
88
+ bidsSimulation.freeCollateralContribution
89
+ )
90
+ ) {
91
+ return asksSimulation;
39
92
  } else {
40
- const worstCaseQuoteTokenAmount = getTokenValue(
41
- spotPosition.openAsks.neg(),
42
- spotMarketAccount.decimals,
43
- oraclePriceData
93
+ return bidsSimulation;
94
+ }
95
+ }
96
+
97
+ export function calculateWeightedTokenValue(
98
+ tokenAmount: BN,
99
+ tokenValue: BN,
100
+ oraclePrice: BN,
101
+ spotMarket: SpotMarketAccount,
102
+ marginCategory: MarginCategory
103
+ ): { weight: BN; weightedTokenValue: BN } {
104
+ let weight: BN;
105
+ if (tokenValue.gte(ZERO)) {
106
+ weight = calculateAssetWeight(
107
+ tokenAmount,
108
+ oraclePrice,
109
+ spotMarket,
110
+ marginCategory
111
+ );
112
+ } else {
113
+ weight = calculateLiabilityWeight(
114
+ tokenAmount.abs(),
115
+ spotMarket,
116
+ marginCategory
44
117
  );
45
- return [tokenAmountAllAsksFill, worstCaseQuoteTokenAmount];
46
118
  }
119
+
120
+ return {
121
+ weight: weight,
122
+ weightedTokenValue: tokenValue
123
+ .mul(weight)
124
+ .div(SPOT_MARKET_WEIGHT_PRECISION),
125
+ };
126
+ }
127
+
128
+ export function simulateOrderFill(
129
+ tokenAmount: BN,
130
+ tokenValue: BN,
131
+ openOrders: BN,
132
+ strictOraclePrice: StrictOraclePrice,
133
+ spotMarket: SpotMarketAccount,
134
+ marginCategory: MarginCategory
135
+ ): OrderFillSimulation {
136
+ const ordersValue = getTokenValue(openOrders.neg(), spotMarket.decimals, {
137
+ price: strictOraclePrice.max(),
138
+ });
139
+ const tokenAmountAfterFill = tokenAmount.add(openOrders);
140
+ const tokenValueAfterFill = tokenValue.add(ordersValue.neg());
141
+
142
+ const { weight, weightedTokenValue: weightedTokenValueAfterFill } =
143
+ calculateWeightedTokenValue(
144
+ tokenAmountAfterFill,
145
+ tokenValueAfterFill,
146
+ strictOraclePrice.current,
147
+ spotMarket,
148
+ marginCategory
149
+ );
150
+
151
+ const freeCollateralContribution =
152
+ weightedTokenValueAfterFill.add(ordersValue);
153
+
154
+ return {
155
+ tokenAmount: tokenAmountAfterFill,
156
+ ordersValue: ordersValue,
157
+ tokenValue: tokenValueAfterFill,
158
+ weight,
159
+ weightedTokenValue: weightedTokenValueAfterFill,
160
+ freeCollateralContribution,
161
+ };
47
162
  }
@@ -0,0 +1,19 @@
1
+ import { BN } from '@coral-xyz/anchor';
2
+
3
+ export class StrictOraclePrice {
4
+ current: BN;
5
+ twap?: BN;
6
+
7
+ constructor(current: BN, twap?: BN) {
8
+ this.current = current;
9
+ this.twap = twap;
10
+ }
11
+
12
+ public max(): BN {
13
+ return this.twap ? BN.max(this.twap, this.current) : this.current;
14
+ }
15
+
16
+ public min(): BN {
17
+ return this.twap ? BN.min(this.twap, this.current) : this.current;
18
+ }
19
+ }
package/src/types.ts CHANGED
@@ -655,6 +655,7 @@ export type SpotMarketAccount = {
655
655
  maintenanceLiabilityWeight: number;
656
656
  liquidatorFee: number;
657
657
  imfFactor: number;
658
+ scaleInitialAssetWeightStart: BN;
658
659
 
659
660
  withdrawGuardThreshold: BN;
660
661
  depositTokenTwap: BN;