@drift-labs/sdk 2.43.0-beta.9 → 2.44.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -418,14 +418,15 @@ class DriftClient {
418
418
  return result;
419
419
  }
420
420
  async initializeUserAccount(subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, referrerInfo) {
421
+ const initializeIxs = [];
421
422
  const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(subAccountId, name, referrerInfo);
422
- const tx = new web3_js_1.Transaction();
423
423
  if (subAccountId === 0) {
424
424
  if (!(await this.checkIfAccountExists(this.getUserStatsAccountPublicKey()))) {
425
- tx.add(await this.getInitializeUserStatsIx());
425
+ initializeIxs.push(await this.getInitializeUserStatsIx());
426
426
  }
427
427
  }
428
- tx.add(initializeUserAccountIx);
428
+ initializeIxs.push(initializeUserAccountIx);
429
+ const tx = await this.buildTransaction(initializeIxs);
429
430
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
430
431
  await this.addUser(subAccountId);
431
432
  return [txSig, userAccountPublicKey];
@@ -1052,18 +1053,19 @@ class DriftClient {
1052
1053
  */
1053
1054
  async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, fromSubAccountId, referrerInfo, txParams) {
1054
1055
  var _a;
1056
+ const ixs = [];
1055
1057
  const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(subAccountId, name, referrerInfo);
1056
1058
  const additionalSigners = [];
1057
1059
  const spotMarket = this.getSpotMarketAccount(marketIndex);
1058
1060
  const isSolMarket = spotMarket.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
1059
- const tx = new web3_js_1.Transaction();
1060
- tx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
1061
- units: (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : 600000,
1062
- }));
1061
+ let params = {
1062
+ computeUnits: (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : 600000,
1063
+ };
1063
1064
  if (txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) {
1064
- tx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
1065
- microLamports: txParams.computeUnitsPrice,
1066
- }));
1065
+ params = {
1066
+ ...params,
1067
+ computeUnitsPrice: txParams.computeUnitsPrice,
1068
+ };
1067
1069
  }
1068
1070
  const authority = this.wallet.publicKey;
1069
1071
  const isFromSubaccount = fromSubAccountId !== null &&
@@ -1073,40 +1075,41 @@ class DriftClient {
1073
1075
  if (createWSOLTokenAccount) {
1074
1076
  const { ixs: startIxs, pubkey } = await this.getWrappedSolAccountCreationIxs(amount, true);
1075
1077
  userTokenAccount = pubkey;
1076
- startIxs.forEach((ix) => {
1077
- tx.add(ix);
1078
- });
1078
+ ixs.push(...startIxs);
1079
1079
  }
1080
1080
  const depositCollateralIx = isFromSubaccount
1081
1081
  ? await this.getTransferDepositIx(amount, marketIndex, fromSubAccountId, subAccountId)
1082
1082
  : await this.getDepositInstruction(amount, marketIndex, userTokenAccount, subAccountId, false, false);
1083
1083
  if (subAccountId === 0) {
1084
1084
  if (!(await this.checkIfAccountExists(this.getUserStatsAccountPublicKey()))) {
1085
- tx.add(await this.getInitializeUserStatsIx());
1085
+ ixs.push(await this.getInitializeUserStatsIx());
1086
1086
  }
1087
1087
  }
1088
- tx.add(initializeUserAccountIx).add(depositCollateralIx);
1088
+ ixs.push(initializeUserAccountIx, depositCollateralIx);
1089
1089
  // Close the wrapped sol account at the end of the transaction
1090
1090
  if (createWSOLTokenAccount) {
1091
- tx.add((0, spl_token_1.createCloseAccountInstruction)(userTokenAccount, authority, authority, []));
1091
+ ixs.push((0, spl_token_1.createCloseAccountInstruction)(userTokenAccount, authority, authority, []));
1092
1092
  }
1093
+ const tx = await this.buildTransaction(ixs, params);
1093
1094
  const { txSig, slot } = await this.sendTransaction(tx, additionalSigners, this.opts);
1094
1095
  this.spotMarketLastSlotCache.set(marketIndex, slot);
1095
1096
  await this.addUser(subAccountId);
1096
1097
  return [txSig, userAccountPublicKey];
1097
1098
  }
