@drift-labs/sdk 2.86.0-beta.4 → 2.86.0-beta.6

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.86.0-beta.4
1
+ 2.86.0-beta.6
@@ -179,6 +179,10 @@ export declare class AdminClient extends DriftClient {
179
179
  getUpdatePrelaunchOracleParamsIx(perpMarketIndex: number, price?: BN, maxPrice?: BN): Promise<TransactionInstruction>;
180
180
  deletePrelaunchOracle(perpMarketIndex: number): Promise<TransactionSignature>;
181
181
  getDeletePrelaunchOracleIx(perpMarketIndex: number, price?: BN, maxPrice?: BN): Promise<TransactionInstruction>;
182
+ updateSpotMarketFuel(spotMarketIndex: number, fuelBoostDeposits?: number, fuelBoostBorrows?: number, fuelBoostTaker?: number, fuelBoostMaker?: number): Promise<TransactionSignature>;
183
+ getUpdateSpotMarketFuelIx(spotMarketIndex: number, fuelBoostDeposits?: number, fuelBoostBorrows?: number, fuelBoostTaker?: number, fuelBoostMaker?: number): Promise<TransactionInstruction>;
184
+ updatePerpMarketFuel(perpMarketIndex: number, fuelBoostTaker?: number, fuelBoostMaker?: number, fuelBoostPosition?: number): Promise<TransactionSignature>;
185
+ getUpdatePerpMarketFuelIx(perpMarketIndex: number, fuelBoostTaker?: number, fuelBoostMaker?: number, fuelBoostPosition?: number): Promise<TransactionInstruction>;
182
186
  initializePythPullOracle(feedId: string): Promise<TransactionSignature>;
183
187
  getInitializePythPullOracleIx(feedId: string): Promise<TransactionInstruction>;
184
188
  }
@@ -1631,6 +1631,42 @@ class AdminClient extends driftClient_1.DriftClient {
1631
1631
  },
1632
1632
  });
1633
1633
  }
1634
+ async updateSpotMarketFuel(spotMarketIndex, fuelBoostDeposits, fuelBoostBorrows, fuelBoostTaker, fuelBoostMaker) {
1635
+ const updateSpotMarketFuelIx = await this.getUpdateSpotMarketFuelIx(spotMarketIndex, fuelBoostDeposits || null, fuelBoostBorrows || null, fuelBoostTaker || null, fuelBoostMaker || null);
1636
+ const tx = await this.buildTransaction(updateSpotMarketFuelIx);
1637
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
1638
+ return txSig;
1639
+ }
1640
+ async getUpdateSpotMarketFuelIx(spotMarketIndex, fuelBoostDeposits, fuelBoostBorrows, fuelBoostTaker, fuelBoostMaker) {
1641
+ const spotMarketPublicKey = await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex);
1642
+ return await this.program.instruction.updateSpotMarketFuel(fuelBoostDeposits || null, fuelBoostBorrows || null, fuelBoostTaker || null, fuelBoostMaker || null, {
1643
+ accounts: {
1644
+ admin: this.isSubscribed
1645
+ ? this.getStateAccount().admin
1646
+ : this.wallet.publicKey,
1647
+ state: await this.getStatePublicKey(),
1648
+ spotMarket: spotMarketPublicKey,
1649
+ },
1650
+ });
1651
+ }
1652
+ async updatePerpMarketFuel(perpMarketIndex, fuelBoostTaker, fuelBoostMaker, fuelBoostPosition) {
1653
+ const updatePerpMarketFuelIx = await this.getUpdatePerpMarketFuelIx(perpMarketIndex, fuelBoostTaker || null, fuelBoostMaker || null, fuelBoostPosition || null);
1654
+ const tx = await this.buildTransaction(updatePerpMarketFuelIx);
1655
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
1656
+ return txSig;
1657
+ }
1658
+ async getUpdatePerpMarketFuelIx(perpMarketIndex, fuelBoostTaker, fuelBoostMaker, fuelBoostPosition) {
1659
+ const perpMarketPublicKey = await (0, pda_1.getPerpMarketPublicKey)(this.program.programId, perpMarketIndex);
1660
+ return await this.program.instruction.updatePerpMarketFuel(fuelBoostTaker || null, fuelBoostMaker || null, fuelBoostPosition || null, {
1661
+ accounts: {
1662
+ admin: this.isSubscribed
1663
+ ? this.getStateAccount().admin
1664
+ : this.wallet.publicKey,
1665
+ state: await this.getStatePublicKey(),
1666
+ perpMarket: perpMarketPublicKey,
1667
+ },
1668
+ });
1669
+ }
1634
1670
  async initializePythPullOracle(feedId) {
1635
1671
  const initializePythPullOracleIx = await this.getInitializePythPullOracleIx(feedId);
1636
1672
  const tx = await this.buildTransaction(initializePythPullOracleIx);
@@ -65,3 +65,4 @@ export declare const ACCOUNT_AGE_DELETION_CUTOFF_SECONDS: number;
65
65
  export declare const IDLE_TIME_SLOTS = 9000;
66
66
  export declare const SLOT_TIME_ESTIMATE_MS = 400;
67
67
  export declare const DUST_POSITION_SIZE: BN;
68
+ export declare const FUEL_WINDOW: BN;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MARGIN_PRECISION = exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.PRICE_TO_QUOTE_PRECISION = exports.PRICE_DIV_PEG = exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.BASE_PRECISION_EXP = exports.BASE_PRECISION = exports.AMM_RESERVE_PRECISION = exports.PEG_PRECISION = exports.FUNDING_RATE_BUFFER_PRECISION = exports.FUNDING_RATE_PRECISION = exports.PRICE_PRECISION = exports.QUOTE_PRECISION = exports.LIQUIDATION_FEE_PRECISION = exports.SPOT_MARKET_IMF_PRECISION = exports.SPOT_MARKET_IMF_PRECISION_EXP = exports.SPOT_MARKET_BALANCE_PRECISION = exports.SPOT_MARKET_BALANCE_PRECISION_EXP = exports.SPOT_MARKET_WEIGHT_PRECISION = exports.SPOT_MARKET_UTILIZATION_PRECISION = exports.SPOT_MARKET_UTILIZATION_PRECISION_EXP = exports.SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION = exports.SPOT_MARKET_CUMULATIVE_INTEREST_PRECISION_EXP = exports.SPOT_MARKET_RATE_PRECISION = exports.SPOT_MARKET_RATE_PRECISION_EXP = exports.AMM_RESERVE_PRECISION_EXP = exports.PEG_PRECISION_EXP = exports.FUNDING_RATE_PRECISION_EXP = exports.PRICE_PRECISION_EXP = exports.FUNDING_RATE_BUFFER_PRECISION_EXP = exports.QUOTE_PRECISION_EXP = exports.CONCENTRATION_PRECISION = exports.PERCENTAGE_PRECISION = exports.PERCENTAGE_PRECISION_EXP = exports.MAX_LEVERAGE_ORDER_SIZE = exports.MAX_LEVERAGE = exports.TEN_MILLION = exports.BN_MAX = exports.TEN_THOUSAND = exports.TEN = exports.NINE = exports.EIGHT = exports.SEVEN = exports.SIX = exports.FIVE = exports.FOUR = exports.THREE = exports.TWO = exports.ONE = exports.ZERO = void 0;
4
- exports.DUST_POSITION_SIZE = exports.SLOT_TIME_ESTIMATE_MS = exports.IDLE_TIME_SLOTS = exports.ACCOUNT_AGE_DELETION_CUTOFF_SECONDS = exports.DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT = exports.OPEN_ORDER_MARGIN_REQUIREMENT = exports.LAMPORTS_EXP = exports.LAMPORTS_PRECISION = exports.QUOTE_SPOT_MARKET_INDEX = exports.ONE_YEAR = exports.ONE_HOUR = exports.FIVE_MINUTE = exports.FUNDING_RATE_OFFSET_DENOMINATOR = exports.LIQUIDATION_PCT_PRECISION = exports.BID_ASK_SPREAD_PRECISION = void 0;
4
+ exports.FUEL_WINDOW = exports.DUST_POSITION_SIZE = exports.SLOT_TIME_ESTIMATE_MS = exports.IDLE_TIME_SLOTS = exports.ACCOUNT_AGE_DELETION_CUTOFF_SECONDS = exports.DEFAULT_REVENUE_SINCE_LAST_FUNDING_SPREAD_RETREAT = exports.OPEN_ORDER_MARGIN_REQUIREMENT = exports.LAMPORTS_EXP = exports.LAMPORTS_PRECISION = exports.QUOTE_SPOT_MARKET_INDEX = exports.ONE_YEAR = exports.ONE_HOUR = exports.FIVE_MINUTE = exports.FUNDING_RATE_OFFSET_DENOMINATOR = exports.LIQUIDATION_PCT_PRECISION = exports.BID_ASK_SPREAD_PRECISION = void 0;
5
5
  const web3_js_1 = require("@solana/web3.js");
6
6
  const __1 = require("../");
7
7
  exports.ZERO = new __1.BN(0);
@@ -69,3 +69,4 @@ exports.ACCOUNT_AGE_DELETION_CUTOFF_SECONDS = 60 * 60 * 24 * 13; // 13 days
69
69
  exports.IDLE_TIME_SLOTS = 9000;
70
70
  exports.SLOT_TIME_ESTIMATE_MS = 400;
71
71
  exports.DUST_POSITION_SIZE = exports.QUOTE_PRECISION.divn(100); // Dust position is any position smaller than 1c
72
+ exports.FUEL_WINDOW = new __1.BN(60 * 60 * 24 * 28); // 28 days
@@ -271,13 +271,13 @@ exports.MainnetSpotMarkets = [
271
271
  {
272
272
  symbol: 'POPCAT',
273
273
  marketIndex: 20,
274
- oracle: new web3_js_1.PublicKey('2stQe1XLGkuTZ22gQrgZKsb93iG9mWXSLfANMPRjs5Ky'),
274
+ oracle: new web3_js_1.PublicKey('3GjpjC8TWsPqjyFSiR7saGxgzD8zqYJNsBnWpenZPEBy'),
275
275
  oracleSource: __1.OracleSource.SWITCHBOARD,
276
276
  mint: new web3_js_1.PublicKey('7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr'),
277
277
  precision: new __1.BN(10).pow(numericConstants_1.NINE),
278
278
  precisionExp: numericConstants_1.NINE,
279
279
  launchTs: 1720013054000,
280
- phoenixMarket: new web3_js_1.PublicKey('3GjpjC8TWsPqjyFSiR7saGxgzD8zqYJNsBnWpenZPEBy'),
280
+ phoenixMarket: new web3_js_1.PublicKey('31XgvAQ1HgFQEk31KdszbPkVXKaQqB1bgYZPoDrFpSR2'),
281
281
  },
282
282
  ];
283
283
  exports.SpotMarkets = {
@@ -2244,6 +2244,42 @@
2244
2244
  ],
2245
2245
  "args": []
2246
2246
  },
