@drift-labs/sdk 0.1.36-master.6 → 0.1.36-master.7

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.
@@ -18,6 +18,7 @@ export declare function calculateBaseAssetValue(market: Market, userPosition: Us
18
18
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
19
19
  */
20
20
  export declare function calculatePositionPNL(market: Market, marketPosition: UserPosition, withFunding?: boolean): BN;
21
+ export declare function calculateSettledPositionPNL(market: Market, marketPosition: UserPosition): BN;
21
22
  /**
22
23
  *
23
24
  * @param market
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.calculatePositionFundingPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
3
+ exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateEntryPrice = exports.calculatePositionFundingPNL = exports.calculateSettledPositionPNL = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
4
4
  const __1 = require("../");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const types_1 = require("../types");
7
7
  const amm_1 = require("./amm");
8
+ const settlement_1 = require("../settlement");
8
9
  /**
9
10
  * calculateBaseAssetValue
10
11
  * = market value of closing entire position
@@ -60,6 +61,23 @@ function calculatePositionPNL(market, marketPosition, withFunding = false) {
60
61
  return pnl;
61
62
  }
62
63
  exports.calculatePositionPNL = calculatePositionPNL;
64
+ function calculateSettledPositionPNL(market, marketPosition) {
65
+ let pnl = calculatePositionPNL(market, marketPosition);
66
+ if (pnl.gt(numericConstants_1.ZERO)) {
67
+ try {
68
+ pnl = pnl
69
+ .mul(new __1.BN(settlement_1.SETTLEMENT_RATIOS[marketPosition.marketIndex.toNumber()]))
70
+ .div(settlement_1.SETTLEMENT_RATIO_PRECISION);
71
+ }
72
+ catch (e) {
73
+ console.log(pnl.toString());
74
+ console.log(marketPosition.marketIndex.toNumber());
75
+ throw e;
76
+ }
77
+ }
78
+ return pnl;
79
+ }
80
+ exports.calculateSettledPositionPNL = calculateSettledPositionPNL;
63
81
  /**
64
82
  *
65
83
  * @param market
@@ -0,0 +1,4 @@
1
+ /// <reference types="bn.js" />
2
+ import { BN } from '@project-serum/anchor';
3
+ export declare const SETTLEMENT_RATIO_PRECISION: BN;
4
+ export declare const SETTLEMENT_RATIOS: number[];
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SETTLEMENT_RATIOS = exports.SETTLEMENT_RATIO_PRECISION = void 0;
4
+ const anchor_1 = require("@project-serum/anchor");
5
+ exports.SETTLEMENT_RATIO_PRECISION = new anchor_1.BN(1000000);
6
+ exports.SETTLEMENT_RATIOS = [
7
+ 291786, 243613, 712271, 293771, 555181, 604938, 241133, 218489, 251741,
8
+ 883058, 51614, 531737, 956092, 106424, 727107, 477277, 217325, 127477, 248561,
9
+ 565938, 59349,
10
+ ];
package/lib/types.d.ts CHANGED
@@ -275,6 +275,12 @@ export declare type OrderStateAccount = {
275
275
  orderFillerRewardStructure: OrderFillerRewardStructure;
276
276
  minOrderQuoteAssetAmount: BN;
277
277
  };
278
+ export declare type SettlementStateAccount = {
279
+ totalSettlementValue: BN;
280
+ collateralAvailableToClaim: BN;
281
+ collateralClaimed: BN;
282
+ enabled: boolean;
283
+ };
278
284
  export declare type MarketsAccount = {
279
285
  markets: Market[];
280
286
  };
@@ -337,6 +343,11 @@ export declare type UserAccount = {
337
343
  totalTokenDiscount: BN;
338
344
  totalReferralReward: BN;
339
345
  totalRefereeDiscount: BN;
346
+ settledPositionValue: BN;
347
+ collateralClaimed: BN;
348
+ lastCollateralAvailableToClaim: BN;
349
+ forgoPositionSettlement: number;
350
+ hasSettledPosition: number;
340
351
  };
341
352
  export declare type UserOrdersAccount = {
342
353
  orders: Order[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.1.36-master.6",
3
+ "version": "0.1.36-master.7",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
package/src/addresses.ts CHANGED
@@ -69,3 +69,14 @@ export async function getUserOrdersAccountPublicKey(
69
69
  await getUserOrdersAccountPublicKeyAndNonce(programId, userAccount)
70
70
  )[0];
71
71
  }
72
+
73
+ export async function getSettlementStatePublicKey(
74
+ programId: PublicKey
75
+ ): Promise<PublicKey> {
76
+ return (
77
+ await anchor.web3.PublicKey.findProgramAddress(
78
+ [Buffer.from(anchor.utils.bytes.utf8.encode('settlement_state'))],
79
+ programId
80
+ )
81
+ )[0];
82
+ }
package/src/admin.ts CHANGED
@@ -18,6 +18,8 @@ import {
18
18
  getClearingHouseStateAccountPublicKey,
19
19
  getClearingHouseStateAccountPublicKeyAndNonce,
20
20
  getOrderStateAccountPublicKeyAndNonce,
21
+ getSettlementStatePublicKey,
22
+ getUserAccountPublicKey,
21
23
  } from './addresses';
22
24
  import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
23
25
  import { ClearingHouse } from './clearingHouse';
@@ -733,4 +735,85 @@ export class Admin extends ClearingHouse {
733
735
  },
734
736
  });
735
737
  }
738
+
739
+ public async transferFromInsuranceVaultToCollateralVault(): Promise<TransactionSignature> {
740
+ const state = await this.getStateAccount();
741
+ return await this.program.rpc.transferFromInsuranceVaultToCollateralVault({
742
+ accounts: {
743
+ admin: this.wallet.publicKey,
744
+ state: await this.getStatePublicKey(),
745
+ insuranceVault: state.insuranceVault,
746
+ insuranceVaultAuthority: state.insuranceVaultAuthority,
747
+ collateralVault: state.collateralVault,
748
+ tokenProgram: TOKEN_PROGRAM_ID,
749
+ },
750
+ });
751
+ }
752
+
753
+ public async adminUpdateUserForgoSettlement(
754
+ authority: PublicKey
755
+ ): Promise<TransactionSignature> {
756
+ const user = await getUserAccountPublicKey(
757
+ this.program.programId,
758
+ authority
759
+ );
760
+
761
+ return await this.program.rpc.adminUpdateUserForgoSettlement({
762
+ accounts: {
763
+ admin: this.wallet.publicKey,
764
+ state: await this.getStatePublicKey(),
765
+ user: user,
766
+ },
767
+ });
768
+ }
769
+
770
+ public async initializeSettlementState(): Promise<TransactionSignature> {
771
+ const settlementState = await getSettlementStatePublicKey(
772
+ this.program.programId
773
+ );
774
+
775
+ const settlementSize = await this.getTotalSettlementSize();
776
+
777
+ return await this.program.rpc.initializeSettlementState(settlementSize, {
778
+ accounts: {
779
+ admin: this.wallet.publicKey,
780
+ state: await this.getStatePublicKey(),
781
+ settlementState: settlementState,
782
+ rent: SYSVAR_RENT_PUBKEY,
783
+ systemProgram: anchor.web3.SystemProgram.programId,
784
+ collateralVault: (await this.getStateAccount()).collateralVault,
785
+ },
786
+ });
787
+ }
788
+
789
+ public async updateSettlementState(): Promise<TransactionSignature> {
790
+ const settlementState = await getSettlementStatePublicKey(
791
+ this.program.programId
792
+ );
793
+
794
+ return await this.program.rpc.updateSettlementState({
795
+ accounts: {
796
+ admin: this.wallet.publicKey,
797
+ state: await this.getStatePublicKey(),
798
+ settlementState: settlementState,
799
+ collateralVault: (await this.getStateAccount()).collateralVault,
800
+ },
801
+ });
802
+ }
803
+
804
+ public async updateSettlementStateEnabled(
805
+ enabled: boolean
806
+ ): Promise<TransactionSignature> {
807
+ const settlementState = await getSettlementStatePublicKey(
808
+ this.program.programId
809
+ );
810
+
811
+ return await this.program.rpc.updateSettlementStateEnabled(enabled, {
812
+ accounts: {
813
+ admin: this.wallet.publicKey,
814
+ state: await this.getStatePublicKey(),
815
+ settlementState: settlementState,
816
+ },
817
+ });
818
+ }
736
819
  }
@@ -22,6 +22,7 @@ import {
22
22
  Order,
23
23
  ExtendedCurveHistoryAccount,
24
24
  UserPositionsAccount,
25
+ SettlementStateAccount,
25
26
  } from './types';
26
27
  import * as anchor from '@project-serum/anchor';
27
28
  import clearingHouseIDL from './idl/clearing_house.json';
@@ -42,6 +43,7 @@ import StrictEventEmitter from 'strict-event-emitter-types';
42
43
  import {
43
44
  getClearingHouseStateAccountPublicKey,
44
45
  getOrderStateAccountPublicKey,
46
+ getSettlementStatePublicKey,
45
47
  getUserAccountPublicKey,
46
48
  getUserAccountPublicKeyAndNonce,
47
49
  getUserOrdersAccountPublicKey,
@@ -56,9 +58,17 @@ import { TxSender } from './tx/types';
56
58
  import { wrapInTx } from './tx/utils';
57
59
  import {
58
60
  getClearingHouse,
61
+ getPollingClearingHouseConfig,
59
62
  getWebSocketClearingHouseConfig,
60
63
  } from './factory/clearingHouse';
61
64
  import { ZERO } from './constants/numericConstants';
65
+ import { BulkAccountLoader } from './accounts/bulkAccountLoader';
66
+ import { ClearingHouseUser } from './clearingHouseUser';
67
+ import {
68
+ getClearingHouseUser,
69
+ getPollingClearingHouseUserConfig,
70
+ } from './factory/clearingHouseUser';
71
+ import { bulkPollingUserSubscribe } from './accounts/bulkUserSubscription';
62
72
 
63
73
  /**
64
74
  * # ClearingHouse
@@ -186,6 +196,13 @@ export class ClearingHouse {
186
196
  return this.accountSubscriber.getStateAccount();
187
197
  }
188
198
 
199
+ public async getSettlementAccount(): Promise<SettlementStateAccount> {
200
+ // @ts-ignore
201
+ return await this.program.account.settlementState.fetch(
202
+ await getSettlementStatePublicKey(this.program.programId)
203
+ );
204
+ }
205
+
189
206
  public getMarketsAccount(): MarketsAccount {
190
207
  return this.accountSubscriber.getMarketsAccount();
191
208
  }
@@ -1405,4 +1422,122 @@ export class ClearingHouse {
1405
1422
  public triggerEvent(eventName: keyof ClearingHouseAccountEvents, data?: any) {
1406
1423
  this.eventEmitter.emit(eventName, data);
1407
1424
  }
1425
+
1426
+ public async settlePositionAndClaimCollateral(
1427
+ collateralAccountPublicKey: PublicKey
1428
+ ): Promise<TransactionSignature> {
1429
+ const settlePositionIx = await this.getSettlePositionIx();
1430
+ const claimCollateralIx = await this.getClaimCollateralIx(
1431
+ collateralAccountPublicKey
1432
+ );
1433
+ const tx = new Transaction().add(settlePositionIx).add(claimCollateralIx);
1434
+
1435
+ return this.txSender.send(tx, [], this.opts);
1436
+ }
1437
+
1438
+ public async getSettlePositionIx(): Promise<TransactionInstruction> {
1439
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
1440
+ const user: any = await this.program.account.user.fetch(
1441
+ userAccountPublicKey
1442
+ );
1443
+ const state = this.getStateAccount();
1444
+
1445
+ const settlementState = await getSettlementStatePublicKey(
1446
+ this.program.programId
1447
+ );
1448
+
1449
+ return await this.program.instruction.settlePosition({
1450
+ accounts: {
1451
+ state: await this.getStatePublicKey(),
1452
+ user: userAccountPublicKey,
1453
+ markets: state.markets,
1454
+ authority: this.wallet.publicKey,
1455
+ userPositions: user.positions,
1456
+ settlementState,
1457
+ fundingPaymentHistory: state.fundingPaymentHistory,
1458
+ },
1459
+ });
1460
+ }
1461
+
1462
+ public async getClaimCollateralIx(
1463
+ collateralAccountPublicKey: PublicKey
1464
+ ): Promise<TransactionInstruction> {
1465
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
1466
+ const state = this.getStateAccount();
1467
+
1468
+ const settlementState = await getSettlementStatePublicKey(
1469
+ this.program.programId
1470
+ );
1471
+
1472
+ return await this.program.instruction.claimCollateral({
1473
+ accounts: {
1474
+ state: await this.getStatePublicKey(),
1475
+ user: userAccountPublicKey,
1476
+ collateralVault: state.collateralVault,
1477
+ collateralVaultAuthority: state.collateralVaultAuthority,
1478
+ userCollateralAccount: collateralAccountPublicKey,
1479
+ authority: this.wallet.publicKey,
1480
+ tokenProgram: TOKEN_PROGRAM_ID,
1481
+ settlementState,
1482
+ },
1483
+ });
1484
+ }
1485
+
1486
+ public async getTotalSettlementSize(): Promise<BN> {
1487
+ const accountLoader = new BulkAccountLoader(
1488
+ this.connection,
1489
+ 'processed',
1490
+ 50000
1491
+ );
1492
+ const clearingHouse = getClearingHouse(
1493
+ getPollingClearingHouseConfig(
1494
+ this.connection,
1495
+ this.wallet,
1496
+ this.program.programId,
1497
+ accountLoader
1498
+ )
1499
+ );
1500
+
1501
+ console.log('loading all users');
1502
+ const programUserAccounts =
1503
+ (await this.program.account.user.all()) as any[];
1504
+ const userArray: ClearingHouseUser[] = [];
1505
+ for (const programUserAccount of programUserAccounts) {
1506
+ const user = getClearingHouseUser(
1507
+ getPollingClearingHouseUserConfig(
1508
+ clearingHouse,
1509
+ programUserAccount.account.authority,
1510
+ accountLoader
1511
+ )
1512
+ );
1513
+ userArray.push(user);
1514
+ }
1515
+
1516
+ console.log('subscribing all users');
1517
+ await bulkPollingUserSubscribe(userArray, accountLoader);
1518
+
1519
+ console.log('calculating settlement size');
1520
+ const settlementSize = userArray.reduce((collateralToBeSettled, user) => {
1521
+ return collateralToBeSettled.add(
1522
+ user.getUserAccount().forgoPositionSettlement === 0
1523
+ ? user.getSettledPositionValue()
1524
+ : ZERO
1525
+ );
1526
+ }, ZERO);
1527
+
1528
+ for (const user of userArray) {
1529
+ await user.unsubscribe();
1530
+ }
1531
+
1532
+ return settlementSize;
1533
+ }
1534
+
1535
+ public async updateUserForgoSettlement(): Promise<TransactionSignature> {
1536
+ return await this.program.rpc.updateUserForgoSettlement({
1537
+ accounts: {
1538
+ authority: this.wallet.publicKey,
1539
+ user: await this.getUserAccountPublicKey(),
1540
+ },
1541
+ });
1542
+ }
1408
1543
  }
@@ -6,12 +6,16 @@ import {
6
6
  isVariant,
7
7
  MarginCategory,
8
8
  Order,
9
+ SettlementStateAccount,
9
10
  UserAccount,
10
11
  UserOrdersAccount,
11
12
  UserPosition,
12
13
  UserPositionsAccount,
13
14
  } from './types';
14
- import { calculateEntryPrice } from './math/position';
15
+ import {
16
+ calculateEntryPrice,
17
+ calculateSettledPositionPNL,
18
+ } from './math/position';
15
19
  import {
16
20
  MARK_PRICE_PRECISION,
17
21
  AMM_TO_QUOTE_PRECISION_RATIO,
@@ -833,4 +837,63 @@ export class ClearingHouseUser {
833
837
 
834
838
  return this.getTotalPositionValue().sub(currentMarketPositionValueUSDC);
835
839
  }
840
+
841
+ public getClaimableCollateral(settlementState: SettlementStateAccount): BN {
842
+ return this.getSettledPositionValue()
843
+ .mul(
844
+ settlementState.collateralAvailableToClaim.sub(
845
+ this.getUserAccount().lastCollateralAvailableToClaim
846
+ )
847
+ )
848
+ .div(settlementState.totalSettlementValue);
849
+ }
850
+
851
+ public getSettledPositionValue(): BN {
852
+ return BN.max(
853
+ this.getUserAccount()
854
+ .collateral.add(
855
+ this.getUnrealizedFundingPNL().div(PRICE_TO_QUOTE_PRECISION)
856
+ )
857
+ .add(this.getSettledPositionsPNL()),
858
+ ZERO
859
+ );
860
+ }
861
+
862
+ public getSettledPositionsPNL(): BN {
863
+ return this.getUserPositionsAccount().positions.reduce(
864
+ (pnl, marketPosition) => {
865
+ const market = this.clearingHouse.getMarket(marketPosition.marketIndex);
866
+ return pnl.add(calculateSettledPositionPNL(market, marketPosition));
867
+ },
868
+ ZERO
869
+ );
870
+ }
871
+
872
+ public async estimateClaimableCollateral(): Promise<BN> {
873
+ const currentCollateralVaultBalance = new BN(
874
+ (
875
+ await this.clearingHouse.connection.getTokenAccountBalance(
876
+ this.clearingHouse.getStateAccount().collateralVault
877
+ )
878
+ ).value.amount
879
+ );
880
+ const currentInsuranceVaultBalance = new BN(
881
+ (
882
+ await this.clearingHouse.connection.getTokenAccountBalance(
883
+ this.clearingHouse.getStateAccount().insuranceVault
884
+ )
885
+ ).value.amount
886
+ );
887
+
888
+ const totalClaimableCollateral = currentCollateralVaultBalance.add(
889
+ currentInsuranceVaultBalance
890
+ );
891
+ const totalEstimatedSettlementValue =
892
+ await this.clearingHouse.getTotalSettlementSize();
893
+ const userSettledPositionValue = await this.getSettledPositionValue();
894
+
895
+ return totalClaimableCollateral
896
+ .mul(userSettledPositionValue)
897
+ .div(totalEstimatedSettlementValue);
898
+ }
836
899
  }