1098
1099
  async initializeUserAccountForDevnet(subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, marketIndex, tokenFaucet, amount, referrerInfo) {
1100
+ const ixs = [];
1099
1101
  const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
1100
1102
  const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(subAccountId, name, referrerInfo);
1101
1103
  const depositCollateralIx = await this.getDepositInstruction(amount, marketIndex, associateTokenPublicKey, subAccountId, false, false);
1102
- const tx = new web3_js_1.Transaction().add(createAssociatedAccountIx).add(mintToIx);
1104
+ ixs.push(createAssociatedAccountIx, mintToIx);
1103
1105
  if (subAccountId === 0) {
1104
1106
  if (!(await this.checkIfAccountExists(this.getUserStatsAccountPublicKey()))) {
1105
- tx.add(await this.getInitializeUserStatsIx());
1107
+ ixs.push(await this.getInitializeUserStatsIx());
1106
1108
  }
1107
1109
  }
1108
- tx.add(initializeUserAccountIx).add(depositCollateralIx);
1109
- const txSig = await this.program.provider.sendAndConfirm(tx, []);
1110
+ ixs.push(initializeUserAccountIx, depositCollateralIx);
1111
+ const tx = await this.buildTransaction(ixs);
1112
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
1110
1113
  await this.addUser(subAccountId);
1111
1114
  return [txSig, userAccountPublicKey];
1112
1115
  }
@@ -1118,10 +1121,7 @@ class DriftClient {
1118
1121
  * @param reduceOnly
1119
1122
  */
1120
1123
  async withdraw(amount, marketIndex, associatedTokenAddress, reduceOnly = false) {
1121
- const tx = new web3_js_1.Transaction();
1122
- tx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
1123
- units: 600000,
1124
- }));
1124
+ const withdrawIxs = [];
1125
1125
  const additionalSigners = [];
1126
1126
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1127
1127
  const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