2247
+ {
2248
+ "name": "updateUserGovTokenInsuranceStake",
2249
+ "accounts": [
2250
+ {
2251
+ "name": "state",
2252
+ "isMut": false,
2253
+ "isSigner": false
2254
+ },
2255
+ {
2256
+ "name": "spotMarket",
2257
+ "isMut": false,
2258
+ "isSigner": false
2259
+ },
2260
+ {
2261
+ "name": "insuranceFundStake",
2262
+ "isMut": true,
2263
+ "isSigner": false
2264
+ },
2265
+ {
2266
+ "name": "userStats",
2267
+ "isMut": true,
2268
+ "isSigner": false
2269
+ },
2270
+ {
2271
+ "name": "authority",
2272
+ "isMut": false,
2273
+ "isSigner": true
2274
+ },
2275
+ {
2276
+ "name": "insuranceFundVault",
2277
+ "isMut": true,
2278
+ "isSigner": false
2279
+ }
2280
+ ],
2281
+ "args": []
2282
+ },
2247
2283
  {
2248
2284
  "name": "initializeInsuranceFundStake",
2249
2285
  "accounts": [
@@ -5079,6 +5115,92 @@
5079
5115
  }
5080
5116
  ]
5081
5117
  },
5118
+ {
5119
+ "name": "updatePerpMarketFuel",
5120
+ "accounts": [
5121
+ {
5122
+ "name": "admin",
5123
+ "isMut": false,
5124
+ "isSigner": true
5125
+ },
5126
+ {
5127
+ "name": "state",
5128
+ "isMut": false,
5129
+ "isSigner": false
5130
+ },
5131
+ {
5132
+ "name": "perpMarket",
5133
+ "isMut": true,
5134
+ "isSigner": false
5135
+ }
5136
+ ],
5137
+ "args": [
5138
+ {
5139
+ "name": "fuelBoostTaker",
5140
+ "type": {
5141
+ "option": "u8"
5142
+ }
5143
+ },
5144
+ {
5145
+ "name": "fuelBoostMaker",
5146
+ "type": {
5147
+ "option": "u8"
5148
+ }
5149
+ },
5150
+ {
5151
+ "name": "fuelBoostPosition",
5152
+ "type": {
5153
+ "option": "u8"
5154
+ }
5155
+ }
5156
+ ]
5157
+ },
5158
+ {
5159
+ "name": "updateSpotMarketFuel",
5160
+ "accounts": [
5161
+ {
5162
+ "name": "admin",
5163
+ "isMut": false,
5164
+ "isSigner": true
5165
+ },
5166
+ {
5167
+ "name": "state",
5168
+ "isMut": false,
5169
+ "isSigner": false
5170
+ },
5171
+ {
5172
+ "name": "spotMarket",
5173
+ "isMut": true,
5174
+ "isSigner": false
5175
+ }
5176
+ ],
5177
+ "args": [
5178
+ {
5179
+ "name": "fuelBoostDeposits",
5180
+ "type": {
5181
+ "option": "u8"
5182
+ }
5183
+ },
5184
+ {
5185
+ "name": "fuelBoostBorrows",
5186
+ "type": {
5187
+ "option": "u8"
5188
+ }
5189
+ },
5190
+ {
5191
+ "name": "fuelBoostTaker",
5192
+ "type": {
5193
+ "option": "u8"
5194
+ }
5195
+ },
5196
+ {
5197
+ "name": "fuelBoostMaker",
5198
+ "type": {
5199
+ "option": "u8"
5200
+ }
5201
+ }
5202
+ ]
5203
+ },
5082
5204
  {
5083
5205
  "name": "updateAdmin",
5084
5206
  "accounts": [
@@ -5918,12 +6040,36 @@
5918
6040
  ],
5919
6041
  "type": "i16"
5920
6042
  },
