@drift-labs/sdk 2.84.0-beta.6 → 2.85.0-beta.0

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.84.0-beta.6
1
+ 2.85.0-beta.0
@@ -89,6 +89,8 @@ export declare class AdminClient extends DriftClient {
89
89
  getUpdateSpotMarketRevenueSettlePeriodIx(spotMarketIndex: number, revenueSettlePeriod: BN): Promise<TransactionInstruction>;
90
90
  updateSpotMarketMaxTokenDeposits(spotMarketIndex: number, maxTokenDeposits: BN): Promise<TransactionSignature>;
91
91
  getUpdateSpotMarketMaxTokenDepositsIx(spotMarketIndex: number, maxTokenDeposits: BN): Promise<TransactionInstruction>;
92
+ updateSpotMarketMaxTokenBorrows(spotMarketIndex: number, maxTokenBorrows: BN): Promise<TransactionSignature>;
93
+ getUpdateSpotMarketMaxTokenBorrowsIx(spotMarketIndex: number, maxTokenBorrows: BN): Promise<TransactionInstruction>;
92
94
  updateSpotMarketScaleInitialAssetWeightStart(spotMarketIndex: number, scaleInitialAssetWeightStart: BN): Promise<TransactionSignature>;
93
95
  getUpdateSpotMarketScaleInitialAssetWeightStartIx(spotMarketIndex: number, scaleInitialAssetWeightStart: BN): Promise<TransactionInstruction>;
94
96
  updateInsuranceFundUnstakingPeriod(spotMarketIndex: number, insuranceWithdrawEscrowPeriod: BN): Promise<TransactionSignature>;
@@ -125,8 +127,8 @@ export declare class AdminClient extends DriftClient {
125
127
  getUpdateDiscountMintIx(discountMint: PublicKey): Promise<TransactionInstruction>;
126
128
  updateSpotMarketMarginWeights(spotMarketIndex: number, initialAssetWeight: number, maintenanceAssetWeight: number, initialLiabilityWeight: number, maintenanceLiabilityWeight: number, imfFactor?: number): Promise<TransactionSignature>;
127
129
  getUpdateSpotMarketMarginWeightsIx(spotMarketIndex: number, initialAssetWeight: number, maintenanceAssetWeight: number, initialLiabilityWeight: number, maintenanceLiabilityWeight: number, imfFactor?: number): Promise<TransactionInstruction>;
128
- updateSpotMarketBorrowRate(spotMarketIndex: number, optimalUtilization: number, optimalBorrowRate: number, optimalMaxRate: number): Promise<TransactionSignature>;
129
- getUpdateSpotMarketBorrowRateIx(spotMarketIndex: number, optimalUtilization: number, optimalBorrowRate: number, optimalMaxRate: number): Promise<TransactionInstruction>;
130
+ updateSpotMarketBorrowRate(spotMarketIndex: number, optimalUtilization: number, optimalBorrowRate: number, optimalMaxRate: number, minBorrowRate?: number | undefined): Promise<TransactionSignature>;
131
+ getUpdateSpotMarketBorrowRateIx(spotMarketIndex: number, optimalUtilization: number, optimalBorrowRate: number, optimalMaxRate: number, minBorrowRate?: number | undefined): Promise<TransactionInstruction>;
130
132
  updateSpotMarketAssetTier(spotMarketIndex: number, assetTier: AssetTier): Promise<TransactionSignature>;
131
133
  getUpdateSpotMarketAssetTierIx(spotMarketIndex: number, assetTier: AssetTier): Promise<TransactionInstruction>;
132
134
  updateSpotMarketStatus(spotMarketIndex: number, marketStatus: MarketStatus): Promise<TransactionSignature>;
@@ -829,6 +829,23 @@ class AdminClient extends driftClient_1.DriftClient {
829
829
  },
830
830
  });
831
831
  }
