@drift-labs/sdk 0.2.0-master.27 → 0.2.0-master.29

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.
@@ -29,4 +29,5 @@ export declare function calculateOracleSpread(price: BN, oraclePriceData: Oracle
29
29
  export declare function calculateMarketMarginRatio(market: PerpMarketAccount, size: BN, marginCategory: MarginCategory): number;
30
30
  export declare function calculateUnrealizedAssetWeight(market: PerpMarketAccount, quoteSpotMarket: SpotMarketAccount, unrealizedPnl: BN, marginCategory: MarginCategory, oraclePriceData: OraclePriceData): BN;
31
31
  export declare function calculateMarketAvailablePNL(perpMarket: PerpMarketAccount, spotMarket: SpotMarketAccount): BN;
32
- export declare function calculateNetUserImbalance(market: PerpMarketAccount, bank: SpotMarketAccount, oraclePriceData: OraclePriceData): BN;
32
+ export declare function calculateNetUserPnl(perpMarket: PerpMarketAccount, oraclePriceData: OraclePriceData): BN;
33
+ export declare function calculateNetUserPnlImbalance(perpMarket: PerpMarketAccount, spotMarket: SpotMarketAccount, oraclePriceData: OraclePriceData): BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateNetUserImbalance = exports.calculateMarketAvailablePNL = exports.calculateUnrealizedAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateMarkOracleSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateMarkPrice = void 0;
3
+ exports.calculateNetUserPnlImbalance = exports.calculateNetUserPnl = exports.calculateMarketAvailablePNL = exports.calculateUnrealizedAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateMarkOracleSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateMarkPrice = void 0;
4
4
  const anchor_1 = require("@project-serum/anchor");
5
5
  const types_1 = require("../types");
6
6
  const amm_1 = require("./amm");
@@ -78,7 +78,7 @@ function calculateUnrealizedAssetWeight(market, quoteSpotMarket, unrealizedPnl,
78
78
  case 'Initial':
79
79
  assetWeight = new anchor_1.BN(market.unrealizedInitialAssetWeight);
80
80
  if (market.unrealizedMaxImbalance.gt(numericConstants_1.ZERO)) {
81
- const netUnsettledPnl = calculateNetUserImbalance(market, quoteSpotMarket, oraclePriceData);
81
+ const netUnsettledPnl = calculateNetUserPnlImbalance(market, quoteSpotMarket, oraclePriceData);
82
82
  if (netUnsettledPnl.gt(market.unrealizedMaxImbalance)) {
83
83
  assetWeight = assetWeight
84
84
  .mul(market.unrealizedMaxImbalance)
@@ -98,17 +98,22 @@ function calculateMarketAvailablePNL(perpMarket, spotMarket) {
98
98
  return (0, spotBalance_1.getTokenAmount)(perpMarket.pnlPool.balance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
99
99
  }
100
100
  exports.calculateMarketAvailablePNL = calculateMarketAvailablePNL;
101
- function calculateNetUserImbalance(market, bank, oraclePriceData) {
102
- const netUserPositionValue = market.amm.netBaseAssetAmount
101
+ function calculateNetUserPnl(perpMarket, oraclePriceData) {
102
+ const netUserPositionValue = perpMarket.amm.netBaseAssetAmount
103
103
  .mul(oraclePriceData.price)
104
104
  .div(numericConstants_1.BASE_PRECISION)
105
105
  .div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
106
- const netUserCostBasis = market.amm.quoteAssetAmountLong
107
- .add(market.amm.quoteAssetAmountShort)
108
- .sub(market.amm.cumulativeSocialLoss);
109
- const userEntitledPnl = netUserPositionValue.add(netUserCostBasis);
110
- const pnlPool = (0, spotBalance_1.getTokenAmount)(market.pnlPool.balance, bank, types_1.SpotBalanceType.DEPOSIT);
111
- const imbalance = userEntitledPnl.sub(pnlPool);
106
+ const netUserCostBasis = perpMarket.amm.quoteAssetAmountLong
107
+ .add(perpMarket.amm.quoteAssetAmountShort)
108
+ .sub(perpMarket.amm.cumulativeSocialLoss);
109
+ const netUserPnl = netUserPositionValue.add(netUserCostBasis);
110
+ return netUserPnl;
111
+ }
112
+ exports.calculateNetUserPnl = calculateNetUserPnl;
113
+ function calculateNetUserPnlImbalance(perpMarket, spotMarket, oraclePriceData) {
114
+ const netUserPnl = calculateNetUserPnl(perpMarket, oraclePriceData);
115
+ const pnlPool = (0, spotBalance_1.getTokenAmount)(perpMarket.pnlPool.balance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
116
+ const imbalance = netUserPnl.sub(pnlPool);
112
117
  return imbalance;
113
118
  }
114
- exports.calculateNetUserImbalance = calculateNetUserImbalance;
119
+ exports.calculateNetUserPnlImbalance = calculateNetUserPnlImbalance;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="bn.js" />
2
- import { BN } from '../';
2
+ import { BN, SpotMarketAccount } from '../';
3
3
  import { OraclePriceData } from '../oracles/types';
4
4
  import { PerpMarketAccount, PositionDirection, PerpPosition } from '../types';
5
5
  /**
@@ -10,7 +10,7 @@ import { PerpMarketAccount, PositionDirection, PerpPosition } from '../types';
10
10
  * @param oraclePriceData
11
11
  * @returns Base Asset Value. : Precision QUOTE_PRECISION
12
12
  */
13
- export declare function calculateBaseAssetValue(market: PerpMarketAccount, userPosition: PerpPosition, oraclePriceData: OraclePriceData): BN;
13
+ export declare function calculateBaseAssetValue(market: PerpMarketAccount, userPosition: PerpPosition, oraclePriceData: OraclePriceData, useSpread?: boolean, skipUpdate?: boolean): BN;
14
14
  /**
15
15
  * calculatePositionPNL
16
16
  * = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
@@ -21,7 +21,7 @@ export declare function calculateBaseAssetValue(market: PerpMarketAccount, userP
21
21
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
22
22
  */
23
23
  export declare function calculatePositionPNL(market: PerpMarketAccount, perpPosition: PerpPosition, withFunding: boolean, oraclePriceData: OraclePriceData): BN;
24
- export declare function calculateUnsettledPnl(market: PerpMarketAccount, perpPosition: PerpPosition, oraclePriceData: OraclePriceData): BN;
24
+ export declare function calculateClaimablePnl(market: PerpMarketAccount, spotMarket: SpotMarketAccount, perpPosition: PerpPosition, oraclePriceData: OraclePriceData): BN;
25
25
  /**
26
26
  *
27
27
  * @param market
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateUnsettledPnl = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
3
+ exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateClaimablePnl = 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
8
  const margin_1 = require("./margin");
9
+ const market_1 = require("./market");
9
10
  /**
10
11
  * calculateBaseAssetValue
11
12
  * = market value of closing entire position
@@ -14,23 +15,28 @@ const margin_1 = require("./margin");
14
15
  * @param oraclePriceData
15
16
  * @returns Base Asset Value. : Precision QUOTE_PRECISION
16
17
  */
17
- function calculateBaseAssetValue(market, userPosition, oraclePriceData) {
18
+ function calculateBaseAssetValue(market, userPosition, oraclePriceData, useSpread = true, skipUpdate = false) {
18
19
  if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
19
20
  return numericConstants_1.ZERO;
20
21
  }
21
22
  const directionToClose = findDirectionToClose(userPosition);
22
23
  let prepegAmm;
23
- if (market.amm.baseSpread > 0) {
24
- const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, directionToClose, oraclePriceData);
25
- prepegAmm = {
26
- baseAssetReserve,
27
- quoteAssetReserve,
28
- sqrtK: sqrtK,
29
- pegMultiplier: newPeg,
30
- };
24
+ if (!skipUpdate) {
25
+ if (market.amm.baseSpread > 0 && useSpread) {
26
+ const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, directionToClose, oraclePriceData);
27
+ prepegAmm = {
28
+ baseAssetReserve,
29
+ quoteAssetReserve,
30
+ sqrtK: sqrtK,
31
+ pegMultiplier: newPeg,
32
+ };
33
+ }
34
+ else {
35
+ prepegAmm = (0, amm_1.calculateUpdatedAMM)(market.amm, oraclePriceData);
36
+ }
31
37
  }
32
38
  else {
33
- prepegAmm = (0, amm_1.calculateUpdatedAMM)(market.amm, oraclePriceData);
39
+ prepegAmm = market.amm;
34
40
  }
35
41
  const [newQuoteAssetReserve, _] = (0, amm_1.calculateAmmReservesAfterSwap)(prepegAmm, 'base', userPosition.baseAssetAmount.abs(), (0, amm_1.getSwapDirection)('base', directionToClose));
36
42
  switch (directionToClose) {
@@ -75,19 +81,20 @@ function calculatePositionPNL(market, perpPosition, withFunding = false, oracleP
75
81
  return pnl;
76
82
  }
77
83
  exports.calculatePositionPNL = calculatePositionPNL;
78
- function calculateUnsettledPnl(market, perpPosition, oraclePriceData) {
84
+ function calculateClaimablePnl(market, spotMarket, perpPosition, oraclePriceData) {
79
85
  const unrealizedPnl = calculatePositionPNL(market, perpPosition, true, oraclePriceData);
80
- let unsettledPnl = unrealizedPnl;
86
+ const fundingPnL = calculatePositionFundingPNL(market, perpPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
87
+ let unsettledPnl = unrealizedPnl.add(fundingPnL);
81
88
  if (unrealizedPnl.gt(numericConstants_1.ZERO)) {
82
- const fundingPnL = calculatePositionFundingPNL(market, perpPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
89
+ const excessPnlPool = __1.BN.max(numericConstants_1.ZERO, (0, market_1.calculateNetUserPnlImbalance)(market, spotMarket, oraclePriceData).mul(new __1.BN(-1)));
83
90
  const maxPositivePnl = __1.BN.max(perpPosition.quoteAssetAmount
84
91
  .sub(perpPosition.quoteEntryAmount)
85
- .add(fundingPnL), numericConstants_1.ZERO);
92
+ .add(excessPnlPool), numericConstants_1.ZERO);
86
93
  unsettledPnl = __1.BN.min(maxPositivePnl, unrealizedPnl);
87
94
  }
88
95
  return unsettledPnl;
89
96
  }
90
- exports.calculateUnsettledPnl = calculateUnsettledPnl;
97
+ exports.calculateClaimablePnl = calculateClaimablePnl;
91
98
  /**
92
99
  *
93
100
  * @param market
package/lib/math/repeg.js CHANGED
@@ -71,6 +71,14 @@ function calculateBudgetedKBN(x, y, budget, Q, d) {
71
71
  .div(numericConstants_1.AMM_RESERVE_PRECISION)
72
72
  .div(numericConstants_1.QUOTE_PRECISION);
73
73
  const denom2 = pegged_y_d_d;
74
+ // protocol is spending to increase k
75
+ if (C.lt(numericConstants_1.ZERO)) {
76
+ // thus denom1 is negative and solution is unstable
77
+ if (denom1.lt(pegged_y_d_d.abs())) {
78
+ console.log('budget cost exceeds stable K solution');
79
+ return [new anchor_1.BN(10000), new anchor_1.BN(1)];
80
+ }
81
+ }
74
82
  const numerator = numer1.sub(numer2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
75
83
  const denominator = denom1.add(denom2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
76
84
  return [numerator, denominator];
package/lib/types.d.ts CHANGED
@@ -419,8 +419,6 @@ export declare type StateAccount = {
419
419
  exchangePaused: boolean;
420
420
  adminControlsPrices: boolean;
421
421
  insuranceVault: PublicKey;
422
- perpFeeStructure: FeeStructure;
423
- spotFeeStructure: FeeStructure;
424
422
  totalFee: BN;
425
423
  totalFeeWithdrawn: BN;
426
424
  whitelistMint: PublicKey;
@@ -436,6 +434,8 @@ export declare type StateAccount = {
436
434
  minPerpAuctionDuration: number;
437
435
  defaultSpotAuctionDuration: number;
438
436
  liquidationMarginBufferRatio: number;
437
+ perpFeeStructure: FeeStructure;
438
+ spotFeeStructure: FeeStructure;
439
439
  };
440
440
  export declare type PerpMarketAccount = {
441
441
  status: MarketStatus;
@@ -581,7 +581,7 @@ export declare type PerpPosition = {
581
581
  openOrders: BN;
582
582
  openBids: BN;
583
583
  openAsks: BN;
584
- realizedPnl: BN;
584
+ settledPnl: BN;
585
585
  lpShares: BN;
586
586
  lastFeePerLp: BN;
587
587
  lastNetBaseAssetAmountPerLp: BN;
@@ -605,10 +605,11 @@ export declare type UserStatsAccount = {
605
605
  isReferrer: boolean;
606
606
  totalReferrerReward: BN;
607
607
  authority: PublicKey;
608
- quoteAssetInsuranceFundStake: BN;
608
+ stakedQuoteAssetAmount: BN;
609
609
  };
610
610
  export declare type UserAccount = {
611
611
  authority: PublicKey;
612
+ delegate: PublicKey;
612
613
  name: number[];
613
614
  userId: number;
614
615
  spotPositions: SpotPosition[];
@@ -733,40 +734,27 @@ export interface IWallet {
733
734
  publicKey: PublicKey;
734
735
  }
735
736
  export declare type FeeStructure = {
736
- feeNumerator: BN;
737
- feeDenominator: BN;
738
- discountTokenTiers: {
739
- firstTier: {
740
- minimumBalance: BN;
741
- discountNumerator: BN;
742
- discountDenominator: BN;
743
- };
744
- secondTier: {
745
- minimumBalance: BN;
746
- discountNumerator: BN;
747
- discountDenominator: BN;
748
- };
749
- thirdTier: {
750
- minimumBalance: BN;
751
- discountNumerator: BN;
752
- discountDenominator: BN;
753
- };
754
- fourthTier: {
755
- minimumBalance: BN;
756
- discountNumerator: BN;
757
- discountDenominator: BN;
758
- };
759
- };
760
- referralDiscount: {
761
- referrerRewardNumerator: BN;
762
- referrerRewardDenominator: BN;
763
- refereeDiscountNumerator: BN;
764
- refereeDiscountDenominator: BN;
765
- };
737
+ feeTiers: FeeTier[];
766
738
  makerRebateNumerator: BN;
767
739
  makerRebateDenominator: BN;
768
740
  fillerRewardStructure: OrderFillerRewardStructure;
769
741
  flatFillerFee: BN;
742
+ referrerRewardEpochUpperBound: BN;
743
+ };
744
+ export declare type FeeTier = {
745
+ feeNumerator: number;
746
+ feeDenominator: number;
747
+ makerRebateNumerator: number;
748
+ makerRebateDenominator: number;
749
+ referrerRewardNumerator: number;
750
+ referrerRewardDenominator: number;
751
+ refereeFeeNumerator: number;
752
+ refereeFeeDenominator: number;
753
+ };
754
+ export declare type OrderFillerRewardStructure = {
755
+ rewardNumerator: BN;
756
+ rewardDenominator: BN;
757
+ timeBasedRewardLowerBound: BN;
770
758
  };
771
759
  export declare type OracleGuardRails = {
772
760
  priceDivergence: {
@@ -780,11 +768,6 @@ export declare type OracleGuardRails = {
780
768
  };
781
769
  useForLiquidations: boolean;
782
770
  };
783
- export declare type OrderFillerRewardStructure = {
784
- rewardNumerator: BN;
785
- rewardDenominator: BN;
786
- timeBasedRewardLowerBound: BN;
787
- };
788
771
  export declare type MarginCategory = 'Initial' | 'Maintenance';
789
772
  export declare type InsuranceFundStake = {
790
773
  marketIndex: BN;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.2.0-master.27",
3
+ "version": "0.2.0-master.29",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
package/src/admin.ts CHANGED
@@ -3,12 +3,7 @@ import {
3
3
  SYSVAR_RENT_PUBKEY,
4
4
  TransactionSignature,
5
5
  } from '@solana/web3.js';
6
- import {
7
- FeeStructure,
8
- OracleGuardRails,
9
- OracleSource,
10
- OrderFillerRewardStructure,
11
- } from './types';
6
+ import { FeeStructure, OracleGuardRails, OracleSource } from './types';
12
7
  import { BN } from '@project-serum/anchor';
13
8
  import * as anchor from '@project-serum/anchor';
14
9
  import {
@@ -278,7 +273,7 @@ export class Admin extends ClearingHouse {
278
273
  marketIndex: BN,
279
274
  concentrationScale: BN
280
275
  ): Promise<TransactionSignature> {
281
- return await this.program.rpc.updateConcentrationScale(concentrationScale, {
276
+ return await this.program.rpc.updateConcentrationCoef(concentrationScale, {
282
277
  accounts: {
283
278
  state: await this.getStatePublicKey(),
284
279
  admin: this.wallet.publicKey,
@@ -611,22 +606,21 @@ export class Admin extends ClearingHouse {
611
606
  );
612
607
  }
613
608
 
614
- public async updateOrderFillerRewardStructure(
615
- orderFillerRewardStructure: OrderFillerRewardStructure
609
+ public async updatePerpFeeStructure(
610
+ feeStructure: FeeStructure
616
611
  ): Promise<TransactionSignature> {
617
- return await this.program.rpc.updateOrderFillerRewardStructure(
618
- orderFillerRewardStructure,
619
- {
620
- accounts: {
621
- admin: this.wallet.publicKey,
622
- state: await this.getStatePublicKey(),
623
- },
624
- }
625
- );
612
+ return await this.program.rpc.updatePerpFeeStructure(feeStructure, {
613
+ accounts: {
614
+ admin: this.wallet.publicKey,
615
+ state: await this.getStatePublicKey(),
616
+ },
617
+ });
626
618
  }
627
619
 
628
- public async updateFee(fees: FeeStructure): Promise<TransactionSignature> {
629
- return await this.program.rpc.updateFee(fees, {
620
+ public async updateSpotFeeStructure(
621
+ feeStructure: FeeStructure
622
+ ): Promise<TransactionSignature> {
623
+ return await this.program.rpc.updateSpotFeeStructure(feeStructure, {
630
624
  accounts: {
631
625
  admin: this.wallet.publicKey,
632
626
  state: await this.getStatePublicKey(),
@@ -1,5 +1,10 @@
1
1
  import { AnchorProvider, BN, Idl, Program } from '@project-serum/anchor';
2
- import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
2
+ import bs58 from 'bs58';
3
+ import {
4
+ ASSOCIATED_TOKEN_PROGRAM_ID,
5
+ Token,
6
+ TOKEN_PROGRAM_ID,
7
+ } from '@solana/spl-token';
3
8
  import {
4
9
  StateAccount,
5
10
  IWallet,
@@ -97,6 +102,7 @@ export class ClearingHouse {
97
102
  _isSubscribed = false;
98
103
  txSender: TxSender;
99
104
  marketLastSlotCache = new Map<number, number>();
105
+ authority: PublicKey;
100
106
 
101
107
  public get isSubscribed() {
102
108
  return this._isSubscribed && this.accountSubscriber.isSubscribed;
@@ -121,6 +127,7 @@ export class ClearingHouse {
121
127
  this.provider
122
128
  );
123
129
 
130
+ this.authority = config.authority ?? this.wallet.publicKey;
124
131
  const userIds = config.userIds ?? [0];
125
132
  this.activeUserId = config.activeUserId ?? userIds[0];
126
133
  this.userAccountSubscriptionConfig =
@@ -138,7 +145,7 @@ export class ClearingHouse {
138
145
  clearingHouse: this,
139
146
  userStatsAccountPublicKey: getUserStatsAccountPublicKey(
140
147
  this.program.programId,
141
- this.wallet.publicKey
148
+ this.authority
142
149
  ),
143
150
  accountSubscription: this.userAccountSubscriptionConfig,
144
151
  });
@@ -203,7 +210,7 @@ export class ClearingHouse {
203
210
  ): ClearingHouseUser {
204
211
  const userAccountPublicKey = getUserAccountPublicKeySync(
205
212
  this.program.programId,
206
- this.wallet.publicKey,
213
+ this.authority,
207
214
  userId
208
215
  );
209
216
 
@@ -494,6 +501,36 @@ export class ClearingHouse {
494
501
  );
495
502
  }
496
503
 
504
+ public async updateUserDelegate(
505
+ delegate: PublicKey,
506
+ userId = 0
507
+ ): Promise<TransactionSignature> {
508
+ return await this.program.rpc.updateUserDelegate(userId, delegate, {
509
+ accounts: {
510
+ user: await this.getUserAccountPublicKey(),
511
+ authority: this.wallet.publicKey,
512
+ },
513
+ });
514
+ }
515
+
516
+ public async getUserAccountsForDelegate(
517
+ delegate: PublicKey
518
+ ): Promise<UserAccount[]> {
519
+ const programAccounts = await this.program.account.user.all([
520
+ {
521
+ memcmp: {
522
+ offset: 40,
523
+ /** data to match, as base-58 encoded string and limited to less than 129 bytes */
524
+ bytes: bs58.encode(delegate.toBuffer()),
525
+ },
526
+ },
527
+ ]);
528
+
529
+ return programAccounts.map(
530
+ (programAccount) => programAccount.account as UserAccount
531
+ );
532
+ }
533
+
497
534
  public getUser(userId?: number): ClearingHouseUser {
498
535
  userId = userId ?? this.activeUserId;
499
536
  if (!this.users.has(userId)) {
@@ -518,7 +555,7 @@ export class ClearingHouse {
518
555
 
519
556
  this.userStatsAccountPublicKey = getUserStatsAccountPublicKey(
520
557
  this.program.programId,
521
- this.wallet.publicKey
558
+ this.authority
522
559
  );
523
560
  return this.userStatsAccountPublicKey;
524
561
  }
@@ -732,7 +769,7 @@ export class ClearingHouse {
732
769
 
733
770
  const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT);
734
771
 
735
- const authority = this.wallet.publicKey;
772
+ const authority = this.authority;
736
773
 
737
774
  const createWSOLTokenAccount =
738
775
  isSolMarket && collateralAccountPublicKey.equals(authority);
@@ -793,7 +830,7 @@ export class ClearingHouse {
793
830
  const userAccountPublicKey = userId
794
831
  ? await getUserAccountPublicKey(
795
832
  this.program.programId,
796
- this.wallet.publicKey,
833
+ this.authority,
797
834
  userId
798
835
  )
799
836
  : await this.getUserAccountPublicKey();
@@ -841,10 +878,10 @@ export class ClearingHouse {
841
878
  );
842
879
  }
843
880
 
844
- private async checkIfAccountExists(account: PublicKey) {
881
+ private async checkIfAccountExists(account: PublicKey): Promise<boolean> {
845
882
  try {
846
883
  const accountInfo = await this.connection.getAccountInfo(account);
847
- return accountInfo && true;
884
+ return accountInfo != null;
848
885
  } catch (e) {
849
886
  // Doesn't already exist
850
887
  return false;
@@ -947,6 +984,23 @@ export class ClearingHouse {
947
984
  return result;
948
985
  }
949
986
 
987
+ public getAssociatedTokenAccountCreationIx(
988
+ tokenMintAddress: PublicKey,
989
+ associatedTokenAddress: PublicKey
990
+ ): anchor.web3.TransactionInstruction {
991
+ const createAssociatedAccountIx =
992
+ Token.createAssociatedTokenAccountInstruction(
993
+ ASSOCIATED_TOKEN_PROGRAM_ID,
994
+ TOKEN_PROGRAM_ID,
995
+ tokenMintAddress,
996
+ associatedTokenAddress,
997
+ this.wallet.publicKey,
998
+ this.wallet.publicKey
999
+ );
1000
+
1001
+ return createAssociatedAccountIx;
1002
+ }
1003
+
950
1004
  /**
951
1005
  * Creates the Clearing House User account for a user, and deposits some initial collateral
952
1006
  * @param amount
@@ -1109,6 +1163,18 @@ export class ClearingHouse {
1109
1163
  });
1110
1164
 
1111
1165
  signers.forEach((signer) => additionalSigners.push(signer));
1166
+ } else {
1167
+ const accountExists = await this.checkIfAccountExists(userTokenAccount);
1168
+
1169
+ if (!accountExists) {
1170
+ const createAssociatedTokenAccountIx =
1171
+ this.getAssociatedTokenAccountCreationIx(
1172
+ spotMarketAccount.mint,
1173
+ userTokenAccount
1174
+ );
1175
+
1176
+ tx.add(createAssociatedTokenAccountIx);
1177
+ }
1112
1178
  }
1113
1179
 
1114
1180
  const withdrawCollateral = await this.getWithdrawIx(
@@ -3199,6 +3265,13 @@ export class ClearingHouse {
3199
3265
  return oracleData;
3200
3266
  }
3201
3267
 
3268
+ public getOracleDataForSpotMarket(marketIndex: BN): OraclePriceData {
3269
+ const oracleKey = this.getSpotMarketAccount(marketIndex).oracle;
3270
+ const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
3271
+
3272
+ return oracleData;
3273
+ }
3274
+
3202
3275
  public async initializeInsuranceFundStake(
3203
3276
  marketIndex: BN
3204
3277
  ): Promise<TransactionSignature> {
@@ -19,6 +19,7 @@ export type ClearingHouseConfig = {
19
19
  oracleInfos?: OracleInfo[];
20
20
  env?: DriftEnv;
21
21
  userStats?: boolean;
22
+ authority?: PublicKey; // explicitly pass an authority if signer is delegate
22
23
  };
23
24
 
24
25
  type ClearingHouseSubscriptionConfig =
@@ -142,7 +142,7 @@ export class ClearingHouseUser {
142
142
  openOrders: ZERO,
143
143
  openBids: ZERO,
144
144
  openAsks: ZERO,
145
- realizedPnl: ZERO,
145
+ settledPnl: ZERO,
146
146
  lpShares: ZERO,
147
147
  lastFeePerLp: ZERO,
148
148
  lastNetBaseAssetAmountPerLp: ZERO,
@@ -1071,7 +1071,7 @@ export class ClearingHouseUser {
1071
1071
  openOrders: new BN(0),
1072
1072
  openBids: new BN(0),
1073
1073
  openAsks: new BN(0),
1074
- realizedPnl: ZERO,
1074
+ settledPnl: ZERO,
1075
1075
  lpShares: ZERO,
1076
1076
  lastFeePerLp: ZERO,
1077
1077
  lastNetBaseAssetAmountPerLp: ZERO,
@@ -1395,11 +1395,11 @@ export class ClearingHouseUser {
1395
1395
  * @returns feeForQuote : Precision QUOTE_PRECISION
1396
1396
  */
1397
1397
  public calculateFeeForQuoteAmount(quoteAmount: BN): BN {
1398
- const feeStructure = this.clearingHouse.getStateAccount().perpFeeStructure;
1399
-
1398
+ const feeTier =
1399
+ this.clearingHouse.getStateAccount().perpFeeStructure.feeTiers[0];
1400
1400
  return quoteAmount
1401
- .mul(feeStructure.feeNumerator)
1402
- .div(feeStructure.feeDenominator);
1401
+ .mul(new BN(feeTier.feeNumerator))
1402
+ .div(new BN(feeTier.feeDenominator));
1403
1403
  }
1404
1404
 
1405
1405
  /**
package/src/config.ts CHANGED
@@ -28,7 +28,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
28
28
  devnet: {
29
29
  ENV: 'devnet',
30
30
  PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
31
- CLEARING_HOUSE_PROGRAM_ID: 'CUowJP5Dea7pkc2mKrkX2RuZUrPXL3u419iBRXyZEWQz',
31
+ CLEARING_HOUSE_PROGRAM_ID: '6MVFno8SFkVffGuCCQzg2wi8FvF8sPRFDNHa13ZPP9cK',
32
32
  USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
33
33
  PERP_MARKETS: DevnetPerpMarkets,
34
34
  SPOT_MARKETS: DevnetSpotMarkets,