6043
+ {
6044
+ "name": "fuelBoostPosition",
6045
+ "docs": [
6046
+ "fuel multiplier for perp funding",
6047
+ "precision: 10"
6048
+ ],
6049
+ "type": "u8"
6050
+ },
6051
+ {
6052
+ "name": "fuelBoostTaker",
6053
+ "docs": [
6054
+ "fuel multiplier for perp taker",
6055
+ "precision: 10"
6056
+ ],
6057
+ "type": "u8"
6058
+ },
6059
+ {
6060
+ "name": "fuelBoostMaker",
6061
+ "docs": [
6062
+ "fuel multiplier for perp maker",
6063
+ "precision: 10"
6064
+ ],
6065
+ "type": "u8"
6066
+ },
5921
6067
  {
5922
6068
  "name": "padding",
5923
6069
  "type": {
5924
6070
  "array": [
5925
6071
  "u8",
5926
- 46
6072
+ 43
5927
6073
  ]
5928
6074
  }
5929
6075
  }
@@ -6376,12 +6522,44 @@
6376
6522
  ],
6377
6523
  "type": "u8"
6378
6524
  },
6525
+ {
6526
+ "name": "fuelBoostDeposits",
6527
+ "docs": [
6528
+ "fuel multiplier for spot deposits",
6529
+ "precision: 10"
6530
+ ],
6531
+ "type": "u8"
6532
+ },
6533
+ {
6534
+ "name": "fuelBoostBorrows",
6535
+ "docs": [
6536
+ "fuel multiplier for spot borrows",
6537
+ "precision: 10"
6538
+ ],
6539
+ "type": "u8"
6540
+ },
6541
+ {
6542
+ "name": "fuelBoostTaker",
6543
+ "docs": [
6544
+ "fuel multiplier for spot taker",
6545
+ "precision: 10"
6546
+ ],
6547
+ "type": "u8"
6548
+ },
6549
+ {
6550
+ "name": "fuelBoostMaker",
6551
+ "docs": [
6552
+ "fuel multiplier for spot maker",
6553
+ "precision: 10"
6554
+ ],
6555
+ "type": "u8"
6556
+ },
6379
6557
  {
6380
6558
  "name": "padding",
6381
6559
  "type": {
6382
6560
  "array": [
6383
6561
  "u8",
6384
- 47
6562
+ 43
6385
6563
  ]
6386
6564
  }
6387
6565
  }
@@ -6729,12 +6907,25 @@
6729
6907
  ],
6730
6908
  "type": "bool"
6731
6909
  },
6910
+ {
6911
+ "name": "padding1",
6912
+ "type": {
6913
+ "array": [
6914
+ "u8",
6915
+ 5
6916
+ ]
6917
+ }
6918
+ },
6919
+ {
6920
+ "name": "lastFuelBonusUpdateTs",
6921
+ "type": "i64"
6922
+ },
6732
6923
  {
6733
6924
  "name": "padding",
6734
6925
  "type": {
6735
6926
  "array": [
6736
6927
  "u8",
6737
- 21
6928
+ 8
6738
6929
  ]
6739
6930
  }
6740
6931
  }
@@ -6855,12 +7046,63 @@
6855
7046
  "name": "disableUpdatePerpBidAskTwap",
6856
7047
  "type": "bool"
6857
7048
  },
7049
+ {
7050
+ "name": "padding1",
7051
+ "type": {
7052
+ "array": [
7053
+ "u8",
7054
+ 6
7055
+ ]
7056
+ }
7057
+ },
7058
+ {
7059
+ "name": "fuelDeposits",
7060
+ "docs": [
7061
+ "sub account id for spot deposit, borrow fuel tracking"
7062
+ ],
7063
+ "type": "u32"
7064
+ },
7065
+ {
7066
+ "name": "fuelBorrows",
7067
+ "docs": [
7068
+ "accumulate fuel bonus for epoch"
7069
+ ],
7070
+ "type": "u32"
7071
+ },
7072
+ {
7073
+ "name": "fuelPositions",
7074
+ "docs": [
7075
+ "accumulated fuel for perp open interest"
7076
+ ],
7077
+ "type": "u32"
7078
+ },
7079
+ {
7080
+ "name": "fuelTaker",
7081
+ "docs": [
7082
+ "accumulate fuel bonus for epoch"
7083
+ ],
7084
+ "type": "u32"
7085
+ },
7086
+ {
7087
+ "name": "fuelMaker",
7088
+ "docs": [
7089
+ "accumulate fuel bonus for epoch"
7090
+ ],
7091
+ "type": "u32"
7092
+ },
7093
+ {
7094
+ "name": "ifStakedGovTokenAmount",
7095
+ "docs": [
7096
+ "The amount of tokens staked in the governance spot markets if"
7097
+ ],
7098
+ "type": "u64"
7099
+ },
6858
7100
  {
6859
7101
  "name": "padding",
6860
7102
  "type": {
6861
7103
  "array": [
6862
7104
  "u8",
6863
- 50
7105
+ 16
6864
7106
  ]
6865
7107
  }
6866
7108
  }