832
+ async updateSpotMarketMaxTokenBorrows(spotMarketIndex, maxTokenBorrows) {
833
+ const updateSpotMarketMaxTokenBorrowsIx = await this.getUpdateSpotMarketMaxTokenBorrowsIx(spotMarketIndex, maxTokenBorrows);
834
+ const tx = await this.buildTransaction(updateSpotMarketMaxTokenBorrowsIx);
835
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
836
+ return txSig;
837
+ }
838
+ async getUpdateSpotMarketMaxTokenBorrowsIx(spotMarketIndex, maxTokenBorrows) {
839
+ return this.program.instruction.updateSpotMarketMaxTokenBorrows(maxTokenBorrows, {
840
+ accounts: {
841
+ admin: this.isSubscribed
842
+ ? this.getStateAccount().admin
843
+ : this.wallet.publicKey,
844
+ state: await this.getStatePublicKey(),
845
+ spotMarket: await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex),
846
+ },
847
+ });
848
+ }
832
849
  async updateSpotMarketScaleInitialAssetWeightStart(spotMarketIndex, scaleInitialAssetWeightStart) {
833
850
  const updateSpotMarketScaleInitialAssetWeightStartIx = await this.getUpdateSpotMarketScaleInitialAssetWeightStartIx(spotMarketIndex, scaleInitialAssetWeightStart);
834
851
  const tx = await this.buildTransaction(updateSpotMarketScaleInitialAssetWeightStartIx);
@@ -1150,14 +1167,14 @@ class AdminClient extends driftClient_1.DriftClient {
1150
1167
  },
1151
1168
  });
1152
1169
  }
