@drift-labs/sdk 2.74.0-beta.1 → 2.74.0-beta.10

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 (53) hide show
  1. package/VERSION +1 -1
  2. package/lib/adminClient.d.ts +5 -2
  3. package/lib/adminClient.js +17 -4
  4. package/lib/blockhashSubscriber/BlockhashSubscriber.d.ts +21 -0
  5. package/lib/blockhashSubscriber/BlockhashSubscriber.js +73 -0
  6. package/lib/blockhashSubscriber/index.d.ts +1 -0
  7. package/lib/blockhashSubscriber/index.js +17 -0
  8. package/lib/blockhashSubscriber/types.d.ts +7 -0
  9. package/lib/blockhashSubscriber/types.js +2 -0
  10. package/lib/dlob/orderBookLevels.js +47 -12
  11. package/lib/driftClient.d.ts +5 -0
  12. package/lib/driftClient.js +17 -0
  13. package/lib/events/parse.d.ts +1 -1
  14. package/lib/events/parse.js +12 -12
  15. package/lib/idl/drift.json +89 -1
  16. package/lib/index.d.ts +1 -0
  17. package/lib/index.js +1 -0
  18. package/lib/math/funding.js +0 -6
  19. package/lib/math/oracles.js +1 -1
  20. package/lib/math/tiers.js +1 -1
  21. package/lib/oracles/prelaunchOracleClient.js +1 -0
  22. package/lib/oracles/types.d.ts +1 -0
  23. package/lib/tx/baseTxSender.d.ts +1 -1
  24. package/lib/tx/baseTxSender.js +9 -2
  25. package/lib/tx/fastSingleTxSender.d.ts +1 -1
  26. package/lib/tx/fastSingleTxSender.js +11 -3
  27. package/lib/tx/types.d.ts +1 -1
  28. package/lib/types.d.ts +3 -0
  29. package/lib/types.js +1 -0
  30. package/lib/user.d.ts +6 -4
  31. package/lib/user.js +24 -21
  32. package/package.json +1 -1
  33. package/src/adminClient.ts +73 -1
  34. package/src/blockhashSubscriber/BlockhashSubscriber.ts +108 -0
  35. package/src/blockhashSubscriber/index.ts +1 -0
  36. package/src/blockhashSubscriber/types.ts +8 -0
  37. package/src/dlob/orderBookLevels.ts +51 -15
  38. package/src/driftClient.ts +37 -0
  39. package/src/events/parse.ts +26 -12
  40. package/src/idl/drift.json +89 -1
  41. package/src/index.ts +1 -0
  42. package/src/math/funding.ts +0 -4
  43. package/src/math/oracles.ts +1 -1
  44. package/src/math/tiers.ts +1 -1
  45. package/src/oracles/prelaunchOracleClient.ts +1 -0
  46. package/src/oracles/types.ts +1 -0
  47. package/src/tx/baseTxSender.ts +12 -4
  48. package/src/tx/fastSingleTxSender.ts +13 -5
  49. package/src/tx/types.ts +2 -1
  50. package/src/types.ts +1 -0
  51. package/src/user.ts +32 -30
  52. package/tests/amm/test.ts +3 -1
  53. package/tests/dlob/test.ts +57 -0
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.74.0-beta.1
1
+ 2.74.0-beta.10
@@ -5,10 +5,12 @@ import { BN } from '@coral-xyz/anchor';
5
5
  import { DriftClient } from './driftClient';