@@ -1130,23 +1130,24 @@ class DriftClient {
1130
1130
  if (createWSOLTokenAccount) {
1131
1131
  const { ixs, pubkey } = await this.getWrappedSolAccountCreationIxs(amount, false);
1132
1132
  associatedTokenAddress = pubkey;
1133
- ixs.forEach((ix) => {
1134
- tx.add(ix);
1135
- });
1133
+ withdrawIxs.push(...ixs);
1136
1134
  }
1137
1135
  else {
1138
1136
  const accountExists = await this.checkIfAccountExists(associatedTokenAddress);
1139
1137
  if (!accountExists) {
1140
1138
  const createAssociatedTokenAccountIx = this.getAssociatedTokenAccountCreationIx(spotMarketAccount.mint, associatedTokenAddress);
1141
- tx.add(createAssociatedTokenAccountIx);
1139
+ withdrawIxs.push(createAssociatedTokenAccountIx);
1142
1140
  }
1143
1141
  }
1144
- const withdrawCollateral = await this.getWithdrawIx(amount, spotMarketAccount.marketIndex, associatedTokenAddress, reduceOnly);
1145
- tx.add(withdrawCollateral);
1142
+ const withdrawCollateralIx = await this.getWithdrawIx(amount, spotMarketAccount.marketIndex, associatedTokenAddress, reduceOnly);
1143
+ withdrawIxs.push(withdrawCollateralIx);
1146
1144
  // Close the wrapped sol account at the end of the transaction
1147
1145
  if (createWSOLTokenAccount) {
1148
- tx.add((0, spl_token_1.createCloseAccountInstruction)(associatedTokenAddress, authority, authority, []));
1146
+ withdrawIxs.push((0, spl_token_1.createCloseAccountInstruction)(associatedTokenAddress, authority, authority, []));
1149
1147
  }
1148
+ const tx = await this.buildTransaction(withdrawIxs, {
1149
+ computeUnits: 600000,
1150
+ });
1150
1151
  const { txSig, slot } = await this.sendTransaction(tx, additionalSigners, this.opts);
1151
1152
  this.spotMarketLastSlotCache.set(marketIndex, slot);
1152
1153
  return txSig;
@@ -1365,9 +1366,10 @@ class DriftClient {
1365
1366
  * @param makerInfo
1366
1367
  * @param txParams
1367
1368
  * @param bracketOrdersParams
1369
+ * @param cancelExistingOrders - Builds and returns an extra transaciton to cancel the existing orders in the same perp market. Intended use is to auto-cancel TP/SL orders when closing a position. Ignored if orderParams.marketType is not MarketType.PERP
1368
1370
  * @returns
1369
1371
  */
1370
- async sendMarketOrderAndGetSignedFillTx(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo) {
1372
+ async sendMarketOrderAndGetSignedFillTx(orderParams, userAccountPublicKey, userAccount, makerInfo, txParams, bracketOrdersParams = new Array(), referrerInfo, cancelExistingOrders) {
1371
1373
  const marketIndex = orderParams.marketIndex;
1372
1374
  const orderId = userAccount.nextOrderId;
1373
1375
  const bracketOrderIxs = [];
@@ -1380,20 +1382,31 @@ class DriftClient {
1380
1382
  orderId,
1381
1383
  marketIndex,
1382
1384
  }, makerInfo, referrerInfo);
1385
+ let cancelOrdersIx;
1386
+ let cancelExistingOrdersTx;
1387
+ if (cancelExistingOrders && (0, types_1.isVariant)(orderParams.marketType, 'perp')) {
1388
+ cancelOrdersIx = await this.getCancelOrdersIx(orderParams.marketType, orderParams.marketIndex, null);
1389
+ //@ts-ignore
1390
+ cancelExistingOrdersTx = await this.buildTransaction([cancelOrdersIx], txParams, this.txVersion);
1391
+ }
1383
1392
  // use versioned transactions if there is a lookup table account and wallet is compatible
1384
1393
  if (this.txVersion === 0) {
1385
1394
  const versionedMarketOrderTx = await this.buildTransaction([placePerpOrderIx].concat(bracketOrderIxs), txParams, 0);
1386
1395
  const versionedFillTx = await this.buildTransaction([fillPerpOrderIx], txParams, 0);
1387
- const [signedVersionedMarketOrderTx, signedVersionedFillTx] = await this.provider.wallet.signAllTransactions([
1388
- //@ts-ignore
1396
+ const [signedVersionedMarketOrderTx, signedVersionedFillTx, signedCancelExistingOrdersTx,] = await this.provider.wallet.signAllTransactions([
1389
1397
  versionedMarketOrderTx,
1390
- //@ts-ignore
1391
1398
  versionedFillTx,
1392
- ]);
1399
+ cancelExistingOrdersTx,
1400
+ ].filter((tx) => tx !== undefined));
1393
1401
  const { txSig, slot } = await this.txSender.sendRawTransaction(signedVersionedMarketOrderTx.serialize(), this.opts);
1394
1402
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
1395
- // @ts-ignore
1396
- return { txSig, signedFillTx: signedVersionedFillTx };
1403
+ return {
1404
+ txSig,
1405
+ // @ts-ignore
1406
+ signedFillTx: signedVersionedFillTx,
1407
+ // @ts-ignore
1408
+ signedCancelExistingOrdersTx,
1409
+ };
1397
1410
  }
1398
1411
  else {
1399
1412
  const marketOrderTx = (0, utils_1.wrapInTx)(placePerpOrderIx, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice);
@@ -1407,10 +1420,10 @@ class DriftClient {
1407
1420
  fillTx.recentBlockhash = currentBlockHash;
1408
1421
  marketOrderTx.feePayer = userAccount.authority;
1409
1422
  fillTx.feePayer = userAccount.authority;
1410
- const [signedMarketOrderTx, signedFillTx] = await this.provider.wallet.signAllTransactions([marketOrderTx, fillTx]);
1423
+ const [signedMarketOrderTx, signedFillTx, signedCancelExistingOrdersTx] = await this.provider.wallet.signAllTransactions([marketOrderTx, fillTx, cancelExistingOrdersTx].filter((tx) => tx !== undefined));
1411
1424
  const { txSig, slot } = await this.sendTransaction(signedMarketOrderTx, [], this.opts, true);
1412
1425
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
1413
- return { txSig, signedFillTx };
1426
+ return { txSig, signedFillTx, signedCancelExistingOrdersTx };
1414
1427
  }
1415
1428
  }
1416
1429
  async placePerpOrder(orderParams, txParams) {
@@ -1587,7 +1600,7 @@ class DriftClient {
1587
1600
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1588
1601
  let readablePerpMarketIndex = undefined;
1589
1602
  let readableSpotMarketIndexes = undefined;
1590
- if (marketIndex) {
1603
+ if (typeof marketIndex === 'number') {
1591
1604
  if (marketType && (0, types_1.isVariant)(marketType, 'perp')) {
1592
1605
  readablePerpMarketIndex = marketIndex;
1593
1606
  }
@@ -2107,6 +2120,9 @@ class DriftClient {
2107
2120
  });
2108
2121
  quote = fetchedQuote;
2109
2122
  }
2123
+ if (!quote) {
2124
+ throw new Error("Could not fetch Jupiter's quote. Please try again.");
2125
+ }
2110
2126
  const transaction = await jupiterClient.getSwap({
2111
2127
  quote,
2112
2128
  userPublicKey: this.provider.wallet.publicKey,
@@ -2623,12 +2639,12 @@ class DriftClient {
2623
2639
  oraclePriceOffset: newOraclePriceOffset || null,
2624
2640
  triggerPrice: newTriggerPrice || null,
2625
2641
  triggerCondition: newTriggerCondition || null,
2626
- auctionDuration: auctionDuration || null,
2627
- auctionStartPrice: auctionStartPrice || null,
2628
- auctionEndPrice: auctionEndPrice || null,
2629
- reduceOnly: reduceOnly || null,
2642
+ auctionDuration: auctionDuration || 0,
2643
+ auctionStartPrice: auctionStartPrice || numericConstants_1.ZERO,
2644
+ auctionEndPrice: auctionEndPrice || numericConstants_1.ZERO,
2645
+ reduceOnly: reduceOnly || false,
2630
2646
  postOnly: postOnly || null,
2631
- immediateOrCancel: immediateOrCancel || null,
2647
+ immediateOrCancel: immediateOrCancel || false,
2632
2648
  policy: policy || null,
2633
2649
  maxTs: maxTs || null,
2634
2650
  };
@@ -2677,12 +2693,12 @@ class DriftClient {
2677
2693
  oraclePriceOffset: newOraclePriceOffset || null,
2678
2694
  triggerPrice: newTriggerPrice || null,
2679
2695
  triggerCondition: newTriggerCondition || null,
2680
- auctionDuration: auctionDuration || null,
2681
- auctionStartPrice: auctionStartPrice || null,
2682
- auctionEndPrice: auctionEndPrice || null,
2683
- reduceOnly: reduceOnly || null,
2696
+ auctionDuration: auctionDuration || 0,
2697
+ auctionStartPrice: auctionStartPrice || numericConstants_1.ZERO,
2698
+ auctionEndPrice: auctionEndPrice || numericConstants_1.ZERO,
2699
+ reduceOnly: reduceOnly || false,
2684
2700
  postOnly: postOnly || null,
2685
- immediateOrCancel: immediateOrCancel || null,
2701
+ immediateOrCancel: immediateOrCancel || false,
2686
2702
  policy: policy || null,
2687
2703
  maxTs: maxTs || null,
2688
2704
  };
@@ -2698,11 +2714,7 @@ class DriftClient {
2698
2714
  }
2699
2715
  async settlePNLs(users, marketIndexes) {
2700
2716
  const ixs = await this.getSettlePNLsIxs(users, marketIndexes);
2701
- const tx = new web3_js_1.Transaction()
2702
- .add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
2703
- units: 1000000,
2704
- }))
2705
- .add(...ixs);
2717
+ const tx = await this.buildTransaction(ixs, { computeUnits: 1000000 });
2706
2718
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
2707
2719
  return txSig;
2708
2720
  }
@@ -3030,7 +3042,7 @@ class DriftClient {
3030
3042
  * Add to an insurance fund stake and optionally initialize the account
3031
3043
  */
3032
3044
  async addInsuranceFundStake({ marketIndex, amount, collateralAccountPublicKey, initializeStakeAccount, fromSubaccount, }) {
3033
- const tx = new web3_js_1.Transaction();
3045
+ const addIfStakeIxs = [];
3034
3046
  const additionalSigners = [];
3035
3047
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
3036
3048
  const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
@@ -3040,7 +3052,7 @@ class DriftClient {
3040
3052
  const { ixs, pubkey } = await this.getWrappedSolAccountCreationIxs(amount, true);
3041
3053
  tokenAccount = pubkey;
3042
3054
  ixs.forEach((ix) => {
3043
- tx.add(ix);
3055
+ addIfStakeIxs.push(ix);
3044
3056
  });
3045
3057
  }
3046
3058
  else {
@@ -3048,17 +3060,18 @@ class DriftClient {
3048
3060
  }
3049
3061
  if (fromSubaccount) {
3050
3062
  const withdrawIx = await this.getWithdrawIx(amount, marketIndex, tokenAccount);
3051
- tx.add(withdrawIx);
3063
+ addIfStakeIxs.push(withdrawIx);
3052
3064
  }
3053
3065
  if (initializeStakeAccount) {
3054
3066
  const initializeIx = await this.getInitializeInsuranceFundStakeIx(marketIndex);
3055
- tx.add(initializeIx);
3067
+ addIfStakeIxs.push(initializeIx);
3056
3068
  }
3057
3069
  const addFundsIx = await this.getAddInsuranceFundStakeIx(marketIndex, amount, tokenAccount);
3058
- tx.add(addFundsIx);
3070
+ addIfStakeIxs.push(addFundsIx);
3059
3071
  if (createWSOLTokenAccount) {
3060
- tx.add((0, spl_token_1.createCloseAccountInstruction)(tokenAccount, this.wallet.publicKey, this.wallet.publicKey, []));
3072
+ addIfStakeIxs.push((0, spl_token_1.createCloseAccountInstruction)(tokenAccount, this.wallet.publicKey, this.wallet.publicKey, []));
3061
3073
  }
3074
+ const tx = await this.buildTransaction(addIfStakeIxs);
3062
3075
  const { txSig } = await this.sendTransaction(tx, additionalSigners, this.opts);
3063
3076
  return txSig;
3064
3077
  }
@@ -3070,7 +3083,7 @@ class DriftClient {
3070
3083
  useMarketLastSlotCache: true,
3071
3084
  writableSpotMarketIndexes: [marketIndex],
3072
3085
  });
3073
- const tx = await this.program.transaction.requestRemoveInsuranceFundStake(marketIndex, amount, {
3086
+ const ix = await this.program.instruction.requestRemoveInsuranceFundStake(marketIndex, amount, {
3074
3087
  accounts: {
3075
3088
  state: await this.getStatePublicKey(),
3076
3089
  spotMarket: spotMarketAccount.pubkey,
@@ -3081,6 +3094,7 @@ class DriftClient {
3081
3094
  },
3082
3095
  remainingAccounts,
3083
3096
  });
3097
+ const tx = await this.buildTransaction(ix);
3084
3098
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
3085
3099
  return txSig;
3086
3100
  }
@@ -3092,7 +3106,7 @@ class DriftClient {
3092
3106
  useMarketLastSlotCache: true,
3093
3107
  writableSpotMarketIndexes: [marketIndex],
3094
3108
  });
3095
- const tx = await this.program.transaction.cancelRequestRemoveInsuranceFundStake(marketIndex, {
3109
+ const ix = await this.program.instruction.cancelRequestRemoveInsuranceFundStake(marketIndex, {
3096
3110
  accounts: {
3097
3111
  state: await this.getStatePublicKey(),
3098
3112
  spotMarket: spotMarketAccount.pubkey,
@@ -3103,11 +3117,12 @@ class DriftClient {
3103
3117
  },
3104
3118
  remainingAccounts,
3105
3119
  });
3120
+ const tx = await this.buildTransaction(ix);
3106
3121
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
3107
3122
  return txSig;
3108
3123
  }
3109
3124
  async removeInsuranceFundStake(marketIndex, collateralAccountPublicKey) {
3110
- const tx = new web3_js_1.Transaction();
3125
+ const removeIfStakeIxs = [];
3111
3126
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
3112
3127
  const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
3113
3128
  const additionalSigners = [];
@@ -3118,7 +3133,7 @@ class DriftClient {
3118
3133
  const { ixs, pubkey } = await this.getWrappedSolAccountCreationIxs(numericConstants_1.ZERO, true);
3119
3134
  tokenAccount = pubkey;
3120
3135
  ixs.forEach((ix) => {
3121
- tx.add(ix);
3136
+ removeIfStakeIxs.push(ix);
3122
3137
  });
3123
3138
  }
3124
3139
  else {
@@ -3143,11 +3158,12 @@ class DriftClient {
3143
3158
  },
3144
3159
  remainingAccounts,
3145
3160
  });
3146
- tx.add(removeStakeIx);
3161
+ removeIfStakeIxs.push(removeStakeIx);
3147
3162
  // Close the wrapped sol account at the end of the transaction
3148
3163
  if (createWSOLTokenAccount) {
3149
- tx.add((0, spl_token_1.createCloseAccountInstruction)(tokenAccount, this.wallet.publicKey, this.wallet.publicKey, []));
3164
+ removeIfStakeIxs.push((0, spl_token_1.createCloseAccountInstruction)(tokenAccount, this.wallet.publicKey, this.wallet.publicKey, []));
3150
3165
  }
3166
+ const tx = await this.buildTransaction(removeIfStakeIxs);
3151
3167
  const { txSig } = await this.sendTransaction(tx, additionalSigners, this.opts);
3152
3168
  return txSig;
3153
3169
  }
@@ -3158,7 +3174,7 @@ class DriftClient {
3158
3174
  useMarketLastSlotCache: true,
3159
3175
  writableSpotMarketIndexes: [marketIndex],
3160
3176
  });
3161
- const tx = await this.program.transaction.settleRevenueToInsuranceFund(marketIndex, {
3177
+ const ix = await this.program.instruction.settleRevenueToInsuranceFund(marketIndex, {
3162
3178
  accounts: {
3163
3179
  state: await this.getStatePublicKey(),
3164
3180
  spotMarket: spotMarketAccount.pubkey,
@@ -3169,6 +3185,7 @@ class DriftClient {
3169
3185
  },
3170
3186
  remainingAccounts,
3171
3187
  });
3188
+ const tx = await this.buildTransaction(ix);
3172
3189
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
3173
3190
  return txSig;
3174
3191
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.42.0",
2
+ "version": "2.43.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -4098,6 +4098,27 @@
4098
4098
  }
4099
4099
  ]
4100
4100
  },
4101
+ {
4102
+ "name": "updateLiquidationMarginBufferRatio",
4103
+ "accounts": [
4104
+ {
4105
+ "name": "admin",
4106
+ "isMut": false,
4107
+ "isSigner": true
4108
+ },
4109
+ {
4110
+ "name": "state",
4111
+ "isMut": true,
4112
+ "isSigner": false
4113
+ }
4114
+ ],
4115
+ "args": [
4116
+ {
4117
+ "name": "liquidationMarginBufferRatio",
4118
+ "type": "u32"
4119
+ }
4120
+ ]
4121
+ },
4101
4122
  {
4102
4123
  "name": "updateOracleGuardRails",
4103
4124
  "accounts": [
@@ -65,6 +65,9 @@ class JupiterClient {
65
65
  * @param slippageBps the slippage tolerance in basis points
66
66
  */
67
67
  async getSwap({ quote, userPublicKey, slippageBps = 50, }) {
68
+ if (!quote) {
69
+ throw new Error('Jupiter swap quote not provided. Please try again.');
70
+ }
68
71
  const resp = await (await (0, node_fetch_1.default)(`${this.url}/v6/swap`, {
69
72
  method: 'POST',
70
73
  headers: {
@@ -77,8 +80,13 @@ class JupiterClient {
77
80
  }),
78
81
  })).json();
79
82
  const { swapTransaction } = resp;
80
- const swapTransactionBuf = Buffer.from(swapTransaction, 'base64');
81
- return web3_js_1.VersionedTransaction.deserialize(swapTransactionBuf);
83
+ try {
84
+ const swapTransactionBuf = Buffer.from(swapTransaction, 'base64');
85
+ return web3_js_1.VersionedTransaction.deserialize(swapTransactionBuf);
86
+ }
87
+ catch (err) {
88
+ throw new Error('Something went wrong with creating the Jupiter swap transaction. Please try again.');
89
+ }
82
90
  }
83
91
  /**
84
92
  * ** @deprecated - use getSwap
package/lib/math/amm.js CHANGED
@@ -410,7 +410,8 @@ function calculateSpreadReserves(amm, oraclePriceData, now) {
410
410
  quoteAssetReserve: amm.quoteAssetReserve,
411
411
  };
412
412
  }
413
- const quoteAssetReserveDelta = amm.quoteAssetReserve.div(numericConstants_1.BID_ASK_SPREAD_PRECISION.div(new anchor_1.BN(spread / 2)));
413
+ const spreadFraction = anchor_1.BN.max(new anchor_1.BN(spread / 2), numericConstants_1.ONE);
414
+ const quoteAssetReserveDelta = amm.quoteAssetReserve.div(numericConstants_1.BID_ASK_SPREAD_PRECISION.div(spreadFraction));
414
415
  let quoteAssetReserve;
415
416
  if ((0, types_1.isVariant)(direction, 'long')) {
416
417
  quoteAssetReserve = amm.quoteAssetReserve.add(quoteAssetReserveDelta);
package/lib/math/trade.js CHANGED
@@ -415,14 +415,12 @@ function calculateEstimatedPerpEntryPrice(assetType, amount, direction, market,
415
415
  limitOrder = limitOrders.next().value;
416
416
  }
417
417
  }
418
- const entryPrice = cumulativeQuoteFilled
419
- .mul(numericConstants_1.BASE_PRECISION)
420
- .div(cumulativeBaseFilled);
421
- const priceImpact = entryPrice
422
- .sub(bestPrice)
423
- .mul(numericConstants_1.PRICE_PRECISION)
424
- .div(bestPrice)
425
- .abs();
418
+ const entryPrice = cumulativeBaseFilled && cumulativeBaseFilled.gt(numericConstants_1.ZERO)
419
+ ? cumulativeQuoteFilled.mul(numericConstants_1.BASE_PRECISION).div(cumulativeBaseFilled)
420
+ : numericConstants_1.ZERO;
421
+ const priceImpact = bestPrice && bestPrice.gt(numericConstants_1.ZERO)
422
+ ? entryPrice.sub(bestPrice).mul(numericConstants_1.PRICE_PRECISION).div(bestPrice).abs()
423
+ : numericConstants_1.ZERO;
426
424
  return {
427
425
  entryPrice,
428
426
  priceImpact,
@@ -551,14 +549,12 @@ function calculateEstimatedSpotEntryPrice(assetType, amount, direction, market,
551
549
  }
552
550
  }
553
551
  }
554
- const entryPrice = cumulativeQuoteFilled
555
- .mul(basePrecision)
556
- .div(cumulativeBaseFilled);
557
- const priceImpact = entryPrice
558
- .sub(bestPrice)
559
- .mul(numericConstants_1.PRICE_PRECISION)
560
- .div(bestPrice)
561
- .abs();
552
+ const entryPrice = cumulativeBaseFilled && cumulativeBaseFilled.gt(numericConstants_1.ZERO)
553
+ ? cumulativeQuoteFilled.mul(basePrecision).div(cumulativeBaseFilled)
554
+ : numericConstants_1.ZERO;
555
+ const priceImpact = bestPrice && bestPrice.gt(numericConstants_1.ZERO)
556
+ ? entryPrice.sub(bestPrice).mul(numericConstants_1.PRICE_PRECISION).div(bestPrice).abs()
557
+ : numericConstants_1.ZERO;
562
558
  return {
563
559
  entryPrice,
564
560
  priceImpact,
@@ -609,14 +605,12 @@ function calculateEstimatedEntryPriceWithL2(assetType, amount, direction, basePr
609
605
  nextLevel = levels.shift();
610
606
  }
611
607
  }
612
- const entryPrice = cumulativeQuoteFilled
613
- .mul(basePrecision)
614
- .div(cumulativeBaseFilled);
615
- const priceImpact = entryPrice
616
- .sub(bestPrice)
617
- .mul(numericConstants_1.PRICE_PRECISION)
618
- .div(bestPrice)
619
- .abs();
608
+ const entryPrice = cumulativeBaseFilled && cumulativeBaseFilled.gt(numericConstants_1.ZERO)
609
+ ? cumulativeQuoteFilled.mul(basePrecision).div(cumulativeBaseFilled)
610
+ : numericConstants_1.ZERO;
611
+ const priceImpact = bestPrice && bestPrice.gt(numericConstants_1.ZERO)
612
+ ? entryPrice.sub(bestPrice).mul(numericConstants_1.PRICE_PRECISION).div(bestPrice).abs()
613
+ : numericConstants_1.ZERO;
620
614
  return {
621
615
  entryPrice,
622
616
  priceImpact,
@@ -20,7 +20,12 @@ class FastSingleTxSender extends baseTxSender_1.BaseTxSender {
20
20
  }
21
21
  startBlockhashRefreshLoop() {
22
22
  setInterval(async () => {
23
- this.recentBlockhash = (await this.connection.getLatestBlockhash(this.opts)).blockhash;
23
+ try {
24
+ this.recentBlockhash = (await this.connection.getLatestBlockhash(this.opts)).blockhash;
25
+ }
26
+ catch (e) {
27
+ console.error('Error in startBlockhashRefreshLoop: ', e);
28
+ }
24
29
  }, this.blockhashRefreshInterval);
25
30
  }
26
31
  async prepareTx(tx, additionalSigners, opts) {
package/lib/user.js CHANGED
@@ -1677,14 +1677,13 @@ class User {
1677
1677
  withdrawLimit = _1.BN.max(withdrawLimit, userDepositAmount);
1678
1678
  }
1679
1679
  const assetWeight = (0, spotBalance_1.calculateAssetWeight)(userDepositAmount, oracleData.price, spotMarket, 'Initial');
1680
- const amountWithdrawable = assetWeight.eq(numericConstants_1.ZERO)
1681
- ? userDepositAmount
1682
- : freeCollateral
1683
- .mul(numericConstants_1.MARGIN_PRECISION)
1684
- .div(assetWeight)
1685
- .mul(numericConstants_1.PRICE_PRECISION)
1686
- .div(oracleData.price)
1687
- .mul(precisionIncrease);
1680
+ let amountWithdrawable;
1681
+ if (assetWeight.eq(numericConstants_1.ZERO)) {
1682
+ amountWithdrawable = userDepositAmount;
1683
+ }
1684
+ else {
1685
+ amountWithdrawable = (0, _1.divCeil)((0, _1.divCeil)(freeCollateral.mul(numericConstants_1.MARGIN_PRECISION), assetWeight).mul(numericConstants_1.PRICE_PRECISION), oracleData.price).mul(precisionIncrease);
1686
+ }
1688
1687
  const maxWithdrawValue = _1.BN.min(_1.BN.min(amountWithdrawable, userDepositAmount), withdrawLimit.abs());
1689
1688
  if (reduceOnly) {
1690
1689
  return _1.BN.max(maxWithdrawValue, numericConstants_1.ZERO);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.43.0-beta.9",
3
+ "version": "2.44.0-beta.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -14,6 +14,8 @@ export class WebSocketAccountSubscriber<T> implements AccountSubscriber<T> {
14
14
  onChange: (data: T) => void;
15
15
  listenerId?: number;
16
16
  resubTimeoutMs?: number;
17
+ isUnsubscribing = false;
18
+
17
19
  timeoutId?: NodeJS.Timeout;
18
20
 
19
21
  receivingData: boolean;
@@ -34,7 +36,7 @@ export class WebSocketAccountSubscriber<T> implements AccountSubscriber<T> {
34
36
  }
35
37
 
36
38
  async subscribe(onChange: (data: T) => void): Promise<void> {
37
- if (this.listenerId) {
39
+ if (this.listenerId || this.isUnsubscribing) {
38
40
  return;
39
41
  }
40
42
 
@@ -80,6 +82,11 @@ export class WebSocketAccountSubscriber<T> implements AccountSubscriber<T> {
80
82
  throw new Error('onChange callback function must be set');
81
83
  }
82
84
  this.timeoutId = setTimeout(async () => {
85
+ if (this.isUnsubscribing) {
86
+ // If we are in the process of unsubscribing, do not attempt to resubscribe
87
+ return;
88
+ }
89
+
83
90
  if (this.receivingData) {
84
91
  console.log(
85
92
  `No ws data from ${this.accountName} in ${this.resubTimeoutMs}ms, resubscribing`
@@ -154,13 +161,20 @@ export class WebSocketAccountSubscriber<T> implements AccountSubscriber<T> {
154
161
  }
155
162
 
156
163
  unsubscribe(): Promise<void> {
164
+ this.isUnsubscribing = true;
165
+ clearTimeout(this.timeoutId);
166
+ this.timeoutId = undefined;
167
+
157
168
  if (this.listenerId) {
158
- const promise =
159
- this.program.provider.connection.removeAccountChangeListener(
160
- this.listenerId
161
- );
162
- this.listenerId = undefined;
169
+ const promise = this.program.provider.connection
170
+ .removeAccountChangeListener(this.listenerId)
171
+ .then(() => {
172
+ this.listenerId = undefined;
173
+ this.isUnsubscribing = false;
174
+ });
163
175
  return promise;
176
+ } else {
177
+ this.isUnsubscribing = false;
164
178
  }
165
179
  }
166
180
  }