1153
- async updateSpotMarketBorrowRate(spotMarketIndex, optimalUtilization, optimalBorrowRate, optimalMaxRate) {
1154
- const updateSpotMarketBorrowRateIx = await this.getUpdateSpotMarketBorrowRateIx(spotMarketIndex, optimalUtilization, optimalBorrowRate, optimalMaxRate);
1170
+ async updateSpotMarketBorrowRate(spotMarketIndex, optimalUtilization, optimalBorrowRate, optimalMaxRate, minBorrowRate) {
1171
+ const updateSpotMarketBorrowRateIx = await this.getUpdateSpotMarketBorrowRateIx(spotMarketIndex, optimalUtilization, optimalBorrowRate, optimalMaxRate, minBorrowRate);
1155
1172
  const tx = await this.buildTransaction(updateSpotMarketBorrowRateIx);
1156
1173
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
1157
1174
  return txSig;
1158
1175
  }
1159
- async getUpdateSpotMarketBorrowRateIx(spotMarketIndex, optimalUtilization, optimalBorrowRate, optimalMaxRate) {
1160
- return await this.program.instruction.updateSpotMarketBorrowRate(optimalUtilization, optimalBorrowRate, optimalMaxRate, {
1176
+ async getUpdateSpotMarketBorrowRateIx(spotMarketIndex, optimalUtilization, optimalBorrowRate, optimalMaxRate, minBorrowRate) {
1177
+ return await this.program.instruction.updateSpotMarketBorrowRate(optimalUtilization, optimalBorrowRate, optimalMaxRate, minBorrowRate, {
1161
1178
  accounts: {
1162
1179
  admin: this.isSubscribed
1163
1180
  ? this.getStateAccount().admin
@@ -13,7 +13,13 @@ export declare class BlockhashSubscriber {
13
13
  getBlockhashCacheSize(): number;
14
14
  getLatestBlockHeight(): number;
15
15
  getLatestBlockHeightContext(): Context | undefined;
16
- getLatestBlockhash(offset?: number): BlockhashWithExpiryBlockHeight | undefined;
16
+ /**
17
+ * Returns the latest cached blockhash, based on an offset from the latest obtained
18
+ * @param offset Offset to use, defaulting to 0
19
+ * @param offsetType If 'seconds', it will use calculate the actual element offset based on the update interval; otherwise it will return a fixed index
20
+ * @returns Cached blockhash at the given offset, or undefined
21
+ */
22
+ getLatestBlockhash(offset?: number, offsetType?: 'index' | 'seconds'): BlockhashWithExpiryBlockHeight | undefined;
17
23
  pruneBlockhashes(): void;
18
24
  updateBlockhash(): Promise<void>;
19
25
  subscribe(): Promise<void>;
@@ -23,11 +23,20 @@ class BlockhashSubscriber {
23
23
  getLatestBlockHeightContext() {
24
24
  return this.latestBlockHeightContext;
25
25
  }
26
- getLatestBlockhash(offset) {
26
+ /**
27
+ * Returns the latest cached blockhash, based on an offset from the latest obtained
28
+ * @param offset Offset to use, defaulting to 0
29
+ * @param offsetType If 'seconds', it will use calculate the actual element offset based on the update interval; otherwise it will return a fixed index
30
+ * @returns Cached blockhash at the given offset, or undefined
31
+ */
32
+ getLatestBlockhash(offset = 0, offsetType = 'index') {
27
33
  if (this.blockhashes.length === 0) {
28
34
  return undefined;
29
35
  }
30
- const clampedOffset = Math.max(0, Math.min(this.blockhashes.length - 1, offset !== null && offset !== void 0 ? offset : 0));
36
+ const elementOffset = offsetType == 'seconds'
37
+ ? Math.floor((offset * 1000) / this.updateIntervalMs)
38
+ : offset;
39
+ const clampedOffset = Math.max(0, Math.min(this.blockhashes.length - 1, elementOffset));
31
40
  return this.blockhashes[this.blockhashes.length - 1 - clampedOffset];
32
41
  }
33
42
  pruneBlockhashes() {
@@ -99,7 +99,9 @@ export declare class DriftClient {
99
99
  getQuoteSpotMarketAccount(): SpotMarketAccount;
100
100
  getOraclePriceDataAndSlot(oraclePublicKey: PublicKey): DataAndSlot<OraclePriceData> | undefined;
101
101
  getSerumV3FulfillmentConfig(serumMarket: PublicKey): Promise<SerumV3FulfillmentConfigAccount>;
102
+ getSerumV3FulfillmentConfigs(): Promise<SerumV3FulfillmentConfigAccount[]>;
102
103
  getPhoenixV1FulfillmentConfig(phoenixMarket: PublicKey): Promise<PhoenixV1FulfillmentConfigAccount>;
104
+ getPhoenixV1FulfillmentConfigs(): Promise<PhoenixV1FulfillmentConfigAccount[]>;
103
105
  fetchMarketLookupTableAccount(): Promise<AddressLookupTableAccount>;
104
106
  /**
105
107
  * Update the wallet to use for drift transactions and linked user account
@@ -304,10 +304,18 @@ class DriftClient {
304
304
  const address = await (0, pda_1.getSerumFulfillmentConfigPublicKey)(this.program.programId, serumMarket);
305
305
  return (await this.program.account.serumV3FulfillmentConfig.fetch(address));
306
306
  }
307
+ async getSerumV3FulfillmentConfigs() {
308
+ const accounts = await this.program.account.serumV3FulfillmentConfig.all();
309
+ return accounts.map((account) => account.account);
310
+ }
307
311
  async getPhoenixV1FulfillmentConfig(phoenixMarket) {
308
312
  const address = await (0, pda_1.getPhoenixFulfillmentConfigPublicKey)(this.program.programId, phoenixMarket);
309
313
  return (await this.program.account.phoenixV1FulfillmentConfig.fetch(address));
310
314
  }
315
+ async getPhoenixV1FulfillmentConfigs() {
316
+ const accounts = await this.program.account.phoenixV1FulfillmentConfig.all();
317
+ return accounts.map((account) => account.account);
318
+ }
311
319
  async fetchMarketLookupTableAccount() {
312
320
  if (this.lookupTableAccount)
313
321
  return this.lookupTableAccount;
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.83.0",
2
+ "version": "2.84.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -237,6 +237,12 @@ function calculateSpotMarketBorrowCapacity(spotMarketAccount, targetBorrowRate)
237
237
  else {
238
238
  remainingCapacity = anchor_1.BN.max(numericConstants_1.ZERO, totalCapacity.sub(tokenBorrowAmount));
239
239
  }
240
+ if (spotMarketAccount.maxTokenBorrowsFraction > 0) {
241
+ const maxTokenBorrows = spotMarketAccount.maxTokenDeposits
242
+ .mul(new anchor_1.BN(spotMarketAccount.maxTokenBorrowsFraction))
243
+ .divn(10000);
244
+ remainingCapacity = anchor_1.BN.min(remainingCapacity, anchor_1.BN.max(numericConstants_1.ZERO, maxTokenBorrows.sub(tokenBorrowAmount)));
245
+ }
240
246
  return { totalCapacity, remainingCapacity };
241
247
  }
242
248
  exports.calculateSpotMarketBorrowCapacity = calculateSpotMarketBorrowCapacity;
@@ -260,7 +266,7 @@ function calculateInterestRate(bank, delta = numericConstants_1.ZERO) {
260
266
  .mul(borrowRateSlope)
261
267
  .div(numericConstants_1.SPOT_MARKET_UTILIZATION_PRECISION);
262
268
  }
263
- return interestRate;
269
+ return anchor_1.BN.max(interestRate, new anchor_1.BN(bank.minBorrowRate).mul(numericConstants_2.PERCENTAGE_PRECISION.divn(200)));
264
270
  }
265
271
  exports.calculateInterestRate = calculateInterestRate;
266
272
  function calculateDepositRate(bank, delta = numericConstants_1.ZERO) {
package/lib/types.d.ts CHANGED
@@ -810,6 +810,8 @@ export type SpotMarketAccount = {
810
810
  ordersEnabled: boolean;
811
811
  pausedOperations: number;
812
812
  ifPausedOperations: number;
813
+ maxTokenBorrowsFraction: number;
814
+ minBorrowRate: number;
813
815
  };
814
816
  export type PoolBalance = {
815
817
  scaledBalance: BN;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.84.0-beta.6",
3
+ "version": "2.85.0-beta.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -39,8 +39,9 @@
39
39
  "@project-serum/serum": "^0.13.38",
40
40
  "@pythnetwork/client": "2.5.3",
41
41
  "@pythnetwork/pyth-solana-receiver": "^0.7.0",
42
- "@solana/spl-token": "^0.3.7",
42
+ "@solana/spl-token": "0.3.7",
43
43
  "@solana/web3.js": "1.92.3",
44
+ "rpc-websockets": "7.5.1",
44
45
  "strict-event-emitter-types": "^2.0.0",
45
46
  "uuid": "^8.3.2",
46
47
  "zstddec": "^0.1.0"
@@ -51,17 +52,17 @@
51
52
  "@types/chai": "^4.3.1",
52
53
  "@types/jest": "^28.1.3",
53
54
  "@types/mocha": "^9.1.1",
54
- "@typescript-eslint/eslint-plugin": "^4.28.0",
55
- "@typescript-eslint/parser": "^4.28.0",
55
+ "@typescript-eslint/eslint-plugin": "4.28.0",
56
+ "@typescript-eslint/parser": "4.28.0",
56
57
  "chai": "^4.3.6",
57
58
  "encoding": "^0.1.13",
58
- "eslint": "^7.29.0",
59
- "eslint-config-prettier": "^8.3.0",
60
- "eslint-plugin-prettier": "^3.4.0",
59
+ "eslint": "7.29.0",
60
+ "eslint-config-prettier": "8.3.0",
61
+ "eslint-plugin-prettier": "3.4.0",
61
62
  "lodash": "^4.17.21",
62
63
  "mocha": "^10.0.0",
63
64
  "object-sizeof": "^2.6.3",
64
- "prettier": "^3.0.1",
65
+ "prettier": "3.0.1",
65
66
  "ts-node": "^10.8.0",
66
67
  "typescript": "^4.9.5"
67
68
  },
@@ -1812,6 +1812,44 @@ export class AdminClient extends DriftClient {
1812
1812
  );
1813
1813
  }
1814
1814
 
1815
+ public async updateSpotMarketMaxTokenBorrows(
1816
+ spotMarketIndex: number,
1817
+ maxTokenBorrows: BN
1818
+ ): Promise<TransactionSignature> {
1819
+ const updateSpotMarketMaxTokenBorrowsIx =
1820
+ await this.getUpdateSpotMarketMaxTokenBorrowsIx(
1821
+ spotMarketIndex,
1822
+ maxTokenBorrows
1823
+ );
1824
+
1825
+ const tx = await this.buildTransaction(updateSpotMarketMaxTokenBorrowsIx);
1826
+
1827
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
1828
+
1829
+ return txSig;
1830
+ }
1831
+
1832
+ public async getUpdateSpotMarketMaxTokenBorrowsIx(
1833
+ spotMarketIndex: number,
1834
+ maxTokenBorrows: BN
1835
+ ): Promise<TransactionInstruction> {
1836
+ return this.program.instruction.updateSpotMarketMaxTokenBorrows(
1837
+ maxTokenBorrows,
1838
+ {
1839
+ accounts: {
1840
+ admin: this.isSubscribed
1841
+ ? this.getStateAccount().admin
1842
+ : this.wallet.publicKey,
1843
+ state: await this.getStatePublicKey(),
1844
+ spotMarket: await getSpotMarketPublicKey(
1845
+ this.program.programId,
1846
+ spotMarketIndex
1847
+ ),
1848
+ },
1849
+ }
1850
+ );
1851
+ }
1852
+
1815
1853
  public async updateSpotMarketScaleInitialAssetWeightStart(
1816
1854
  spotMarketIndex: number,
1817
1855
  scaleInitialAssetWeightStart: BN
@@ -2506,14 +2544,16 @@ export class AdminClient extends DriftClient {
2506
2544
  spotMarketIndex: number,
2507
2545
  optimalUtilization: number,
2508
2546
  optimalBorrowRate: number,
2509
- optimalMaxRate: number
2547
+ optimalMaxRate: number,
2548
+ minBorrowRate?: number | undefined
2510
2549
  ): Promise<TransactionSignature> {
2511
2550
  const updateSpotMarketBorrowRateIx =
2512
2551
  await this.getUpdateSpotMarketBorrowRateIx(
2513
2552
  spotMarketIndex,
2514
2553
  optimalUtilization,
2515
2554
  optimalBorrowRate,
2516
- optimalMaxRate
2555
+ optimalMaxRate,
2556
+ minBorrowRate
2517
2557
  );
2518
2558
 
2519
2559
  const tx = await this.buildTransaction(updateSpotMarketBorrowRateIx);
@@ -2527,12 +2567,14 @@ export class AdminClient extends DriftClient {
2527
2567
  spotMarketIndex: number,
2528
2568
  optimalUtilization: number,
2529
2569
  optimalBorrowRate: number,
2530
- optimalMaxRate: number
2570
+ optimalMaxRate: number,
2571
+ minBorrowRate?: number | undefined
2531
2572
  ): Promise<TransactionInstruction> {
2532
2573
  return await this.program.instruction.updateSpotMarketBorrowRate(
2533
2574
  optimalUtilization,
2534
2575
  optimalBorrowRate,
2535
2576
  optimalMaxRate,
2577
+ minBorrowRate,
2536
2578
  {
2537
2579
  accounts: {
2538
2580
  admin: this.isSubscribed
@@ -39,15 +39,28 @@ export class BlockhashSubscriber {
39
39
  return this.latestBlockHeightContext;
40
40
  }
41
41
 
42
+ /**
43
+ * Returns the latest cached blockhash, based on an offset from the latest obtained
44
+ * @param offset Offset to use, defaulting to 0
45
+ * @param offsetType If 'seconds', it will use calculate the actual element offset based on the update interval; otherwise it will return a fixed index
46
+ * @returns Cached blockhash at the given offset, or undefined
47
+ */
42
48
  getLatestBlockhash(
43
- offset?: number
49
+ offset = 0,
50
+ offsetType: 'index' | 'seconds' = 'index'
44
51
  ): BlockhashWithExpiryBlockHeight | undefined {
45
52
  if (this.blockhashes.length === 0) {
46
53
  return undefined;
47
54
  }
55
+
56
+ const elementOffset =
57
+ offsetType == 'seconds'
58
+ ? Math.floor((offset * 1000) / this.updateIntervalMs)
59
+ : offset;
60
+
48
61
  const clampedOffset = Math.max(
49
62
  0,
50
- Math.min(this.blockhashes.length - 1, offset ?? 0)
63
+ Math.min(this.blockhashes.length - 1, elementOffset)
51
64
  );
52
65
 
53
66
  return this.blockhashes[this.blockhashes.length - 1 - clampedOffset];
@@ -524,6 +524,15 @@ export class DriftClient {
524
524
  )) as SerumV3FulfillmentConfigAccount;
525
525
  }
526
526
 
527
+ public async getSerumV3FulfillmentConfigs(): Promise<
528
+ SerumV3FulfillmentConfigAccount[]
529
+ > {
530
+ const accounts = await this.program.account.serumV3FulfillmentConfig.all();
531
+ return accounts.map(
532
+ (account) => account.account
533
+ ) as SerumV3FulfillmentConfigAccount[];
534
+ }
535
+
527
536
  public async getPhoenixV1FulfillmentConfig(
528
537
  phoenixMarket: PublicKey
529
538
  ): Promise<PhoenixV1FulfillmentConfigAccount> {
@@ -536,6 +545,16 @@ export class DriftClient {
536
545
  )) as PhoenixV1FulfillmentConfigAccount;
537
546
  }
538
547
 
548
+ public async getPhoenixV1FulfillmentConfigs(): Promise<
549
+ PhoenixV1FulfillmentConfigAccount[]
550
+ > {
551
+ const accounts =
552
+ await this.program.account.phoenixV1FulfillmentConfig.all();
553
+ return accounts.map(
554
+ (account) => account.account
555
+ ) as PhoenixV1FulfillmentConfigAccount[];
556
+ }
557
+
539
558
  public async fetchMarketLookupTableAccount(): Promise<AddressLookupTableAccount> {
540
559
  if (this.lookupTableAccount) return this.lookupTableAccount;
541
560
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.83.0",
2
+ "version": "2.84.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -363,6 +363,17 @@ export function calculateSpotMarketBorrowCapacity(
363
363
  remainingCapacity = BN.max(ZERO, totalCapacity.sub(tokenBorrowAmount));
364
364
  }
365
365
 
366
+ if (spotMarketAccount.maxTokenBorrowsFraction > 0) {
367
+ const maxTokenBorrows = spotMarketAccount.maxTokenDeposits
368
+ .mul(new BN(spotMarketAccount.maxTokenBorrowsFraction))
369
+ .divn(10000);
370
+
371
+ remainingCapacity = BN.min(
372
+ remainingCapacity,
373
+ BN.max(ZERO, maxTokenBorrows.sub(tokenBorrowAmount))
374
+ );
375
+ }
376
+
366
377
  return { totalCapacity, remainingCapacity };
367
378
  }
368
379
 
@@ -395,7 +406,10 @@ export function calculateInterestRate(
395
406
  .div(SPOT_MARKET_UTILIZATION_PRECISION);
396
407
  }
397
408
 
398
- return interestRate;
409
+ return BN.max(
410
+ interestRate,
411
+ new BN(bank.minBorrowRate).mul(PERCENTAGE_PRECISION.divn(200))
412
+ );
399
413
  }
400
414
 
401
415
  export function calculateDepositRate(
package/src/types.ts CHANGED
@@ -731,6 +731,9 @@ export type SpotMarketAccount = {
731
731
  pausedOperations: number;
732
732
 
733
733
  ifPausedOperations: number;
734
+
735
+ maxTokenBorrowsFraction: number;
736
+ minBorrowRate: number;
734
737
  };
735
738
 
736
739
  export type PoolBalance = {