@drift-labs/sdk 2.42.0-beta.0 → 2.42.0-beta.2

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/VERSION CHANGED
@@ -1 +1 @@
1
- 2.42.0-beta.0
1
+ 2.42.0-beta.2
@@ -103,7 +103,7 @@ export declare class DriftClient {
103
103
  * @param includeDelegates
104
104
  */
105
105
  updateWallet(newWallet: IWallet, subAccountIds?: number[], activeSubAccountId?: number, includeDelegates?: boolean, authoritySubaccountMap?: Map<string, number[]>): Promise<boolean>;
106
- switchActiveUser(subAccountId: number, authority?: PublicKey): void;
106
+ switchActiveUser(subAccountId: number, authority?: PublicKey): Promise<void>;
107
107
  addUser(subAccountId: number, authority?: PublicKey, userAccount?: UserAccount): Promise<boolean>;
108
108
  /**
109
109
  * Adds and subscribes to users based on params set by the constructor or by updateWallet.
@@ -339,10 +339,24 @@ class DriftClient {
339
339
  }
340
340
  return success;
341
341
  }
342
- switchActiveUser(subAccountId, authority) {
342
+ async switchActiveUser(subAccountId, authority) {
343
+ var _a;
344
+ const authorityChanged = !((_a = this.authority) === null || _a === void 0 ? void 0 : _a.equals(authority));
343
345
  this.activeSubAccountId = subAccountId;
344
346
  this.authority = authority !== null && authority !== void 0 ? authority : this.authority;
345
347
  this.userStatsAccountPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, this.authority);
348
+ /* If changing the user authority ie switching from delegate to non-delegate account, need to re-subscribe to the user stats account */
349
+ if (authorityChanged) {
350
+ if (this.userStats && this.userStats.isSubscribed) {
351
+ await this.userStats.unsubscribe();
352
+ }
353
+ this.userStats = new userStats_1.UserStats({
354
+ driftClient: this,
355
+ userStatsAccountPublicKey: this.userStatsAccountPublicKey,
356
+ accountSubscription: this.userAccountSubscriptionConfig,
357
+ });
358
+ this.userStats.subscribe();
359
+ }
346
360
  }
