@drift-labs/sdk 0.2.0-master.36 → 0.2.0-master.37
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/addresses/pda.js +2 -2
- package/lib/admin.d.ts +3 -3
- package/lib/admin.js +3 -3
- package/lib/clearingHouse.d.ts +16 -6
- package/lib/clearingHouse.js +145 -39
- package/lib/clearingHouseUser.js +7 -26
- package/lib/config.js +1 -1
- package/lib/factory/bigNum.d.ts +1 -0
- package/lib/factory/bigNum.js +26 -4
- package/lib/idl/clearing_house.json +330 -280
- package/lib/math/funding.js +3 -2
- package/lib/math/market.js +4 -6
- package/lib/math/position.d.ts +7 -1
- package/lib/math/position.js +18 -2
- package/lib/math/spotBalance.js +5 -5
- package/lib/types.d.ts +18 -16
- package/package.json +1 -1
- package/src/addresses/pda.ts +2 -2
- package/src/admin.ts +13 -13
- package/src/clearingHouse.ts +181 -40
- package/src/clearingHouseUser.ts +9 -25
- package/src/config.ts +1 -1
- package/src/factory/bigNum.ts +27 -4
- package/src/idl/clearing_house.json +330 -280
- package/src/math/funding.ts +3 -5
- package/src/math/market.ts +4 -6
- package/src/math/position.ts +18 -1
- package/src/math/spotBalance.ts +9 -9
- package/src/types.ts +18 -16
- package/tests/dlob/helpers.ts +47 -43
package/src/clearingHouse.ts
CHANGED
|
@@ -86,7 +86,7 @@ type RemainingAccountParams = {
|
|
|
86
86
|
writablePerpMarketIndexes?: number[];
|
|
87
87
|
writableSpotMarketIndexes?: number[];
|
|
88
88
|
readablePerpMarketIndex?: number;
|
|
89
|
-
|
|
89
|
+
readableSpotMarketIndexes?: number[];
|
|
90
90
|
useMarketLastSlotCache?: boolean;
|
|
91
91
|
};
|
|
92
92
|
|
|
@@ -108,7 +108,8 @@ export class ClearingHouse {
|
|
|
108
108
|
eventEmitter: StrictEventEmitter<EventEmitter, ClearingHouseAccountEvents>;
|
|
109
109
|
_isSubscribed = false;
|
|
110
110
|
txSender: TxSender;
|
|
111
|
-
|
|
111
|
+
perpMarketLastSlotCache = new Map<number, number>();
|
|
112
|
+
spotMarketLastSlotCache = new Map<number, number>();
|
|
112
113
|
authority: PublicKey;
|
|
113
114
|
|
|
114
115
|
public get isSubscribed() {
|
|
@@ -664,11 +665,14 @@ export class ClearingHouse {
|
|
|
664
665
|
this.getRemainingAccountMapsForUsers(params.userAccounts);
|
|
665
666
|
|
|
666
667
|
if (params.useMarketLastSlotCache) {
|
|
667
|
-
const
|
|
668
|
-
for (const [
|
|
668
|
+
const lastUserSlot = this.getUserAccountAndSlot()?.slot;
|
|
669
|
+
for (const [
|
|
670
|
+
marketIndex,
|
|
671
|
+
slot,
|
|
672
|
+
] of this.perpMarketLastSlotCache.entries()) {
|
|
669
673
|
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
670
674
|
// otherwise remove from slot
|
|
671
|
-
if (slot >
|
|
675
|
+
if (slot > lastUserSlot) {
|
|
672
676
|
const marketAccount = this.getPerpMarketAccount(marketIndex);
|
|
673
677
|
perpMarketAccountMap.set(marketIndex, {
|
|
674
678
|
pubkey: marketAccount.pubkey,
|
|
@@ -681,7 +685,32 @@ export class ClearingHouse {
|
|
|
681
685
|
isWritable: false,
|
|
682
686
|
});
|
|
683
687
|
} else {
|
|
684
|
-
this.
|
|
688
|
+
this.perpMarketLastSlotCache.delete(marketIndex);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
for (const [
|
|
693
|
+
marketIndex,
|
|
694
|
+
slot,
|
|
695
|
+
] of this.spotMarketLastSlotCache.entries()) {
|
|
696
|
+
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
697
|
+
// otherwise remove from slot
|
|
698
|
+
if (slot > lastUserSlot) {
|
|
699
|
+
const marketAccount = this.getSpotMarketAccount(marketIndex);
|
|
700
|
+
spotMarketAccountMap.set(marketIndex, {
|
|
701
|
+
pubkey: marketAccount.pubkey,
|
|
702
|
+
isSigner: false,
|
|
703
|
+
isWritable: false,
|
|
704
|
+
});
|
|
705
|
+
if (!marketAccount.oracle.equals(PublicKey.default)) {
|
|
706
|
+
oracleAccountMap.set(marketAccount.oracle.toString(), {
|
|
707
|
+
pubkey: marketAccount.oracle,
|
|
708
|
+
isSigner: false,
|
|
709
|
+
isWritable: false,
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
} else {
|
|
713
|
+
this.spotMarketLastSlotCache.delete(marketIndex);
|
|
685
714
|
}
|
|
686
715
|
}
|
|
687
716
|
}
|
|
@@ -720,21 +749,23 @@ export class ClearingHouse {
|
|
|
720
749
|
}
|
|
721
750
|
}
|
|
722
751
|
|
|
723
|
-
if (params.
|
|
724
|
-
const
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
isWritable: false,
|
|
731
|
-
});
|
|
732
|
-
if (spotMarketAccount.marketIndex !== 0) {
|
|
733
|
-
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
734
|
-
pubkey: spotMarketAccount.oracle,
|
|
752
|
+
if (params.readableSpotMarketIndexes !== undefined) {
|
|
753
|
+
for (const readableSpotMarketIndex of params.readableSpotMarketIndexes) {
|
|
754
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
755
|
+
readableSpotMarketIndex
|
|
756
|
+
);
|
|
757
|
+
spotMarketAccountMap.set(readableSpotMarketIndex, {
|
|
758
|
+
pubkey: spotMarketAccount.pubkey,
|
|
735
759
|
isSigner: false,
|
|
736
760
|
isWritable: false,
|
|
737
761
|
});
|
|
762
|
+
if (spotMarketAccount.marketIndex !== 0) {
|
|
763
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
764
|
+
pubkey: spotMarketAccount.oracle,
|
|
765
|
+
isSigner: false,
|
|
766
|
+
isWritable: false,
|
|
767
|
+
});
|
|
768
|
+
}
|
|
738
769
|
}
|
|
739
770
|
}
|
|
740
771
|
|
|
@@ -793,6 +824,17 @@ export class ClearingHouse {
|
|
|
793
824
|
isWritable: false,
|
|
794
825
|
});
|
|
795
826
|
}
|
|
827
|
+
|
|
828
|
+
if (
|
|
829
|
+
!spotPosition.openAsks.eq(ZERO) ||
|
|
830
|
+
!spotPosition.openBids.eq(ZERO)
|
|
831
|
+
) {
|
|
832
|
+
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
833
|
+
pubkey: this.getQuoteSpotMarketAccount().pubkey,
|
|
834
|
+
isSigner: false,
|
|
835
|
+
isWritable: false,
|
|
836
|
+
});
|
|
837
|
+
}
|
|
796
838
|
}
|
|
797
839
|
}
|
|
798
840
|
for (const position of userAccount.perpPositions) {
|
|
@@ -894,11 +936,12 @@ export class ClearingHouse {
|
|
|
894
936
|
);
|
|
895
937
|
}
|
|
896
938
|
|
|
897
|
-
const { txSig } = await this.txSender.send(
|
|
939
|
+
const { txSig, slot } = await this.txSender.send(
|
|
898
940
|
tx,
|
|
899
941
|
additionalSigners,
|
|
900
942
|
this.opts
|
|
901
943
|
);
|
|
944
|
+
this.spotMarketLastSlotCache.set(marketIndex, slot);
|
|
902
945
|
return txSig;
|
|
903
946
|
}
|
|
904
947
|
|
|
@@ -1119,12 +1162,12 @@ export class ClearingHouse {
|
|
|
1119
1162
|
);
|
|
1120
1163
|
}
|
|
1121
1164
|
|
|
1122
|
-
const { txSig } = await this.txSender.send(
|
|
1165
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1123
1166
|
tx,
|
|
1124
1167
|
additionalSigners,
|
|
1125
1168
|
this.opts
|
|
1126
1169
|
);
|
|
1127
|
-
|
|
1170
|
+
this.spotMarketLastSlotCache.set(marketIndex, slot);
|
|
1128
1171
|
return [txSig, userAccountPublicKey];
|
|
1129
1172
|
}
|
|
1130
1173
|
|
|
@@ -1242,11 +1285,12 @@ export class ClearingHouse {
|
|
|
1242
1285
|
);
|
|
1243
1286
|
}
|
|
1244
1287
|
|
|
1245
|
-
const { txSig } = await this.txSender.send(
|
|
1288
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1246
1289
|
tx,
|
|
1247
1290
|
additionalSigners,
|
|
1248
1291
|
this.opts
|
|
1249
1292
|
);
|
|
1293
|
+
this.spotMarketLastSlotCache.set(marketIndex, slot);
|
|
1250
1294
|
return txSig;
|
|
1251
1295
|
}
|
|
1252
1296
|
|
|
@@ -1262,6 +1306,7 @@ export class ClearingHouse {
|
|
|
1262
1306
|
userAccounts: [this.getUserAccount()],
|
|
1263
1307
|
useMarketLastSlotCache: true,
|
|
1264
1308
|
writableSpotMarketIndexes: [marketIndex],
|
|
1309
|
+
readableSpotMarketIndexes: [QUOTE_SPOT_MARKET_INDEX],
|
|
1265
1310
|
});
|
|
1266
1311
|
|
|
1267
1312
|
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
@@ -1293,7 +1338,7 @@ export class ClearingHouse {
|
|
|
1293
1338
|
fromSubAccountId: number,
|
|
1294
1339
|
toSubAccountId: number
|
|
1295
1340
|
): Promise<TransactionSignature> {
|
|
1296
|
-
const { txSig } = await this.txSender.send(
|
|
1341
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1297
1342
|
wrapInTx(
|
|
1298
1343
|
await this.getTransferDepositIx(
|
|
1299
1344
|
amount,
|
|
@@ -1305,6 +1350,12 @@ export class ClearingHouse {
|
|
|
1305
1350
|
[],
|
|
1306
1351
|
this.opts
|
|
1307
1352
|
);
|
|
1353
|
+
if (
|
|
1354
|
+
fromSubAccountId === this.activeSubAccountId ||
|
|
1355
|
+
toSubAccountId === this.activeSubAccountId
|
|
1356
|
+
) {
|
|
1357
|
+
this.spotMarketLastSlotCache.set(marketIndex, slot);
|
|
1358
|
+
}
|
|
1308
1359
|
return txSig;
|
|
1309
1360
|
}
|
|
1310
1361
|
|
|
@@ -1356,6 +1407,7 @@ export class ClearingHouse {
|
|
|
1356
1407
|
toUser,
|
|
1357
1408
|
userStats: this.getUserStatsAccountPublicKey(),
|
|
1358
1409
|
state: await this.getStatePublicKey(),
|
|
1410
|
+
spotMarketVault: this.getQuoteSpotMarketAccount().vault,
|
|
1359
1411
|
},
|
|
1360
1412
|
remainingAccounts,
|
|
1361
1413
|
});
|
|
@@ -1530,7 +1582,7 @@ export class ClearingHouse {
|
|
|
1530
1582
|
[],
|
|
1531
1583
|
this.opts
|
|
1532
1584
|
);
|
|
1533
|
-
this.
|
|
1585
|
+
this.perpMarketLastSlotCache.set(marketIndex, slot);
|
|
1534
1586
|
return txSig;
|
|
1535
1587
|
}
|
|
1536
1588
|
|
|
@@ -1619,7 +1671,7 @@ export class ClearingHouse {
|
|
|
1619
1671
|
true
|
|
1620
1672
|
);
|
|
1621
1673
|
|
|
1622
|
-
this.
|
|
1674
|
+
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
1623
1675
|
|
|
1624
1676
|
return { txSig, signedFillTx };
|
|
1625
1677
|
}
|
|
@@ -1632,7 +1684,7 @@ export class ClearingHouse {
|
|
|
1632
1684
|
[],
|
|
1633
1685
|
this.opts
|
|
1634
1686
|
);
|
|
1635
|
-
this.
|
|
1687
|
+
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
1636
1688
|
return txSig;
|
|
1637
1689
|
}
|
|
1638
1690
|
|
|
@@ -1993,11 +2045,13 @@ export class ClearingHouse {
|
|
|
1993
2045
|
public async placeSpotOrder(
|
|
1994
2046
|
orderParams: OptionalOrderParams
|
|
1995
2047
|
): Promise<TransactionSignature> {
|
|
1996
|
-
const { txSig } = await this.txSender.send(
|
|
2048
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1997
2049
|
wrapInTx(await this.getPlaceSpotOrderIx(orderParams)),
|
|
1998
2050
|
[],
|
|
1999
2051
|
this.opts
|
|
2000
2052
|
);
|
|
2053
|
+
this.spotMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2054
|
+
this.spotMarketLastSlotCache.set(QUOTE_SPOT_MARKET_INDEX, slot);
|
|
2001
2055
|
return txSig;
|
|
2002
2056
|
}
|
|
2003
2057
|
|
|
@@ -2010,7 +2064,10 @@ export class ClearingHouse {
|
|
|
2010
2064
|
const remainingAccounts = this.getRemainingAccounts({
|
|
2011
2065
|
userAccounts: [this.getUserAccount()],
|
|
2012
2066
|
useMarketLastSlotCache: true,
|
|
2013
|
-
|
|
2067
|
+
readableSpotMarketIndexes: [
|
|
2068
|
+
orderParams.marketIndex,
|
|
2069
|
+
QUOTE_SPOT_MARKET_INDEX,
|
|
2070
|
+
],
|
|
2014
2071
|
});
|
|
2015
2072
|
|
|
2016
2073
|
return await this.program.instruction.placeSpotOrder(orderParams, {
|
|
@@ -2291,7 +2348,7 @@ export class ClearingHouse {
|
|
|
2291
2348
|
[],
|
|
2292
2349
|
this.opts
|
|
2293
2350
|
);
|
|
2294
|
-
this.
|
|
2351
|
+
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2295
2352
|
return txSig;
|
|
2296
2353
|
}
|
|
2297
2354
|
|
|
@@ -2374,7 +2431,7 @@ export class ClearingHouse {
|
|
|
2374
2431
|
this.opts
|
|
2375
2432
|
);
|
|
2376
2433
|
|
|
2377
|
-
this.
|
|
2434
|
+
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2378
2435
|
|
|
2379
2436
|
return txSig;
|
|
2380
2437
|
}
|
|
@@ -2431,7 +2488,7 @@ export class ClearingHouse {
|
|
|
2431
2488
|
makerInfo?: MakerInfo,
|
|
2432
2489
|
referrerInfo?: ReferrerInfo
|
|
2433
2490
|
): Promise<TransactionSignature> {
|
|
2434
|
-
const { txSig } = await this.txSender.send(
|
|
2491
|
+
const { txSig, slot } = await this.txSender.send(
|
|
2435
2492
|
wrapInTx(
|
|
2436
2493
|
await this.getPlaceAndTakeSpotOrderIx(
|
|
2437
2494
|
orderParams,
|
|
@@ -2443,6 +2500,8 @@ export class ClearingHouse {
|
|
|
2443
2500
|
[],
|
|
2444
2501
|
this.opts
|
|
2445
2502
|
);
|
|
2503
|
+
this.spotMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2504
|
+
this.spotMarketLastSlotCache.set(QUOTE_SPOT_MARKET_INDEX, slot);
|
|
2446
2505
|
return txSig;
|
|
2447
2506
|
}
|
|
2448
2507
|
|
|
@@ -2524,26 +2583,30 @@ export class ClearingHouse {
|
|
|
2524
2583
|
public async placeAndMakeSpotOrder(
|
|
2525
2584
|
orderParams: OptionalOrderParams,
|
|
2526
2585
|
takerInfo: TakerInfo,
|
|
2586
|
+
fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
|
|
2527
2587
|
referrerInfo?: ReferrerInfo
|
|
2528
2588
|
): Promise<TransactionSignature> {
|
|
2529
|
-
const { txSig } = await this.txSender.send(
|
|
2589
|
+
const { txSig, slot } = await this.txSender.send(
|
|
2530
2590
|
wrapInTx(
|
|
2531
2591
|
await this.getPlaceAndMakeSpotOrderIx(
|
|
2532
2592
|
orderParams,
|
|
2533
2593
|
takerInfo,
|
|
2594
|
+
fulfillmentConfig,
|
|
2534
2595
|
referrerInfo
|
|
2535
2596
|
)
|
|
2536
2597
|
),
|
|
2537
2598
|
[],
|
|
2538
2599
|
this.opts
|
|
2539
2600
|
);
|
|
2540
|
-
|
|
2601
|
+
this.spotMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2602
|
+
this.spotMarketLastSlotCache.set(QUOTE_SPOT_MARKET_INDEX, slot);
|
|
2541
2603
|
return txSig;
|
|
2542
2604
|
}
|
|
2543
2605
|
|
|
2544
2606
|
public async getPlaceAndMakeSpotOrderIx(
|
|
2545
2607
|
orderParams: OptionalOrderParams,
|
|
2546
2608
|
takerInfo: TakerInfo,
|
|
2609
|
+
fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
|
|
2547
2610
|
referrerInfo?: ReferrerInfo
|
|
2548
2611
|
): Promise<TransactionInstruction> {
|
|
2549
2612
|
orderParams = this.getOrderParams(orderParams, MarketType.SPOT);
|
|
@@ -2572,10 +2635,19 @@ export class ClearingHouse {
|
|
|
2572
2635
|
});
|
|
2573
2636
|
}
|
|
2574
2637
|
|
|
2638
|
+
if (fulfillmentConfig) {
|
|
2639
|
+
this.addSerumRemainingAccounts(
|
|
2640
|
+
orderParams.marketIndex,
|
|
2641
|
+
remainingAccounts,
|
|
2642
|
+
fulfillmentConfig
|
|
2643
|
+
);
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2575
2646
|
const takerOrderId = takerInfo.order.orderId;
|
|
2576
2647
|
return await this.program.instruction.placeAndMakeSpotOrder(
|
|
2577
2648
|
orderParams,
|
|
2578
2649
|
takerOrderId,
|
|
2650
|
+
fulfillmentConfig ? fulfillmentConfig.fulfillmentType : null,
|
|
2579
2651
|
{
|
|
2580
2652
|
accounts: {
|
|
2581
2653
|
state: await this.getStatePublicKey(),
|
|
@@ -2614,6 +2686,66 @@ export class ClearingHouse {
|
|
|
2614
2686
|
});
|
|
2615
2687
|
}
|
|
2616
2688
|
|
|
2689
|
+
/**
|
|
2690
|
+
* Modifies an open order by closing it and replacing it with a new order.
|
|
2691
|
+
* @param orderId: The open order to modify
|
|
2692
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
2693
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
2694
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
2695
|
+
* @returns
|
|
2696
|
+
*/
|
|
2697
|
+
public async modifyPerpOrder(
|
|
2698
|
+
orderId: number,
|
|
2699
|
+
newBaseAmount?: BN,
|
|
2700
|
+
newLimitPrice?: BN,
|
|
2701
|
+
newOraclePriceOffset?: number
|
|
2702
|
+
): Promise<TransactionSignature> {
|
|
2703
|
+
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
2704
|
+
throw new Error(
|
|
2705
|
+
`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`
|
|
2706
|
+
);
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
const openOrder = this.getUser().getOrder(orderId);
|
|
2710
|
+
if (!openOrder) {
|
|
2711
|
+
throw new Error(`No open order with id ${orderId.toString()}`);
|
|
2712
|
+
}
|
|
2713
|
+
const cancelOrderIx = await this.getCancelOrderIx(orderId);
|
|
2714
|
+
|
|
2715
|
+
const newOrderParams: OptionalOrderParams = {
|
|
2716
|
+
orderType: openOrder.orderType,
|
|
2717
|
+
marketType: openOrder.marketType,
|
|
2718
|
+
direction: openOrder.direction,
|
|
2719
|
+
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
2720
|
+
price: newLimitPrice || openOrder.price,
|
|
2721
|
+
marketIndex: openOrder.marketIndex,
|
|
2722
|
+
reduceOnly: openOrder.reduceOnly,
|
|
2723
|
+
postOnly: openOrder.postOnly,
|
|
2724
|
+
immediateOrCancel: openOrder.immediateOrCancel,
|
|
2725
|
+
triggerPrice: openOrder.triggerPrice,
|
|
2726
|
+
triggerCondition: openOrder.triggerCondition,
|
|
2727
|
+
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
2728
|
+
auctionDuration: openOrder.auctionDuration,
|
|
2729
|
+
maxTs: openOrder.maxTs,
|
|
2730
|
+
auctionStartPrice: openOrder.auctionStartPrice,
|
|
2731
|
+
auctionEndPrice: openOrder.auctionEndPrice,
|
|
2732
|
+
};
|
|
2733
|
+
const placeOrderIx = await this.getPlacePerpOrderIx(newOrderParams);
|
|
2734
|
+
|
|
2735
|
+
const tx = new Transaction();
|
|
2736
|
+
tx.add(
|
|
2737
|
+
ComputeBudgetProgram.requestUnits({
|
|
2738
|
+
units: 1_000_000,
|
|
2739
|
+
additionalFee: 0,
|
|
2740
|
+
})
|
|
2741
|
+
);
|
|
2742
|
+
tx.add(cancelOrderIx);
|
|
2743
|
+
tx.add(placeOrderIx);
|
|
2744
|
+
const { txSig, slot } = await this.txSender.send(tx, [], this.opts);
|
|
2745
|
+
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
2746
|
+
return txSig;
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2617
2749
|
public async settlePNLs(
|
|
2618
2750
|
users: {
|
|
2619
2751
|
settleeUserAccountPublicKey: PublicKey;
|
|
@@ -2680,6 +2812,7 @@ export class ClearingHouse {
|
|
|
2680
2812
|
state: await this.getStatePublicKey(),
|
|
2681
2813
|
authority: this.wallet.publicKey,
|
|
2682
2814
|
user: settleeUserAccountPublicKey,
|
|
2815
|
+
spotMarketVault: this.getQuoteSpotMarketAccount().vault,
|
|
2683
2816
|
},
|
|
2684
2817
|
remainingAccounts: remainingAccounts,
|
|
2685
2818
|
});
|
|
@@ -2689,7 +2822,8 @@ export class ClearingHouse {
|
|
|
2689
2822
|
userAccountPublicKey: PublicKey,
|
|
2690
2823
|
userAccount: UserAccount,
|
|
2691
2824
|
marketIndex: number,
|
|
2692
|
-
maxBaseAssetAmount: BN
|
|
2825
|
+
maxBaseAssetAmount: BN,
|
|
2826
|
+
limitPrice?: BN
|
|
2693
2827
|
): Promise<TransactionSignature> {
|
|
2694
2828
|
const { txSig, slot } = await this.txSender.send(
|
|
2695
2829
|
wrapInTx(
|
|
@@ -2697,13 +2831,14 @@ export class ClearingHouse {
|
|
|
2697
2831
|
userAccountPublicKey,
|
|
2698
2832
|
userAccount,
|
|
2699
2833
|
marketIndex,
|
|
2700
|
-
maxBaseAssetAmount
|
|
2834
|
+
maxBaseAssetAmount,
|
|
2835
|
+
limitPrice
|
|
2701
2836
|
)
|
|
2702
2837
|
),
|
|
2703
2838
|
[],
|
|
2704
2839
|
this.opts
|
|
2705
2840
|
);
|
|
2706
|
-
this.
|
|
2841
|
+
this.perpMarketLastSlotCache.set(marketIndex, slot);
|
|
2707
2842
|
return txSig;
|
|
2708
2843
|
}
|
|
2709
2844
|
|
|
@@ -2711,7 +2846,8 @@ export class ClearingHouse {
|
|
|
2711
2846
|
userAccountPublicKey: PublicKey,
|
|
2712
2847
|
userAccount: UserAccount,
|
|
2713
2848
|
marketIndex: number,
|
|
2714
|
-
maxBaseAssetAmount: BN
|
|
2849
|
+
maxBaseAssetAmount: BN,
|
|
2850
|
+
limitPrice?: BN
|
|
2715
2851
|
): Promise<TransactionInstruction> {
|
|
2716
2852
|
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
2717
2853
|
this.program.programId,
|
|
@@ -2730,6 +2866,7 @@ export class ClearingHouse {
|
|
|
2730
2866
|
return await this.program.instruction.liquidatePerp(
|
|
2731
2867
|
marketIndex,
|
|
2732
2868
|
maxBaseAssetAmount,
|
|
2869
|
+
limitPrice ?? null,
|
|
2733
2870
|
{
|
|
2734
2871
|
accounts: {
|
|
2735
2872
|
state: await this.getStatePublicKey(),
|
|
@@ -2751,7 +2888,7 @@ export class ClearingHouse {
|
|
|
2751
2888
|
liabilityMarketIndex: number,
|
|
2752
2889
|
maxLiabilityTransfer: BN
|
|
2753
2890
|
): Promise<TransactionSignature> {
|
|
2754
|
-
const { txSig } = await this.txSender.send(
|
|
2891
|
+
const { txSig, slot } = await this.txSender.send(
|
|
2755
2892
|
wrapInTx(
|
|
2756
2893
|
await this.getLiquidateSpotIx(
|
|
2757
2894
|
userAccountPublicKey,
|
|
@@ -2764,6 +2901,8 @@ export class ClearingHouse {
|
|
|
2764
2901
|
[],
|
|
2765
2902
|
this.opts
|
|
2766
2903
|
);
|
|
2904
|
+
this.spotMarketLastSlotCache.set(assetMarketIndex, slot);
|
|
2905
|
+
this.spotMarketLastSlotCache.set(liabilityMarketIndex, slot);
|
|
2767
2906
|
return txSig;
|
|
2768
2907
|
}
|
|
2769
2908
|
|
|
@@ -2826,7 +2965,8 @@ export class ClearingHouse {
|
|
|
2826
2965
|
[],
|
|
2827
2966
|
this.opts
|
|
2828
2967
|
);
|
|
2829
|
-
this.
|
|
2968
|
+
this.perpMarketLastSlotCache.set(perpMarketIndex, slot);
|
|
2969
|
+
this.spotMarketLastSlotCache.set(liabilityMarketIndex, slot);
|
|
2830
2970
|
return txSig;
|
|
2831
2971
|
}
|
|
2832
2972
|
|
|
@@ -2889,7 +3029,8 @@ export class ClearingHouse {
|
|
|
2889
3029
|
[],
|
|
2890
3030
|
this.opts
|
|
2891
3031
|
);
|
|
2892
|
-
this.
|
|
3032
|
+
this.perpMarketLastSlotCache.set(perpMarketIndex, slot);
|
|
3033
|
+
this.spotMarketLastSlotCache.set(assetMarketIndex, slot);
|
|
2893
3034
|
return txSig;
|
|
2894
3035
|
}
|
|
2895
3036
|
|
package/src/clearingHouseUser.ts
CHANGED
|
@@ -143,6 +143,7 @@ export class ClearingHouseUser {
|
|
|
143
143
|
marketIndex,
|
|
144
144
|
quoteAssetAmount: ZERO,
|
|
145
145
|
quoteEntryAmount: ZERO,
|
|
146
|
+
quoteBreakEvenAmount: ZERO,
|
|
146
147
|
openOrders: 0,
|
|
147
148
|
openBids: ZERO,
|
|
148
149
|
openAsks: ZERO,
|
|
@@ -773,30 +774,12 @@ export class ClearingHouseUser {
|
|
|
773
774
|
settledPosition.baseAssetAmount.add(dustBaa);
|
|
774
775
|
perpPosition.quoteAssetAmount = settledPosition.quoteAssetAmount;
|
|
775
776
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
openAsks = market.amm.maxBaseAssetReserve
|
|
780
|
-
.sub(market.amm.baseAssetReserve)
|
|
781
|
-
.mul(perpPosition.lpShares)
|
|
782
|
-
.div(market.amm.sqrtK)
|
|
783
|
-
.mul(new BN(-1));
|
|
784
|
-
} else {
|
|
785
|
-
openAsks = ZERO;
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
let openBids;
|
|
789
|
-
if (market.amm.minBaseAssetReserve < market.amm.baseAssetReserve) {
|
|
790
|
-
openBids = market.amm.baseAssetReserve
|
|
791
|
-
.sub(market.amm.minBaseAssetReserve)
|
|
792
|
-
.mul(perpPosition.lpShares)
|
|
793
|
-
.div(market.amm.sqrtK);
|
|
794
|
-
} else {
|
|
795
|
-
openBids = ZERO;
|
|
796
|
-
}
|
|
777
|
+
const [totalOpenBids, totalOpenAsks] = this.getPerpBidAsks(
|
|
778
|
+
market.marketIndex
|
|
779
|
+
);
|
|
797
780
|
|
|
798
|
-
perpPosition.openAsks =
|
|
799
|
-
perpPosition.openBids =
|
|
781
|
+
perpPosition.openAsks = totalOpenAsks;
|
|
782
|
+
perpPosition.openBids = totalOpenBids;
|
|
800
783
|
}
|
|
801
784
|
|
|
802
785
|
let valuationPrice = this.getOracleDataForPerpMarket(
|
|
@@ -1118,6 +1101,7 @@ export class ClearingHouseUser {
|
|
|
1118
1101
|
remainderBaseAssetAmount: 0,
|
|
1119
1102
|
quoteAssetAmount: new BN(0),
|
|
1120
1103
|
lastCumulativeFundingRate: ZERO,
|
|
1104
|
+
quoteBreakEvenAmount: new BN(0),
|
|
1121
1105
|
quoteEntryAmount: new BN(0),
|
|
1122
1106
|
openOrders: 0,
|
|
1123
1107
|
openBids: new BN(0),
|
|
@@ -1487,7 +1471,7 @@ export class ClearingHouseUser {
|
|
|
1487
1471
|
|
|
1488
1472
|
const amountWithdrawable = freeCollateral
|
|
1489
1473
|
.mul(MARGIN_PRECISION)
|
|
1490
|
-
.div(spotMarket.initialAssetWeight)
|
|
1474
|
+
.div(new BN(spotMarket.initialAssetWeight))
|
|
1491
1475
|
.mul(PRICE_PRECISION)
|
|
1492
1476
|
.div(oracleData.price)
|
|
1493
1477
|
.mul(precisionIncrease);
|
|
@@ -1526,7 +1510,7 @@ export class ClearingHouseUser {
|
|
|
1526
1510
|
|
|
1527
1511
|
const maxLiabilityAllowed = freeCollatAfterWithdraw
|
|
1528
1512
|
.mul(MARGIN_PRECISION)
|
|
1529
|
-
.div(spotMarket.initialLiabilityWeight)
|
|
1513
|
+
.div(new BN(spotMarket.initialLiabilityWeight))
|
|
1530
1514
|
.mul(PRICE_PRECISION)
|
|
1531
1515
|
.div(oracleData.price)
|
|
1532
1516
|
.mul(precisionIncrease);
|
package/src/config.ts
CHANGED
|
@@ -29,7 +29,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
|
|
|
29
29
|
devnet: {
|
|
30
30
|
ENV: 'devnet',
|
|
31
31
|
PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
|
|
32
|
-
CLEARING_HOUSE_PROGRAM_ID: '
|
|
32
|
+
CLEARING_HOUSE_PROGRAM_ID: 'jAEeKs9twxAJmXZHqS2p459xW7FMDjoyvuqthRo9qGS',
|
|
33
33
|
USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
|
|
34
34
|
SERUM_V3: 'DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY',
|
|
35
35
|
V2_ALPHA_TICKET_MINT_ADDRESS:
|
package/src/factory/bigNum.ts
CHANGED
|
@@ -9,6 +9,11 @@ export class BigNum {
|
|
|
9
9
|
static delim = '.';
|
|
10
10
|
static spacer = ',';
|
|
11
11
|
|
|
12
|
+
public static setLocale(locale: string): void {
|
|
13
|
+
BigNum.delim = (1.1).toLocaleString(locale).slice(1, 2) || '.';
|
|
14
|
+
BigNum.spacer = (1000).toLocaleString(locale).slice(1, 2) || ',';
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
constructor(
|
|
13
18
|
val: BN | number | string,
|
|
14
19
|
precisionVal: BN | number | string = new BN(0)
|
|
@@ -566,7 +571,21 @@ export class BigNum {
|
|
|
566
571
|
* @returns
|
|
567
572
|
*/
|
|
568
573
|
public toNum() {
|
|
569
|
-
|
|
574
|
+
let printedValue = this.print();
|
|
575
|
+
|
|
576
|
+
// Must convert any non-US delimiters and spacers to US format before using parseFloat
|
|
577
|
+
if (BigNum.delim !== '.' || BigNum.spacer !== ',') {
|
|
578
|
+
printedValue = printedValue
|
|
579
|
+
.split('')
|
|
580
|
+
.map((char) => {
|
|
581
|
+
if (char === BigNum.delim) return '.';
|
|
582
|
+
if (char === BigNum.spacer) return ',';
|
|
583
|
+
return char;
|
|
584
|
+
})
|
|
585
|
+
.join('');
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
return parseFloat(printedValue);
|
|
570
589
|
}
|
|
571
590
|
|
|
572
591
|
static fromJSON(json: { val: string; precision: string }) {
|
|
@@ -599,12 +618,16 @@ export class BigNum {
|
|
|
599
618
|
static fromPrint(val: string, precisionShift?: BN): BigNum {
|
|
600
619
|
// Handle empty number edge cases
|
|
601
620
|
if (!val) return BigNum.from(ZERO, precisionShift);
|
|
602
|
-
if (!val.replace(BigNum.delim, ''))
|
|
621
|
+
if (!val.replace(BigNum.delim, '')) {
|
|
603
622
|
return BigNum.from(ZERO, precisionShift);
|
|
623
|
+
}
|
|
604
624
|
|
|
605
|
-
const
|
|
625
|
+
const sides = val.split(BigNum.delim);
|
|
626
|
+
const rightSide = sides[1];
|
|
627
|
+
const leftSide = sides[0].replace(/\D/g, '');
|
|
628
|
+
const bnInput = `${leftSide ?? ''}${rightSide ?? ''}`;
|
|
606
629
|
|
|
607
|
-
const rawBn = new BN(
|
|
630
|
+
const rawBn = new BN(bnInput);
|
|
608
631
|
|
|
609
632
|
const rightSideLength = rightSide?.length ?? 0;
|
|
610
633
|
|