package/lib/index.d.ts CHANGED
@@ -64,6 +64,7 @@ export * from './slot/SlotSubscriber';
64
64
  export * from './wallet';
65
65
  export * from './types';
66
66
  export * from './math/utils';
67
+ export * from './math/fuel';
67
68
  export * from './config';
68
69
  export * from './constants/numericConstants';
69
70
  export * from './serum/serumSubscriber';
package/lib/index.js CHANGED
@@ -87,6 +87,7 @@ __exportStar(require("./slot/SlotSubscriber"), exports);
87
87
  __exportStar(require("./wallet"), exports);
88
88
  __exportStar(require("./types"), exports);
89
89
  __exportStar(require("./math/utils"), exports);
90
+ __exportStar(require("./math/fuel"), exports);
90
91
  __exportStar(require("./config"), exports);
91
92
  __exportStar(require("./constants/numericConstants"), exports);
92
93
  __exportStar(require("./serum/serumSubscriber"), exports);
@@ -0,0 +1,5 @@
1
+ /// <reference types="bn.js" />
2
+ import { BN } from '@coral-xyz/anchor';
3
+ import { SpotMarketAccount, PerpMarketAccount } from '..';
4
+ export declare function calculateSpotFuelBonus(spotMarket: SpotMarketAccount, signedTokenValue: BN, fuelBonusNumerator: BN): BN;
5
+ export declare function calculatePerpFuelBonus(perpMarket: PerpMarketAccount, baseAssetValue: BN, fuelBonusNumerator: BN): BN;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculatePerpFuelBonus = exports.calculateSpotFuelBonus = void 0;
4
+ const anchor_1 = require("@coral-xyz/anchor");
5
+ const numericConstants_1 = require("../constants/numericConstants");
6
+ function calculateSpotFuelBonus(spotMarket, signedTokenValue, fuelBonusNumerator) {
7
+ let result;
8
+ if (signedTokenValue.abs().lt(new anchor_1.BN(1))) {
9
+ result = numericConstants_1.ZERO;
10
+ }
11
+ else if (signedTokenValue.gt(new anchor_1.BN(0))) {
12
+ result = signedTokenValue
13
+ .abs()
14
+ .mul(fuelBonusNumerator)
15
+ .mul(new anchor_1.BN(spotMarket.fuelBoostDeposits))
16
+ .div(numericConstants_1.FUEL_WINDOW)
17
+ .div(numericConstants_1.QUOTE_PRECISION.div(new anchor_1.BN(10)));
18
+ }
19
+ else {
20
+ result = signedTokenValue
21
+ .abs()
22
+ .mul(fuelBonusNumerator)
23
+ .mul(new anchor_1.BN(spotMarket.fuelBoostBorrows))
24
+ .div(numericConstants_1.FUEL_WINDOW)
25
+ .div(numericConstants_1.QUOTE_PRECISION.div(new anchor_1.BN(10)));
26
+ }
27
+ return result;
28
+ }
29
+ exports.calculateSpotFuelBonus = calculateSpotFuelBonus;
30
+ function calculatePerpFuelBonus(perpMarket, baseAssetValue, fuelBonusNumerator) {
31
+ let result;
32
+ if (baseAssetValue.abs().lte(numericConstants_1.QUOTE_PRECISION)) {
33
+ result = new anchor_1.BN(0);
34
+ }
35
+ else {
36
+ result = baseAssetValue
37
+ .abs()
38
+ .mul(fuelBonusNumerator)
39
+ .mul(new anchor_1.BN(perpMarket.fuelBoostPosition))
40
+ .div(numericConstants_1.FUEL_WINDOW)
41
+ .div(numericConstants_1.QUOTE_PRECISION.div(new anchor_1.BN(10)));
42
+ }
43
+ return result;
44
+ }
45
+ exports.calculatePerpFuelBonus = calculatePerpFuelBonus;
package/lib/types.d.ts CHANGED
@@ -731,6 +731,7 @@ export type PerpMarketAccount = {
731
731
  quoteSpotMarketIndex: number;
732
732
  feeAdjustment: number;
733
733
  pausedOperations: number;
734
+ fuelBoostPosition: number;
734
735
  };
