@drift-labs/sdk 2.86.0-beta.3 → 2.86.0-beta.30

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.
Files changed (42) hide show
  1. package/VERSION +1 -1
  2. package/lib/addresses/pda.d.ts +1 -0
  3. package/lib/addresses/pda.js +8 -1
  4. package/lib/adminClient.d.ts +8 -0
  5. package/lib/adminClient.js +79 -0
  6. package/lib/bankrun/bankrunConnection.d.ts +1 -0
  7. package/lib/bankrun/bankrunConnection.js +6 -0
  8. package/lib/constants/numericConstants.d.ts +3 -0
  9. package/lib/constants/numericConstants.js +4 -1
  10. package/lib/constants/perpMarkets.js +142 -118
  11. package/lib/constants/spotMarkets.js +40 -38
  12. package/lib/driftClient.d.ts +12 -14
  13. package/lib/driftClient.js +144 -9
  14. package/lib/idl/drift.json +551 -4
  15. package/lib/idl/pyth_solana_receiver.json +628 -0
  16. package/lib/index.d.ts +1 -0
  17. package/lib/index.js +1 -0
  18. package/lib/math/fuel.d.ts +6 -0
  19. package/lib/math/fuel.js +55 -0
  20. package/lib/types.d.ts +35 -2
  21. package/lib/types.js +3 -2
  22. package/lib/user.d.ts +8 -0
  23. package/lib/user.js +64 -0
  24. package/package.json +1 -1
  25. package/src/addresses/pda.ts +15 -0
  26. package/src/adminClient.ts +208 -0
  27. package/src/bankrun/bankrunConnection.ts +13 -0
  28. package/src/constants/numericConstants.ts +4 -0
  29. package/src/constants/perpMarkets.ts +146 -118
  30. package/src/constants/spotMarkets.ts +42 -38
  31. package/src/driftClient.ts +197 -16
  32. package/src/idl/drift.json +551 -4
  33. package/src/idl/openbook.json +3854 -0
  34. package/src/idl/pyth_solana_receiver.json +628 -0
  35. package/src/index.ts +1 -0
  36. package/src/math/fuel.ts +70 -0
  37. package/src/types.ts +42 -2
  38. package/src/user.ts +177 -0
  39. package/tests/ci/verifyConstants.ts +214 -0
  40. package/tests/dlob/helpers.ts +30 -0
  41. package/tests/user/helpers.ts +1 -0
  42. package/tests/user/test.ts +2 -0
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculatePerpFuelBonus = exports.calculateSpotFuelBonus = exports.calculateInsuranceFuelBonus = void 0;
4
+ const anchor_1 = require("@coral-xyz/anchor");
5
+ const numericConstants_1 = require("../constants/numericConstants");
6
+ function calculateInsuranceFuelBonus(spotMarket, tokenStakeAmount, fuelBonusNumerator) {
7
+ const result = tokenStakeAmount
8
+ .abs()
9
+ .mul(fuelBonusNumerator)
10
+ .mul(new anchor_1.BN(spotMarket.fuelBoostInsurance))
11
+ .div(numericConstants_1.FUEL_WINDOW)
12
+ .div(numericConstants_1.QUOTE_PRECISION.div(new anchor_1.BN(10)));
13
+ return result;
14
+ }
15
+ exports.calculateInsuranceFuelBonus = calculateInsuranceFuelBonus;
16
+ function calculateSpotFuelBonus(spotMarket, signedTokenValue, fuelBonusNumerator) {
17
+ let result;
18
+ if (signedTokenValue.abs().lte(numericConstants_1.QUOTE_PRECISION)) {
19
+ result = numericConstants_1.ZERO;
20
+ }
21
+ else if (signedTokenValue.gt(new anchor_1.BN(0))) {
22
+ result = signedTokenValue
23
+ .abs()
24
+ .mul(fuelBonusNumerator)
25
+ .mul(new anchor_1.BN(spotMarket.fuelBoostDeposits))
26
+ .div(numericConstants_1.FUEL_WINDOW)
27
+ .div(numericConstants_1.QUOTE_PRECISION.div(new anchor_1.BN(10)));
28
+ }
29
+ else {
30
+ result = signedTokenValue
31
+ .abs()
32
+ .mul(fuelBonusNumerator)
33
+ .mul(new anchor_1.BN(spotMarket.fuelBoostBorrows))
34
+ .div(numericConstants_1.FUEL_WINDOW)
35
+ .div(numericConstants_1.QUOTE_PRECISION.div(new anchor_1.BN(10)));
36
+ }
37
+ return result;
38
+ }
39
+ exports.calculateSpotFuelBonus = calculateSpotFuelBonus;
40
+ function calculatePerpFuelBonus(perpMarket, baseAssetValue, fuelBonusNumerator) {
41
+ let result;
42
+ if (baseAssetValue.abs().lte(numericConstants_1.QUOTE_PRECISION)) {
43
+ result = new anchor_1.BN(0);
44
+ }
45
+ else {
46
+ result = baseAssetValue
47
+ .abs()
48
+ .mul(fuelBonusNumerator)
49
+ .mul(new anchor_1.BN(perpMarket.fuelBoostPosition))
50
+ .div(numericConstants_1.FUEL_WINDOW)
51
+ .div(numericConstants_1.QUOTE_PRECISION.div(new anchor_1.BN(10)));
52
+ }
53
+ return result;
54
+ }
55
+ exports.calculatePerpFuelBonus = calculatePerpFuelBonus;
package/lib/types.d.ts CHANGED
@@ -55,8 +55,9 @@ export declare enum PerpOperation {
55
55
  export declare enum SpotOperation {
56
56
  UPDATE_CUMULATIVE_INTEREST = 1,
57
57
  FILL = 2,
58
- WITHDRAW = 4,
59
- LIQUIDATION = 8
58
+ DEPOSIT = 4,
59
+ WITHDRAW = 8,
60
+ LIQUIDATION = 16
60
61
  }
61
62
  export declare enum InsuranceFundOperation {
62
63
  INIT = 1,
@@ -731,6 +732,9 @@ export type PerpMarketAccount = {
731
732
  quoteSpotMarketIndex: number;
732
733
  feeAdjustment: number;
733
734
  pausedOperations: number;
735
+ fuelBoostTaker: number;
736
+ fuelBoostMaker: number;
737
+ fuelBoostPosition: number;
734
738
  };
735
739
  export type HistoricalOracleData = {
736
740
  lastOraclePrice: BN;
@@ -812,6 +816,11 @@ export type SpotMarketAccount = {
812
816
  ifPausedOperations: number;
813
817
  maxTokenBorrowsFraction: number;
814
818
  minBorrowRate: number;
819
+ fuelBoostDeposits: number;
820
+ fuelBoostBorrows: number;
821
+ fuelBoostTaker: number;
822
+ fuelBoostMaker: number;
823
+ fuelBoostInsurance: number;
815
824
  };
816
825
  export type PoolBalance = {
817
826
  scaledBalance: BN;
@@ -939,6 +948,14 @@ export type UserStatsAccount = {
939
948
  isReferrer: boolean;
940
949
  authority: PublicKey;
941
950
  ifStakedQuoteAssetAmount: BN;
951
+ lastFuelIfBonusUpdateTs: number;
952
+ fuelInsurance: number;
953
+ fuelDeposits: number;
954
+ fuelBorrows: number;
955
+ fuelPositions: number;
956
+ fuelTaker: number;
957
+ fuelMaker: number;
958
+ ifStakedGovTokenAmount: BN;
942
959
  };
943
960
  export type UserAccount = {
944
961
  authority: PublicKey;
@@ -967,6 +984,7 @@ export type UserAccount = {
967
984
  hasOpenOrder: boolean;
968
985
  openAuctions: number;
969
986
  hasOpenAuction: boolean;
987
+ lastFuelBonusUpdateTs: number;
970
988
  };
971
989
  export type SpotPosition = {
972
990
  marketIndex: number;
@@ -1185,6 +1203,21 @@ export type PhoenixV1FulfillmentConfigAccount = {
1185
1203
  fulfillmentType: SpotFulfillmentType;
1186
1204
  status: SpotFulfillmentStatus;
1187
1205
  };
1206
+ export type OpenbookV2FulfillmentConfigAccount = {
1207
+ pubkey: PublicKey;
1208
+ openbookV2ProgramId: PublicKey;
1209
+ openbookV2Market: PublicKey;
1210
+ openbookV2MarketAuthority: PublicKey;
1211
+ openbookV2EventHeap: PublicKey;
1212
+ openbookV2Bids: PublicKey;
1213
+ openbookV2Asks: PublicKey;
1214
+ openbookV2BaseVault: PublicKey;
1215
+ openbookV2QuoteVault: PublicKey;
1216
+ marketIndex: number;
1217
+ fulfillmentType: SpotFulfillmentType;
1218
+ status: SpotFulfillmentStatus;
1219
+ remainingAccounts?: PublicKey[];
1220
+ };
1188
1221
  export type ReferrerNameAccount = {
1189
1222
  name: number[];
1190
1223
  user: PublicKey;
package/lib/types.js CHANGED
@@ -40,8 +40,9 @@ var SpotOperation;
40
40
  (function (SpotOperation) {
41
41
  SpotOperation[SpotOperation["UPDATE_CUMULATIVE_INTEREST"] = 1] = "UPDATE_CUMULATIVE_INTEREST";
42
42
  SpotOperation[SpotOperation["FILL"] = 2] = "FILL";
43
- SpotOperation[SpotOperation["WITHDRAW"] = 4] = "WITHDRAW";
44
- SpotOperation[SpotOperation["LIQUIDATION"] = 8] = "LIQUIDATION";
43
+ SpotOperation[SpotOperation["DEPOSIT"] = 4] = "DEPOSIT";
44
+ SpotOperation[SpotOperation["WITHDRAW"] = 8] = "WITHDRAW";
45
+ SpotOperation[SpotOperation["LIQUIDATION"] = 16] = "LIQUIDATION";
45
46
  })(SpotOperation = exports.SpotOperation || (exports.SpotOperation = {}));
46
47
  var InsuranceFundOperation;
47
48
  (function (InsuranceFundOperation) {
package/lib/user.d.ts CHANGED
@@ -136,6 +136,14 @@ 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: BN;
141
+ borrowFuel: BN;
142
+ positionFuel: BN;
143
+ takerFuel: BN;
144
+ makerFuel: BN;
145
+ insuranceFuel: BN;
146
+ };
139
147
  getSpotMarketAssetAndLiabilityValue(marketIndex?: number, marginCategory?: MarginCategory, liquidationBuffer?: BN, includeOpenOrders?: boolean, strict?: boolean, now?: BN): {
140
148
  totalAssetValue: BN;
141
149
  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,69 @@ 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
+ insuranceFuel: numericConstants_1.ZERO,
547
+ takerFuel: numericConstants_1.ZERO,
548
+ makerFuel: numericConstants_1.ZERO,
549
+ depositFuel: numericConstants_1.ZERO,
550
+ borrowFuel: numericConstants_1.ZERO,
551
+ positionFuel: numericConstants_1.ZERO,
552
+ };
553
+ if (includeSettled) {
554
+ const userStats = this.driftClient
555
+ .getUserStats()
556
+ .getAccount();
557
+ result.insuranceFuel = result.insuranceFuel.add(new _1.BN(userStats.fuelInsurance));
558
+ result.takerFuel = result.takerFuel.add(new _1.BN(userStats.fuelTaker));
559
+ result.makerFuel = result.makerFuel.add(new _1.BN(userStats.fuelMaker));
560
+ result.depositFuel = result.depositFuel.add(new _1.BN(userStats.fuelDeposits));
561
+ result.borrowFuel = result.borrowFuel.add(new _1.BN(userStats.fuelBorrows));
562
+ result.positionFuel = result.positionFuel.add(new _1.BN(userStats.fuelPositions));
563
+ }
564
+ if (includeUnsettled) {
565
+ const fuelBonusNumerator = _1.BN.max(now.sub(_1.BN.max(new _1.BN(userAccount.lastFuelBonusUpdateTs), numericConstants_1.FUEL_START_TS)), numericConstants_1.ZERO);
566
+ if (fuelBonusNumerator.gt(numericConstants_1.ZERO)) {
567
+ for (const spotPosition of this.getActiveSpotPositions()) {
568
+ const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
569
+ const tokenAmount = this.getTokenAmount(spotPosition.marketIndex);
570
+ const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
571
+ const twap5min = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
572
+ );
573
+ const strictOraclePrice = new strictOraclePrice_1.StrictOraclePrice(oraclePriceData.price, twap5min);
574
+ const signedTokenValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
575
+ if (signedTokenValue.gt(numericConstants_1.ZERO)) {
576
+ result.depositFuel = result.depositFuel.add((0, fuel_1.calculateSpotFuelBonus)(spotMarketAccount, signedTokenValue, fuelBonusNumerator));
577
+ }
578
+ else {
579
+ result.borrowFuel = result.borrowFuel.add((0, fuel_1.calculateSpotFuelBonus)(spotMarketAccount, signedTokenValue, fuelBonusNumerator));
580
+ }
581
+ }
582
+ for (const perpPosition of this.getActivePerpPositions()) {
583
+ const oraclePriceData = this.getOracleDataForPerpMarket(perpPosition.marketIndex);
584
+ const perpMarketAccount = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
585
+ const baseAssetValue = this.getPerpPositionValue(perpPosition.marketIndex, oraclePriceData, false);
586
+ result.positionFuel = result.positionFuel.add((0, fuel_1.calculatePerpFuelBonus)(perpMarketAccount, baseAssetValue, fuelBonusNumerator));
587
+ }
588
+ }
589
+ const userStats = this.driftClient
590
+ .getUserStats()
591
+ .getAccount();
592
+ // todo: get real time ifStakedGovTokenAmount using ifStakeAccount
593
+ if (userStats.ifStakedGovTokenAmount.gt(numericConstants_1.ZERO)) {
594
+ const spotMarketAccount = this.driftClient.getSpotMarketAccount(numericConstants_1.GOV_SPOT_MARKET_INDEX);
595
+ const fuelBonusNumeratorUserStats = _1.BN.max(now.sub(_1.BN.max(new _1.BN(userStats.lastFuelIfBonusUpdateTs), numericConstants_1.FUEL_START_TS)), numericConstants_1.ZERO);
596
+ result.insuranceFuel = result.insuranceFuel.add((0, fuel_1.calculateInsuranceFuelBonus)(spotMarketAccount, userStats.ifStakedGovTokenAmount, fuelBonusNumeratorUserStats));
597
+ }
598
+ if (userStats.ifStakedQuoteAssetAmount.gt(numericConstants_1.ZERO)) {
599
+ const spotMarketAccount = this.driftClient.getSpotMarketAccount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
600
+ const fuelBonusNumeratorUserStats = _1.BN.max(now.sub(_1.BN.max(new _1.BN(userStats.lastFuelIfBonusUpdateTs), numericConstants_1.FUEL_START_TS)), numericConstants_1.ZERO);
601
+ result.insuranceFuel = result.insuranceFuel.add((0, fuel_1.calculateInsuranceFuelBonus)(spotMarketAccount, userStats.ifStakedQuoteAssetAmount, fuelBonusNumeratorUserStats));
602
+ }
603
+ }
604
+ return result;
605
+ }
542
606
  getSpotMarketAssetAndLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false, now) {
543
607
  now = now || new _1.BN(new Date().getTime() / 1000);
544
608
  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.3",
3
+ "version": "2.86.0-beta.30",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -202,6 +202,21 @@ export function getPhoenixFulfillmentConfigPublicKey(
202
202
  )[0];
203
203
  }
204
204
 
205
+ export function getOpenbookV2FulfillmentConfigPublicKey(
206
+ programId: PublicKey,
207
+ market: PublicKey
208
+ ): PublicKey {
209
+ return PublicKey.findProgramAddressSync(
210
+ [
211
+ Buffer.from(
212
+ anchor.utils.bytes.utf8.encode('openbook_v2_fulfillment_config')
213
+ ),
214
+ market.toBuffer(),
215
+ ],
216
+ programId
217
+ )[0];
218
+ }
219
+
205
220
  export function getReferrerNamePublicKeySync(
206
221
  programId: PublicKey,
207
222
  nameBuffer: number[]
@@ -29,7 +29,9 @@ import {
29
29
  getPhoenixFulfillmentConfigPublicKey,
30
30
  getProtocolIfSharesTransferConfigPublicKey,
31
31
  getPrelaunchOraclePublicKey,
32
+ getOpenbookV2FulfillmentConfigPublicKey,
32
33
  getPythPullOraclePublicKey,
34
+ getUserStatsAccountPublicKey,
33
35
  } from './addresses/pda';
34
36
  import { squareRootBN } from './math/utils';
35
37
  import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
@@ -48,6 +50,10 @@ import { PROGRAM_ID as PHOENIX_PROGRAM_ID } from '@ellipsis-labs/phoenix-sdk';
48
50
  import { DRIFT_ORACLE_RECEIVER_ID } from './config';
49
51
  import { getFeedIdUint8Array } from './util/pythPullOracleUtils';
50
52
 
53
+ const OPENBOOK_PROGRAM_ID = new PublicKey(
54
+ 'opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb'
55
+ );
56
+
51
57
  export class AdminClient extends DriftClient {
52
58
  public async initialize(
53
59
  usdcMint: PublicKey,
@@ -385,6 +391,52 @@ export class AdminClient extends DriftClient {
385
391
  );
386
392
  }
387
393
 
394
+ public async initializeOpenbookV2FulfillmentConfig(
395
+ marketIndex: number,
396
+ openbookMarket: PublicKey
397
+ ): Promise<TransactionSignature> {
398
+ const initializeIx = await this.getInitializeOpenbookV2FulfillmentConfigIx(
399
+ marketIndex,
400
+ openbookMarket
401
+ );
402
+
403
+ const tx = await this.buildTransaction(initializeIx);
404
+
405
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
406
+
407
+ return txSig;
408
+ }
409
+
410
+ public async getInitializeOpenbookV2FulfillmentConfigIx(
411
+ marketIndex: number,
412
+ openbookMarket: PublicKey
413
+ ): Promise<TransactionInstruction> {
414
+ const openbookFulfillmentConfig = getOpenbookV2FulfillmentConfigPublicKey(
415
+ this.program.programId,
416
+ openbookMarket
417
+ );
418
+
419
+ return this.program.instruction.initializeOpenbookV2FulfillmentConfig(
420
+ marketIndex,
421
+ {
422
+ accounts: {
423
+ baseSpotMarket: this.getSpotMarketAccount(marketIndex).pubkey,
424
+ quoteSpotMarket: this.getQuoteSpotMarketAccount().pubkey,
425
+ state: await this.getStatePublicKey(),
426
+ openbookV2Program: OPENBOOK_PROGRAM_ID,
427
+ openbookV2Market: openbookMarket,
428
+ driftSigner: this.getSignerPublicKey(),
429
+ openbookV2FulfillmentConfig: openbookFulfillmentConfig,
430
+ admin: this.isSubscribed
431
+ ? this.getStateAccount().admin
432
+ : this.wallet.publicKey,
433
+ rent: SYSVAR_RENT_PUBKEY,
434
+ systemProgram: anchor.web3.SystemProgram.programId,
435
+ },
436
+ }
437
+ );
438
+ }
439
+
388
440
  public async initializePerpMarket(
389
441
  marketIndex: number,
390
442
  priceOracle: PublicKey,
@@ -3533,6 +3585,162 @@ export class AdminClient extends DriftClient {
3533
3585
  });
3534
3586
  }
3535
3587
 
3588
+ public async updateSpotMarketFuel(
3589
+ spotMarketIndex: number,
3590
+ fuelBoostDeposits?: number,
3591
+ fuelBoostBorrows?: number,
3592
+ fuelBoostTaker?: number,
3593
+ fuelBoostMaker?: number,
3594
+ fuelBoostInsurance?: number
3595
+ ): Promise<TransactionSignature> {
3596
+ const updateSpotMarketFuelIx = await this.getUpdateSpotMarketFuelIx(
3597
+ spotMarketIndex,
3598
+ fuelBoostDeposits || null,
3599
+ fuelBoostBorrows || null,
3600
+ fuelBoostTaker || null,
3601
+ fuelBoostMaker || null,
3602
+ fuelBoostInsurance || null
3603
+ );
3604
+
3605
+ const tx = await this.buildTransaction(updateSpotMarketFuelIx);
3606
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
3607
+
3608
+ return txSig;
3609
+ }
3610
+
3611
+ public async getUpdateSpotMarketFuelIx(
3612
+ spotMarketIndex: number,
3613
+ fuelBoostDeposits?: number,
3614
+ fuelBoostBorrows?: number,
3615
+ fuelBoostTaker?: number,
3616
+ fuelBoostMaker?: number,
3617
+ fuelBoostInsurance?: number
3618
+ ): Promise<TransactionInstruction> {
3619
+ const spotMarketPublicKey = await getSpotMarketPublicKey(
3620
+ this.program.programId,
3621
+ spotMarketIndex
3622
+ );
3623
+
3624
+ return await this.program.instruction.updateSpotMarketFuel(
3625
+ fuelBoostDeposits || null,
3626
+ fuelBoostBorrows || null,
3627
+ fuelBoostTaker || null,
3628
+ fuelBoostMaker || null,
3629
+ fuelBoostInsurance || null,
3630
+ {
3631
+ accounts: {
3632
+ admin: this.isSubscribed
3633
+ ? this.getStateAccount().admin
3634
+ : this.wallet.publicKey,
3635
+ state: await this.getStatePublicKey(),
3636
+ spotMarket: spotMarketPublicKey,
3637
+ },
3638
+ }
3639
+ );
3640
+ }
3641
+
3642
+ public async updatePerpMarketFuel(
3643
+ perpMarketIndex: number,
3644
+ fuelBoostTaker?: number,
3645
+ fuelBoostMaker?: number,
3646
+ fuelBoostPosition?: number
3647
+ ): Promise<TransactionSignature> {
3648
+ const updatePerpMarketFuelIx = await this.getUpdatePerpMarketFuelIx(
3649
+ perpMarketIndex,
3650
+ fuelBoostTaker || null,
3651
+ fuelBoostMaker || null,
3652
+ fuelBoostPosition || null
3653
+ );
3654
+
3655
+ const tx = await this.buildTransaction(updatePerpMarketFuelIx);
3656
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
3657
+
3658
+ return txSig;
3659
+ }
3660
+
3661
+ public async getUpdatePerpMarketFuelIx(
3662
+ perpMarketIndex: number,
3663
+ fuelBoostTaker?: number,
3664
+ fuelBoostMaker?: number,
3665
+ fuelBoostPosition?: number
3666
+ ): Promise<TransactionInstruction> {
3667
+ const perpMarketPublicKey = await getPerpMarketPublicKey(
3668
+ this.program.programId,
3669
+ perpMarketIndex
3670
+ );
3671
+
3672
+ return await this.program.instruction.updatePerpMarketFuel(
3673
+ fuelBoostTaker || null,
3674
+ fuelBoostMaker || null,
3675
+ fuelBoostPosition || null,
3676
+ {
3677
+ accounts: {
3678
+ admin: this.isSubscribed
3679
+ ? this.getStateAccount().admin
3680
+ : this.wallet.publicKey,
3681
+ state: await this.getStatePublicKey(),
3682
+ perpMarket: perpMarketPublicKey,
3683
+ },
3684
+ }
3685
+ );
3686
+ }
3687
+
3688
+ public async initUserFuel(
3689
+ user: PublicKey,
3690
+ authority: PublicKey,
3691
+ fuelBonusDeposits?: number,
3692
+ fuelBonusBorrows?: number,
3693
+ fuelBonusTaker?: number,
3694
+ fuelBonusMaker?: number,
3695
+ fuelBonusInsurance?: number
3696
+ ): Promise<TransactionSignature> {
3697
+ const updatePerpMarketFuelIx = await this.getInitUserFuelIx(
3698
+ user,
3699
+ authority,
3700
+ fuelBonusDeposits,
3701
+ fuelBonusBorrows,
3702
+ fuelBonusTaker,
3703
+ fuelBonusMaker,
3704
+ fuelBonusInsurance
3705
+ );
3706
+
3707
+ const tx = await this.buildTransaction(updatePerpMarketFuelIx);
3708
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
3709
+
3710
+ return txSig;
3711
+ }
3712
+
3713
+ public async getInitUserFuelIx(
3714
+ user: PublicKey,
3715
+ authority: PublicKey,
3716
+ fuelBonusDeposits?: number,
3717
+ fuelBonusBorrows?: number,
3718
+ fuelBonusTaker?: number,
3719
+ fuelBonusMaker?: number,
3720
+ fuelBonusInsurance?: number
3721
+ ): Promise<TransactionInstruction> {
3722
+ const userStats = await getUserStatsAccountPublicKey(
3723
+ this.program.programId,
3724
+ authority
3725
+ );
3726
+
3727
+ return await this.program.instruction.initUserFuel(
3728
+ fuelBonusDeposits || null,
3729
+ fuelBonusBorrows || null,
3730
+ fuelBonusTaker || null,
3731
+ fuelBonusMaker || null,
3732
+ fuelBonusInsurance || null,
3733
+ {
3734
+ accounts: {
3735
+ admin: this.wallet.publicKey,
3736
+ state: await this.getStatePublicKey(),
3737
+ user,
3738
+ userStats,
3739
+ },
3740
+ }
3741
+ );
3742
+ }
3743
+
3536
3744
  public async initializePythPullOracle(
3537
3745
  feedId: string
3538
3746
  ): Promise<TransactionSignature> {
@@ -118,6 +118,19 @@ export class BankrunContextWrapper {
118
118
  );
119
119
  await this.context.setClock(newClock);
120
120
  }
121
+
122
+ async setTimestamp(unix_timestamp: number): Promise<void> {
123
+ const currentClock = await this.context.banksClient.getClock();
124
+ const newUnixTimestamp = BigInt(unix_timestamp);
125
+ const newClock = new Clock(
126
+ currentClock.slot,
127
+ currentClock.epochStartTimestamp,
128
+ currentClock.epoch,
129
+ currentClock.leaderScheduleEpoch,
130
+ newUnixTimestamp
131
+ );
132
+ await this.context.setClock(newClock);
133
+ }
121
134
  }
122
135
 
123
136
  export class BankrunConnection {
@@ -90,6 +90,7 @@ export const ONE_HOUR = new BN(60 * 60);
90
90
  export const ONE_YEAR = new BN(31536000);
91
91
 
92
92
  export const QUOTE_SPOT_MARKET_INDEX = 0;
93
+ export const GOV_SPOT_MARKET_INDEX = 15;
93
94
 
94
95
  export const LAMPORTS_PRECISION = new BN(LAMPORTS_PER_SOL);
95
96
  export const LAMPORTS_EXP = new BN(Math.log10(LAMPORTS_PER_SOL));
@@ -105,3 +106,6 @@ export const IDLE_TIME_SLOTS = 9000;
105
106
  export const SLOT_TIME_ESTIMATE_MS = 400;
106
107
 
107
108
  export const DUST_POSITION_SIZE = QUOTE_PRECISION.divn(100); // Dust position is any position smaller than 1c
109
+
110
+ export const FUEL_WINDOW = new BN(60 * 60 * 24 * 28); // 28 days
111
+ export const FUEL_START_TS = new BN(1722384000); // unix timestamp