@drift-labs/sdk 2.21.0-beta.0 → 2.21.0-beta.2

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/lib/dlob/DLOB.js CHANGED
@@ -633,8 +633,10 @@ class DLOB {
633
633
  * @returns
634
634
  */
635
635
  *getMakerLimitAsks(marketIndex, slot, marketType, oraclePriceData, fallbackBid) {
636
+ const isPerpMarket = (0, __1.isVariant)(marketType, 'perp');
636
637
  for (const node of this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData)) {
637
- if (fallbackBid &&
638
+ if (isPerpMarket &&
639
+ fallbackBid &&
638
640
  node.getPrice(oraclePriceData, slot).lte(fallbackBid)) {
639
641
  continue;
640
642
  }
@@ -668,8 +670,10 @@ class DLOB {
668
670
  * @returns
669
671
  */
670
672
  *getMakerLimitBids(marketIndex, slot, marketType, oraclePriceData, fallbackAsk) {
673
+ const isPerpMarket = (0, __1.isVariant)(marketType, 'perp');
671
674
  for (const node of this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData)) {
672
- if (fallbackAsk &&
675
+ if (isPerpMarket &&
676
+ fallbackAsk &&
673
677
  node.getPrice(oraclePriceData, slot).gte(fallbackAsk)) {
674
678
  continue;
675
679
  }
@@ -145,7 +145,7 @@ export declare class DriftClient {
145
145
  * @param fromSubAccountId
146
146
  * @returns
147
147
  */
148
- initializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, marketIndex?: number, subAccountId?: number, name?: string, fromSubAccountId?: number, referrerInfo?: ReferrerInfo): Promise<[TransactionSignature, PublicKey]>;
148
+ initializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, marketIndex?: number, subAccountId?: number, name?: string, fromSubAccountId?: number, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<[TransactionSignature, PublicKey]>;
149
149
  initializeUserAccountForDevnet(subAccountId: number, name: string, marketIndex: number, tokenFaucet: TokenFaucet, amount: BN, referrerInfo?: ReferrerInfo): Promise<[TransactionSignature, PublicKey]>;
150
150
  withdraw(amount: BN, marketIndex: number, userTokenAccount: PublicKey, reduceOnly?: boolean): Promise<TransactionSignature>;
151
151
  getWithdrawIx(amount: BN, marketIndex: number, userTokenAccount: PublicKey, reduceOnly?: boolean): Promise<TransactionInstruction>;
@@ -191,6 +191,7 @@ export declare class DriftClient {
191
191
  getCancelOrdersIx(marketType: MarketType | null, marketIndex: number | null, direction: PositionDirection | null): Promise<TransactionInstruction>;
192
192
  fillPerpOrder(userAccountPublicKey: PublicKey, user: UserAccount, order?: Pick<Order, 'marketIndex' | 'orderId'>, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
193
193
  getFillPerpOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Pick<Order, 'marketIndex' | 'orderId'>, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
194
+ getRevertFillIx(): Promise<TransactionInstruction>;
194
195
  placeSpotOrder(orderParams: OptionalOrderParams, txParams?: TxParams): Promise<TransactionSignature>;
195
196
  getPlaceSpotOrderIx(orderParams: OptionalOrderParams): Promise<TransactionInstruction>;
196
197
  fillSpotOrder(userAccountPublicKey: PublicKey, user: UserAccount, order?: Order, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
@@ -201,8 +202,8 @@ export declare class DriftClient {
201
202
  getTriggerOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order): Promise<TransactionInstruction>;
202
203
  forceCancelOrders(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams): Promise<TransactionSignature>;
203
204
  getForceCancelOrdersIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<TransactionInstruction>;
204
- updateUserInactive(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams): Promise<TransactionSignature>;
205
- getUpdateUserInactiveIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<TransactionInstruction>;
205
+ updateUserIdle(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams): Promise<TransactionSignature>;
206
+ getUpdateUserIdleIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<TransactionInstruction>;
206
207
  placeAndTakePerpOrder(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
207
208
  getPlaceAndTakePerpOrderIx(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
208
209
  placeAndMakePerpOrder(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
@@ -820,12 +820,21 @@ class DriftClient {
820
820
  * @param fromSubAccountId
821
821
  * @returns
822
822
  */
823
- async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, fromSubAccountId, referrerInfo) {
823
+ async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, fromSubAccountId, referrerInfo, txParams) {
824
+ var _a;
824
825
  const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(subAccountId, name, referrerInfo);
825
826
  const additionalSigners = [];
826
827
  const spotMarket = this.getSpotMarketAccount(marketIndex);
827
828
  const isSolMarket = spotMarket.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
828
829
  const tx = new web3_js_1.Transaction();
830
+ tx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
831
+ units: (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : 600000,
832
+ }));
833
+ if (txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) {
834
+ tx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
835
+ microLamports: txParams.computeUnitsPrice,
836
+ }));
837
+ }
829
838
  const authority = this.wallet.publicKey;
830
839
  const createWSOLTokenAccount = isSolMarket && userTokenAccount.equals(authority);
831
840
  if (createWSOLTokenAccount) {
@@ -1357,6 +1366,18 @@ class DriftClient {
1357
1366
  remainingAccounts,
1358
1367
  });
1359
1368
  }
1369
+ async getRevertFillIx() {
1370
+ const fillerPublicKey = await this.getUserAccountPublicKey();
1371
+ const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
1372
+ return this.program.instruction.revertFill({
1373
+ accounts: {
1374
+ state: await this.getStatePublicKey(),
1375
+ filler: fillerPublicKey,
1376
+ fillerStats: fillerStatsPublicKey,
1377
+ authority: this.wallet.publicKey,
1378
+ },
1379
+ });
1380
+ }
1360
1381
  async placeSpotOrder(orderParams, txParams) {
1361
1382
  const { txSig, slot } = await this.sendTransaction((0, utils_1.wrapInTx)(await this.getPlaceSpotOrderIx(orderParams), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
1362
1383
  this.spotMarketLastSlotCache.set(orderParams.marketIndex, slot);
@@ -1592,16 +1613,16 @@ class DriftClient {
1592
1613
  remainingAccounts,
1593
1614
  });
1594
1615
  }
1595
- async updateUserInactive(userAccountPublicKey, user, txParams) {
1596
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getUpdateUserInactiveIx(userAccountPublicKey, user), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
1616
+ async updateUserIdle(userAccountPublicKey, user, txParams) {
1617
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getUpdateUserIdleIx(userAccountPublicKey, user), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
1597
1618
  return txSig;
1598
1619
  }
1599
- async getUpdateUserInactiveIx(userAccountPublicKey, userAccount) {
1620
+ async getUpdateUserIdleIx(userAccountPublicKey, userAccount) {
1600
1621
  const fillerPublicKey = await this.getUserAccountPublicKey();
1601
1622
  const remainingAccounts = this.getRemainingAccounts({
1602
1623
  userAccounts: [userAccount],
1603
1624
  });
1604
- return await this.program.instruction.updateUserInactive({
1625
+ return await this.program.instruction.updateUserIdle({
1605
1626
  accounts: {
1606
1627
  state: await this.getStatePublicKey(),
1607
1628
  filler: fillerPublicKey,
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.21.0-beta.0",
2
+ "version": "2.21.0-beta.2",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -909,6 +909,32 @@
909
909
  }
910
910
  ]
911
911
  },
912
+ {
913
+ "name": "revertFill",
914
+ "accounts": [
915
+ {
916
+ "name": "state",
917
+ "isMut": false,
918
+ "isSigner": false
919
+ },
920
+ {
921
+ "name": "authority",
922
+ "isMut": false,
923
+ "isSigner": true
924
+ },
925
+ {
926
+ "name": "filler",
927
+ "isMut": true,
928
+ "isSigner": false
929
+ },
930
+ {
931
+ "name": "fillerStats",
932
+ "isMut": true,
933
+ "isSigner": false
934
+ }
935
+ ],
936
+ "args": []
937
+ },
912
938
  {
913
939
  "name": "fillSpotOrder",
914
940
  "accounts": [
@@ -1023,6 +1049,32 @@
1023
1049
  ],
1024
1050
  "args": []
1025
1051
  },
1052
+ {
1053
+ "name": "updateUserIdle",
1054
+ "accounts": [
1055
+ {
1056
+ "name": "state",
1057
+ "isMut": false,
1058
+ "isSigner": false
1059
+ },
1060
+ {
1061
+ "name": "authority",
1062
+ "isMut": false,
1063
+ "isSigner": true
1064
+ },
1065
+ {
1066
+ "name": "filler",
1067
+ "isMut": true,
1068
+ "isSigner": false
1069
+ },
1070
+ {
1071
+ "name": "user",
1072
+ "isMut": true,
1073
+ "isSigner": false
1074
+ }
1075
+ ],
1076
+ "args": []
1077
+ },
1026
1078
  {
1027
1079
  "name": "settlePnl",
1028
1080
  "accounts": [
@@ -8742,6 +8794,11 @@
8742
8794
  "code": 6238,
8743
8795
  "name": "UserNotInactive",
8744
8796
  "msg": "User Not Inactive"
8797
+ },
8798
+ {
8799
+ "code": 6239,
8800
+ "name": "RevertFill",
8801
+ "msg": "RevertFill"
8745
8802
  }
8746
8803
  ]
8747
8804
  }
@@ -31,12 +31,12 @@ class RetryTxSender {
31
31
  async prepareTx(tx, additionalSigners, opts) {
32
32
  tx.feePayer = this.provider.wallet.publicKey;
33
33
  tx.recentBlockhash = (await this.provider.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash;
34
- const signedTx = await this.provider.wallet.signTransaction(tx);
35
34
  additionalSigners
36
35
  .filter((s) => s !== undefined)
37
36
  .forEach((kp) => {
38
- signedTx.partialSign(kp);
37
+ tx.partialSign(kp);
39
38
  });
39
+ const signedTx = await this.provider.wallet.signTransaction(tx);
40
40
  return signedTx;
41
41
  }
42
42
  async sendVersionedTransaction(ixs, lookupTableAccounts, additionalSigners, opts) {
package/lib/types.d.ts CHANGED
@@ -847,7 +847,7 @@ export type UserAccount = {
847
847
  liquidationMarginFreed: BN;
848
848
  lastActiveSlot: BN;
849
849
  isMarginTradingEnabled: boolean;
850
- inactive: boolean;
850
+ idle: boolean;
851
851
  };
852
852
  export type SpotPosition = {
853
853
  marketIndex: number;
package/lib/user.js CHANGED
@@ -1214,7 +1214,7 @@ class User {
1214
1214
  }
1215
1215
  canMakeIdle(slot, slotsBeforeIdle) {
1216
1216
  const userAccount = this.getUserAccount();
1217
- if (userAccount.inactive) {
1217
+ if (userAccount.idle) {
1218
1218
  return false;
1219
1219
  }
1220
1220
  const userLastActiveSlot = userAccount.lastActiveSlot;
@@ -40,4 +40,5 @@ export declare class UserMap implements UserMapInterface {
40
40
  updateWithEventRecord(record: WrappedEvent<any>): Promise<void>;
41
41
  values(): IterableIterator<User>;
42
42
  size(): number;
43
+ sync(includeIdle?: boolean): Promise<void>;
43
44
  }
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.UserMap = void 0;
4
7
  const __1 = require("..");
5
8
  const web3_js_1 = require("@solana/web3.js");
9
+ const bs58_1 = __importDefault(require("bs58"));
6
10
  class UserMap {
7
11
  constructor(driftClient, accountSubscription) {
8
12
  this.userMap = new Map();
@@ -131,5 +135,42 @@ class UserMap {
131
135
  size() {
132
136
  return this.userMap.size;
133
137
  }
138
+ async sync(includeIdle = true) {
139
+ let filters = undefined;
140
+ if (!includeIdle) {
141
+ filters = [
142
+ {
143
+ memcmp: {
144
+ offset: 4350,
145
+ bytes: bs58_1.default.encode(Uint8Array.from([0])),
146
+ },
147
+ },
148
+ ];
149
+ }
150
+ const programAccounts = await this.driftClient.connection.getProgramAccounts(this.driftClient.program.programId, {
151
+ commitment: this.driftClient.connection.commitment,
152
+ filters: [
153
+ {
154
+ memcmp: this.driftClient.program.coder.accounts.memcmp('User'),
155
+ },
156
+ ...(Array.isArray(filters) ? filters : []),
157
+ ],
158
+ });
159
+ const programAccountMap = new Map();
160
+ for (const programAccount of programAccounts) {
161
+ programAccountMap.set(programAccount.pubkey.toString(), programAccount.account);
162
+ }
163
+ for (const key of programAccountMap.keys()) {
164
+ if (!this.has(key)) {
165
+ await this.addPubkey(new web3_js_1.PublicKey(key));
166
+ }
167
+ }
168
+ for (const [key, user] of this.userMap.entries()) {
169
+ if (!programAccountMap.has(key)) {
170
+ await user.unsubscribe();
171
+ this.userMap.delete(key);
172
+ }
173
+ }
174
+ }
134
175
  }
135
176
  exports.UserMap = UserMap;
@@ -18,4 +18,5 @@ export declare class UserStatsMap {
18
18
  mustGet(authorityPublicKey: string): Promise<UserStats>;
19
19
  values(): IterableIterator<UserStats>;
20
20
  size(): number;
21
+ sync(): Promise<void>;
21
22
  }
@@ -137,5 +137,24 @@ class UserStatsMap {
137
137
  size() {
138
138
  return this.userStatsMap.size;
139
139
  }
140
+ async sync() {
141
+ const programAccounts = await this.driftClient.connection.getProgramAccounts(this.driftClient.program.programId, {
142
+ commitment: this.driftClient.connection.commitment,
143
+ filters: [
144
+ {
145
+ memcmp: this.driftClient.program.coder.accounts.memcmp('UserStats'),
146
+ },
147
+ ],
148
+ });
149
+ const programAccountMap = new Map();
150
+ for (const programAccount of programAccounts) {
151
+ programAccountMap.set(new web3_js_1.PublicKey(programAccount.account.data.slice(8, 40)).toString(), programAccount.account);
152
+ }
153
+ for (const key of programAccountMap.keys()) {
154
+ if (!this.has(key)) {
155
+ await this.addUserStat(new web3_js_1.PublicKey(key));
156
+ }
157
+ }
158
+ }
140
159
  }
141
160
  exports.UserStatsMap = UserStatsMap;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.21.0-beta.0",
3
+ "version": "2.21.0-beta.2",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assert = void 0;
4
+ function assert(condition, error) {
5
+ if (!condition) {
6
+ throw new Error(error || 'Unspecified AssertionError');
7
+ }
8
+ }
9
+ exports.assert = assert;
package/src/dlob/DLOB.ts CHANGED
@@ -1148,6 +1148,7 @@ export class DLOB {
1148
1148
  oraclePriceData: OraclePriceData,
1149
1149
  fallbackBid?: BN
1150
1150
  ): Generator<DLOBNode> {
1151
+ const isPerpMarket = isVariant(marketType, 'perp');
1151
1152
  for (const node of this.getRestingLimitAsks(
1152
1153
  marketIndex,
1153
1154
  slot,
@@ -1155,6 +1156,7 @@ export class DLOB {
1155
1156
  oraclePriceData
1156
1157
  )) {
1157
1158
  if (
1159
+ isPerpMarket &&
1158
1160
  fallbackBid &&
1159
1161
  node.getPrice(oraclePriceData, slot).lte(fallbackBid)
1160
1162
  ) {
@@ -1213,6 +1215,7 @@ export class DLOB {
1213
1215
  oraclePriceData: OraclePriceData,
1214
1216
  fallbackAsk?: BN
1215
1217
  ): Generator<DLOBNode> {
1218
+ const isPerpMarket = isVariant(marketType, 'perp');
1216
1219
  for (const node of this.getRestingLimitBids(
1217
1220
  marketIndex,
1218
1221
  slot,
@@ -1220,6 +1223,7 @@ export class DLOB {
1220
1223
  oraclePriceData
1221
1224
  )) {
1222
1225
  if (
1226
+ isPerpMarket &&
1223
1227
  fallbackAsk &&
1224
1228
  node.getPrice(oraclePriceData, slot).gte(fallbackAsk)
1225
1229
  ) {
@@ -1329,7 +1329,8 @@ export class DriftClient {
1329
1329
  subAccountId = 0,
1330
1330
  name = DEFAULT_USER_NAME,
1331
1331
  fromSubAccountId?: number,
1332
- referrerInfo?: ReferrerInfo
1332
+ referrerInfo?: ReferrerInfo,
1333
+ txParams?: TxParams
1333
1334
  ): Promise<[TransactionSignature, PublicKey]> {
1334
1335
  const [userAccountPublicKey, initializeUserAccountIx] =
1335
1336
  await this.getInitializeUserInstructions(
@@ -1346,6 +1347,20 @@ export class DriftClient {
1346
1347
 
1347
1348
  const tx = new Transaction();
1348
1349
 
1350
+ tx.add(
1351
+ ComputeBudgetProgram.setComputeUnitLimit({
1352
+ units: txParams?.computeUnits ?? 600_000,
1353
+ })
1354
+ );
1355
+
1356
+ if (txParams?.computeUnitsPrice) {
1357
+ tx.add(
1358
+ ComputeBudgetProgram.setComputeUnitPrice({
1359
+ microLamports: txParams.computeUnitsPrice,
1360
+ })
1361
+ );
1362
+ }
1363
+
1349
1364
  const authority = this.wallet.publicKey;
1350
1365
 
1351
1366
  const createWSOLTokenAccount =
@@ -2394,6 +2409,20 @@ export class DriftClient {
2394
2409
  });
2395
2410
  }
2396
2411
 
2412
+ public async getRevertFillIx(): Promise<TransactionInstruction> {
2413
+ const fillerPublicKey = await this.getUserAccountPublicKey();
2414
+ const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
2415
+
2416
+ return this.program.instruction.revertFill({
2417
+ accounts: {
2418
+ state: await this.getStatePublicKey(),
2419
+ filler: fillerPublicKey,
2420
+ fillerStats: fillerStatsPublicKey,
2421
+ authority: this.wallet.publicKey,
2422
+ },
2423
+ });
2424
+ }
2425
+
2397
2426
  public async placeSpotOrder(
2398
2427
  orderParams: OptionalOrderParams,
2399
2428
  txParams?: TxParams
@@ -2759,14 +2788,14 @@ export class DriftClient {
2759
2788
  });
2760
2789
  }
2761
2790
 
2762
- public async updateUserInactive(
2791
+ public async updateUserIdle(
2763
2792
  userAccountPublicKey: PublicKey,
2764
2793
  user: UserAccount,
2765
2794
  txParams?: TxParams
2766
2795
  ): Promise<TransactionSignature> {
2767
2796
  const { txSig } = await this.txSender.send(
2768
2797
  wrapInTx(
2769
- await this.getUpdateUserInactiveIx(userAccountPublicKey, user),
2798
+ await this.getUpdateUserIdleIx(userAccountPublicKey, user),
2770
2799
  txParams?.computeUnits,
2771
2800
  txParams?.computeUnitsPrice
2772
2801
  ),
@@ -2776,7 +2805,7 @@ export class DriftClient {
2776
2805
  return txSig;
2777
2806
  }
2778
2807
 
2779
- public async getUpdateUserInactiveIx(
2808
+ public async getUpdateUserIdleIx(
2780
2809
  userAccountPublicKey: PublicKey,
2781
2810
  userAccount: UserAccount
2782
2811
  ): Promise<TransactionInstruction> {
@@ -2786,7 +2815,7 @@ export class DriftClient {
2786
2815
  userAccounts: [userAccount],
2787
2816
  });
2788
2817
 
2789
- return await this.program.instruction.updateUserInactive({
2818
+ return await this.program.instruction.updateUserIdle({
2790
2819
  accounts: {
2791
2820
  state: await this.getStatePublicKey(),
2792
2821
  filler: fillerPublicKey,
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.21.0-beta.0",
2
+ "version": "2.21.0-beta.2",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -909,6 +909,32 @@
909
909
  }
910
910
  ]
911
911
  },
912
+ {
913
+ "name": "revertFill",
914
+ "accounts": [
915
+ {
916
+ "name": "state",
917
+ "isMut": false,
918
+ "isSigner": false
919
+ },
920
+ {
921
+ "name": "authority",
922
+ "isMut": false,
923
+ "isSigner": true
924
+ },
925
+ {
926
+ "name": "filler",
927
+ "isMut": true,
928
+ "isSigner": false
929
+ },
930
+ {
931
+ "name": "fillerStats",
932
+ "isMut": true,
933
+ "isSigner": false
934
+ }
935
+ ],
936
+ "args": []
937
+ },
912
938
  {
913
939
  "name": "fillSpotOrder",
914
940
  "accounts": [
@@ -1023,6 +1049,32 @@
1023
1049
  ],
1024
1050
  "args": []
1025
1051
  },
1052
+ {
1053
+ "name": "updateUserIdle",
1054
+ "accounts": [
1055
+ {
1056
+ "name": "state",
1057
+ "isMut": false,
1058
+ "isSigner": false
1059
+ },
1060
+ {
1061
+ "name": "authority",
1062
+ "isMut": false,
1063
+ "isSigner": true
1064
+ },
1065
+ {
1066
+ "name": "filler",
1067
+ "isMut": true,
1068
+ "isSigner": false
1069
+ },
1070
+ {
1071
+ "name": "user",
1072
+ "isMut": true,
1073
+ "isSigner": false
1074
+ }
1075
+ ],
1076
+ "args": []
1077
+ },
1026
1078
  {
1027
1079
  "name": "settlePnl",
1028
1080
  "accounts": [
@@ -8742,6 +8794,11 @@
8742
8794
  "code": 6238,
8743
8795
  "name": "UserNotInactive",
8744
8796
  "msg": "User Not Inactive"
8797
+ },
8798
+ {
8799
+ "code": 6239,
8800
+ "name": "RevertFill",
8801
+ "msg": "RevertFill"
8745
8802
  }
8746
8803
  ]
8747
8804
  }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTokenAccount = void 0;
4
+ const spl_token_1 = require("@solana/spl-token");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ function parseTokenAccount(data) {
7
+ const accountInfo = spl_token_1.AccountLayout.decode(data);
8
+ accountInfo.mint = new web3_js_1.PublicKey(accountInfo.mint);
9
+ accountInfo.owner = new web3_js_1.PublicKey(accountInfo.owner);
10
+ accountInfo.amount = spl_token_1.u64.fromBuffer(accountInfo.amount);
11
+ if (accountInfo.delegateOption === 0) {
12
+ accountInfo.delegate = null;
13
+ // eslint-disable-next-line new-cap
14
+ accountInfo.delegatedAmount = new spl_token_1.u64(0);
15
+ }
16
+ else {
17
+ accountInfo.delegate = new web3_js_1.PublicKey(accountInfo.delegate);
18
+ accountInfo.delegatedAmount = spl_token_1.u64.fromBuffer(accountInfo.delegatedAmount);
19
+ }
20
+ accountInfo.isInitialized = accountInfo.state !== 0;
21
+ accountInfo.isFrozen = accountInfo.state === 2;
22
+ if (accountInfo.isNativeOption === 1) {
23
+ accountInfo.rentExemptReserve = spl_token_1.u64.fromBuffer(accountInfo.isNative);
24
+ accountInfo.isNative = true;
25
+ }
26
+ else {
27
+ accountInfo.rentExemptReserve = null;
28
+ accountInfo.isNative = false;
29
+ }
30
+ if (accountInfo.closeAuthorityOption === 0) {
31
+ accountInfo.closeAuthority = null;
32
+ }
33
+ else {
34
+ accountInfo.closeAuthority = new web3_js_1.PublicKey(accountInfo.closeAuthority);
35
+ }
36
+ return accountInfo;
37
+ }
38
+ exports.parseTokenAccount = parseTokenAccount;
@@ -75,13 +75,14 @@ export class RetryTxSender implements TxSender {
75
75
  )
76
76
  ).blockhash;
77
77
 
78
- const signedTx = await this.provider.wallet.signTransaction(tx);
79
78
  additionalSigners
80
79
  .filter((s): s is Signer => s !== undefined)
81
80
  .forEach((kp) => {
82
- signedTx.partialSign(kp);
81
+ tx.partialSign(kp);
83
82
  });
84
83
 
84
+ const signedTx = await this.provider.wallet.signTransaction(tx);
85
+
85
86
  return signedTx;
86
87
  }
87
88
 
package/src/types.ts CHANGED
@@ -800,7 +800,7 @@ export type UserAccount = {
800
800
  liquidationMarginFreed: BN;
801
801
  lastActiveSlot: BN;
802
802
  isMarginTradingEnabled: boolean;
803
- inactive: boolean;
803
+ idle: boolean;
804
804
  };
805
805
 
806
806
  export type SpotPosition = {
package/src/user.ts CHANGED
@@ -2173,7 +2173,7 @@ export class User {
2173
2173
 
2174
2174
  public canMakeIdle(slot: BN, slotsBeforeIdle: BN): boolean {
2175
2175
  const userAccount = this.getUserAccount();
2176
- if (userAccount.inactive) {
2176
+ if (userAccount.idle) {
2177
2177
  return false;
2178
2178
  }
2179
2179
 
@@ -15,7 +15,9 @@ import {
15
15
  LPRecord,
16
16
  } from '..';
17
17
 
18
- import { PublicKey } from '@solana/web3.js';
18
+ import { AccountInfo, PublicKey } from '@solana/web3.js';
19
+ import { Buffer } from 'buffer';
20
+ import bs58 from 'bs58';
19
21
 
20
22
  export interface UserMapInterface {
21
23
  fetchAllUsers(): Promise<void>;
@@ -177,4 +179,53 @@ export class UserMap implements UserMapInterface {
177
179
  public size(): number {
178
180
  return this.userMap.size;
179
181
  }
182
+
183
+ public async sync(includeIdle = true) {
184
+ let filters = undefined;
185
+ if (!includeIdle) {
186
+ filters = [
187
+ {
188
+ memcmp: {
189
+ offset: 4350,
190
+ bytes: bs58.encode(Uint8Array.from([0])),
191
+ },
192
+ },
193
+ ];
194
+ }
195
+
196
+ const programAccounts =
197
+ await this.driftClient.connection.getProgramAccounts(
198
+ this.driftClient.program.programId,
199
+ {
200
+ commitment: this.driftClient.connection.commitment,
201
+ filters: [
202
+ {
203
+ memcmp: this.driftClient.program.coder.accounts.memcmp('User'),
204
+ },
205
+ ...(Array.isArray(filters) ? filters : []),
206
+ ],
207
+ }
208
+ );
209
+
210
+ const programAccountMap = new Map<string, AccountInfo<Buffer>>();
211
+ for (const programAccount of programAccounts) {
212
+ programAccountMap.set(
213
+ programAccount.pubkey.toString(),
214
+ programAccount.account
215
+ );
216
+ }
217
+
218
+ for (const key of programAccountMap.keys()) {
219
+ if (!this.has(key)) {
220
+ await this.addPubkey(new PublicKey(key));
221
+ }
222
+ }
223
+
224
+ for (const [key, user] of this.userMap.entries()) {
225
+ if (!programAccountMap.has(key)) {
226
+ await user.unsubscribe();
227
+ this.userMap.delete(key);
228
+ }
229
+ }
230
+ }
180
231
  }
@@ -17,9 +17,10 @@ import {
17
17
  InsuranceFundStakeRecord,
18
18
  } from '..';
19
19
  import { ProgramAccount } from '@project-serum/anchor';
20
- import { PublicKey } from '@solana/web3.js';
20
+ import { AccountInfo, PublicKey } from '@solana/web3.js';
21
21
 
22
22
  import { UserMap } from './userMap';
23
+ import { Buffer } from 'buffer';
23
24
 
24
25
  export class UserStatsMap {
25
26
  /**
@@ -190,4 +191,34 @@ export class UserStatsMap {
190
191
  public size(): number {
191
192
  return this.userStatsMap.size;
192
193
  }
194
+
195
+ public async sync() {
196
+ const programAccounts =
197
+ await this.driftClient.connection.getProgramAccounts(
198
+ this.driftClient.program.programId,
199
+ {
200
+ commitment: this.driftClient.connection.commitment,
201
+ filters: [
202
+ {
203
+ memcmp:
204
+ this.driftClient.program.coder.accounts.memcmp('UserStats'),
205
+ },
206
+ ],
207
+ }
208
+ );
209
+
210
+ const programAccountMap = new Map<string, AccountInfo<Buffer>>();
211
+ for (const programAccount of programAccounts) {
212
+ programAccountMap.set(
213
+ new PublicKey(programAccount.account.data.slice(8, 40)).toString(),
214
+ programAccount.account
215
+ );
216
+ }
217
+
218
+ for (const key of programAccountMap.keys()) {
219
+ if (!this.has(key)) {
220
+ await this.addUserStat(new PublicKey(key));
221
+ }
222
+ }
223
+ }
193
224
  }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.findComputeUnitConsumption = void 0;
13
+ function findComputeUnitConsumption(programId, connection, txSignature, commitment = 'confirmed') {
14
+ return __awaiter(this, void 0, void 0, function* () {
15
+ const tx = yield connection.getTransaction(txSignature, { commitment });
16
+ const computeUnits = [];
17
+ const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of ([0-9]{0,7}) compute units`);
18
+ tx.meta.logMessages.forEach((logMessage) => {
19
+ const match = logMessage.match(regex);
20
+ if (match && match[1]) {
21
+ computeUnits.push(match[1]);
22
+ }
23
+ });
24
+ return computeUnits;
25
+ });
26
+ }
27
+ exports.findComputeUnitConsumption = findComputeUnitConsumption;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTokenAddress = void 0;
4
+ const spl_token_1 = require("@solana/spl-token");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ const getTokenAddress = (mintAddress, userPubKey) => {
7
+ return spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey(mintAddress), new web3_js_1.PublicKey(userPubKey));
8
+ };
9
+ exports.getTokenAddress = getTokenAddress;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.promiseTimeout = void 0;
4
+ function promiseTimeout(promise, timeoutMs) {
5
+ let timeoutId;
6
+ const timeoutPromise = new Promise((resolve) => {
7
+ timeoutId = setTimeout(() => resolve(null), timeoutMs);
8
+ });
9
+ return Promise.race([promise, timeoutPromise]).then((result) => {
10
+ clearTimeout(timeoutId);
11
+ return result;
12
+ });
13
+ }
14
+ exports.promiseTimeout = promiseTimeout;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.estimateTps = void 0;
13
+ function estimateTps(programId, connection, failed) {
14
+ return __awaiter(this, void 0, void 0, function* () {
15
+ let signatures = yield connection.getSignaturesForAddress(programId, undefined, 'finalized');
16
+ if (failed) {
17
+ signatures = signatures.filter((signature) => signature.err);
18
+ }
19
+ const numberOfSignatures = signatures.length;
20
+ if (numberOfSignatures === 0) {
21
+ return 0;
22
+ }
23
+ return (numberOfSignatures /
24
+ (signatures[0].blockTime - signatures[numberOfSignatures - 1].blockTime));
25
+ });
26
+ }
27
+ exports.estimateTps = estimateTps;