735
736
  export type HistoricalOracleData = {
736
737
  lastOraclePrice: BN;
@@ -812,6 +813,8 @@ export type SpotMarketAccount = {
812
813
  ifPausedOperations: number;
813
814
  maxTokenBorrowsFraction: number;
814
815
  minBorrowRate: number;
816
+ fuelBoostDeposits: number;
817
+ fuelBoostBorrows: number;
815
818
  };
816
819
  export type PoolBalance = {
817
820
  scaledBalance: BN;
@@ -939,6 +942,12 @@ export type UserStatsAccount = {
939
942
  isReferrer: boolean;
940
943
  authority: PublicKey;
941
944
  ifStakedQuoteAssetAmount: BN;
945
+ fuelDeposits: number;
946
+ fuelBorrows: number;
947
+ fuelPositions: number;
948
+ fuelTaker: number;
949
+ fuelMaker: number;
950
+ ifStakedGovTokenAmount: BN;
942
951
  };
943
952
  export type UserAccount = {
944
953
  authority: PublicKey;
@@ -967,6 +976,7 @@ export type UserAccount = {
967
976
  hasOpenOrder: boolean;
968
977
  openAuctions: number;
969
978
  hasOpenAuction: boolean;
979
+ lastFuelBonusUpdateTs: BN;
970
980
  };
971
981
  export type SpotPosition = {
972
982
  marketIndex: number;
package/lib/user.d.ts CHANGED
@@ -136,6 +136,13 @@ export declare class User {
136
136
  * @returns : Precision QUOTE_PRECISION
137
137
  */
138
138
  getUnrealizedFundingPNL(marketIndex?: number): BN;
139
+ getFuelBonus(now: BN, includeSettled?: boolean, includeUnsettled?: boolean): {
140
+ depositFuel: any;
141
+ borrowFuel: any;
142
+ positionFuel: any;
143
+ takerFuel: any;
144
+ makerFuel: any;
145
+ };
139
146
  getSpotMarketAssetAndLiabilityValue(marketIndex?: number, marginCategory?: MarginCategory, liquidationBuffer?: BN, includeOpenOrders?: boolean, strict?: boolean, now?: BN): {
140
147
  totalAssetValue: BN;
141
148
  totalLiabilityValue: BN;
package/lib/user.js CHANGED
@@ -14,6 +14,7 @@ const spotPosition_1 = require("./math/spotPosition");
14
14
  const oracles_1 = require("./math/oracles");
15
15
  const tiers_1 = require("./math/tiers");
16
16
  const strictOraclePrice_1 = require("./oracles/strictOraclePrice");
17
+ const fuel_1 = require("./math/fuel");
17
18
  class User {
18
19
  get isSubscribed() {
19
20
  return this._isSubscribed && this.accountSubscriber.isSubscribed;
@@ -539,6 +540,51 @@ class User {
539
540
  return pnl.add((0, _1.calculatePositionFundingPNL)(market, perpPosition));
540
541
  }, numericConstants_1.ZERO);
541
542
  }
543
+ getFuelBonus(now, includeSettled = true, includeUnsettled = true) {
544
+ const userAccount = this.getUserAccount();
545
+ const result = {
546
+ takerFuel: numericConstants_1.ZERO,
547
+ makerFuel: numericConstants_1.ZERO,
548
+ depositFuel: numericConstants_1.ZERO,
549
+ borrowFuel: numericConstants_1.ZERO,
550
+ positionFuel: numericConstants_1.ZERO,
551
+ };
552
+ if (includeSettled) {
553
+ const userStats = this.driftClient
554
+ .getUserStats()
555
+ .getAccount();
556
+ result.takerFuel = result.takerFuel.addn(userStats.fuelTaker);
557
+ result.makerFuel = result.makerFuel.addn(userStats.fuelMaker);
558
+ result.depositFuel = result.depositFuel.addn(userStats.fuelDeposits);
559
+ result.borrowFuel = result.borrowFuel.addn(userStats.fuelBorrows);
560
+ result.positionFuel = result.positionFuel.addn(userStats.fuelPositions);
561
+ }
562
+ if (includeUnsettled) {
563
+ const fuelBonusNumerator = now.sub(userAccount.lastFuelBonusUpdateTs);
564
+ for (const spotPosition of this.getActiveSpotPositions()) {
565
+ const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
566
+ const tokenAmount = this.getTokenAmount(spotPosition.marketIndex);
567
+ const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
568
+ const twap5min = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
569
+ );
570
+ const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price, twap5min);
571
+ const signedTokenValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
572
+ if (signedTokenValue.gt(numericConstants_1.ZERO)) {
573
+ result.depositFuel = result.depositFuel.add((0, fuel_1.calculateSpotFuelBonus)(spotMarketAccount, signedTokenValue, fuelBonusNumerator));
574
+ }
575
+ else {
576
+ result.borrowFuel = result.borrowFuel.add((0, fuel_1.calculateSpotFuelBonus)(spotMarketAccount, signedTokenValue, fuelBonusNumerator));
577
+ }
578
+ }
579
+ for (const perpPosition of this.getActivePerpPositions()) {
580
+ const oraclePriceData = this.getOracleDataForPerpMarket(perpPosition.marketIndex);
581
+ const perpMarketAccount = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
582
+ const baseAssetValue = this.getPerpPositionValue(perpPosition.marketIndex, oraclePriceData, false);
583
+ result.positionFuel = result.positionFuel.add((0, fuel_1.calculatePerpFuelBonus)(perpMarketAccount, baseAssetValue, fuelBonusNumerator));
584
+ }
585
+ }
586
+ return result;
587
+ }
542
588
  getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false, now) {
543
589
  now = now || new _1.BN(new Date().getTime() / 1000);
544
590
  let netQuoteValue = numericConstants_1.ZERO;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.86.0-beta.4",
3
+ "version": "2.86.0-beta.6",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -3533,6 +3533,102 @@ export class AdminClient extends DriftClient {
3533
3533
  });
3534
3534
  }
3535
3535
 
3536
+ public async updateSpotMarketFuel(
3537
+ spotMarketIndex: number,
3538
+ fuelBoostDeposits?: number,
3539
+ fuelBoostBorrows?: number,
3540
+ fuelBoostTaker?: number,
3541
+ fuelBoostMaker?: number
3542
+ ): Promise<TransactionSignature> {
3543
+ const updateSpotMarketFuelIx = await this.getUpdateSpotMarketFuelIx(
3544
+ spotMarketIndex,
3545
+ fuelBoostDeposits || null,
3546
+ fuelBoostBorrows || null,
3547
+ fuelBoostTaker || null,
3548
+ fuelBoostMaker || null
3549
+ );
3550
+
3551
+ const tx = await this.buildTransaction(updateSpotMarketFuelIx);
3552
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
3553
+
3554
+ return txSig;
3555
+ }
3556
+
3557
+ public async getUpdateSpotMarketFuelIx(
3558
+ spotMarketIndex: number,
3559
+ fuelBoostDeposits?: number,
3560
+ fuelBoostBorrows?: number,
3561
+ fuelBoostTaker?: number,
3562
+ fuelBoostMaker?: number
3563
+ ): Promise<TransactionInstruction> {
3564
+ const spotMarketPublicKey = await getSpotMarketPublicKey(
3565
+ this.program.programId,
3566
+ spotMarketIndex
3567
+ );
3568
+
3569
+ return await this.program.instruction.updateSpotMarketFuel(
3570
+ fuelBoostDeposits || null,
3571
+ fuelBoostBorrows || null,
3572
+ fuelBoostTaker || null,
3573
+ fuelBoostMaker || null,
3574
+ {
3575
+ accounts: {
3576
+ admin: this.isSubscribed
3577
+ ? this.getStateAccount().admin
3578
+ : this.wallet.publicKey,
3579
+ state: await this.getStatePublicKey(),
3580
+ spotMarket: spotMarketPublicKey,
3581
+ },
3582
+ }
3583
+ );
3584
+ }
3585
+
3586
+ public async updatePerpMarketFuel(
3587
+ perpMarketIndex: number,
3588
+ fuelBoostTaker?: number,
3589
+ fuelBoostMaker?: number,
3590
+ fuelBoostPosition?: number
3591
+ ): Promise<TransactionSignature> {
3592
+ const updatePerpMarketFuelIx = await this.getUpdatePerpMarketFuelIx(
3593
+ perpMarketIndex,
3594
+ fuelBoostTaker || null,
3595
+ fuelBoostMaker || null,
3596
+ fuelBoostPosition || null
3597
+ );
3598
+
3599
+ const tx = await this.buildTransaction(updatePerpMarketFuelIx);
3600
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
3601
+
3602
+ return txSig;
3603
+ }
3604
+
3605
+ public async getUpdatePerpMarketFuelIx(
3606
+ perpMarketIndex: number,
3607
+ fuelBoostTaker?: number,
3608
+ fuelBoostMaker?: number,
3609
+ fuelBoostPosition?: number
3610
+ ): Promise<TransactionInstruction> {
3611
+ const perpMarketPublicKey = await getPerpMarketPublicKey(
3612
+ this.program.programId,
3613
+ perpMarketIndex
3614
+ );
3615
+
3616
+ return await this.program.instruction.updatePerpMarketFuel(
3617
+ fuelBoostTaker || null,
3618
+ fuelBoostMaker || null,
3619
+ fuelBoostPosition || null,
3620
+ {
3621
+ accounts: {
3622
+ admin: this.isSubscribed
3623
+ ? this.getStateAccount().admin
3624
+ : this.wallet.publicKey,
3625
+ state: await this.getStatePublicKey(),
3626
+ perpMarket: perpMarketPublicKey,
3627
+ },
3628
+ }
3629
+ );
3630
+ }
3631
+
3536
3632
  public async initializePythPullOracle(
3537
3633
  feedId: string
3538
3634
  ): Promise<TransactionSignature> {
@@ -105,3 +105,5 @@ export const IDLE_TIME_SLOTS = 9000;
105
105
  export const SLOT_TIME_ESTIMATE_MS = 400;
106
106
 
107
107
  export const DUST_POSITION_SIZE = QUOTE_PRECISION.divn(100); // Dust position is any position smaller than 1c
108
+
109
+ export const FUEL_WINDOW = new BN(60 * 60 * 24 * 28); // 28 days
@@ -337,14 +337,14 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
337
337
  {
338
338
  symbol: 'POPCAT',
339
339
  marketIndex: 20,
340
- oracle: new PublicKey('2stQe1XLGkuTZ22gQrgZKsb93iG9mWXSLfANMPRjs5Ky'),
340
+ oracle: new PublicKey('3GjpjC8TWsPqjyFSiR7saGxgzD8zqYJNsBnWpenZPEBy'),
341
341
  oracleSource: OracleSource.SWITCHBOARD,
342
342
  mint: new PublicKey('7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr'),
343
343
  precision: new BN(10).pow(NINE),
344
344
  precisionExp: NINE,
345
345
  launchTs: 1720013054000,
346
346
  phoenixMarket: new PublicKey(
347
- '3GjpjC8TWsPqjyFSiR7saGxgzD8zqYJNsBnWpenZPEBy'
347
+ '31XgvAQ1HgFQEk31KdszbPkVXKaQqB1bgYZPoDrFpSR2'
348
348
  ),
349
349
  },
350
350
  ];
@@ -2244,6 +2244,42 @@
2244
2244
  ],
2245
2245
  "args": []
2246
2246
  },