347
361
  async addUser(subAccountId, authority, userAccount) {
348
362
  authority = authority !== null && authority !== void 0 ? authority : this.authority;
package/lib/user.d.ts CHANGED
@@ -335,8 +335,19 @@ export declare class User {
335
335
  * @returns leverageRatio : Precision TEN_THOUSAND
336
336
  */
337
337
  accountLeverageRatioAfterTrade(targetMarketIndex: number, targetMarketType: MarketType, tradeQuoteAmount: BN, tradeSide: PositionDirection, includeOpenOrders?: boolean): BN;
338
+ getUserFeeTier(marketType: MarketType): import("./types").FeeTier;
338
339
  /**
339
- * Calculates how much fee will be taken for a given sized trade
340
+ * Calculates taker / maker fee (as a percentage, e.g. .001 = 10 basis points) for particular marketType
341
+ * @param marketType
342
+ * @param positionMarketIndex
343
+ * @returns : {takerFee: number, makerFee: number} Precision None
344
+ */
345
+ getMarketFees(marketType: MarketType, marketIndex?: number): {
346
+ takerFee: number;
347
+ makerFee: number;
348
+ };
349
+ /**
350
+ * Calculates how much perp fee will be taken for a given sized trade
340
351
  * @param quoteAmount
341
352
  * @returns feeForQuote : Precision QUOTE_PRECISION
342
353
  */
package/lib/user.js CHANGED
@@ -1590,13 +1590,67 @@ class User {
1590
1590
  .div(netAssetValue);
1591
1591
  return newLeverage;
1592
1592
  }
1593
+ getUserFeeTier(marketType) {
1594
+ const state = this.driftClient.getStateAccount();
1595
+ let feeTierIndex = 0;
1596
+ if ((0, types_1.isVariant)(marketType, 'perp')) {
1597
+ const userStatsAccount = this.driftClient
1598
+ .getUserStats()
1599
+ .getAccount();
1600
+ const total30dVolume = userStatsAccount.takerVolume30D.add(userStatsAccount.makerVolume30D); // todo: update using now and lastTs?
1601
+ const stakedQuoteAssetAmount = userStatsAccount.ifStakedQuoteAssetAmount;
1602
+ const volumeTiers = [
1603
+ new _1.BN(100000000).mul(numericConstants_1.QUOTE_PRECISION),
1604
+ new _1.BN(50000000).mul(numericConstants_1.QUOTE_PRECISION),
1605
+ new _1.BN(10000000).mul(numericConstants_1.QUOTE_PRECISION),
1606
+ new _1.BN(5000000).mul(numericConstants_1.QUOTE_PRECISION),
1607
+ new _1.BN(1000000).mul(numericConstants_1.QUOTE_PRECISION),
1608
+ ];
1609
+ const stakedTiers = [
1610
+ new _1.BN(10000).mul(numericConstants_1.QUOTE_PRECISION),
1611
+ new _1.BN(5000).mul(numericConstants_1.QUOTE_PRECISION),
1612
+ new _1.BN(2000).mul(numericConstants_1.QUOTE_PRECISION),
1613
+ new _1.BN(1000).mul(numericConstants_1.QUOTE_PRECISION),
1614
+ new _1.BN(500).mul(numericConstants_1.QUOTE_PRECISION),
1615
+ ];
1616
+ for (let i = 0; i < volumeTiers.length; i++) {
1617
+ if (total30dVolume.gte(volumeTiers[i]) ||
1618
+ stakedQuoteAssetAmount.gte(stakedTiers[i])) {
1619
+ feeTierIndex = 5 - i;
1620
+ break;
1621
+ }
1622
+ }
1623
+ return state.perpFeeStructure.feeTiers[feeTierIndex];
1624
+ }
1625
+ return state.spotFeeStructure.feeTiers[feeTierIndex];
1626
+ }
1627
+ /**
1628
+ * Calculates taker / maker fee (as a percentage, e.g. .001 = 10 basis points) for particular marketType
1629
+ * @param marketType
1630
+ * @param positionMarketIndex
1631
+ * @returns : {takerFee: number, makerFee: number} Precision None
1632
+ */
1633
+ getMarketFees(marketType, marketIndex) {
1634
+ const feeTier = this.getUserFeeTier(marketType);
1635
+ let takerFee = feeTier.feeNumerator / feeTier.feeDenominator;
1636
+ let makerFee = feeTier.makerRebateNumerator / feeTier.makerRebateDenominator;
1637
+ if (marketIndex && (0, types_1.isVariant)(marketType, 'perp')) {
1638
+ const marketAccount = this.driftClient.getPerpMarketAccount(marketIndex);
1639
+ takerFee += (takerFee * marketAccount.feeAdjustment) / 100;
1640
+ makerFee += (makerFee * marketAccount.feeAdjustment) / 100;
1641
+ }
1642
+ return {
1643
+ takerFee,
1644
+ makerFee,
1645
+ };
1646
+ }
1593
1647
  /**
1594
- * Calculates how much fee will be taken for a given sized trade
1648
+ * Calculates how much perp fee will be taken for a given sized trade
1595
1649
  * @param quoteAmount
1596
1650
  * @returns feeForQuote : Precision QUOTE_PRECISION
1597
1651
  */
1598
1652
  calculateFeeForQuoteAmount(quoteAmount) {
1599
- const feeTier = this.driftClient.getStateAccount().perpFeeStructure.feeTiers[0];
1653
+ const feeTier = this.getUserFeeTier(_1.MarketType.PERP);
1600
1654
  return quoteAmount
1601
1655
  .mul(new _1.BN(feeTier.feeNumerator))
1602
1656
  .div(new _1.BN(feeTier.feeDenominator));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.42.0-beta.0",
3
+ "version": "2.42.0-beta.2",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -588,13 +588,30 @@ export class DriftClient {
588
588
  return success;
589
589
  }
590
590
 
591
- public switchActiveUser(subAccountId: number, authority?: PublicKey) {
591
+ public async switchActiveUser(subAccountId: number, authority?: PublicKey) {
592
+ const authorityChanged = !this.authority?.equals(authority);
593
+
592
594
  this.activeSubAccountId = subAccountId;
593
595
  this.authority = authority ?? this.authority;
594
596
  this.userStatsAccountPublicKey = getUserStatsAccountPublicKey(
595
597
  this.program.programId,
596
598
  this.authority
597
599
  );
600
+
601
+ /* If changing the user authority ie switching from delegate to non-delegate account, need to re-subscribe to the user stats account */
602
+ if (authorityChanged) {
603
+ if (this.userStats && this.userStats.isSubscribed) {
604
+ await this.userStats.unsubscribe();
605
+ }
606
+
607
+ this.userStats = new UserStats({
608
+ driftClient: this,
609
+ userStatsAccountPublicKey: this.userStatsAccountPublicKey,
610
+ accountSubscription: this.userAccountSubscriptionConfig,
611
+ });
612
+
613
+ this.userStats.subscribe();
614
+ }
598
615
  }
599
616
 
600
617
  public async addUser(
package/src/user.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  isOneOfVariant,
13
13
  PerpMarketAccount,
14
14
  HealthComponents,
15
+ UserStatsAccount,
15
16
  } from './types';
16
17
  import { calculateEntryPrice, positionIsAvailable } from './math/position';
17
18
  import {
@@ -2909,14 +2910,82 @@ export class User {
2909
2910
  return newLeverage;
2910
2911
  }
2911
2912
 
2913
+ public getUserFeeTier(marketType: MarketType) {
2914
+ const state = this.driftClient.getStateAccount();
2915
+
2916
+ let feeTierIndex = 0;
2917
+ if (isVariant(marketType, 'perp')) {
2918
+ const userStatsAccount: UserStatsAccount = this.driftClient
2919
+ .getUserStats()
2920
+ .getAccount();
2921
+
2922
+ const total30dVolume = userStatsAccount.takerVolume30D.add(
2923
+ userStatsAccount.makerVolume30D
2924
+ ); // todo: update using now and lastTs?
2925
+
2926
+ const stakedQuoteAssetAmount = userStatsAccount.ifStakedQuoteAssetAmount;
2927
+ const volumeTiers = [
2928
+ new BN(100_000_000).mul(QUOTE_PRECISION),
2929
+ new BN(50_000_000).mul(QUOTE_PRECISION),
2930
+ new BN(10_000_000).mul(QUOTE_PRECISION),
2931
+ new BN(5_000_000).mul(QUOTE_PRECISION),
2932
+ new BN(1_000_000).mul(QUOTE_PRECISION),
2933
+ ];
2934
+ const stakedTiers = [
2935
+ new BN(10000).mul(QUOTE_PRECISION),
2936
+ new BN(5000).mul(QUOTE_PRECISION),
2937
+ new BN(2000).mul(QUOTE_PRECISION),
2938
+ new BN(1000).mul(QUOTE_PRECISION),
2939
+ new BN(500).mul(QUOTE_PRECISION),
2940
+ ];
2941
+
2942
+ for (let i = 0; i < volumeTiers.length; i++) {
2943
+ if (
2944
+ total30dVolume.gte(volumeTiers[i]) ||
2945
+ stakedQuoteAssetAmount.gte(stakedTiers[i])
2946
+ ) {
2947
+ feeTierIndex = 5 - i;
2948
+ break;
2949
+ }
2950
+ }
2951
+
2952
+ return state.perpFeeStructure.feeTiers[feeTierIndex];
2953
+ }
2954
+
2955
+ return state.spotFeeStructure.feeTiers[feeTierIndex];
2956
+ }
2957
+
2958
+ /**
2959
+ * Calculates taker / maker fee (as a percentage, e.g. .001 = 10 basis points) for particular marketType
2960
+ * @param marketType
2961
+ * @param positionMarketIndex
2962
+ * @returns : {takerFee: number, makerFee: number} Precision None
2963
+ */
2964
+ public getMarketFees(marketType: MarketType, marketIndex?: number) {
2965
+ const feeTier = this.getUserFeeTier(marketType);
2966
+ let takerFee = feeTier.feeNumerator / feeTier.feeDenominator;
2967
+ let makerFee =
2968
+ feeTier.makerRebateNumerator / feeTier.makerRebateDenominator;
2969
+
2970
+ if (marketIndex && isVariant(marketType, 'perp')) {
2971
+ const marketAccount = this.driftClient.getPerpMarketAccount(marketIndex);
2972
+ takerFee += (takerFee * marketAccount.feeAdjustment) / 100;
2973
+ makerFee += (makerFee * marketAccount.feeAdjustment) / 100;
2974
+ }
2975
+
2976
+ return {
2977
+ takerFee,
2978
+ makerFee,
2979
+ };
2980
+ }
2981
+
2912
2982
  /**
2913
- * Calculates how much fee will be taken for a given sized trade
2983
+ * Calculates how much perp fee will be taken for a given sized trade
2914
2984
  * @param quoteAmount
2915
2985
  * @returns feeForQuote : Precision QUOTE_PRECISION
2916
2986
  */
2917
2987
  public calculateFeeForQuoteAmount(quoteAmount: BN): BN {
2918
- const feeTier =
2919
- this.driftClient.getStateAccount().perpFeeStructure.feeTiers[0];
2988
+ const feeTier = this.getUserFeeTier(MarketType.PERP);
2920
2989
  return quoteAmount
2921
2990
  .mul(new BN(feeTier.feeNumerator))
2922
2991
  .div(new BN(feeTier.feeDenominator));