@drift-labs/sdk 2.31.1-beta.1 → 2.31.1-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.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.31.1-beta.1
1
+ 2.31.1-beta.10
@@ -0,0 +1,23 @@
1
+ /// <reference types="node" />
2
+ import { DataAndSlot, UserAccountEvents, UserAccountSubscriber } from './types';
3
+ import { PublicKey } from '@solana/web3.js';
4
+ import StrictEventEmitter from 'strict-event-emitter-types';
5
+ import { EventEmitter } from 'events';
6
+ import { UserAccount } from '../types';
7
+ export declare class MockUserAccountSubscriber implements UserAccountSubscriber {
8
+ isSubscribed: boolean;
9
+ eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
10
+ userAccountPublicKey: PublicKey;
11
+ callbackId?: string;
12
+ errorCallbackId?: string;
13
+ user: DataAndSlot<UserAccount>;
14
+ constructor(userAccountPublicKey: PublicKey, data: UserAccount, slot: number);
15
+ subscribe(_userAccount?: UserAccount): Promise<boolean>;
16
+ addToAccountLoader(): Promise<void>;
17
+ fetch(): Promise<void>;
18
+ doesAccountExist(): boolean;
19
+ unsubscribe(): Promise<void>;
20
+ assertIsSubscribed(): void;
21
+ getUserAccountAndSlot(): DataAndSlot<UserAccount>;
22
+ updateData(userAccount: UserAccount, slot: number): void;
23
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MockUserAccountSubscriber = void 0;
4
+ const events_1 = require("events");
5
+ class MockUserAccountSubscriber {
6
+ constructor(userAccountPublicKey, data, slot) {
7
+ this.isSubscribed = true;
8
+ this.eventEmitter = new events_1.EventEmitter();
9
+ this.userAccountPublicKey = userAccountPublicKey;
10
+ this.user = { data, slot };
11
+ }
12
+ async subscribe(_userAccount) {
13
+ return true;
14
+ }
15
+ async addToAccountLoader() { }
16
+ async fetch() { }
17
+ doesAccountExist() {
18
+ return this.user !== undefined;
19
+ }
20
+ async unsubscribe() { }
21
+ assertIsSubscribed() { }
22
+ getUserAccountAndSlot() {
23
+ return this.user;
24
+ }
25
+ updateData(userAccount, slot) {
26
+ this.user = { data: userAccount, slot };
27
+ this.eventEmitter.emit('userAccountUpdate', userAccount);
28
+ this.eventEmitter.emit('update');
29
+ }
30
+ }
31
+ exports.MockUserAccountSubscriber = MockUserAccountSubscriber;
@@ -124,6 +124,16 @@ exports.DevnetPerpMarkets = [
124
124
  launchTs: 1683125906000,
125
125
  oracleSource: __1.OracleSource.PYTH,
126
126
  },
127
+ {
128
+ fullName: 'RNDR',
129
+ category: ['Infra'],
130
+ symbol: 'RNDR-PERP',
131
+ baseAssetSymbol: 'RNDR',
132
+ marketIndex: 12,
133
+ oracle: new web3_js_1.PublicKey('C2QvUPBiU3fViSyqA4nZgGyYqLgYf9PRpd8B8oLoo48w'),
134
+ launchTs: 1683125906000,
135
+ oracleSource: __1.OracleSource.PYTH,
136
+ },
127
137
  ];