2247
+ {
2248
+ "name": "updateUserGovTokenInsuranceStake",
2249
+ "accounts": [
2250
+ {
2251
+ "name": "state",
2252
+ "isMut": false,
2253
+ "isSigner": false
2254
+ },
2255
+ {
2256
+ "name": "spotMarket",
2257
+ "isMut": false,
2258
+ "isSigner": false
2259
+ },
2260
+ {
2261
+ "name": "insuranceFundStake",
2262
+ "isMut": true,
2263
+ "isSigner": false
2264
+ },
2265
+ {
2266
+ "name": "userStats",
2267
+ "isMut": true,
2268
+ "isSigner": false
2269
+ },
2270
+ {
2271
+ "name": "authority",
2272
+ "isMut": false,
2273
+ "isSigner": true
2274
+ },
2275
+ {
2276
+ "name": "insuranceFundVault",
2277
+ "isMut": true,
2278
+ "isSigner": false
2279
+ }
2280
+ ],
2281
+ "args": []
2282
+ },
2247
2283
  {
2248
2284
  "name": "initializeInsuranceFundStake",
2249
2285
  "accounts": [
@@ -5079,6 +5115,92 @@
5079
5115
  }
5080
5116
  ]
5081
5117
  },
5118
+ {
5119
+ "name": "updatePerpMarketFuel",
5120
+ "accounts": [
5121
+ {
5122
+ "name": "admin",
5123
+ "isMut": false,
5124
+ "isSigner": true
5125
+ },
5126
+ {
5127
+ "name": "state",
5128
+ "isMut": false,
5129
+ "isSigner": false
5130
+ },
5131
+ {
5132
+ "name": "perpMarket",
5133
+ "isMut": true,
5134
+ "isSigner": false
5135
+ }
5136
+ ],
5137
+ "args": [
5138
+ {
5139
+ "name": "fuelBoostTaker",
5140
+ "type": {
5141
+ "option": "u8"
5142
+ }
5143
+ },
5144
+ {
5145
+ "name": "fuelBoostMaker",
5146
+ "type": {
5147
+ "option": "u8"
5148
+ }
5149
+ },
5150
+ {
5151
+ "name": "fuelBoostPosition",
5152
+ "type": {
5153
+ "option": "u8"
5154
+ }
5155
+ }
5156
+ ]
5157
+ },
5158
+ {
5159
+ "name": "updateSpotMarketFuel",
5160
+ "accounts": [
5161
+ {
5162
+ "name": "admin",
5163
+ "isMut": false,
5164
+ "isSigner": true
5165
+ },
5166
+ {
5167
+ "name": "state",
5168
+ "isMut": false,
5169
+ "isSigner": false
5170
+ },
5171
+ {
5172
+ "name": "spotMarket",
5173
+ "isMut": true,
5174
+ "isSigner": false
5175
+ }
5176
+ ],
5177
+ "args": [
5178
+ {
5179
+ "name": "fuelBoostDeposits",
5180
+ "type": {
5181
+ "option": "u8"
5182
+ }
5183
+ },
5184
+ {
5185
+ "name": "fuelBoostBorrows",
5186
+ "type": {
5187
+ "option": "u8"
5188
+ }
5189
+ },
5190
+ {
5191
+ "name": "fuelBoostTaker",
5192
+ "type": {
5193
+ "option": "u8"
5194
+ }
5195
+ },
5196
+ {
5197
+ "name": "fuelBoostMaker",
5198
+ "type": {
5199
+ "option": "u8"
5200
+ }
5201
+ }
5202
+ ]
5203
+ },
5082
5204
  {
5083
5205
  "name": "updateAdmin",
5084
5206
  "accounts": [
@@ -5918,12 +6040,36 @@
5918
6040
  ],
5919
6041
  "type": "i16"
5920
6042
  },
6043
+ {
6044
+ "name": "fuelBoostPosition",
6045
+ "docs": [
6046
+ "fuel multiplier for perp funding",
6047
+ "precision: 10"
6048
+ ],
6049
+ "type": "u8"
6050
+ },
6051
+ {
6052
+ "name": "fuelBoostTaker",
6053
+ "docs": [
6054
+ "fuel multiplier for perp taker",
6055
+ "precision: 10"
6056
+ ],
6057
+ "type": "u8"
6058
+ },
6059
+ {
6060
+ "name": "fuelBoostMaker",
6061
+ "docs": [
6062
+ "fuel multiplier for perp maker",
6063
+ "precision: 10"
6064
+ ],
6065
+ "type": "u8"
6066
+ },
5921
6067
  {
5922
6068
  "name": "padding",
5923
6069
  "type": {
5924
6070
  "array": [
5925
6071
  "u8",
5926
- 46
6072
+ 43
5927
6073
  ]
5928
6074
  }
5929
6075
  }
