@drift-labs/sdk 0.1.21-master.0 → 0.1.21-master.3
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/lib/accounts/bulkAccountLoader.d.ts +0 -1
- package/lib/accounts/bulkAccountLoader.js +4 -2
- package/lib/accounts/bulkUserSubscription.d.ts +0 -1
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +5 -2
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +23 -1
- package/lib/accounts/pollingTokenAccountSubscriber.d.ts +0 -1
- package/lib/accounts/pollingUserAccountSubscriber.d.ts +3 -2
- package/lib/accounts/pollingUserAccountSubscriber.js +13 -0
- package/lib/accounts/types.d.ts +8 -3
- package/lib/accounts/utils.d.ts +0 -1
- package/lib/accounts/webSocketAccountSubscriber.d.ts +0 -1
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +5 -2
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +25 -0
- package/lib/accounts/webSocketUserAccountSubscriber.d.ts +3 -2
- package/lib/accounts/webSocketUserAccountSubscriber.js +11 -0
- package/lib/addresses.d.ts +4 -1
- package/lib/addresses.js +28 -1
- package/lib/admin.d.ts +10 -4
- package/lib/admin.js +48 -3
- package/lib/assert/assert.d.ts +0 -1
- package/lib/clearingHouse.d.ts +27 -2
- package/lib/clearingHouse.js +307 -7
- package/lib/clearingHouseUser.d.ts +15 -17
- package/lib/clearingHouseUser.js +105 -84
- package/lib/config.d.ts +0 -1
- package/lib/constants/markets.d.ts +0 -1
- package/lib/constants/markets.js +8 -0
- package/lib/constants/numericConstants.d.ts +1 -1
- package/lib/constants/numericConstants.js +2 -1
- package/lib/examples/makeTradeExample.d.ts +0 -1
- package/lib/factory/clearingHouse.d.ts +0 -1
- package/lib/factory/clearingHouseUser.d.ts +0 -1
- package/lib/idl/clearing_house.json +1066 -39
- package/lib/index.d.ts +3 -1
- package/lib/index.js +3 -0
- package/lib/math/amm.d.ts +1 -1
- package/lib/math/amm.js +31 -8
- package/lib/math/conversion.d.ts +0 -1
- package/lib/math/funding.d.ts +0 -1
- package/lib/math/insuranceFund.d.ts +0 -1
- package/lib/math/market.d.ts +2 -2
- package/lib/math/market.js +11 -1
- package/lib/math/orders.d.ts +3 -0
- package/lib/math/orders.js +32 -0
- package/lib/math/position.d.ts +4 -2
- package/lib/math/position.js +18 -4
- package/lib/math/trade.d.ts +0 -1
- package/lib/math/utils.d.ts +0 -1
- package/lib/mockUSDCFaucet.d.ts +0 -1
- package/lib/orderParams.d.ts +7 -0
- package/lib/orderParams.js +108 -0
- package/lib/orders.d.ts +6 -0
- package/lib/orders.js +136 -0
- package/lib/pythClient.d.ts +0 -1
- package/lib/token/index.d.ts +0 -1
- package/lib/tx/defaultTxSender.d.ts +0 -1
- package/lib/tx/types.d.ts +0 -1
- package/lib/tx/utils.d.ts +0 -1
- package/lib/types.d.ts +145 -2
- package/lib/types.js +36 -1
- package/lib/util/computeUnits.d.ts +0 -1
- package/lib/util/tps.d.ts +0 -1
- package/lib/wallet.d.ts +0 -1
- package/package.json +1 -1
- package/src/accounts/bulkAccountLoader.ts +3 -3
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +33 -0
- package/src/accounts/pollingUserAccountSubscriber.ts +30 -2
- package/src/accounts/types.ts +11 -2
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +47 -0
- package/src/accounts/webSocketUserAccountSubscriber.ts +29 -2
- package/src/addresses.ts +37 -0
- package/src/admin.ts +84 -6
- package/src/clearingHouse.ts +430 -5
- package/src/clearingHouseUser.ts +164 -102
- package/src/constants/markets.ts +8 -0
- package/src/constants/numericConstants.ts +1 -0
- package/src/idl/clearing_house.json +1066 -39
- package/src/index.ts +3 -0
- package/src/math/amm.ts +47 -14
- package/src/math/market.ts +28 -2
- package/src/math/orders.ts +44 -0
- package/src/math/position.ts +23 -3
- package/src/orderParams.ts +151 -0
- package/src/orders.ts +236 -0
- package/src/types.ts +129 -1
- package/tsconfig.json +0 -1
- package/lib/accounts/bulkAccountLoader.d.ts.map +0 -1
- package/lib/accounts/bulkUserSubscription.d.ts.map +0 -1
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts.map +0 -1
- package/lib/accounts/pollingTokenAccountSubscriber.d.ts.map +0 -1
- package/lib/accounts/pollingUserAccountSubscriber.d.ts.map +0 -1
- package/lib/accounts/types.d.ts.map +0 -1
- package/lib/accounts/utils.d.ts.map +0 -1
- package/lib/accounts/webSocketAccountSubscriber.d.ts.map +0 -1
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts.map +0 -1
- package/lib/accounts/webSocketUserAccountSubscriber.d.ts.map +0 -1
- package/lib/addresses.d.ts.map +0 -1
- package/lib/admin.d.ts.map +0 -1
- package/lib/assert/assert.d.ts.map +0 -1
- package/lib/clearingHouse.d.ts.map +0 -1
- package/lib/clearingHouseUser.d.ts.map +0 -1
- package/lib/config.d.ts.map +0 -1
- package/lib/constants/markets.d.ts.map +0 -1
- package/lib/constants/numericConstants.d.ts.map +0 -1
- package/lib/examples/makeTradeExample.d.ts.map +0 -1
- package/lib/factory/clearingHouse.d.ts.map +0 -1
- package/lib/factory/clearingHouseUser.d.ts.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/math/amm.d.ts.map +0 -1
- package/lib/math/conversion.d.ts.map +0 -1
- package/lib/math/funding.d.ts.map +0 -1
- package/lib/math/insuranceFund.d.ts.map +0 -1
- package/lib/math/market.d.ts.map +0 -1
- package/lib/math/position.d.ts.map +0 -1
- package/lib/math/trade.d.ts.map +0 -1
- package/lib/math/utils.d.ts.map +0 -1
- package/lib/mockUSDCFaucet.d.ts.map +0 -1
- package/lib/pythClient.d.ts.map +0 -1
- package/lib/token/index.d.ts.map +0 -1
- package/lib/tx/defaultTxSender.d.ts.map +0 -1
- package/lib/tx/types.d.ts.map +0 -1
- package/lib/tx/utils.d.ts.map +0 -1
- package/lib/types.d.ts.map +0 -1
- package/lib/util/computeUnits.d.ts.map +0 -1
- package/lib/util/tps.d.ts.map +0 -1
- package/lib/wallet.d.ts.map +0 -1
package/src/clearingHouseUser.ts
CHANGED
|
@@ -2,8 +2,14 @@ import { PublicKey } from '@solana/web3.js';
|
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
4
4
|
import { ClearingHouse } from './clearingHouse';
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
Order,
|
|
7
|
+
UserAccount,
|
|
8
|
+
UserOrdersAccount,
|
|
9
|
+
UserPosition,
|
|
10
|
+
UserPositionsAccount,
|
|
11
|
+
} from './types';
|
|
12
|
+
import { calculateEntryPrice, isEmptyPosition } from './math/position';
|
|
7
13
|
import {
|
|
8
14
|
MARK_PRICE_PRECISION,
|
|
9
15
|
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
@@ -23,6 +29,8 @@ import {
|
|
|
23
29
|
calculatePositionFundingPNL,
|
|
24
30
|
calculatePositionPNL,
|
|
25
31
|
PositionDirection,
|
|
32
|
+
getUserOrdersAccountPublicKey,
|
|
33
|
+
calculateNewStateAfterOrder,
|
|
26
34
|
calculateTradeSlippage,
|
|
27
35
|
BN,
|
|
28
36
|
} from '.';
|
|
@@ -37,6 +45,7 @@ export class ClearingHouseUser {
|
|
|
37
45
|
authority: PublicKey;
|
|
38
46
|
accountSubscriber: UserAccountSubscriber;
|
|
39
47
|
userAccountPublicKey?: PublicKey;
|
|
48
|
+
userOrdersAccountPublicKey?: PublicKey;
|
|
40
49
|
_isSubscribed = false;
|
|
41
50
|
eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
|
|
42
51
|
|
|
@@ -111,6 +120,10 @@ export class ClearingHouseUser {
|
|
|
111
120
|
return this.accountSubscriber.getUserPositionsAccount();
|
|
112
121
|
}
|
|
113
122
|
|
|
123
|
+
public getUserOrdersAccount(): UserOrdersAccount | undefined {
|
|
124
|
+
return this.accountSubscriber.getUserOrdersAccount();
|
|
125
|
+
}
|
|
126
|
+
|
|
114
127
|
/**
|
|
115
128
|
* Gets the user's current position for a given market. If the user has no position returns undefined
|
|
116
129
|
* @param marketIndex
|
|
@@ -128,9 +141,30 @@ export class ClearingHouseUser {
|
|
|
128
141
|
lastCumulativeFundingRate: ZERO,
|
|
129
142
|
marketIndex,
|
|
130
143
|
quoteAssetAmount: ZERO,
|
|
144
|
+
openOrders: ZERO,
|
|
131
145
|
};
|
|
132
146
|
}
|
|
133
147
|
|
|
148
|
+
/**
|
|
149
|
+
* @param orderId
|
|
150
|
+
* @returns Order
|
|
151
|
+
*/
|
|
152
|
+
public getOrder(orderId: BN): Order | undefined {
|
|
153
|
+
return this.getUserOrdersAccount().orders.find((order) =>
|
|
154
|
+
order.orderId.eq(orderId)
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @param userOrderId
|
|
160
|
+
* @returns Order
|
|
161
|
+
*/
|
|
162
|
+
public getOrderByUserOrderId(userOrderId: number): Order | undefined {
|
|
163
|
+
return this.getUserOrdersAccount().orders.find(
|
|
164
|
+
(order) => order.userOrderId === userOrderId
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
134
168
|
public async getUserAccountPublicKey(): Promise<PublicKey> {
|
|
135
169
|
if (this.userAccountPublicKey) {
|
|
136
170
|
return this.userAccountPublicKey;
|
|
@@ -143,6 +177,18 @@ export class ClearingHouseUser {
|
|
|
143
177
|
return this.userAccountPublicKey;
|
|
144
178
|
}
|
|
145
179
|
|
|
180
|
+
public async getUserOrdersAccountPublicKey(): Promise<PublicKey> {
|
|
181
|
+
if (this.userOrdersAccountPublicKey) {
|
|
182
|
+
return this.userOrdersAccountPublicKey;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
this.userOrdersAccountPublicKey = await getUserOrdersAccountPublicKey(
|
|
186
|
+
this.clearingHouse.program.programId,
|
|
187
|
+
await this.getUserAccountPublicKey()
|
|
188
|
+
);
|
|
189
|
+
return this.userOrdersAccountPublicKey;
|
|
190
|
+
}
|
|
191
|
+
|
|
146
192
|
public async exists(): Promise<boolean> {
|
|
147
193
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
148
194
|
const userAccountRPCResponse =
|
|
@@ -438,6 +484,7 @@ export class ClearingHouseUser {
|
|
|
438
484
|
),
|
|
439
485
|
lastCumulativeFundingRate: new BN(0),
|
|
440
486
|
quoteAssetAmount: new BN(0),
|
|
487
|
+
openOrders: new BN(0),
|
|
441
488
|
};
|
|
442
489
|
|
|
443
490
|
const market = this.clearingHouse.getMarket(
|
|
@@ -528,14 +575,14 @@ export class ClearingHouseUser {
|
|
|
528
575
|
// solves formula for example calc below
|
|
529
576
|
|
|
530
577
|
/* example: assume BTC price is $40k (examine 10% up/down)
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
578
|
+
|
|
579
|
+
if 10k deposit and levered 10x short BTC => BTC up $400 means:
|
|
580
|
+
1. higher base_asset_value (+$4k)
|
|
581
|
+
2. lower collateral (-$4k)
|
|
582
|
+
3. (10k - 4k)/(100k + 4k) => 6k/104k => .0576
|
|
583
|
+
|
|
584
|
+
for 10x long, BTC down $400:
|
|
585
|
+
3. (10k - 4k) / (100k - 4k) = 6k/96k => .0625 */
|
|
539
586
|
|
|
540
587
|
const tc = this.getTotalCollateral();
|
|
541
588
|
const tpv = this.getTotalPositionValue();
|
|
@@ -566,6 +613,7 @@ export class ClearingHouseUser {
|
|
|
566
613
|
lastCumulativeFundingRate:
|
|
567
614
|
currentMarketPosition.lastCumulativeFundingRate,
|
|
568
615
|
quoteAssetAmount: new BN(0),
|
|
616
|
+
openOrders: new BN(0),
|
|
569
617
|
};
|
|
570
618
|
|
|
571
619
|
const market = this.clearingHouse.getMarket(
|
|
@@ -685,21 +733,6 @@ export class ClearingHouseUser {
|
|
|
685
733
|
|
|
686
734
|
/**
|
|
687
735
|
* Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
|
|
688
|
-
*
|
|
689
|
-
* To Calculate Max Quote Available:
|
|
690
|
-
*
|
|
691
|
-
* Case 1: SameSide
|
|
692
|
-
* => Remaining quote to get to maxLeverage
|
|
693
|
-
*
|
|
694
|
-
* Case 2: NOT SameSide && currentLeverage <= maxLeverage
|
|
695
|
-
* => Current opposite position x2 + remaining to get to maxLeverage
|
|
696
|
-
*
|
|
697
|
-
* Case 3: NOT SameSide && currentLeverage > maxLeverage && otherPositions - currentPosition > maxLeverage
|
|
698
|
-
* => strictly reduce current position size
|
|
699
|
-
*
|
|
700
|
-
* Case 4: NOT SameSide && currentLeverage > maxLeverage && otherPositions - currentPosition < maxLeverage
|
|
701
|
-
* => current position + remaining to get to maxLeverage
|
|
702
|
-
*
|
|
703
736
|
* @param marketIndex
|
|
704
737
|
* @param tradeSide
|
|
705
738
|
* @param userMaxLeverageSetting - leverage : Precision TEN_THOUSAND
|
|
@@ -710,28 +743,34 @@ export class ClearingHouseUser {
|
|
|
710
743
|
tradeSide: PositionDirection,
|
|
711
744
|
userMaxLeverageSetting: BN
|
|
712
745
|
): BN {
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
746
|
+
// inline function which get's the current position size on the opposite side of the target trade
|
|
747
|
+
const getOppositePositionValueUSDC = () => {
|
|
748
|
+
if (!currentPosition) return ZERO;
|
|
716
749
|
|
|
717
|
-
|
|
750
|
+
const side = tradeSide === PositionDirection.SHORT ? 'short' : 'long';
|
|
718
751
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
752
|
+
if (side === 'long' && currentPosition?.baseAssetAmount.isNeg()) {
|
|
753
|
+
return this.getPositionValue(targetMarketIndex);
|
|
754
|
+
} else if (
|
|
755
|
+
side === 'short' &&
|
|
756
|
+
!currentPosition?.baseAssetAmount.isNeg()
|
|
757
|
+
) {
|
|
758
|
+
return this.getPositionValue(targetMarketIndex);
|
|
759
|
+
}
|
|
722
760
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
: targetSide === currentPositionSide;
|
|
761
|
+
return ZERO;
|
|
762
|
+
};
|
|
726
763
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
: this.getPositionValue(targetMarketIndex);
|
|
764
|
+
const currentPosition =
|
|
765
|
+
this.getUserPosition(targetMarketIndex) ||
|
|
766
|
+
this.getEmptyPosition(targetMarketIndex);
|
|
731
767
|
|
|
732
768
|
// get current leverage
|
|
733
769
|
const currentLeverage = this.getLeverage();
|
|
734
770
|
|
|
771
|
+
// remaining leverage
|
|
772
|
+
// let remainingLeverage = userMaxLeverageSetting;
|
|
773
|
+
|
|
735
774
|
const remainingLeverage = BN.max(
|
|
736
775
|
userMaxLeverageSetting.sub(currentLeverage),
|
|
737
776
|
ZERO
|
|
@@ -745,57 +784,10 @@ export class ClearingHouseUser {
|
|
|
745
784
|
.mul(totalCollateral)
|
|
746
785
|
.div(TEN_THOUSAND);
|
|
747
786
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
// case 1 : Regular trade where current total position less than max, and no opposite position to account for
|
|
751
|
-
// do nothing
|
|
752
|
-
} else {
|
|
753
|
-
// case 2 : trade where current total position less than max, but need to account for flipping the current position over to the other side
|
|
754
|
-
maxPositionSize = maxPositionSize.add(
|
|
755
|
-
oppositeSizeValueUSDC.mul(new BN(2))
|
|
756
|
-
);
|
|
757
|
-
}
|
|
758
|
-
} else {
|
|
759
|
-
// current leverage is greater than max leverage - can only reduce position size
|
|
760
|
-
|
|
761
|
-
if (!targettingSameSide) {
|
|
762
|
-
const currentPositionQuoteSize =
|
|
763
|
-
this.getPositionValue(targetMarketIndex);
|
|
764
|
-
|
|
765
|
-
const currentTotalQuoteSize = currentLeverage
|
|
766
|
-
.mul(totalCollateral)
|
|
767
|
-
.div(TEN_THOUSAND);
|
|
768
|
-
|
|
769
|
-
const otherPositionsTotalQuoteSize = currentTotalQuoteSize.sub(
|
|
770
|
-
currentPositionQuoteSize
|
|
771
|
-
);
|
|
772
|
-
|
|
773
|
-
const quoteValueOfMaxLeverage = userMaxLeverageSetting
|
|
774
|
-
.mul(totalCollateral)
|
|
775
|
-
.div(TEN_THOUSAND);
|
|
776
|
-
|
|
777
|
-
if (
|
|
778
|
-
otherPositionsTotalQuoteSize
|
|
779
|
-
.sub(currentPositionQuoteSize)
|
|
780
|
-
.gte(quoteValueOfMaxLeverage)
|
|
781
|
-
) {
|
|
782
|
-
// case 3: Can only reduce the current position because it will still be greater than max leverage
|
|
783
|
-
|
|
784
|
-
maxPositionSize = currentPositionQuoteSize;
|
|
785
|
-
} else {
|
|
786
|
-
// case 4: Can reduce the position, and then take extra remaining quote to get to max leverage
|
|
787
|
-
|
|
788
|
-
const allowedQuoteSizeAfterClosingCurrentPosition =
|
|
789
|
-
quoteValueOfMaxLeverage.sub(otherPositionsTotalQuoteSize);
|
|
787
|
+
// add any position we have on the opposite side of the current trade, because we can "flip" the size of this position without taking any extra leverage.
|
|
788
|
+
const oppositeSizeValueUSDC = getOppositePositionValueUSDC();
|
|
790
789
|
|
|
791
|
-
|
|
792
|
-
allowedQuoteSizeAfterClosingCurrentPosition
|
|
793
|
-
);
|
|
794
|
-
}
|
|
795
|
-
} else {
|
|
796
|
-
// do nothing if targetting same side
|
|
797
|
-
}
|
|
798
|
-
}
|
|
790
|
+
maxPositionSize = maxPositionSize.add(oppositeSizeValueUSDC.mul(new BN(2)));
|
|
799
791
|
|
|
800
792
|
// subtract oneMillionth of maxPositionSize
|
|
801
793
|
// => to avoid rounding errors when taking max leverage
|
|
@@ -840,19 +832,13 @@ export class ClearingHouseUser {
|
|
|
840
832
|
|
|
841
833
|
const totalPositionAfterTradeExcludingTargetMarket =
|
|
842
834
|
this.getTotalPositionValueExcludingMarket(targetMarketIndex);
|
|
835
|
+
const newLeverage = currentMarketPositionAfterTrade
|
|
836
|
+
.add(totalPositionAfterTradeExcludingTargetMarket)
|
|
837
|
+
.abs()
|
|
838
|
+
.mul(TEN_THOUSAND)
|
|
839
|
+
.div(this.getTotalCollateral());
|
|
843
840
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
if (totalCollateral.gt(ZERO)) {
|
|
847
|
-
const newLeverage = currentMarketPositionAfterTrade
|
|
848
|
-
.add(totalPositionAfterTradeExcludingTargetMarket)
|
|
849
|
-
.abs()
|
|
850
|
-
.mul(TEN_THOUSAND)
|
|
851
|
-
.div(totalCollateral);
|
|
852
|
-
return newLeverage;
|
|
853
|
-
} else {
|
|
854
|
-
return new BN(0);
|
|
855
|
-
}
|
|
841
|
+
return newLeverage;
|
|
856
842
|
}
|
|
857
843
|
|
|
858
844
|
/**
|
|
@@ -880,9 +866,85 @@ export class ClearingHouseUser {
|
|
|
880
866
|
|
|
881
867
|
let currentMarketPositionValueUSDC = ZERO;
|
|
882
868
|
if (currentMarketPosition) {
|
|
883
|
-
|
|
869
|
+
const market = this.clearingHouse.getMarket(
|
|
870
|
+
currentMarketPosition.marketIndex
|
|
871
|
+
);
|
|
872
|
+
currentMarketPositionValueUSDC = calculateBaseAssetValue(
|
|
873
|
+
market,
|
|
874
|
+
currentMarketPosition
|
|
875
|
+
);
|
|
884
876
|
}
|
|
885
877
|
|
|
886
878
|
return this.getTotalPositionValue().sub(currentMarketPositionValueUSDC);
|
|
887
879
|
}
|
|
880
|
+
|
|
881
|
+
public canFillOrder(order: Order): boolean {
|
|
882
|
+
const userAccount = this.getUserAccount();
|
|
883
|
+
const userPositionsAccount = this.getUserPositionsAccount();
|
|
884
|
+
const userPosition = this.getUserPosition(order.marketIndex);
|
|
885
|
+
const market = this.clearingHouse.getMarket(order.marketIndex);
|
|
886
|
+
|
|
887
|
+
if (isEmptyPosition(userPosition)) {
|
|
888
|
+
return false;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
const newState = calculateNewStateAfterOrder(
|
|
892
|
+
userAccount,
|
|
893
|
+
userPosition,
|
|
894
|
+
market,
|
|
895
|
+
order
|
|
896
|
+
);
|
|
897
|
+
if (newState === null) {
|
|
898
|
+
return false;
|
|
899
|
+
}
|
|
900
|
+
const [userAccountAfter, userPositionAfter, marketAfter] = newState;
|
|
901
|
+
|
|
902
|
+
const totalPositionValue = userPositionsAccount.positions.reduce(
|
|
903
|
+
(positionValue, marketPosition) => {
|
|
904
|
+
let market = this.clearingHouse.getMarket(marketPosition.marketIndex);
|
|
905
|
+
if (marketPosition.marketIndex.eq(order.marketIndex)) {
|
|
906
|
+
market = marketAfter;
|
|
907
|
+
marketPosition = userPositionAfter;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
return positionValue.add(
|
|
911
|
+
calculateBaseAssetValue(market, marketPosition)
|
|
912
|
+
);
|
|
913
|
+
},
|
|
914
|
+
ZERO
|
|
915
|
+
);
|
|
916
|
+
|
|
917
|
+
if (totalPositionValue.eq(ZERO)) {
|
|
918
|
+
return true;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
const unrealizedPnL = userPositionsAccount.positions.reduce(
|
|
922
|
+
(pnl, marketPosition) => {
|
|
923
|
+
let market = this.clearingHouse.getMarket(marketPosition.marketIndex);
|
|
924
|
+
pnl = pnl.add(
|
|
925
|
+
calculatePositionFundingPNL(market, marketPosition).div(
|
|
926
|
+
PRICE_TO_QUOTE_PRECISION
|
|
927
|
+
)
|
|
928
|
+
);
|
|
929
|
+
|
|
930
|
+
if (marketPosition.marketIndex.eq(order.marketIndex)) {
|
|
931
|
+
market = marketAfter;
|
|
932
|
+
marketPosition = userPositionAfter;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
// update
|
|
936
|
+
return pnl.add(calculatePositionPNL(market, marketPosition, false));
|
|
937
|
+
},
|
|
938
|
+
ZERO
|
|
939
|
+
);
|
|
940
|
+
const totalCollateral = userAccountAfter.collateral.add(unrealizedPnL);
|
|
941
|
+
|
|
942
|
+
const marginRatioAfter = totalCollateral
|
|
943
|
+
.mul(TEN_THOUSAND)
|
|
944
|
+
.div(totalPositionValue);
|
|
945
|
+
|
|
946
|
+
const marginRatioInitial =
|
|
947
|
+
this.clearingHouse.getStateAccount().marginRatioInitial;
|
|
948
|
+
return marginRatioAfter.gte(marginRatioInitial);
|
|
949
|
+
}
|
|
888
950
|
}
|
package/src/constants/markets.ts
CHANGED
|
@@ -106,6 +106,14 @@ export const Markets: Market[] = [
|
|
|
106
106
|
mainnetPythOracle: '8JPJJkmDScpcNmBRKGZuPuG2GYAveQgP3t5gFuMymwvF',
|
|
107
107
|
launchTs: 1644382122000,
|
|
108
108
|
},
|
|
109
|
+
{
|
|
110
|
+
symbol: 'LTC-PERP',
|
|
111
|
+
baseAssetSymbol: 'LTC',
|
|
112
|
+
marketIndex: new BN(12),
|
|
113
|
+
devnetPythOracle: 'BLArYBCUYhdWiY8PCUTpvFE21iaJq85dvxLk9bYMobcU',
|
|
114
|
+
mainnetPythOracle: '8RMnV1eD55iqUFJLMguPkYBkq8DCtx81XcmAja93LvRR',
|
|
115
|
+
launchTs: 1645027429000,
|
|
116
|
+
},
|
|
109
117
|
// {
|
|
110
118
|
// symbol: 'mSOL-PERP',
|
|
111
119
|
// baseAssetSymbol: 'mSOL',
|