128
138
  exports.MainnetPerpMarkets = [
129
139
  {
@@ -246,6 +256,16 @@ exports.MainnetPerpMarkets = [
246
256
  launchTs: 1683125906000,
247
257
  oracleSource: __1.OracleSource.PYTH,
248
258
  },
259
+ {
260
+ fullName: 'RNDR',
261
+ category: ['Infra'],
262
+ symbol: 'RNDR-PERP',
263
+ baseAssetSymbol: 'RNDR',
264
+ marketIndex: 12,
265
+ oracle: new web3_js_1.PublicKey('CYGfrBJB9HgLf9iZyN4aH5HvUAi2htQ4MjPxeXMf4Egn'),
266
+ launchTs: 1683125906000,
267
+ oracleSource: __1.OracleSource.PYTH,
268
+ },
249
269
  ];
250
270
  exports.PerpMarkets = {
251
271
  devnet: exports.DevnetPerpMarkets,
@@ -14,6 +14,7 @@ import { User } from './user';
14
14
  import { UserSubscriptionConfig } from './userConfig';
15
15
  import { UserStats } from './userStats';
16
16
  import { JupiterClient, Route, SwapMode } from './jupiter/jupiterClient';
17
+ import { UserStatsSubscriptionConfig } from './userStatsConfig';
17
18
  type RemainingAccountParams = {
18
19
  userAccounts: UserAccount[];
19
20
  writablePerpMarketIndexes?: number[];
@@ -36,6 +37,7 @@ export declare class DriftClient {
36
37
  userStats?: UserStats;
37
38
  activeSubAccountId: number;
38
39
  userAccountSubscriptionConfig: UserSubscriptionConfig;
40
+ userStatsAccountSubscriptionConfig: UserStatsSubscriptionConfig;
39
41
  accountSubscriber: DriftClientAccountSubscriber;
40
42
  eventEmitter: StrictEventEmitter<EventEmitter, DriftClientAccountEvents>;
41
43
  _isSubscribed: boolean;
@@ -49,6 +51,7 @@ export declare class DriftClient {
49
51
  authoritySubAccountMap?: Map<string, number[]>;
50
52
  skipLoadUsers?: boolean;
51
53
  txVersion: TransactionVersion;
54
+ txParams: TxParams;
52
55
  get isSubscribed(): boolean;
53
56
  set isSubscribed(val: boolean);
54
57
  constructor(config: DriftClientConfig);
@@ -121,6 +124,7 @@ export declare class DriftClient {
121
124
  getReferrerNameAccountsForAuthority(authority: PublicKey): Promise<ReferrerNameAccount[]>;
122
125
  deleteUser(subAccountId?: number, txParams?: TxParams): Promise<TransactionSignature>;
123
126
  getUser(subAccountId?: number, authority?: PublicKey): User;
127
+ hasUser(subAccountId?: number, authority?: PublicKey): boolean;
124
128
  getUsers(): User[];
125
129
  getUserStats(): UserStats;
126
130
  fetchReferrerNameAccount(name: string): Promise<ReferrerNameAccount | undefined>;
@@ -188,7 +192,7 @@ export declare class DriftClient {
188
192
  private getWrappedSolAccountCreationIxs;
189
193
  getAssociatedTokenAccountCreationIx(tokenMintAddress: PublicKey, associatedTokenAddress: PublicKey): anchor.web3.TransactionInstruction;
190
194
  /**
191
- * Creates the Clearing House User account for a user, and deposits some initial collateral
195
+ * Creates the User account for a user, and deposits some initial collateral
192
196
  * @param amount
193
197
  * @param userTokenAccount
194
198
  * @param marketIndex
@@ -228,6 +232,7 @@ export declare class DriftClient {
228
232
  getRemovePerpLpSharesIx(marketIndex: number, sharesToBurn?: BN): Promise<TransactionInstruction>;
229
233
  addPerpLpShares(amount: BN, marketIndex: number, txParams?: TxParams): Promise<TransactionSignature>;
230
234
  getAddPerpLpSharesIx(amount: BN, marketIndex: number): Promise<TransactionInstruction>;
235
+ getQuoteValuePerLpShare(marketIndex: number): BN;
231
236
  /**
232
237
  * @deprecated use {@link placePerpOrder} or {@link placeAndTakePerpOrder} instead
233
238
  */
@@ -64,7 +64,7 @@ class DriftClient {
64
64
  this._isSubscribed = val;
65
65
  }
66
66
  constructor(config) {
67
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
67
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
68
68
  this.users = new Map();
69
69
  this._isSubscribed = false;
70
70
  this.perpMarketLastSlotCache = new Map();
@@ -78,6 +78,10 @@ class DriftClient {
78
78
  this.activeSubAccountId = (_c = config.activeSubAccountId) !== null && _c !== void 0 ? _c : 0;
79
79
  this.skipLoadUsers = (_d = config.skipLoadUsers) !== null && _d !== void 0 ? _d : false;
80
80
  this.txVersion = (_e = config.txVersion) !== null && _e !== void 0 ? _e : 'legacy';
81
+ this.txParams = {
82
+ computeUnits: (_g = (_f = config.txParams) === null || _f === void 0 ? void 0 : _f.computeUnits) !== null && _g !== void 0 ? _g : 600000,
83
+ computeUnitsPrice: (_j = (_h = config.txParams) === null || _h === void 0 ? void 0 : _h.computeUnitsPrice) !== null && _j !== void 0 ? _j : 0,
84
+ };
81
85
  if (config.includeDelegates && config.subAccountIds) {
82
86
  throw new Error('Can only pass one of includeDelegates or subAccountIds. If you want to specify subaccount ids for multiple authorities, pass authoritySubaccountMap instead');
83
87
  }
@@ -92,16 +96,25 @@ class DriftClient {
92
96
  : config.subAccountIds
93
97
  ? new Map([[this.authority.toString(), config.subAccountIds]])
94
98
  : new Map();
95
- this.includeDelegates = (_f = config.includeDelegates) !== null && _f !== void 0 ? _f : false;
96
- this.userAccountSubscriptionConfig =
97
- ((_g = config.accountSubscription) === null || _g === void 0 ? void 0 : _g.type) === 'polling'
98
- ? {
99
- type: 'polling',
100
- accountLoader: config.accountSubscription.accountLoader,
101
- }
102
- : {
103
- type: 'websocket',
104
- };
99
+ this.includeDelegates = (_k = config.includeDelegates) !== null && _k !== void 0 ? _k : false;
100
+ if (((_l = config.accountSubscription) === null || _l === void 0 ? void 0 : _l.type) === 'polling') {
101
+ this.userAccountSubscriptionConfig = {
102
+ type: 'polling',
103
+ accountLoader: config.accountSubscription.accountLoader,
104
+ };
105
+ this.userStatsAccountSubscriptionConfig = {
106
+ type: 'polling',
107
+ accountLoader: config.accountSubscription.accountLoader,
108
+ };
109
+ }
110
+ else {
111
+ this.userAccountSubscriptionConfig = {
112
+ type: 'websocket',
113
+ };
114
+ this.userStatsAccountSubscriptionConfig = {
115
+ type: 'websocket',
116
+ };
117
+ }
105
118
  if (config.userStats) {
106
119
  this.userStats = new userStats_1.UserStats({
107
120
  driftClient: this,
@@ -116,14 +129,19 @@ class DriftClient {
116
129
  const noMarketsAndOraclesSpecified = config.perpMarketIndexes === undefined &&
117
130
  config.spotMarketIndexes === undefined &&
118
131
  config.oracleInfos === undefined;
119
- if (((_h = config.accountSubscription) === null || _h === void 0 ? void 0 : _h.type) === 'polling') {
120
- this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (_j = config.perpMarketIndexes) !== null && _j !== void 0 ? _j : [], (_k = config.spotMarketIndexes) !== null && _k !== void 0 ? _k : [], (_l = config.oracleInfos) !== null && _l !== void 0 ? _l : [], noMarketsAndOraclesSpecified);
132
+ if (((_m = config.accountSubscription) === null || _m === void 0 ? void 0 : _m.type) === 'polling') {
133
+ this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (_o = config.perpMarketIndexes) !== null && _o !== void 0 ? _o : [], (_p = config.spotMarketIndexes) !== null && _p !== void 0 ? _p : [], (_q = config.oracleInfos) !== null && _q !== void 0 ? _q : [], noMarketsAndOraclesSpecified);
121
134
  }
122
135
  else {
123
- this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (_m = config.perpMarketIndexes) !== null && _m !== void 0 ? _m : [], (_o = config.spotMarketIndexes) !== null && _o !== void 0 ? _o : [], (_p = config.oracleInfos) !== null && _p !== void 0 ? _p : [], noMarketsAndOraclesSpecified);
136
+ this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (_r = config.perpMarketIndexes) !== null && _r !== void 0 ? _r : [], (_s = config.spotMarketIndexes) !== null && _s !== void 0 ? _s : [], (_t = config.oracleInfos) !== null && _t !== void 0 ? _t : [], noMarketsAndOraclesSpecified);
124
137
  }
125
138
  this.eventEmitter = this.accountSubscriber.eventEmitter;
126
- this.txSender = new retryTxSender_1.RetryTxSender(this.provider, (_q = config.txSenderConfig) === null || _q === void 0 ? void 0 : _q.timeout, (_r = config.txSenderConfig) === null || _r === void 0 ? void 0 : _r.retrySleep, (_s = config.txSenderConfig) === null || _s === void 0 ? void 0 : _s.additionalConnections);
139
+ this.txSender =
140
+ (_u = config.txSender) !== null && _u !== void 0 ? _u : new retryTxSender_1.RetryTxSender({
141
+ connection: this.connection,
142
+ wallet: this.wallet,
143
+ opts: this.opts,
144
+ });
127
145
  }
128
146
  getUserMapKey(subAccountId, authority) {
129
147
  return `${subAccountId}_${authority.toString()}`;
@@ -274,7 +292,7 @@ class DriftClient {
274
292
  const newProgram = new anchor_1.Program(drift_json_1.default, this.program.programId, newProvider);
275
293
  this.skipLoadUsers = false;
276
294
  // Update provider for txSender with new wallet details
277
- this.txSender.provider = newProvider;
295
+ this.txSender.wallet = newWallet;
278
296
  this.wallet = newWallet;
279
297
  this.provider = newProvider;
280
298
  this.program = newProgram;
@@ -304,7 +322,7 @@ class DriftClient {
304
322
  this.userStats = new userStats_1.UserStats({
305
323
  driftClient: this,
306
324
  userStatsAccountPublicKey: this.getUserStatsAccountPublicKey(),
307
- accountSubscription: this.userAccountSubscriptionConfig,
325
+ accountSubscription: this.userStatsAccountSubscriptionConfig,
308
326
  });
309
327
  await this.userStats.subscribe();
310
328
  }
@@ -606,10 +624,16 @@ class DriftClient {
606
624
  authority = authority !== null && authority !== void 0 ? authority : this.authority;
607
625
  const userMapKey = this.getUserMapKey(subAccountId, authority);
608
626
  if (!this.users.has(userMapKey)) {
609
- throw new Error(`Clearing House has no user for user id ${userMapKey}`);
627
+ throw new Error(`DriftClient has no user for user id ${userMapKey}`);
610
628
  }
611
629
  return this.users.get(userMapKey);
612
630
  }
631
+ hasUser(subAccountId, authority) {
632
+ subAccountId = subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId;
633
+ authority = authority !== null && authority !== void 0 ? authority : this.authority;
634
+ const userMapKey = this.getUserMapKey(subAccountId, authority);
635
+ return this.users.has(userMapKey);
636
+ }
613
637
  getUsers() {
614
638
  // delegate users get added to the end
615
639
  return [...this.users.values()]
@@ -1064,7 +1088,7 @@ class DriftClient {
1064
1088
  return (0, spl_token_1.createAssociatedTokenAccountInstruction)(this.wallet.publicKey, associatedTokenAddress, this.wallet.publicKey, tokenMintAddress);
1065
1089
  }
1066
1090
  /**
1067
- * Creates the Clearing House User account for a user, and deposits some initial collateral
1091
+ * Creates the User account for a user, and deposits some initial collateral
1068
1092
  * @param amount
1069
1093
  * @param userTokenAccount
1070
1094
  * @param marketIndex
@@ -1349,6 +1373,19 @@ class DriftClient {
1349
1373
  remainingAccounts: remainingAccounts,
1350
1374
  });
1351
1375
  }
1376
+ getQuoteValuePerLpShare(marketIndex) {
1377
+ const perpMarketAccount = this.getPerpMarketAccount(marketIndex);
1378
+ const openBids = anchor_1.BN.max(perpMarketAccount.amm.baseAssetReserve.sub(perpMarketAccount.amm.minBaseAssetReserve), numericConstants_1.ZERO);
1379
+ const openAsks = anchor_1.BN.max(perpMarketAccount.amm.maxBaseAssetReserve.sub(perpMarketAccount.amm.baseAssetReserve), numericConstants_1.ZERO);
1380
+ const oraclePriceData = this.getOracleDataForPerpMarket(marketIndex);
1381
+ const maxOpenBidsAsks = anchor_1.BN.max(openBids, openAsks);
1382
+ const quoteValuePerLpShare = maxOpenBidsAsks
1383
+ .mul(oraclePriceData.price)
1384
+ .mul(numericConstants_1.QUOTE_PRECISION)
1385
+ .div(numericConstants_1.PRICE_PRECISION)
1386
+ .div(perpMarketAccount.amm.sqrtK);
1387
+ return quoteValuePerLpShare;
1388
+ }
1352
1389
  /**
1353
1390
  * @deprecated use {@link placePerpOrder} or {@link placeAndTakePerpOrder} instead
1354
1391
  */
@@ -3049,13 +3086,13 @@ class DriftClient {
3049
3086
  async buildTransaction(instructions, txParams, txVersion, lookupTables) {
3050
3087
  var _a, _b;
3051
3088
  const allIx = [];
3052
- const computeUnits = (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : 600000;
3089
+ const computeUnits = (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : this.txParams.computeUnits;
3053
3090
  if (computeUnits !== 200000) {
3054
3091
  allIx.push(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
3055
3092
  units: computeUnits,
3056
3093
  }));
3057
3094
  }
3058
- const computeUnitsPrice = (_b = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) !== null && _b !== void 0 ? _b : 0;
3095
+ const computeUnitsPrice = (_b = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) !== null && _b !== void 0 ? _b : this.txParams.computeUnitsPrice;
3059
3096
  if (computeUnitsPrice !== 0) {
3060
3097
  allIx.push(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
3061
3098
  microLamports: computeUnitsPrice,
@@ -1,8 +1,9 @@
1
1
  import { ConfirmOptions, Connection, PublicKey, TransactionVersion } from '@solana/web3.js';
2
- import { IWallet } from './types';
2
+ import { IWallet, TxParams } from './types';
3
3
  import { OracleInfo } from './oracles/types';
4
4
  import { BulkAccountLoader } from './accounts/bulkAccountLoader';
5
5
  import { DriftEnv } from './config';
6
+ import { TxSender } from './tx/types';
6
7
  export type DriftClientConfig = {
7
8
  connection: Connection;
8
9
  wallet: IWallet;
@@ -10,7 +11,7 @@ export type DriftClientConfig = {
10
11
  programID?: PublicKey;
11
12
  accountSubscription?: DriftClientSubscriptionConfig;
12
13
  opts?: ConfirmOptions;
13
- txSenderConfig?: TxSenderConfig;
14
+ txSender?: TxSender;
14
15
  subAccountIds?: number[];
15
16
  activeSubAccountId?: number;
16
17
  perpMarketIndexes?: number[];
@@ -23,6 +24,7 @@ export type DriftClientConfig = {
23
24
  authoritySubAccountMap?: Map<string, number[]>;
24
25
  skipLoadUsers?: boolean;
25
26
  txVersion?: TransactionVersion;
27
+ txParams?: TxParams;
26
28
  };
27
29
  export type DriftClientSubscriptionConfig = {
28
30
  type: 'websocket';
@@ -30,10 +32,3 @@ export type DriftClientSubscriptionConfig = {
30
32
  type: 'polling';
31
33
  accountLoader: BulkAccountLoader;
32
34
  };
33
- type TxSenderConfig = {
34
- type: 'retry';
35
- timeout?: number;
36
- retrySleep?: number;
37
- additionalConnections?: Connection[];
38
- };
39
- export {};
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.31.1-beta.0",
2
+ "version": "2.31.1-beta.9",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -0,0 +1,4 @@
1
+ import { PerpMarketAccount, SpotMarketAccount } from '../types';
2
+ export declare function getPerpMarketTierNumber(perpMarket: PerpMarketAccount): number;
3
+ export declare function getSpotMarketTierNumber(spotMarket: SpotMarketAccount): number;
4
+ export declare function perpTierIsAsSafeAs(perpTier: number, otherPerpTier: number, otherSpotTier: number): boolean;
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.perpTierIsAsSafeAs = exports.getSpotMarketTierNumber = exports.getPerpMarketTierNumber = void 0;
4
+ const types_1 = require("../types");
5
+ function getPerpMarketTierNumber(perpMarket) {
6
+ if ((0, types_1.isVariant)(perpMarket.contractTier, 'a')) {
7
+ return 0;
8
+ }
9
+ else if ((0, types_1.isVariant)(perpMarket.contractTier, 'b')) {
10
+ return 1;
11
+ }
12
+ else if ((0, types_1.isVariant)(perpMarket.contractTier, 'c')) {
13
+ return 2;
14
+ }
15
+ else if ((0, types_1.isVariant)(perpMarket.contractTier, 'speculative')) {
16
+ return 3;
17
+ }
18
+ else if ((0, types_1.isVariant)(perpMarket.contractTier, 'isolated')) {
19
+ return 4;
20
+ }
21
+ else {
22
+ return 5;
23
+ }
24
+ }
25
+ exports.getPerpMarketTierNumber = getPerpMarketTierNumber;
26
+ function getSpotMarketTierNumber(spotMarket) {
27
+ if ((0, types_1.isVariant)(spotMarket.assetTier, 'collateral')) {
28
+ return 0;
29
+ }
30
+ else if ((0, types_1.isVariant)(spotMarket.assetTier, 'protected')) {
31
+ return 1;
32
+ }
33
+ else if ((0, types_1.isVariant)(spotMarket.assetTier, 'cross')) {
34
+ return 2;
35
+ }
36
+ else if ((0, types_1.isVariant)(spotMarket.assetTier, 'isolated')) {
37
+ return 3;
38
+ }
39
+ else if ((0, types_1.isVariant)(spotMarket.assetTier, 'unlisted')) {
40
+ return 4;
41
+ }
42
+ else {
43
+ return 5;
44
+ }
45
+ }
46
+ exports.getSpotMarketTierNumber = getSpotMarketTierNumber;
47
+ function perpTierIsAsSafeAs(perpTier, otherPerpTier, otherSpotTier) {
48
+ const asSafeAsPerp = perpTier <= otherPerpTier;
49
+ const asSafeAsSpot = otherSpotTier === 4 || (otherSpotTier >= 2 && perpTier <= 2);
50
+ return asSafeAsSpot && asSafeAsPerp;
51
+ }
52
+ exports.perpTierIsAsSafeAs = perpTierIsAsSafeAs;
@@ -1,16 +1,26 @@
1
1
  /// <reference types="node" />
2
2
  import { TxSender, TxSigAndSlot } from './types';
3
3
  import { Commitment, ConfirmOptions, RpcResponseAndContext, Signer, SignatureResult, Transaction, TransactionSignature, Connection, VersionedTransaction, TransactionInstruction, AddressLookupTableAccount } from '@solana/web3.js';
4
- import { AnchorProvider } from '@coral-xyz/anchor';
4
+ import { IWallet } from '../types';
5
5
  type ResolveReference = {
6
6
  resolve?: () => void;
7
7
  };
8
8
  export declare class RetryTxSender implements TxSender {
9
- provider: AnchorProvider;
9
+ connection: Connection;
10
+ wallet: IWallet;
11
+ opts: ConfirmOptions;
10
12
  timeout: number;
11
13
  retrySleep: number;
12
14
  additionalConnections: Connection[];
13
- constructor(provider: AnchorProvider, timeout?: number, retrySleep?: number, additionalConnections?: Connection[]);
15
+ timoutCount: number;
16
+ constructor({ connection, wallet, opts, timeout, retrySleep, additionalConnections, }: {
17
+ connection: Connection;
18
+ wallet: IWallet;
19
+ opts?: ConfirmOptions;
20
+ timeout?: number;
21
+ retrySleep?: number;
22
+ additionalConnections?: any;
23
+ });
14
24
  send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
15
25
  prepareTx(tx: Transaction, additionalSigners: Array<Signer>, opts: ConfirmOptions): Promise<Transaction>;
16
26
  getVersionedTransaction(ixs: TransactionInstruction[], lookupTableAccounts: AddressLookupTableAccount[], additionalSigners?: Array<Signer>, opts?: ConfirmOptions): Promise<VersionedTransaction>;
@@ -22,5 +32,6 @@ export declare class RetryTxSender implements TxSender {
22
32
  promiseTimeout<T>(promises: Promise<T>[], timeoutMs: number): Promise<T | null>;
23
33
  sendToAdditionalConnections(rawTx: Buffer | Uint8Array, opts: ConfirmOptions): void;
24
34
  addAdditionalConnection(newConnection: Connection): void;
35
+ getTimeoutCount(): number;
25
36
  }
26
37
  export {};
@@ -5,15 +5,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.RetryTxSender = void 0;
7
7
  const web3_js_1 = require("@solana/web3.js");
8
+ const anchor_1 = require("@coral-xyz/anchor");
8
9
  const assert_1 = __importDefault(require("assert"));
9
10
  const bs58_1 = __importDefault(require("bs58"));
10
11
  const DEFAULT_TIMEOUT = 35000;
11
12
  const DEFAULT_RETRY = 8000;
12
13
  class RetryTxSender {
13
- constructor(provider, timeout, retrySleep, additionalConnections = new Array()) {
14
- this.provider = provider;
15
- this.timeout = timeout !== null && timeout !== void 0 ? timeout : DEFAULT_TIMEOUT;
16
- this.retrySleep = retrySleep !== null && retrySleep !== void 0 ? retrySleep : DEFAULT_RETRY;
14
+ constructor({ connection, wallet, opts = anchor_1.AnchorProvider.defaultOptions(), timeout = DEFAULT_TIMEOUT, retrySleep = DEFAULT_RETRY, additionalConnections = new Array(), }) {
15
+ this.timoutCount = 0;
16
+ this.connection = connection;
17
+ this.wallet = wallet;
18
+ this.opts = opts;
19
+ this.timeout = timeout;
20
+ this.retrySleep = retrySleep;
17
21
  this.additionalConnections = additionalConnections;
18
22
  }
19
23
  async send(tx, additionalSigners, opts, preSigned) {
@@ -21,7 +25,7 @@ class RetryTxSender {
21
25
  additionalSigners = [];
22
26
  }
23
27
  if (opts === undefined) {
24
- opts = this.provider.opts;
28
+ opts = this.opts;
25
29
  }
26
30
  const signedTx = preSigned
27
31
  ? tx
@@ -29,14 +33,14 @@ class RetryTxSender {
29
33
  return this.sendRawTransaction(signedTx.serialize(), opts);
30
34
  }
31
35
  async prepareTx(tx, additionalSigners, opts) {
32
- tx.feePayer = this.provider.wallet.publicKey;
33
- tx.recentBlockhash = (await this.provider.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash;
36
+ tx.feePayer = this.wallet.publicKey;
37
+ tx.recentBlockhash = (await this.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash;
34
38
  additionalSigners
35
39
  .filter((s) => s !== undefined)
36
40
  .forEach((kp) => {
37
41
  tx.partialSign(kp);
38
42
  });
39
- const signedTx = await this.provider.wallet.signTransaction(tx);
43
+ const signedTx = await this.wallet.signTransaction(tx);
40
44
  return signedTx;
41
45
  }
42
46
  async getVersionedTransaction(ixs, lookupTableAccounts, additionalSigners, opts) {
@@ -44,11 +48,11 @@ class RetryTxSender {
44
48
  additionalSigners = [];
45
49
  }
46
50
  if (opts === undefined) {
47
- opts = this.provider.opts;
51
+ opts = this.opts;
48
52
  }
49
53
  const message = new web3_js_1.TransactionMessage({
50
- payerKey: this.provider.wallet.publicKey,
51
- recentBlockhash: (await this.provider.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash,
54
+ payerKey: this.wallet.publicKey,
55
+ recentBlockhash: (await this.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash,
52
56
  instructions: ixs,
53
57
  }).compileToV0Message(lookupTableAccounts);
54
58
  const tx = new web3_js_1.VersionedTransaction(message);
@@ -60,9 +64,9 @@ class RetryTxSender {
60
64
  signedTx = tx;
61
65
  // @ts-ignore
62
66
  }
63
- else if (this.provider.wallet.payer) {
67
+ else if (this.wallet.payer) {
64
68
  // @ts-ignore
65
- tx.sign((additionalSigners !== null && additionalSigners !== void 0 ? additionalSigners : []).concat(this.provider.wallet.payer));
69
+ tx.sign((additionalSigners !== null && additionalSigners !== void 0 ? additionalSigners : []).concat(this.wallet.payer));
66
70
  signedTx = tx;
67
71
  }
68
72
  else {
@@ -70,10 +74,10 @@ class RetryTxSender {
70
74
  tx.sign([kp]);
71
75
  });
72
76
  // @ts-ignore
73
- signedTx = await this.provider.wallet.signTransaction(tx);
77
+ signedTx = await this.wallet.signTransaction(tx);
74
78
  }
75
79
  if (opts === undefined) {
76
- opts = this.provider.opts;
80
+ opts = this.opts;
77
81
  }
78
82
  return this.sendRawTransaction(signedTx.serialize(), opts);
79
83
  }
@@ -81,7 +85,7 @@ class RetryTxSender {
81
85
  const startTime = this.getTimestamp();
82
86
  let txid;
83
87
  try {
84
- txid = await this.provider.connection.sendRawTransaction(rawTransaction, opts);
88
+ txid = await this.connection.sendRawTransaction(rawTransaction, opts);
85
89
  this.sendToAdditionalConnections(rawTransaction, opts);
86
90
  }
87
91
  catch (e) {
@@ -102,7 +106,7 @@ class RetryTxSender {
102
106
  while (!done && this.getTimestamp() - startTime < this.timeout) {
103
107
  await this.sleep(resolveReference);
104
108
  if (!done) {
105
- this.provider.connection
109
+ this.connection
106
110
  .sendRawTransaction(rawTransaction, opts)
107
111
  .catch((e) => {
108
112
  console.error(e);
@@ -136,12 +140,9 @@ class RetryTxSender {
136
140
  }
137
141
  (0, assert_1.default)(decodedSignature.length === 64, 'signature has invalid length');
138
142
  const start = Date.now();
139
- const subscriptionCommitment = commitment || this.provider.opts.commitment;
143
+ const subscriptionCommitment = commitment || this.opts.commitment;
140
144
  const subscriptionIds = new Array();
141
- const connections = [
142
- this.provider.connection,
143
- ...this.additionalConnections,
144
- ];
145
+ const connections = [this.connection, ...this.additionalConnections];
145
146
  let response = null;
146
147
  const promises = connections.map((connection, i) => {
147
148
  let subscriptionId;
@@ -174,6 +175,7 @@ class RetryTxSender {
174
175
  }
175
176
  }
176
177
  if (response === null) {
178
+ this.timoutCount += 1;
177
179
  const duration = (Date.now() - start) / 1000;
178
180
  throw new Error(`Transaction was not confirmed in ${duration.toFixed(2)} seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools.`);
179
181
  }
@@ -217,5 +219,8 @@ class RetryTxSender {
217
219
  this.additionalConnections.push(newConnection);
218
220
  }
219
221
  }
222
+ getTimeoutCount() {
223
+ return this.timoutCount;
224
+ }
220
225
  }
221
226
  exports.RetryTxSender = RetryTxSender;
package/lib/tx/types.d.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  /// <reference types="node" />
2
- import { Provider } from '@coral-xyz/anchor';
3
2
  import { AddressLookupTableAccount, ConfirmOptions, Signer, Transaction, TransactionInstruction, TransactionSignature, VersionedTransaction } from '@solana/web3.js';
3
+ import { IWallet } from '../types';
4
4
  export type TxSigAndSlot = {
5
5
  txSig: TransactionSignature;
6
6
  slot: number;
7
7
  };
8
8
  export interface TxSender {
9
- provider: Provider;
9
+ wallet: IWallet;
10
10
  send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
11
11
  sendVersionedTransaction(tx: VersionedTransaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
12
12
  getVersionedTransaction(ixs: TransactionInstruction[], lookupTableAccounts: AddressLookupTableAccount[], additionalSigners?: Array<Signer>, opts?: ConfirmOptions): Promise<VersionedTransaction>;
13
13
  sendRawTransaction(rawTransaction: Buffer | Uint8Array, opts: ConfirmOptions): Promise<TxSigAndSlot>;
14
+ getTimeoutCount(): number;
14
15
  }
package/lib/user.d.ts CHANGED
@@ -107,6 +107,7 @@ export declare class User {
107
107
  */
108
108
  getMaintenanceMarginRequirement(liquidationBuffer?: BN): BN;
109
109
  getActivePerpPositions(): PerpPosition[];
110
+ getActiveSpotPositions(): SpotPosition[];
110
111
  /**
111
112
  * calculates unrealized position price pnl
112
113
  * @returns : Precision QUOTE_PRECISION
@@ -185,7 +186,11 @@ export declare class User {
185
186
  * @returns : Precision TEN_THOUSAND
186
187
  */
187
188
  getMarginRatio(): BN;
188
- canBeLiquidated(): boolean;
189
+ canBeLiquidated(): {
190
+ canBeLiquidated: boolean;
191
+ marginRequirement: BN;
192
+ totalCollateral: BN;
193
+ };
189
194
  isBeingLiquidated(): boolean;
190
195
  isBankrupt(): boolean;
191
196
  /**
@@ -277,6 +282,10 @@ export declare class User {
277
282
  maxDepositAmount: BN;
278
283
  };
279
284
  canMakeIdle(slot: BN, slotsBeforeIdle: BN): boolean;
285
+ getSafestTiers(): {
286
+ perpTier: number;
287
+ spotTier: number;
288
+ };
280
289
  /**
281
290
  * Get the total position value, excluding any position coming from the given target market
282
291
  * @param marketToIgnore