@@ -6376,12 +6522,44 @@
6376
6522
  ],
6377
6523
  "type": "u8"
6378
6524
  },
6525
+ {
6526
+ "name": "fuelBoostDeposits",
6527
+ "docs": [
6528
+ "fuel multiplier for spot deposits",
6529
+ "precision: 10"
6530
+ ],
6531
+ "type": "u8"
6532
+ },
6533
+ {
6534
+ "name": "fuelBoostBorrows",
6535
+ "docs": [
6536
+ "fuel multiplier for spot borrows",
6537
+ "precision: 10"
6538
+ ],
6539
+ "type": "u8"
6540
+ },
6541
+ {
6542
+ "name": "fuelBoostTaker",
6543
+ "docs": [
6544
+ "fuel multiplier for spot taker",
6545
+ "precision: 10"
6546
+ ],
6547
+ "type": "u8"
6548
+ },
6549
+ {
6550
+ "name": "fuelBoostMaker",
6551
+ "docs": [
6552
+ "fuel multiplier for spot maker",
6553
+ "precision: 10"
6554
+ ],
6555
+ "type": "u8"
6556
+ },
6379
6557
  {
6380
6558
  "name": "padding",
6381
6559
  "type": {
6382
6560
  "array": [
6383
6561
  "u8",
6384
- 47
6562
+ 43
6385
6563
  ]
6386
6564
  }
6387
6565
  }
@@ -6729,12 +6907,25 @@
6729
6907
  ],
6730
6908
  "type": "bool"
6731
6909
  },
6910
+ {
6911
+ "name": "padding1",
6912
+ "type": {
6913
+ "array": [
6914
+ "u8",
6915
+ 5
6916
+ ]
6917
+ }
6918
+ },
6919
+ {
6920
+ "name": "lastFuelBonusUpdateTs",
6921
+ "type": "i64"
6922
+ },
6732
6923
  {
6733
6924
  "name": "padding",
6734
6925
  "type": {
6735
6926
  "array": [
6736
6927
  "u8",
6737
- 21
6928
+ 8
6738
6929
  ]
6739
6930
  }
6740
6931
  }
@@ -6855,12 +7046,63 @@
6855
7046
  "name": "disableUpdatePerpBidAskTwap",
6856
7047
  "type": "bool"
6857
7048
  },
7049
+ {
7050
+ "name": "padding1",
7051
+ "type": {
7052
+ "array": [
7053
+ "u8",
7054
+ 6
7055
+ ]
7056
+ }
7057
+ },
7058
+ {
7059
+ "name": "fuelDeposits",
7060
+ "docs": [
7061
+ "sub account id for spot deposit, borrow fuel tracking"
7062
+ ],
7063
+ "type": "u32"
7064
+ },
7065
+ {
7066
+ "name": "fuelBorrows",
7067
+ "docs": [
7068
+ "accumulate fuel bonus for epoch"
7069
+ ],
7070
+ "type": "u32"
7071
+ },
7072
+ {
7073
+ "name": "fuelPositions",
7074
+ "docs": [
7075
+ "accumulated fuel for perp open interest"
7076
+ ],
7077
+ "type": "u32"
7078
+ },
7079
+ {
7080
+ "name": "fuelTaker",
7081
+ "docs": [
7082
+ "accumulate fuel bonus for epoch"
7083
+ ],
7084
+ "type": "u32"
7085
+ },
7086
+ {
7087
+ "name": "fuelMaker",
7088
+ "docs": [
7089
+ "accumulate fuel bonus for epoch"
7090
+ ],
7091
+ "type": "u32"
7092
+ },
7093
+ {
7094
+ "name": "ifStakedGovTokenAmount",
7095
+ "docs": [
7096
+ "The amount of tokens staked in the governance spot markets if"
7097
+ ],
7098
+ "type": "u64"
7099
+ },
6858
7100
  {
6859
7101
  "name": "padding",
6860
7102
  "type": {
6861
7103
  "array": [
6862
7104
  "u8",
6863
- 50
7105
+ 16
6864
7106
  ]
6865
7107
  }
6866
7108
  }
package/src/index.ts CHANGED
@@ -65,6 +65,7 @@ export * from './slot/SlotSubscriber';
65
65
  export * from './wallet';
66
66
  export * from './types';
67
67
  export * from './math/utils';
68
+ export * from './math/fuel';
68
69
  export * from './config';
69
70
  export * from './constants/numericConstants';
70
71
  export * from './serum/serumSubscriber';
@@ -0,0 +1,56 @@
1
+ import { BN } from '@coral-xyz/anchor';
2
+ import { SpotMarketAccount, PerpMarketAccount } from '..';
3
+ import {
4
+ QUOTE_PRECISION,
5
+ ZERO,
6
+ FUEL_WINDOW,
7
+ } from '../constants/numericConstants';
8
+
9
+ export function calculateSpotFuelBonus(
10
+ spotMarket: SpotMarketAccount,
11
+ signedTokenValue: BN,
12
+ fuelBonusNumerator: BN
13
+ ): BN {
14
+ let result: BN;
15
+
16
+ if (signedTokenValue.abs().lt(new BN(1))) {
17
+ result = ZERO;
18
+ } else if (signedTokenValue.gt(new BN(0))) {
19
+ result = signedTokenValue
20
+ .abs()
21
+ .mul(fuelBonusNumerator)
22
+ .mul(new BN(spotMarket.fuelBoostDeposits))
23
+ .div(FUEL_WINDOW)
24
+ .div(QUOTE_PRECISION.div(new BN(10)));
25
+ } else {
26
+ result = signedTokenValue
27
+ .abs()
28
+ .mul(fuelBonusNumerator)
29
+ .mul(new BN(spotMarket.fuelBoostBorrows))
30
+ .div(FUEL_WINDOW)
31
+ .div(QUOTE_PRECISION.div(new BN(10)));
32
+ }
33
+
34
+ return result;
35
+ }
36
+
37
+ export function calculatePerpFuelBonus(
38
+ perpMarket: PerpMarketAccount,
39
+ baseAssetValue: BN,
40
+ fuelBonusNumerator: BN
41
+ ): BN {
42
+ let result: BN;
43
+
44
+ if (baseAssetValue.abs().lte(QUOTE_PRECISION)) {
45
+ result = new BN(0);
46
+ } else {
47
+ result = baseAssetValue
48
+ .abs()
49
+ .mul(fuelBonusNumerator)
50
+ .mul(new BN(perpMarket.fuelBoostPosition))
51
+ .div(FUEL_WINDOW)
52
+ .div(QUOTE_PRECISION.div(new BN(10)));
53
+ }
54
+
55
+ return result;
56
+ }
package/src/types.ts CHANGED
@@ -636,6 +636,8 @@ export type PerpMarketAccount = {
636
636
  quoteSpotMarketIndex: number;
637
637
  feeAdjustment: number;
638
638
  pausedOperations: number;
639
+
640
+ fuelBoostPosition: number;
639
641
  };