6
6
  export declare class AdminClient extends DriftClient {
7
7
  initialize(usdcMint: PublicKey, _adminControlsPrices: boolean): Promise<[TransactionSignature]>;
8
- initializeSpotMarket(mint: PublicKey, optimalUtilization: number, optimalRate: number, maxRate: number, oracle: PublicKey, oracleSource: OracleSource, initialAssetWeight: number, maintenanceAssetWeight: number, initialLiabilityWeight: number, maintenanceLiabilityWeight: number, imfFactor?: number, liquidatorFee?: number, activeStatus?: boolean, name?: string): Promise<TransactionSignature>;
8
+ initializeSpotMarket(mint: PublicKey, optimalUtilization: number, optimalRate: number, maxRate: number, oracle: PublicKey, oracleSource: OracleSource, initialAssetWeight: number, maintenanceAssetWeight: number, initialLiabilityWeight: number, maintenanceLiabilityWeight: number, imfFactor?: number, liquidatorFee?: number, ifLiquidationFee?: number, activeStatus?: boolean, assetTier?: {
9
+ collateral: {};
10
+ }, scaleInitialAssetWeightStart?: BN, withdrawGuardThreshold?: BN, orderTickSize?: BN, orderStepSize?: BN, ifTotalFactor?: number, name?: string): Promise<TransactionSignature>;
9
11
  initializeSerumFulfillmentConfig(marketIndex: number, serumMarket: PublicKey, serumProgram: PublicKey): Promise<TransactionSignature>;
10
12
  initializePhoenixFulfillmentConfig(marketIndex: number, phoenixMarket: PublicKey): Promise<TransactionSignature>;
11
- initializePerpMarket(marketIndex: number, priceOracle: PublicKey, baseAssetReserve: BN, quoteAssetReserve: BN, periodicity: BN, pegMultiplier?: BN, oracleSource?: OracleSource, marginRatioInitial?: number, marginRatioMaintenance?: number, liquidatorFee?: number, activeStatus?: boolean, name?: string): Promise<TransactionSignature>;
13
+ initializePerpMarket(marketIndex: number, priceOracle: PublicKey, baseAssetReserve: BN, quoteAssetReserve: BN, periodicity: BN, pegMultiplier?: BN, oracleSource?: OracleSource, marginRatioInitial?: number, marginRatioMaintenance?: number, liquidatorFee?: number, ifLiquidatorFee?: number, imfFactor?: number, activeStatus?: boolean, baseSpread?: number, maxSpread?: number, maxOpenInterest?: BN, maxRevenueWithdrawPerPeriod?: BN, quoteMaxInsurance?: BN, orderStepSize?: BN, orderTickSize?: BN, minOrderSize?: BN, concentrationCoefScale?: BN, curveUpdateIntensity?: number, ammJitIntensity?: number, name?: string): Promise<TransactionSignature>;
12
14
  deleteInitializedPerpMarket(marketIndex: number): Promise<TransactionSignature>;
13
15
  moveAmmPrice(perpMarketIndex: number, baseAssetReserve: BN, quoteAssetReserve: BN, sqrtK?: BN): Promise<TransactionSignature>;
14
16
  updateK(perpMarketIndex: number, sqrtK: BN): Promise<TransactionSignature>;
@@ -83,4 +85,5 @@ export declare class AdminClient extends DriftClient {
83
85
  updateProtocolIfSharesTransferConfig(whitelistedSigners?: PublicKey[], maxTransferPerEpoch?: BN): Promise<TransactionSignature>;
84
86
  initializePrelaunchOracle(perpMarketIndex: number, price?: BN, maxPrice?: BN): Promise<TransactionSignature>;
85
87
  updatePrelaunchOracleParams(perpMarketIndex: number, price?: BN, maxPrice?: BN): Promise<TransactionSignature>;
88
+ deletePrelaunchOracle(perpMarketIndex: number): Promise<TransactionSignature>;
86
89
  }
@@ -59,13 +59,13 @@ class AdminClient extends driftClient_1.DriftClient {
59
59
  const { txSig } = await super.sendTransaction(tx, [], this.opts);
60
60
  return [txSig];
61
61
  }
62
- async initializeSpotMarket(mint, optimalUtilization, optimalRate, maxRate, oracle, oracleSource, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor = 0, liquidatorFee = 0, activeStatus = true, name = userName_1.DEFAULT_MARKET_NAME) {
62
+ async initializeSpotMarket(mint, optimalUtilization, optimalRate, maxRate, oracle, oracleSource, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor = 0, liquidatorFee = 0, ifLiquidationFee = 0, activeStatus = true, assetTier = types_1.AssetTier.COLLATERAL, scaleInitialAssetWeightStart = numericConstants_1.ZERO, withdrawGuardThreshold = numericConstants_1.ZERO, orderTickSize = numericConstants_1.ONE, orderStepSize = numericConstants_1.ONE, ifTotalFactor = 0, name = userName_1.DEFAULT_MARKET_NAME) {
63
63
  const spotMarketIndex = this.getStateAccount().numberOfSpotMarkets;
64
64
  const spotMarket = await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex);
65
65
  const spotMarketVault = await (0, pda_1.getSpotMarketVaultPublicKey)(this.program.programId, spotMarketIndex);
66
66
  const insuranceFundVault = await (0, pda_1.getInsuranceFundVaultPublicKey)(this.program.programId, spotMarketIndex);
67
67
  const nameBuffer = (0, userName_1.encodeName)(name);
68
- const initializeIx = await this.program.instruction.initializeSpotMarket(optimalUtilization, optimalRate, maxRate, oracleSource, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor, liquidatorFee, activeStatus, nameBuffer, {
68
+ const initializeIx = await this.program.instruction.initializeSpotMarket(optimalUtilization, optimalRate, maxRate, oracleSource, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor, liquidatorFee, ifLiquidationFee, activeStatus, assetTier, scaleInitialAssetWeightStart, withdrawGuardThreshold, orderTickSize, orderStepSize, ifTotalFactor, nameBuffer, {
69
69
  accounts: {
70
70
  admin: this.wallet.publicKey,
71
71
  state: await this.getStatePublicKey(),
@@ -133,11 +133,11 @@ class AdminClient extends driftClient_1.DriftClient {
133
133
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
134
134
  return txSig;
135
135
  }
136
- async initializePerpMarket(marketIndex, priceOracle, baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier = numericConstants_1.PEG_PRECISION, oracleSource = types_1.OracleSource.PYTH, marginRatioInitial = 2000, marginRatioMaintenance = 500, liquidatorFee = 0, activeStatus = true, name = userName_1.DEFAULT_MARKET_NAME) {
136
+ async initializePerpMarket(marketIndex, priceOracle, baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier = numericConstants_1.PEG_PRECISION, oracleSource = types_1.OracleSource.PYTH, marginRatioInitial = 2000, marginRatioMaintenance = 500, liquidatorFee = 0, ifLiquidatorFee = 10000, imfFactor = 0, activeStatus = true, baseSpread = 0, maxSpread = 142500, maxOpenInterest = numericConstants_1.ZERO, maxRevenueWithdrawPerPeriod = numericConstants_1.ZERO, quoteMaxInsurance = numericConstants_1.ZERO, orderStepSize = numericConstants_1.BASE_PRECISION.divn(10000), orderTickSize = numericConstants_1.PRICE_PRECISION.divn(100000), minOrderSize = numericConstants_1.BASE_PRECISION.divn(10000), concentrationCoefScale = numericConstants_1.ONE, curveUpdateIntensity = 0, ammJitIntensity = 0, name = userName_1.DEFAULT_MARKET_NAME) {
137
137
  const currentPerpMarketIndex = this.getStateAccount().numberOfMarkets;
138
138
  const perpMarketPublicKey = await (0, pda_1.getPerpMarketPublicKey)(this.program.programId, currentPerpMarketIndex);
139
139
  const nameBuffer = (0, userName_1.encodeName)(name);
140
- const initializeMarketIx = await this.program.instruction.initializePerpMarket(marketIndex, baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier, oracleSource, marginRatioInitial, marginRatioMaintenance, liquidatorFee, activeStatus, nameBuffer, {
140
+ const initializeMarketIx = await this.program.instruction.initializePerpMarket(marketIndex, baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier, oracleSource, marginRatioInitial, marginRatioMaintenance, liquidatorFee, ifLiquidatorFee, imfFactor, activeStatus, baseSpread, maxSpread, maxOpenInterest, maxRevenueWithdrawPerPeriod, quoteMaxInsurance, orderStepSize, orderTickSize, minOrderSize, concentrationCoefScale, curveUpdateIntensity, ammJitIntensity, nameBuffer, {
141
141
  accounts: {
142
142
  state: await this.getStatePublicKey(),
143
143
  admin: this.wallet.publicKey,
@@ -1083,5 +1083,18 @@ class AdminClient extends driftClient_1.DriftClient {
1083
1083
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
1084
1084
  return txSig;
1085
1085
  }
1086
+ async deletePrelaunchOracle(perpMarketIndex) {
1087
+ const deletePrelaunchOracleIx = await this.program.instruction.deletePrelaunchOracle(perpMarketIndex, {
1088
+ accounts: {
1089
+ admin: this.wallet.publicKey,
1090
+ state: await this.getStatePublicKey(),
1091
+ prelaunchOracle: await (0, pda_1.getPrelaunchOraclePublicKey)(this.program.programId, perpMarketIndex),
1092
+ perpMarket: await (0, pda_1.getPerpMarketPublicKey)(this.program.programId, perpMarketIndex),
1093
+ },
1094
+ });
1095
+ const tx = await this.buildTransaction(deletePrelaunchOracleIx);
1096
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
1097
+ return txSig;
1098
+ }
1086
1099
  }
1087
1100
  exports.AdminClient = AdminClient;
@@ -0,0 +1,21 @@
1
+ import { BlockhashWithExpiryBlockHeight, Context } from '@solana/web3.js';
2
+ import { BlockhashSubscriberConfig } from './types';
3
+ export declare class BlockhashSubscriber {
4
+ private connection;
5
+ private isSubscribed;
6
+ private latestBlockHeight;
7
+ private latestBlockHeightContext;
8
+ private blockhashes;
9
+ private updateBlockhashIntervalId;
10
+ private commitment;
11
+ private updateIntervalMs;
12
+ constructor(config: BlockhashSubscriberConfig);
13
+ getBlockhashCacheSize(): number;
14
+ getLatestBlockHeight(): number;
15
+ getLatestBlockHeightContext(): Context | undefined;
16
+ getLatestBlockhash(offset?: number): BlockhashWithExpiryBlockHeight | undefined;
17
+ pruneBlockhashes(): void;
18
+ updateBlockhash(): Promise<void>;
19
+ subscribe(): Promise<void>;
20
+ unsubscribe(): void;
21
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BlockhashSubscriber = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ class BlockhashSubscriber {
6
+ constructor(config) {
7
+ var _a, _b;
8
+ this.isSubscribed = false;
9
+ this.blockhashes = [];
10
+ if (!config.connection && !config.rpcUrl) {
11
+ throw new Error('BlockhashSubscriber requires one of connection or rpcUrl must be provided');
12
+ }
13
+ this.connection = config.connection || new web3_js_1.Connection(config.rpcUrl);
14
+ this.commitment = (_a = config.commitment) !== null && _a !== void 0 ? _a : 'confirmed';
15
+ this.updateIntervalMs = (_b = config.updateIntervalMs) !== null && _b !== void 0 ? _b : 1000;
16
+ }
17
+ getBlockhashCacheSize() {
18
+ return this.blockhashes.length;
19
+ }
20
+ getLatestBlockHeight() {
21
+ return this.latestBlockHeight;
22
+ }
23
+ getLatestBlockHeightContext() {
24
+ return this.latestBlockHeightContext;
25
+ }
26
+ getLatestBlockhash(offset) {
27
+ if (this.blockhashes.length === 0) {
28
+ return undefined;
29
+ }
30
+ const clampedOffset = Math.max(0, Math.min(this.blockhashes.length - 1, offset !== null && offset !== void 0 ? offset : 0));
31
+ return this.blockhashes[this.blockhashes.length - 1 - clampedOffset];
32
+ }
33
+ pruneBlockhashes() {
34
+ if (this.latestBlockHeight) {
35
+ this.blockhashes = this.blockhashes.filter((blockhash) => blockhash.lastValidBlockHeight > this.latestBlockHeight);
36
+ }
37
+ }
38
+ async updateBlockhash() {
39
+ const [resp, lastConfirmedBlockHeight] = await Promise.all([
40
+ this.connection.getLatestBlockhashAndContext({
41
+ commitment: this.commitment,
42
+ }),
43
+ this.connection.getBlockHeight({ commitment: this.commitment }),
44
+ ]);
45
+ this.latestBlockHeight = lastConfirmedBlockHeight;
46
+ this.latestBlockHeightContext = resp.context;
47
+ // avoid caching duplicate blockhashes
48
+ if (this.blockhashes.length > 0) {
49
+ if (resp.value.blockhash ===
50
+ this.blockhashes[this.blockhashes.length - 1].blockhash) {
51
+ return;
52
+ }
53
+ }
54
+ this.blockhashes.push(resp.value);
55
+ this.pruneBlockhashes();
56
+ }
57
+ async subscribe() {
58
+ if (this.isSubscribed) {
59
+ return;
60
+ }
61
+ this.isSubscribed = true;
62
+ await this.updateBlockhash();
63
+ this.updateBlockhashIntervalId = setInterval(this.updateBlockhash.bind(this), this.updateIntervalMs);
64
+ }
65
+ unsubscribe() {
66
+ if (this.updateBlockhashIntervalId) {
67
+ clearInterval(this.updateBlockhashIntervalId);
68
+ this.updateBlockhashIntervalId = undefined;
69
+ }
70
+ this.isSubscribed = false;
71
+ }
72
+ }
73
+ exports.BlockhashSubscriber = BlockhashSubscriber;
@@ -0,0 +1 @@
1
+ export * from './BlockhashSubscriber';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./BlockhashSubscriber"), exports);
@@ -0,0 +1,7 @@
1
+ import { Commitment, Connection } from '@solana/web3.js';
2
+ export type BlockhashSubscriberConfig = {
3
+ rpcUrl?: string;
4
+ connection?: Connection;
5
+ commitment?: Commitment;
6
+ updateIntervalMs?: number;
7
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -122,6 +122,9 @@ function getVammL2Generator({ marketAccount, oraclePriceData, numOrders, now, to
122
122
  [afterSwapQuoteReserves, afterSwapBaseReserves] =
123
123
  (0, __1.calculateAmmReservesAfterSwap)(bidAmm, 'quote', quoteSwapped, __1.SwapDirection.REMOVE);
124
124
  baseSwapped = bidAmm.baseAssetReserve.sub(afterSwapBaseReserves).abs();
125
+ if (baseSwapped.eq(__1.ZERO)) {
126
+ return;
127
+ }
125
128
  if (remainingBaseLiquidity.lt(baseSwapped)) {
126
129
  baseSwapped = remainingBaseLiquidity;
127
130
  [afterSwapQuoteReserves, afterSwapBaseReserves] =
@@ -170,6 +173,9 @@ function getVammL2Generator({ marketAccount, oraclePriceData, numOrders, now, to
170
173
  [afterSwapQuoteReserves, afterSwapBaseReserves] =
171
174
  (0, __1.calculateAmmReservesAfterSwap)(askAmm, 'quote', quoteSwapped, __1.SwapDirection.ADD);
172
175
  baseSwapped = askAmm.baseAssetReserve.sub(afterSwapBaseReserves).abs();
176
+ if (baseSwapped.eq(__1.ZERO)) {
177
+ return;
178
+ }
173
179
  if (remainingBaseLiquidity.lt(baseSwapped)) {
174
180
  baseSwapped = remainingBaseLiquidity;
175
181
  [afterSwapQuoteReserves, afterSwapBaseReserves] =
@@ -255,6 +261,31 @@ function groupL2Levels(levels, grouping, direction, depth) {
255
261
  }
256
262
  return groupedLevels;
257
263
  }
264
+ /**
265
+ * Method to merge bids or asks by price
266
+ */
267
+ const mergeByPrice = (bidsOrAsks) => {
268
+ const merged = new Map();
269
+ for (const level of bidsOrAsks) {
270
+ const key = level.price.toString();
271
+ if (merged.has(key)) {
272
+ const existing = merged.get(key);
273
+ existing.size = existing.size.add(level.size);
274
+ for (const [source, size] of Object.entries(level.sources)) {
275
+ if (existing.sources[source]) {
276
+ existing.sources[source] = existing.sources[source].add(size);
277
+ }
278
+ else {
279
+ existing.sources[source] = size;
280
+ }
281
+ }
282
+ }
283
+ else {
284
+ merged.set(key, cloneL2Level(level));
285
+ }
286
+ }
287
+ return Array.from(merged.values());
288
+ };
258
289
  /**
259
290
  * The purpose of this function is uncross the L2 orderbook by modifying the bid/ask price at the top of the book
260
291
  * This will make the liquidity look worse but more intuitive (users familiar with clob get confused w temporarily
@@ -336,17 +367,17 @@ function uncrossL2(bids, asks, oraclePrice, oracleTwap5Min, markTwap5Min, groupi
336
367
  bidIndex++;
337
368
  continue;
338
369
  }
370
+ if (userBids.has(nextBid.price.toString())) {
371
+ newBids.push(nextBid);
372
+ bidIndex++;
373
+ continue;
374
+ }
375
+ if (userAsks.has(nextAsk.price.toString())) {
376
+ newAsks.push(nextAsk);
377
+ askIndex++;
378
+ continue;
379
+ }
339
380
  if (nextBid.price.gte(nextAsk.price)) {
340
- if (userBids.has(nextBid.price.toString())) {
341
- newBids.push(nextBid);
342
- bidIndex++;
343
- continue;
344
- }
345
- if (userAsks.has(nextAsk.price.toString())) {
346
- newAsks.push(nextAsk);
347
- askIndex++;
348
- continue;
349
- }
350
381
  if (nextBid.price.gt(referencePrice) &&
351
382
  nextAsk.price.gt(referencePrice)) {
352
383
  let newBidPrice = nextAsk.price.sub(grouping);
@@ -391,9 +422,13 @@ function uncrossL2(bids, asks, oraclePrice, oracleTwap5Min, markTwap5Min, groupi
391
422
  bidIndex++;
392
423
  }
393
424
  }
425
+ newBids.sort((a, b) => b.price.cmp(a.price));
426
+ newAsks.sort((a, b) => a.price.cmp(b.price));
427
+ const finalNewBids = mergeByPrice(newBids);
428
+ const finalNewAsks = mergeByPrice(newAsks);
394
429
  return {
395
- bids: newBids,
396
- asks: newAsks,
430
+ bids: finalNewBids,
431
+ asks: finalNewAsks,
397
432
  };
398
433
  }
399
434
  exports.uncrossL2 = uncrossL2;
@@ -134,6 +134,11 @@ export declare class DriftClient {
134
134
  subAccountId: number;
135
135
  }[]): Promise<TransactionSignature>;
136
136
  getUpdateAdvancedDlpIx(advancedLp: boolean, subAccountId: number): Promise<anchor.web3.TransactionInstruction>;
137
+ updateUserReduceOnly(updates: {
138
+ reduceOnly: boolean;
139
+ subAccountId: number;
140
+ }[]): Promise<TransactionSignature>;
141
+ getUpdateUserReduceOnlyIx(reduceOnly: boolean, subAccountId: number): Promise<anchor.web3.TransactionInstruction>;
137
142
  fetchAllUserAccounts(includeIdle?: boolean): Promise<ProgramAccount<UserAccount>[]>;
138
143
  getUserAccountsForDelegate(delegate: PublicKey): Promise<UserAccount[]>;
139
144
  getUserAccountsAndAddressesForAuthority(authority: PublicKey): Promise<ProgramAccount<UserAccount>[]>;
@@ -627,6 +627,23 @@ class DriftClient {
627
627
  });
628
628
  return ix;
629
629
  }
630
+ async updateUserReduceOnly(updates) {
631
+ const ixs = await Promise.all(updates.map(async ({ reduceOnly, subAccountId }) => {
632
+ return await this.getUpdateUserReduceOnlyIx(reduceOnly, subAccountId);
633
+ }));
634
+ const tx = await this.buildTransaction(ixs, this.txParams);
635
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
636
+ return txSig;
637
+ }
638
+ async getUpdateUserReduceOnlyIx(reduceOnly, subAccountId) {
639
+ const ix = await this.program.instruction.updateUserReduceOnly(subAccountId, reduceOnly, {
640
+ accounts: {
641
+ user: (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, subAccountId),
642
+ authority: this.wallet.publicKey,
643
+ },
644
+ });
645
+ return ix;
646
+ }
630
647
  async fetchAllUserAccounts(includeIdle = true) {
631
648
  let filters = undefined;
632
649
  if (!includeIdle) {
@@ -1,2 +1,2 @@
1
1
  import { Program, Event } from '@coral-xyz/anchor';
2
- export declare function parseLogs(program: Program, logs: string[]): Event[];
2
+ export declare function parseLogs(program: Program, logs: string[], programId?: string): Event[];
@@ -2,19 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseLogs = void 0;
4
4
  const driftProgramId = 'dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH';
5
- const driftProgramStart = `Program ${driftProgramId} invoke`;
6
5
  const PROGRAM_LOG = 'Program log: ';
7
6
  const PROGRAM_DATA = 'Program data: ';
8
7
  const PROGRAM_LOG_START_INDEX = PROGRAM_LOG.length;
9
8
  const PROGRAM_DATA_START_INDEX = PROGRAM_DATA.length;
10
- function parseLogs(program, logs) {
9
+ function parseLogs(program, logs, programId = driftProgramId) {
11
10
  const events = [];
12
11
  const execution = new ExecutionContext();
13
12
  for (const log of logs) {
14
13
  if (log.startsWith('Log truncated')) {
15
14
  break;
16
15
  }
17
- const [event, newProgram, didPop] = handleLog(execution, log, program);
16
+ const [event, newProgram, didPop] = handleLog(execution, log, program, programId);
18
17
  if (event) {
19
18
  events.push(event);
20
19
  }
@@ -28,18 +27,18 @@ function parseLogs(program, logs) {
28
27
  return events;
29
28
  }
30
29
  exports.parseLogs = parseLogs;
31
- function handleLog(execution, log, program) {
30
+ function handleLog(execution, log, program, programId = driftProgramId) {
32
31
  // Executing program is drift program.
33
- if (execution.stack.length > 0 && execution.program() === driftProgramId) {
34
- return handleProgramLog(log, program);
32
+ if (execution.stack.length > 0 && execution.program() === programId) {
33
+ return handleProgramLog(log, program, programId);
35
34
  }
36
35
  // Executing program is not drift program.
37
36
  else {
38
- return [null, ...handleSystemLog(log)];
37
+ return [null, ...handleSystemLog(log, programId)];
39
38
  }
40
39
  }
41
40
  // Handles logs from *drift* program.
42
- function handleProgramLog(log, program) {
41
+ function handleProgramLog(log, program, programId = driftProgramId) {
43
42
  // This is a `msg!` log or a `sol_log_data` log.
44
43
  if (log.startsWith(PROGRAM_LOG)) {
45
44
  const logStr = log.slice(PROGRAM_LOG_START_INDEX);
@@ -52,20 +51,21 @@ function handleProgramLog(log, program) {
52
51
  return [event, null, false];
53
52
  }
54
53
  else {
55
- return [null, ...handleSystemLog(log)];
54
+ return [null, ...handleSystemLog(log, programId)];
56
55
  }
57
56
  }
58
57
  // Handles logs when the current program being executing is *not* drift.
59
- function handleSystemLog(log) {
58
+ function handleSystemLog(log, programId = driftProgramId) {
60
59
  // System component.
61
60
  const logStart = log.split(':')[0];
61
+ const programStart = `Program ${programId} invoke`;
62
62
  // Did the program finish executing?
63
63
  if (logStart.match(/^Program (.*) success/g) !== null) {
64
64
  return [null, true];
65
65
  // Recursive call.
66
66
  }
67
- else if (logStart.startsWith(driftProgramStart)) {
68
- return [driftProgramId, false];
67
+ else if (logStart.startsWith(programStart)) {
68
+ return [programId, false];
69
69
  }
70
70
  // CPI call.
71
71
  else if (logStart.includes('invoke')) {
@@ -2651,10 +2651,40 @@
2651
2651
  "name": "liquidatorFee",
2652
2652
  "type": "u32"
2653
2653
  },
2654
+ {
2655
+ "name": "ifLiquidationFee",
2656
+ "type": "u32"
2657
+ },
2654
2658
  {
2655
2659
  "name": "activeStatus",
2656
2660
  "type": "bool"
2657
2661
  },
2662
+ {
2663
+ "name": "assetTier",
2664
+ "type": {
2665
+ "defined": "AssetTier"
2666
+ }
2667
+ },
2668
+ {
2669
+ "name": "scaleInitialAssetWeightStart",
2670
+ "type": "u64"
2671
+ },
2672
+ {
2673
+ "name": "withdrawGuardThreshold",
2674
+ "type": "u64"
2675
+ },
2676
+ {
2677
+ "name": "orderTickSize",
2678
+ "type": "u64"
2679
+ },
2680
+ {
2681
+ "name": "orderStepSize",
2682
+ "type": "u64"
2683
+ },
2684
+ {
2685
+ "name": "ifTotalFactor",
2686
+ "type": "u32"
2687
+ },
2658
2688
  {
2659
2689
  "name": "name",
2660
2690
  "type": {
@@ -2943,10 +2973,62 @@
2943
2973
  "name": "liquidatorFee",
2944
2974
  "type": "u32"
2945
2975
  },
2976
+ {
2977
+ "name": "ifLiquidationFee",
2978
+ "type": "u32"
2979
+ },
2980
+ {
2981
+ "name": "imfFactor",
2982
+ "type": "u32"
2983
+ },
2946
2984
  {
2947
2985
  "name": "activeStatus",
2948
2986
  "type": "bool"
2949
2987
  },
2988
+ {
2989
+ "name": "baseSpread",
2990
+ "type": "u32"
2991
+ },
2992
+ {
2993
+ "name": "maxSpread",
2994
+ "type": "u32"
2995
+ },
2996
+ {
2997
+ "name": "maxOpenInterest",
2998
+ "type": "u128"
2999
+ },
3000
+ {
3001
+ "name": "maxRevenueWithdrawPerPeriod",
3002
+ "type": "u64"
3003
+ },
3004
+ {
3005
+ "name": "quoteMaxInsurance",
3006
+ "type": "u64"
3007
+ },
3008
+ {
3009
+ "name": "orderStepSize",
3010
+ "type": "u64"
3011
+ },
3012
+ {
3013
+ "name": "orderTickSize",
3014
+ "type": "u64"
3015
+ },
3016
+ {
3017
+ "name": "minOrderSize",
3018
+ "type": "u64"
3019
+ },
3020
+ {
3021
+ "name": "concentrationCoefScale",
3022
+ "type": "u128"
3023
+ },
3024
+ {
3025
+ "name": "curveUpdateIntensity",
3026
+ "type": "u16"
3027
+ },
3028
+ {
3029
+ "name": "ammJitUpdateIntensity",
3030
+ "type": "u16"
3031
+ },
2950
3032
  {
2951
3033
  "name": "name",
2952
3034
  "type": {
@@ -9119,6 +9201,9 @@
9119
9201
  {
9120
9202
  "name": "Speculative"
9121
9203
  },
9204
+ {
9205
+ "name": "HighlySpeculative"
9206
+ },
9122
9207
  {
9123
9208
  "name": "Isolated"
9124
9209
  }
@@ -11626,5 +11711,8 @@
11626
11711
  "name": "CantReclaimRent",
11627
11712
  "msg": "CantReclaimRent"
11628
11713
  }
11629
- ]
11714
+ ],
11715
+ "metadata": {
11716
+ "address": "dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH"
11717
+ }
11630
11718
  }
package/lib/index.d.ts CHANGED
@@ -98,4 +98,5 @@ export * from './auctionSubscriber';
98
98
  export * from './auctionSubscriber/types';
99
99
  export * from './memcmp';
100
100
  export * from './decode/user';
101
+ export * from './blockhashSubscriber';
101
102
  export { BN, PublicKey, pyth };
package/lib/index.js CHANGED
@@ -121,3 +121,4 @@ __exportStar(require("./auctionSubscriber"), exports);
121
121
  __exportStar(require("./auctionSubscriber/types"), exports);
122
122
  __exportStar(require("./memcmp"), exports);
123
123
  __exportStar(require("./decode/user"), exports);
124
+ __exportStar(require("./blockhashSubscriber"), exports);
@@ -148,12 +148,6 @@ function getMaxPriceDivergenceForFundingRate(market, oracleTwap) {
148
148
  else if ((0, types_1.isVariant)(market.contractTier, 'c')) {
149
149
  return oracleTwap.divn(20);
150
150
  }
151
- else if ((0, types_1.isVariant)(market.contractTier, 'speculative')) {
152
- return oracleTwap.divn(10);
153
- }
154
- else if ((0, types_1.isVariant)(market.contractTier, 'isolated')) {
155
- return oracleTwap.divn(10);
156
- }
157
151
  else {
158
152
  return oracleTwap.divn(10);
159
153
  }
@@ -28,7 +28,7 @@ function getMaxConfidenceIntervalMultiplier(market) {
28
28
  else if ((0, types_1.isVariant)(market.contractTier, 'speculative')) {
29
29
  maxConfidenceIntervalMultiplier = new index_1.BN(10);
30
30
  }
31
- else if ((0, types_1.isVariant)(market.contractTier, 'isolated')) {
31
+ else {
32
32
  maxConfidenceIntervalMultiplier = new index_1.BN(50);
33
33
  }
34
34
  return maxConfidenceIntervalMultiplier;
package/lib/math/tiers.js CHANGED
@@ -15,7 +15,7 @@ function getPerpMarketTierNumber(perpMarket) {
15
15
  else if ((0, types_1.isVariant)(perpMarket.contractTier, 'speculative')) {
16
16
  return 3;
17
17
  }
18
- else if ((0, types_1.isVariant)(perpMarket.contractTier, 'isolated')) {
18
+ else if ((0, types_1.isVariant)(perpMarket.contractTier, 'highlySpeculative')) {
19
19
  return 4;
20
20
  }
21
21
  else {
@@ -17,6 +17,7 @@ class PrelaunchOracleClient {
17
17
  slot: prelaunchOracle.ammLastUpdateSlot,
18
18
  confidence: prelaunchOracle.confidence,
19
19
  hasSufficientNumberOfDataPoints: true,
20
+ maxPrice: prelaunchOracle.maxPrice,
20
21
  };
21
22
  }
22
23
  }
@@ -10,6 +10,7 @@ export type OraclePriceData = {
10
10
  hasSufficientNumberOfDataPoints: boolean;
11
11
  twap?: BN;
12
12
  twapConfidence?: BN;
13
+ maxPrice?: BN;
13
14
  };
14
15
  export type OracleInfo = {
15
16
  publicKey: PublicKey;
@@ -22,7 +22,7 @@ export declare abstract class BaseTxSender implements TxSender {
22
22
  });
23
23
  send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean, extraConfirmationOptions?: ExtraConfirmationOptions): Promise<TxSigAndSlot>;
24
24
  prepareTx(tx: Transaction, additionalSigners: Array<Signer>, opts: ConfirmOptions): Promise<Transaction>;
25
- getVersionedTransaction(ixs: TransactionInstruction[], lookupTableAccounts: AddressLookupTableAccount[], additionalSigners?: Array<Signer>, opts?: ConfirmOptions): Promise<VersionedTransaction>;
25
+ getVersionedTransaction(ixs: TransactionInstruction[], lookupTableAccounts: AddressLookupTableAccount[], additionalSigners?: Array<Signer>, opts?: ConfirmOptions, blockhash?: string): Promise<VersionedTransaction>;
26
26
  sendVersionedTransaction(tx: VersionedTransaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean, extraConfirmationOptions?: ExtraConfirmationOptions): Promise<TxSigAndSlot>;
27
27
  sendRawTransaction(rawTransaction: Buffer | Uint8Array, opts: ConfirmOptions): Promise<TxSigAndSlot>;
28
28
  simulateTransaction(tx: VersionedTransaction): Promise<boolean>;
@@ -47,16 +47,23 @@ class BaseTxSender {
47
47
  const signedTx = await this.wallet.signTransaction(tx);
48
48
  return signedTx;
49
49
  }
50
- async getVersionedTransaction(ixs, lookupTableAccounts, additionalSigners, opts) {
50
+ async getVersionedTransaction(ixs, lookupTableAccounts, additionalSigners, opts, blockhash) {
51
51
  if (additionalSigners === undefined) {
52
52
  additionalSigners = [];
53
53
  }
54
54
  if (opts === undefined) {
55
55
  opts = this.opts;
56
56
  }
57
+ let recentBlockhash = '';
58
+ if (blockhash) {
59
+ recentBlockhash = blockhash;
60
+ }
61
+ else {
62
+ recentBlockhash = (await this.connection.getLatestBlockhash(opts.preflightCommitment)).blockhash;
63
+ }
57
64
  const message = new web3_js_1.TransactionMessage({
58
65
  payerKey: this.wallet.publicKey,
59
- recentBlockhash: (await this.connection.getLatestBlockhash(opts.preflightCommitment)).blockhash,
66
+ recentBlockhash,
60
67
  instructions: ixs,
61
68
  }).compileToV0Message(lookupTableAccounts);
62
69
  const tx = new web3_js_1.VersionedTransaction(message);