640
642
 
641
643
  export type HistoricalOracleData = {
@@ -734,6 +736,9 @@ export type SpotMarketAccount = {
734
736
 
735
737
  maxTokenBorrowsFraction: number;
736
738
  minBorrowRate: number;
739
+
740
+ fuelBoostDeposits: number;
741
+ fuelBoostBorrows: number;
737
742
  };
738
743
 
739
744
  export type PoolBalance = {
@@ -876,6 +881,14 @@ export type UserStatsAccount = {
876
881
  isReferrer: boolean;
877
882
  authority: PublicKey;
878
883
  ifStakedQuoteAssetAmount: BN;
884
+
885
+ fuelDeposits: number;
886
+ fuelBorrows: number;
887
+ fuelPositions: number;
888
+ fuelTaker: number;
889
+ fuelMaker: number;
890
+
891
+ ifStakedGovTokenAmount: BN;
879
892
  };
880
893
 
881
894
  export type UserAccount = {
@@ -905,6 +918,8 @@ export type UserAccount = {
905
918
  hasOpenOrder: boolean;
906
919
  openAuctions: number;
907
920
  hasOpenAuction: boolean;
921
+
922
+ lastFuelBonusUpdateTs: BN;
908
923
  };
909
924
 
910
925
  export type SpotPosition = {
package/src/user.ts CHANGED
@@ -88,6 +88,8 @@ import { calculateLiveOracleTwap } from './math/oracles';
88
88
  import { getPerpMarketTierNumber, getSpotMarketTierNumber } from './math/tiers';
89
89
  import { StrictOraclePrice } from './oracles/strictOraclePrice';
90
90
 
91
+ import { calculateSpotFuelBonus, calculatePerpFuelBonus } from './math/fuel';
92
+
91
93
  export class User {
92
94
  driftClient: DriftClient;
93
95
  userAccountPublicKey: PublicKey;
@@ -873,6 +875,113 @@ export class User {
873
875
  }, ZERO);
874
876
  }
875
877
 
878
+ public getFuelBonus(
879
+ now: BN,
880
+ includeSettled = true,
881
+ includeUnsettled = true
882
+ ): {
883
+ depositFuel;
884
+ borrowFuel;
885
+ positionFuel;
886
+ takerFuel;
887
+ makerFuel;
888
+ } {
889
+ const userAccount: UserAccount = this.getUserAccount();
890
+
891
+ const result = {
892
+ takerFuel: ZERO,
893
+ makerFuel: ZERO,
894
+ depositFuel: ZERO,
895
+ borrowFuel: ZERO,
896
+ positionFuel: ZERO,
897
+ };
898
+
899
+ if (includeSettled) {
900
+ const userStats: UserStatsAccount = this.driftClient
901
+ .getUserStats()
902
+ .getAccount();
903
+ result.takerFuel = result.takerFuel.addn(userStats.fuelTaker);
904
+ result.makerFuel = result.makerFuel.addn(userStats.fuelMaker);
905
+ result.depositFuel = result.depositFuel.addn(userStats.fuelDeposits);
906
+ result.borrowFuel = result.borrowFuel.addn(userStats.fuelBorrows);
907
+ result.positionFuel = result.positionFuel.addn(userStats.fuelPositions);
908
+ }
909
+
910
+ if (includeUnsettled) {
911
+ const fuelBonusNumerator = now.sub(userAccount.lastFuelBonusUpdateTs);
912
+ for (const spotPosition of this.getActiveSpotPositions()) {
913
+ const spotMarketAccount: SpotMarketAccount =
914
+ this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
915
+
916
+ const tokenAmount = this.getTokenAmount(spotPosition.marketIndex);
917
+ const oraclePriceData = this.getOracleDataForSpotMarket(
918
+ spotPosition.marketIndex
919
+ );
920
+
921
+ const twap5min = calculateLiveOracleTwap(
922
+ spotMarketAccount.historicalOracleData,
923
+ oraclePriceData,
924
+ now,
925
+ FIVE_MINUTE // 5MIN
926
+ );
927
+ const strictOraclePrice = new StrictOraclePrice(
928
+ oraclePriceData.price,
929
+ twap5min
930
+ );
931
+
932
+ const signedTokenValue = getStrictTokenValue(
933
+ tokenAmount,
934
+ spotMarketAccount.decimals,
935
+ strictOraclePrice
936
+ );
937
+
938
+ if (signedTokenValue.gt(ZERO)) {
939
+ result.depositFuel = result.depositFuel.add(
940
+ calculateSpotFuelBonus(
941
+ spotMarketAccount,
942
+ signedTokenValue,
943
+ fuelBonusNumerator
944
+ )
945
+ );
946
+ } else {
947
+ result.borrowFuel = result.borrowFuel.add(
948
+ calculateSpotFuelBonus(
949
+ spotMarketAccount,
950
+ signedTokenValue,
951
+ fuelBonusNumerator
952
+ )
953
+ );
954
+ }
955
+ }
956
+
957
+ for (const perpPosition of this.getActivePerpPositions()) {
958
+ const oraclePriceData = this.getOracleDataForPerpMarket(
959
+ perpPosition.marketIndex
960
+ );
961
+
962
+ const perpMarketAccount = this.driftClient.getPerpMarketAccount(
963
+ perpPosition.marketIndex
964
+ );
965
+
966
+ const baseAssetValue = this.getPerpPositionValue(
967
+ perpPosition.marketIndex,
968
+ oraclePriceData,
969
+ false
970
+ );
971
+
972
+ result.positionFuel = result.positionFuel.add(
973
+ calculatePerpFuelBonus(
974
+ perpMarketAccount,
975
+ baseAssetValue,
976
+ fuelBonusNumerator
977
+ )
978
+ );
979
+ }
980
+ }
981
+
982
+ return result;
983
+ }
984
+
876
985
  public getSpotMarketAssetAndLiabilityValue(
877
986
  marketIndex?: number,
878
987
  marginCategory?: MarginCategory,