@drift-labs/sdk 0.1.24 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +1 -0
  2. package/lib/accounts/bulkAccountLoader.js +16 -2
  3. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +3 -3
  4. package/lib/accounts/pollingOracleSubscriber.d.ts +26 -0
  5. package/lib/accounts/pollingOracleSubscriber.js +79 -0
  6. package/lib/accounts/pollingTokenAccountSubscriber.js +2 -2
  7. package/lib/accounts/pollingUserAccountSubscriber.js +4 -4
  8. package/lib/accounts/types.d.ts +14 -1
  9. package/lib/accounts/webSocketAccountSubscriber.js +2 -2
  10. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +1 -1
  11. package/lib/accounts/webSocketUserAccountSubscriber.js +2 -2
  12. package/lib/addresses.js +5 -1
  13. package/lib/admin.d.ts +1 -1
  14. package/lib/admin.js +15 -10
  15. package/lib/clearingHouse.d.ts +4 -4
  16. package/lib/clearingHouse.js +56 -25
  17. package/lib/clearingHouseUser.js +18 -18
  18. package/lib/constants/markets.d.ts +8 -6
  19. package/lib/constants/markets.js +85 -26
  20. package/lib/constants/numericConstants.d.ts +1 -0
  21. package/lib/constants/numericConstants.js +2 -1
  22. package/lib/examples/makeTradeExample.js +6 -6
  23. package/lib/factory/oracleClient.d.ts +5 -0
  24. package/lib/factory/oracleClient.js +16 -0
  25. package/lib/idl/clearing_house.json +22 -2
  26. package/lib/idl/switchboard_v2.json +4663 -0
  27. package/lib/index.d.ts +5 -1
  28. package/lib/index.js +10 -2
  29. package/lib/math/amm.js +12 -12
  30. package/lib/math/conversion.js +1 -1
  31. package/lib/math/funding.d.ts +6 -6
  32. package/lib/math/funding.js +5 -17
  33. package/lib/math/market.d.ts +2 -0
  34. package/lib/math/market.js +8 -3
  35. package/lib/math/orders.js +9 -9
  36. package/lib/math/position.js +1 -1
  37. package/lib/math/trade.js +18 -18
  38. package/lib/mockUSDCFaucet.js +5 -1
  39. package/lib/oracles/pythClient.d.ts +14 -0
  40. package/lib/oracles/pythClient.js +53 -0
  41. package/lib/oracles/switchboardClient.d.ts +13 -0
  42. package/lib/oracles/switchboardClient.js +76 -0
  43. package/lib/oracles/types.d.ts +15 -0
  44. package/lib/oracles/types.js +2 -0
  45. package/lib/orderParams.d.ts +1 -1
  46. package/lib/orderParams.js +3 -3
  47. package/lib/orders.d.ts +3 -2
  48. package/lib/orders.js +29 -22
  49. package/lib/tx/retryTxSender.js +1 -1
  50. package/lib/types.d.ts +1 -0
  51. package/package.json +2 -1
  52. package/src/accounts/bulkAccountLoader.js +180 -0
  53. package/src/accounts/bulkAccountLoader.js.map +1 -0
  54. package/src/accounts/bulkAccountLoader.ts +19 -0
  55. package/src/accounts/bulkUserSubscription.js +56 -0
  56. package/src/accounts/bulkUserSubscription.js.map +1 -0
  57. package/src/accounts/pollingClearingHouseAccountSubscriber.js +210 -0
  58. package/src/accounts/pollingClearingHouseAccountSubscriber.js.map +1 -0
  59. package/src/accounts/pollingOracleSubscriber.js +65 -0
  60. package/src/accounts/pollingOracleSubscriber.js.map +1 -0
  61. package/src/accounts/pollingOracleSubscriber.ts +103 -0
  62. package/src/accounts/pollingTokenAccountSubscriber.js +65 -0
  63. package/src/accounts/pollingTokenAccountSubscriber.js.map +1 -0
  64. package/src/accounts/pollingUserAccountSubscriber.js +139 -0
  65. package/src/accounts/pollingUserAccountSubscriber.js.map +1 -0
  66. package/src/accounts/types.js +1 -0
  67. package/src/accounts/types.js.map +1 -0
  68. package/src/accounts/types.ts +22 -1
  69. package/src/accounts/utils.js +1 -0
  70. package/src/accounts/utils.js.map +1 -0
  71. package/src/accounts/webSocketAccountSubscriber.js +15 -27
  72. package/src/accounts/webSocketAccountSubscriber.js.map +1 -0
  73. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +212 -0
  74. package/src/accounts/webSocketClearingHouseAccountSubscriber.js.map +1 -0
  75. package/src/accounts/webSocketUserAccountSubscriber.js +78 -0
  76. package/src/accounts/webSocketUserAccountSubscriber.js.map +1 -0
  77. package/src/addresses.js +20 -44
  78. package/src/addresses.js.map +1 -0
  79. package/src/admin.js +443 -0
  80. package/src/admin.js.map +1 -0
  81. package/src/admin.ts +2 -0
  82. package/src/assert/assert.js +10 -0
  83. package/src/assert/assert.js.map +1 -0
  84. package/src/clearingHouse.js +769 -0
  85. package/src/clearingHouse.js.map +1 -0
  86. package/src/clearingHouse.ts +47 -7
  87. package/src/clearingHouseUser.js +581 -0
  88. package/src/clearingHouseUser.js.map +1 -0
  89. package/src/config.js +37 -0
  90. package/src/config.js.map +1 -0
  91. package/src/constants/markets.js +167 -0
  92. package/src/constants/markets.js.map +1 -0
  93. package/src/constants/markets.ts +93 -31
  94. package/src/constants/numericConstants.js +22 -0
  95. package/src/constants/numericConstants.js.map +1 -0
  96. package/src/constants/numericConstants.ts +1 -0
  97. package/src/factory/clearingHouse.js +65 -0
  98. package/src/factory/clearingHouse.js.map +1 -0
  99. package/src/factory/clearingHouseUser.js +35 -0
  100. package/src/factory/clearingHouseUser.js.map +1 -0
  101. package/src/factory/oracleClient.js +17 -0
  102. package/src/factory/oracleClient.js.map +1 -0
  103. package/src/factory/oracleClient.ts +22 -0
  104. package/src/idl/clearing_house.json +22 -2
  105. package/src/idl/switchboard_v2.json +4663 -0
  106. package/src/index.js +56 -0
  107. package/src/index.js.map +1 -0
  108. package/src/index.ts +5 -1
  109. package/src/math/amm.js +285 -0
  110. package/src/math/amm.js.map +1 -0
  111. package/src/math/conversion.js +16 -0
  112. package/src/math/conversion.js.map +1 -0
  113. package/src/math/funding.js +223 -0
  114. package/src/math/funding.js.map +1 -0
  115. package/src/math/funding.ts +9 -25
  116. package/src/math/insuranceFund.js +23 -0
  117. package/src/math/insuranceFund.js.map +1 -0
  118. package/src/math/market.js +30 -0
  119. package/src/math/market.js.map +1 -0
  120. package/src/math/market.ts +9 -0
  121. package/src/math/orders.js +73 -0
  122. package/src/math/orders.js.map +1 -0
  123. package/src/math/position.js +121 -0
  124. package/src/math/position.js.map +1 -0
  125. package/src/math/trade.js +182 -0
  126. package/src/math/trade.js.map +1 -0
  127. package/src/math/utils.js +27 -0
  128. package/src/math/utils.js.map +1 -0
  129. package/src/mockUSDCFaucet.js +88 -116
  130. package/src/mockUSDCFaucet.js.map +1 -0
  131. package/src/oracles/pythClient.js +39 -0
  132. package/src/oracles/pythClient.js.map +1 -0
  133. package/src/oracles/pythClient.ts +49 -0
  134. package/src/oracles/switchboardClient.js +60 -0
  135. package/src/oracles/switchboardClient.js.map +1 -0
  136. package/src/oracles/switchboardClient.ts +87 -0
  137. package/src/oracles/types.js +3 -0
  138. package/src/oracles/types.js.map +1 -0
  139. package/src/oracles/types.ts +15 -0
  140. package/src/orderParams.js +109 -0
  141. package/src/orderParams.js.map +1 -0
  142. package/src/orderParams.ts +5 -3
  143. package/src/orders.js +172 -0
  144. package/src/orders.js.map +1 -0
  145. package/src/orders.ts +17 -4
  146. package/src/token/index.js +39 -0
  147. package/src/token/index.js.map +1 -0
  148. package/src/tx/defaultTxSender.js +13 -0
  149. package/src/tx/defaultTxSender.js.map +1 -0
  150. package/src/tx/retryTxSender.js +137 -0
  151. package/src/tx/retryTxSender.js.map +1 -0
  152. package/src/tx/types.js +3 -0
  153. package/src/tx/types.js.map +1 -0
  154. package/src/tx/utils.js +9 -0
  155. package/src/tx/utils.js.map +1 -0
  156. package/src/types.js +1 -0
  157. package/src/types.js.map +1 -0
  158. package/src/types.ts +1 -0
  159. package/src/util/computeUnits.js +17 -0
  160. package/src/util/computeUnits.js.map +1 -0
  161. package/src/util/tps.js +17 -0
  162. package/src/util/tps.js.map +1 -0
  163. package/src/wallet.js +23 -0
  164. package/src/wallet.js.map +1 -0
  165. package/lib/pythClient.d.ts +0 -7
  166. package/lib/pythClient.js +0 -25
  167. package/src/pythClient.ts +0 -15
@@ -0,0 +1,76 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.SwitchboardClient = void 0;
16
+ const switchboard_v2_1 = require("@switchboard-xyz/switchboard-v2");
17
+ const web3_js_1 = require("@solana/web3.js");
18
+ const anchor_1 = require("@project-serum/anchor");
19
+ const numericConstants_1 = require("../constants/numericConstants");
20
+ const wallet_1 = require("../wallet");
21
+ const switchboard_v2_json_1 = __importDefault(require("../idl/switchboard_v2.json"));
22
+ // cache switchboard program for every client object since itll always be the same
23
+ const programMap = new Map();
24
+ class SwitchboardClient {
25
+ constructor(connection, env) {
26
+ this.connection = connection;
27
+ this.env = env;
28
+ }
29
+ getOraclePriceData(pricePublicKey) {
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ const accountInfo = yield this.connection.getAccountInfo(pricePublicKey);
32
+ return this.getOraclePriceDataFromBuffer(accountInfo.data);
33
+ });
34
+ }
35
+ getOraclePriceDataFromBuffer(buffer) {
36
+ return __awaiter(this, void 0, void 0, function* () {
37
+ const program = yield this.getProgram();
38
+ const aggregatorAccountData = program.account.aggregatorAccountData.coder.accounts.decode('AggregatorAccountData', buffer);
39
+ const price = convertSwitchboardDecimal(aggregatorAccountData.latestConfirmedRound.result);
40
+ const confidence = convertSwitchboardDecimal(aggregatorAccountData.latestConfirmedRound
41
+ .stdDeviation);
42
+ const slot = aggregatorAccountData.latestConfirmedRound.roundOpenSlot;
43
+ return {
44
+ price,
45
+ slot,
46
+ confidence,
47
+ };
48
+ });
49
+ }
50
+ getProgram() {
51
+ return __awaiter(this, void 0, void 0, function* () {
52
+ if (programMap.has(this.env)) {
53
+ return programMap.get(this.env);
54
+ }
55
+ const program = yield getSwitchboardProgram(this.env, this.connection);
56
+ programMap.set(this.env, program);
57
+ return program;
58
+ });
59
+ }
60
+ }
61
+ exports.SwitchboardClient = SwitchboardClient;
62
+ function getSwitchboardProgram(env, connection) {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ const DEFAULT_KEYPAIR = web3_js_1.Keypair.fromSeed(new Uint8Array(32).fill(1));
65
+ const programId = (0, switchboard_v2_1.getSwitchboardPid)(env);
66
+ const wallet = new wallet_1.Wallet(DEFAULT_KEYPAIR);
67
+ const provider = new anchor_1.Provider(connection, wallet, {});
68
+ return new anchor_1.Program(switchboard_v2_json_1.default, programId, provider);
69
+ });
70
+ }
71
+ function convertSwitchboardDecimal(switchboardDecimal) {
72
+ const switchboardPrecision = numericConstants_1.TEN.pow(new anchor_1.BN(switchboardDecimal.scale));
73
+ return switchboardDecimal.mantissa
74
+ .mul(numericConstants_1.MARK_PRICE_PRECISION)
75
+ .div(switchboardPrecision);
76
+ }
@@ -0,0 +1,15 @@
1
+ /// <reference types="bn.js" />
2
+ /// <reference types="node" />
3
+ import { BN } from '@project-serum/anchor';
4
+ import { PublicKey } from '@solana/web3.js';
5
+ export declare type OraclePriceData = {
6
+ price: BN;
7
+ slot: BN;
8
+ confidence: BN;
9
+ twap?: BN;
10
+ twapConfidence?: BN;
11
+ };
12
+ export interface OracleClient {
13
+ getOraclePriceDataFromBuffer(buffer: Buffer): Promise<OraclePriceData>;
14
+ getOraclePriceData(publicKey: PublicKey): Promise<OraclePriceData>;
15
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,7 +1,7 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { OrderParams, OrderTriggerCondition, PositionDirection } from './types';
3
3
  import { BN } from '@project-serum/anchor';
4
- export declare function getLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
4
+ export declare function getLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number, postOnly?: boolean, oraclePriceOffset?: BN): OrderParams;
5
5
  export declare function getTriggerMarketOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, triggerPrice: BN, triggerCondition: OrderTriggerCondition, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
6
6
  export declare function getTriggerLimitOrderParams(marketIndex: BN, direction: PositionDirection, baseAssetAmount: BN, price: BN, triggerPrice: BN, triggerCondition: OrderTriggerCondition, reduceOnly: boolean, discountToken?: boolean, referrer?: boolean, userOrderId?: number): OrderParams;
7
7
  export declare function getMarketOrderParams(marketIndex: BN, direction: PositionDirection, quoteAssetAmount: BN, baseAssetAmount: BN, reduceOnly: boolean, price?: BN, discountToken?: boolean, referrer?: boolean): OrderParams;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getMarketOrderParams = exports.getTriggerLimitOrderParams = exports.getTriggerMarketOrderParams = exports.getLimitOrderParams = void 0;
4
4
  const types_1 = require("./types");
5
5
  const numericConstants_1 = require("./constants/numericConstants");
6
- function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
6
+ function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, reduceOnly, discountToken = false, referrer = false, userOrderId = 0, postOnly = false, oraclePriceOffset = numericConstants_1.ZERO) {
7
7
  return {
8
8
  orderType: types_1.OrderType.LIMIT,
9
9
  userOrderId,
@@ -13,7 +13,7 @@ function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, red
13
13
  baseAssetAmount,
14
14
  price,
15
15
  reduceOnly,
16
- postOnly: false,
16
+ postOnly,
17
17
  immediateOrCancel: false,
18
18
  positionLimit: numericConstants_1.ZERO,
19
19
  padding0: true,
@@ -24,7 +24,7 @@ function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, red
24
24
  },
25
25
  triggerCondition: types_1.OrderTriggerCondition.ABOVE,
26
26
  triggerPrice: numericConstants_1.ZERO,
27
- oraclePriceOffset: numericConstants_1.ZERO,
27
+ oraclePriceOffset,
28
28
  };
29
29
  }
30
30
  exports.getLimitOrderParams = getLimitOrderParams;
package/lib/orders.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { Market, Order, UserAccount, UserPosition } from './types';
3
3
  import { BN, ClearingHouseUser } from '.';
4
+ import { OraclePriceData } from '.';
4
5
  export declare function calculateNewStateAfterOrder(userAccount: UserAccount, userPosition: UserPosition, market: Market, order: Order): [UserAccount, UserPosition, Market] | null;
5
- export declare function calculateBaseAssetAmountMarketCanExecute(market: Market, order: Order): BN;
6
- export declare function calculateAmountToTradeForLimit(market: Market, order: Order): BN;
6
+ export declare function calculateBaseAssetAmountMarketCanExecute(market: Market, order: Order, oraclePriceData?: OraclePriceData): BN;
7
+ export declare function calculateAmountToTradeForLimit(market: Market, order: Order, oraclePriceData?: OraclePriceData): BN;
7
8
  export declare function calculateAmountToTradeForTriggerLimit(market: Market, order: Order): BN;
8
9
  export declare function calculateBaseAssetAmountUserCanExecute(market: Market, order: Order, user: ClearingHouseUser): BN;
package/lib/orders.js CHANGED
@@ -8,7 +8,7 @@ const numericConstants_1 = require("./constants/numericConstants");
8
8
  const amm_1 = require("./math/amm");
9
9
  const position_1 = require("./math/position");
10
10
  function calculateNewStateAfterOrder(userAccount, userPosition, market, order) {
11
- if (types_1.isVariant(order.status, 'init')) {
11
+ if ((0, types_1.isVariant)(order.status, 'init')) {
12
12
  return null;
13
13
  }
14
14
  const baseAssetAmountToTrade = calculateBaseAssetAmountMarketCanExecute(market, order);
@@ -17,11 +17,11 @@ function calculateNewStateAfterOrder(userAccount, userPosition, market, order) {
17
17
  }
18
18
  const userAccountAfter = Object.assign({}, userAccount);
19
19
  const userPositionAfter = Object.assign({}, userPosition);
20
- const currentPositionDirection = position_1.positionCurrentDirection(userPosition);
20
+ const currentPositionDirection = (0, position_1.positionCurrentDirection)(userPosition);
21
21
  const increasePosition = userPosition.baseAssetAmount.eq(numericConstants_1.ZERO) ||
22
22
  isSameDirection(order.direction, currentPositionDirection);
23
23
  if (increasePosition) {
24
- const marketAfter = market_1.calculateNewMarketAfterTrade(baseAssetAmountToTrade, order.direction, market);
24
+ const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountToTrade, order.direction, market);
25
25
  const { quoteAssetAmountSwapped, baseAssetAmountSwapped } = calculateAmountSwapped(market, marketAfter);
26
26
  userPositionAfter.baseAssetAmount = userPositionAfter.baseAssetAmount.add(baseAssetAmountSwapped);
27
27
  userPositionAfter.quoteAssetAmount = userPositionAfter.quoteAssetAmount.add(quoteAssetAmountSwapped);
@@ -30,10 +30,10 @@ function calculateNewStateAfterOrder(userAccount, userPosition, market, order) {
30
30
  else {
31
31
  const reversePosition = baseAssetAmountToTrade.gt(userPosition.baseAssetAmount.abs());
32
32
  if (reversePosition) {
33
- const intermediateMarket = market_1.calculateNewMarketAfterTrade(userPosition.baseAssetAmount, position_1.findDirectionToClose(userPosition), market);
33
+ const intermediateMarket = (0, market_1.calculateNewMarketAfterTrade)(userPosition.baseAssetAmount, (0, position_1.findDirectionToClose)(userPosition), market);
34
34
  const { quoteAssetAmountSwapped: baseAssetValue } = calculateAmountSwapped(market, intermediateMarket);
35
35
  let pnl;
36
- if (types_1.isVariant(currentPositionDirection, 'long')) {
36
+ if ((0, types_1.isVariant)(currentPositionDirection, 'long')) {
37
37
  pnl = baseAssetValue.sub(userPosition.quoteAssetAmount);
38
38
  }
39
39
  else {
@@ -41,20 +41,20 @@ function calculateNewStateAfterOrder(userAccount, userPosition, market, order) {
41
41
  }
42
42
  userAccountAfter.collateral = userAccountAfter.collateral.add(pnl);
43
43
  const baseAssetAmountLeft = baseAssetAmountToTrade.sub(userPosition.baseAssetAmount.abs());
44
- const marketAfter = market_1.calculateNewMarketAfterTrade(baseAssetAmountLeft, order.direction, intermediateMarket);
44
+ const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountLeft, order.direction, intermediateMarket);
45
45
  const { quoteAssetAmountSwapped, baseAssetAmountSwapped } = calculateAmountSwapped(intermediateMarket, marketAfter);
46
46
  userPositionAfter.quoteAssetAmount = quoteAssetAmountSwapped;
47
47
  userPositionAfter.baseAssetAmount = baseAssetAmountSwapped;
48
48
  return [userAccountAfter, userPositionAfter, marketAfter];
49
49
  }
50
50
  else {
51
- const marketAfter = market_1.calculateNewMarketAfterTrade(baseAssetAmountToTrade, order.direction, market);
51
+ const marketAfter = (0, market_1.calculateNewMarketAfterTrade)(baseAssetAmountToTrade, order.direction, market);
52
52
  const { quoteAssetAmountSwapped: baseAssetValue, baseAssetAmountSwapped, } = calculateAmountSwapped(market, marketAfter);
53
53
  const costBasisRealized = userPosition.quoteAssetAmount
54
54
  .mul(baseAssetAmountSwapped.abs())
55
55
  .div(userPosition.baseAssetAmount.abs());
56
56
  let pnl;
57
- if (types_1.isVariant(currentPositionDirection, 'long')) {
57
+ if ((0, types_1.isVariant)(currentPositionDirection, 'long')) {
58
58
  pnl = baseAssetValue.sub(costBasisRealized);
59
59
  }
60
60
  else {
@@ -80,14 +80,14 @@ function calculateAmountSwapped(marketBefore, marketAfter) {
80
80
  baseAssetAmountSwapped: marketBefore.amm.baseAssetReserve.sub(marketAfter.amm.baseAssetReserve),
81
81
  };
82
82
  }
83
- function calculateBaseAssetAmountMarketCanExecute(market, order) {
84
- if (types_1.isVariant(order.orderType, 'limit')) {
85
- return calculateAmountToTradeForLimit(market, order);
83
+ function calculateBaseAssetAmountMarketCanExecute(market, order, oraclePriceData) {
84
+ if ((0, types_1.isVariant)(order.orderType, 'limit')) {
85
+ return calculateAmountToTradeForLimit(market, order, oraclePriceData);
86
86
  }
87
- else if (types_1.isVariant(order.orderType, 'triggerLimit')) {
87
+ else if ((0, types_1.isVariant)(order.orderType, 'triggerLimit')) {
88
88
  return calculateAmountToTradeForTriggerLimit(market, order);
89
89
  }
90
- else if (types_1.isVariant(order.orderType, 'market')) {
90
+ else if ((0, types_1.isVariant)(order.orderType, 'market')) {
91
91
  // should never be a market order queued
92
92
  return numericConstants_1.ZERO;
93
93
  }
@@ -96,8 +96,15 @@ function calculateBaseAssetAmountMarketCanExecute(market, order) {
96
96
  }
97
97
  }
98
98
  exports.calculateBaseAssetAmountMarketCanExecute = calculateBaseAssetAmountMarketCanExecute;
99
- function calculateAmountToTradeForLimit(market, order) {
100
- const [maxAmountToTrade, direction] = amm_1.calculateMaxBaseAssetAmountToTrade(market.amm, order.price);
99
+ function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
100
+ let limitPrice = order.price;
101
+ if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
102
+ if (!oraclePriceData) {
103
+ throw Error('Cant calculate limit price for oracle offset oracle without OraclePriceData');
104
+ }
105
+ limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
106
+ }
107
+ const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice);
101
108
  // Check that directions are the same
102
109
  const sameDirection = isSameDirection(direction, order.direction);
103
110
  if (!sameDirection) {
@@ -119,8 +126,8 @@ function calculateAmountToTradeForTriggerLimit(market, order) {
119
126
  }
120
127
  exports.calculateAmountToTradeForTriggerLimit = calculateAmountToTradeForTriggerLimit;
121
128
  function isSameDirection(firstDirection, secondDirection) {
122
- return ((types_1.isVariant(firstDirection, 'long') && types_1.isVariant(secondDirection, 'long')) ||
123
- (types_1.isVariant(firstDirection, 'short') && types_1.isVariant(secondDirection, 'short')));
129
+ return (((0, types_1.isVariant)(firstDirection, 'long') && (0, types_1.isVariant)(secondDirection, 'long')) ||
130
+ ((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
124
131
  }
125
132
  function calculateAmountToTradeForTriggerMarket(market, order) {
126
133
  return isTriggerConditionSatisfied(market, order)
@@ -128,8 +135,8 @@ function calculateAmountToTradeForTriggerMarket(market, order) {
128
135
  : numericConstants_1.ZERO;
129
136
  }
130
137
  function isTriggerConditionSatisfied(market, order) {
131
- const markPrice = market_1.calculateMarkPrice(market);
132
- if (types_1.isVariant(order.triggerCondition, 'above')) {
138
+ const markPrice = (0, market_1.calculateMarkPrice)(market);
139
+ if ((0, types_1.isVariant)(order.triggerCondition, 'above')) {
133
140
  return markPrice.gt(order.triggerPrice);
134
141
  }
135
142
  else {
@@ -140,13 +147,13 @@ function calculateBaseAssetAmountUserCanExecute(market, order, user) {
140
147
  const maxLeverage = user.getMaxLeverage(order.marketIndex, 'Initial');
141
148
  const freeCollateral = user.getFreeCollateral();
142
149
  let quoteAssetAmount;
143
- if (_1.isOrderRiskIncreasingInSameDirection(user, order)) {
150
+ if ((0, _1.isOrderRiskIncreasingInSameDirection)(user, order)) {
144
151
  quoteAssetAmount = freeCollateral.mul(maxLeverage).div(_1.TEN_THOUSAND);
145
152
  }
146
153
  else {
147
154
  const position = user.getUserPosition(order.marketIndex) ||
148
155
  user.getEmptyPosition(order.marketIndex);
149
- const positionValue = _1.calculateBaseAssetValue(market, position);
156
+ const positionValue = (0, _1.calculateBaseAssetValue)(market, position);
150
157
  quoteAssetAmount = freeCollateral
151
158
  .mul(maxLeverage)
152
159
  .div(_1.TEN_THOUSAND)
@@ -156,7 +163,7 @@ function calculateBaseAssetAmountUserCanExecute(market, order, user) {
156
163
  return numericConstants_1.ZERO;
157
164
  }
158
165
  const baseAssetReservesBefore = market.amm.baseAssetReserve;
159
- const [_, baseAssetReservesAfter] = _1.calculateAmmReservesAfterSwap(market.amm, 'quote', quoteAssetAmount, types_1.isVariant(order.direction, 'long')
166
+ const [_, baseAssetReservesAfter] = (0, _1.calculateAmmReservesAfterSwap)(market.amm, 'quote', quoteAssetAmount, (0, types_1.isVariant)(order.direction, 'long')
160
167
  ? types_1.SwapDirection.ADD
161
168
  : types_1.SwapDirection.REMOVE);
162
169
  return baseAssetReservesBefore.sub(baseAssetReservesAfter).abs();
@@ -93,7 +93,7 @@ class RetryTxSender {
93
93
  catch (err) {
94
94
  throw new Error('signature must be base58 encoded: ' + signature);
95
95
  }
96
- assert_1.default(decodedSignature.length === 64, 'signature has invalid length');
96
+ (0, assert_1.default)(decodedSignature.length === 64, 'signature has invalid length');
97
97
  const start = Date.now();
98
98
  const subscriptionCommitment = commitment || this.provider.opts.commitment;
99
99
  let subscriptionId;
package/lib/types.d.ts CHANGED
@@ -225,6 +225,7 @@ export declare type OrderRecord = {
225
225
  fee: BN;
226
226
  fillerReward: BN;
227
227
  tradeRecordId: BN;
228
+ quoteAssetAmountSurplus: BN;
228
229
  };
229
230
  export declare type StateAccount = {
230
231
  admin: PublicKey;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.1.24",
3
+ "version": "0.1.27",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -32,6 +32,7 @@
32
32
  "@pythnetwork/client": "^2.5.1",
33
33
  "@solana/spl-token": "^0.1.6",
34
34
  "@solana/web3.js": "^1.22.0",
35
+ "@switchboard-xyz/switchboard-v2": "^0.0.67",
35
36
  "strict-event-emitter-types": "^2.0.0",
36
37
  "uuid": "^8.3.2"
37
38
  },
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BulkAccountLoader = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const uuid_1 = require("uuid");
6
+ const GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = 99;
7
+ const fiveMinutes = 5 * 60 * 1000;
8
+ class BulkAccountLoader {
9
+ constructor(connection, commitment, pollingFrequency) {
10
+ this.accountsToLoad = new Map();
11
+ this.accountData = new Map();
12
+ this.errorCallbacks = new Map();
13
+ this.loggingEnabled = false;
14
+ this.lastUpdate = Date.now();
15
+ this.connection = connection;
16
+ this.commitment = commitment;
17
+ this.pollingFrequency = pollingFrequency;
18
+ }
19
+ addAccount(publicKey, callback) {
20
+ const existingSize = this.accountsToLoad.size;
21
+ const callbackId = (0, uuid_1.v4)();
22
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
23
+ if (existingAccountToLoad) {
24
+ existingAccountToLoad.callbacks.set(callbackId, callback);
25
+ }
26
+ else {
27
+ const callbacks = new Map();
28
+ callbacks.set(callbackId, callback);
29
+ const newAccountToLoad = {
30
+ publicKey,
31
+ callbacks,
32
+ };
33
+ this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
34
+ }
35
+ if (existingSize === 0) {
36
+ this.startPolling();
37
+ }
38
+ // if a new account needs to be polled, remove the cached loadPromise in case client calls load immediately after
39
+ this.loadPromise = undefined;
40
+ return callbackId;
41
+ }
42
+ removeAccount(publicKey, callbackId) {
43
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
44
+ if (existingAccountToLoad) {
45
+ existingAccountToLoad.callbacks.delete(callbackId);
46
+ if (existingAccountToLoad.callbacks.size === 0) {
47
+ this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString());
48
+ }
49
+ }
50
+ if (this.accountsToLoad.size === 0) {
51
+ this.stopPolling();
52
+ }
53
+ }
54
+ addErrorCallbacks(callback) {
55
+ const callbackId = (0, uuid_1.v4)();
56
+ this.errorCallbacks.set(callbackId, callback);
57
+ return callbackId;
58
+ }
59
+ removeErrorCallbacks(callbackId) {
60
+ this.errorCallbacks.delete(callbackId);
61
+ }
62
+ chunks(array, size) {
63
+ return new Array(Math.ceil(array.length / size))
64
+ .fill(null)
65
+ .map((_, index) => index * size)
66
+ .map((begin) => array.slice(begin, begin + size));
67
+ }
68
+ async load() {
69
+ if (this.loadPromise) {
70
+ return this.loadPromise;
71
+ }
72
+ this.loadPromise = new Promise((resolver) => {
73
+ this.loadPromiseResolver = resolver;
74
+ });
75
+ if (this.loggingEnabled) {
76
+ console.log('Loading accounts');
77
+ }
78
+ try {
79
+ const chunks = this.chunks(Array.from(this.accountsToLoad.values()), GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE);
80
+ await Promise.all(chunks.map((chunk) => {
81
+ return this.loadChunk(chunk);
82
+ }));
83
+ }
84
+ catch (e) {
85
+ console.error(`Error in bulkAccountLoader.load()`);
86
+ console.error(e);
87
+ for (const [_, callback] of this.errorCallbacks) {
88
+ callback(e);
89
+ }
90
+ }
91
+ finally {
92
+ this.loadPromiseResolver();
93
+ this.loadPromise = undefined;
94
+ const now = Date.now();
95
+ if (now - this.lastUpdate > fiveMinutes) {
96
+ if (this.loggingEnabled) {
97
+ console.log("Haven't seen updated account in five minutes. Bulk account loader creating new Connection Object");
98
+ }
99
+ this.connection = new web3_js_1.Connection(
100
+ // @ts-ignore
101
+ this.connection._rpcEndpoint, this.connection.commitment);
102
+ }
103
+ }
104
+ }
105
+ async loadChunk(accountsToLoad) {
106
+ if (accountsToLoad.length === 0) {
107
+ return;
108
+ }
109
+ const args = [
110
+ accountsToLoad.map((accountToLoad) => {
111
+ return accountToLoad.publicKey.toBase58();
112
+ }),
113
+ { commitment: this.commitment },
114
+ ];
115
+ // @ts-ignore
116
+ const rpcResponse = await this.connection._rpcRequest('getMultipleAccounts', args);
117
+ const newSlot = rpcResponse.result.context.slot;
118
+ for (const i in accountsToLoad) {
119
+ const accountToLoad = accountsToLoad[i];
120
+ const key = accountToLoad.publicKey.toString();
121
+ const oldRPCResponse = this.accountData.get(key);
122
+ let newBuffer = undefined;
123
+ if (rpcResponse.result.value[i]) {
124
+ const raw = rpcResponse.result.value[i].data[0];
125
+ const dataType = rpcResponse.result.value[i].data[1];
126
+ newBuffer = Buffer.from(raw, dataType);
127
+ }
128
+ if (!oldRPCResponse) {
129
+ this.accountData.set(key, {
130
+ slot: newSlot,
131
+ buffer: newBuffer,
132
+ });
133
+ this.handleAccountCallbacks(accountToLoad, newBuffer);
134
+ this.lastUpdate = Date.now();
135
+ continue;
136
+ }
137
+ if (newSlot <= oldRPCResponse.slot) {
138
+ continue;
139
+ }
140
+ const oldBuffer = oldRPCResponse.buffer;
141
+ if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
142
+ this.accountData.set(key, {
143
+ slot: newSlot,
144
+ buffer: newBuffer,
145
+ });
146
+ this.handleAccountCallbacks(accountToLoad, newBuffer);
147
+ this.lastUpdate = Date.now();
148
+ }
149
+ }
150
+ }
151
+ handleAccountCallbacks(accountToLoad, buffer) {
152
+ for (const [_, callback] of accountToLoad.callbacks) {
153
+ callback(buffer);
154
+ }
155
+ }
156
+ getAccountData(publicKey) {
157
+ const accountData = this.accountData.get(publicKey.toString());
158
+ return accountData === null || accountData === void 0 ? void 0 : accountData.buffer;
159
+ }
160
+ startPolling() {
161
+ if (this.intervalId) {
162
+ return;
163
+ }
164
+ if (this.loggingEnabled) {
165
+ console.log(`startPolling`);
166
+ }
167
+ this.intervalId = setInterval(this.load.bind(this), this.pollingFrequency);
168
+ }
169
+ stopPolling() {
170
+ if (this.intervalId) {
171
+ clearInterval(this.intervalId);
172
+ this.intervalId = undefined;
173
+ if (this.loggingEnabled) {
174
+ console.log(`stopPolling`);
175
+ }
176
+ }
177
+ }
178
+ }
179
+ exports.BulkAccountLoader = BulkAccountLoader;
180
+ //# sourceMappingURL=bulkAccountLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulkAccountLoader.js","sourceRoot":"","sources":["bulkAccountLoader.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,8 @@ type AccountToLoad = {
9
9
 
10
10
  const GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = 99;
11
11
 
12
+ const fiveMinutes = 5 * 60 * 1000;
13
+
12
14
  export class BulkAccountLoader {
13
15
  connection: Connection;
14
16
  commitment: Commitment;
@@ -21,6 +23,7 @@ export class BulkAccountLoader {
21
23
  loadPromise?: Promise<void>;
22
24
  loadPromiseResolver: () => void;
23
25
  loggingEnabled = false;
26
+ lastUpdate = Date.now();
24
27
 
25
28
  public constructor(
26
29
  connection: Connection,
@@ -125,6 +128,20 @@ export class BulkAccountLoader {
125
128
  } finally {
126
129
  this.loadPromiseResolver();
127
130
  this.loadPromise = undefined;
131
+
132
+ const now = Date.now();
133
+ if (now - this.lastUpdate > fiveMinutes) {
134
+ if (this.loggingEnabled) {
135
+ console.log(
136
+ "Haven't seen updated account in five minutes. Bulk account loader creating new Connection Object"
137
+ );
138
+ }
139
+ this.connection = new Connection(
140
+ // @ts-ignore
141
+ this.connection._rpcEndpoint,
142
+ this.connection.commitment
143
+ );
144
+ }
128
145
  }
129
146
  }
130
147
 
@@ -166,6 +183,7 @@ export class BulkAccountLoader {
166
183
  buffer: newBuffer,
167
184
  });
168
185
  this.handleAccountCallbacks(accountToLoad, newBuffer);
186
+ this.lastUpdate = Date.now();
169
187
  continue;
170
188
  }
171
189
 
@@ -180,6 +198,7 @@ export class BulkAccountLoader {
180
198
  buffer: newBuffer,
181
199
  });
182
200
  this.handleAccountCallbacks(accountToLoad, newBuffer);
201
+ this.lastUpdate = Date.now();
183
202
  }
184
203
  }
185
204
  }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bulkPollingUserSubscribe = void 0;
4
+ /**
5
+ * @param users
6
+ * @param accountLoader
7
+ */
8
+ async function bulkPollingUserSubscribe(users, accountLoader) {
9
+ if (users.length === 0) {
10
+ await accountLoader.load();
11
+ return;
12
+ }
13
+ // Fetch all the accounts first
14
+ const program = users[0].clearingHouse.program;
15
+ let userProgramAccounts;
16
+ let orderProgramAccounts;
17
+ await Promise.all([
18
+ (async () => {
19
+ userProgramAccounts = await program.account.user.all();
20
+ })(),
21
+ (async () => {
22
+ orderProgramAccounts = await program.account.userOrders.all();
23
+ })(),
24
+ ]);
25
+ // Create a map of the authority to keys
26
+ const authorityToKeys = new Map();
27
+ const userToAuthority = new Map();
28
+ for (const userProgramAccount of userProgramAccounts) {
29
+ const userAccountPublicKey = userProgramAccount.publicKey;
30
+ const userAccount = userProgramAccount.account;
31
+ authorityToKeys.set(userAccount.authority.toString(), {
32
+ user: userAccountPublicKey,
33
+ userPositions: userAccount.positions,
34
+ userOrders: undefined,
35
+ });
36
+ userToAuthority.set(userAccountPublicKey.toString(), userAccount.authority.toString());
37
+ }
38
+ for (const orderProgramAccount of orderProgramAccounts) {
39
+ const userOrderAccountPublicKey = orderProgramAccount.publicKey;
40
+ const userOrderAccount = orderProgramAccount.account;
41
+ const authority = userToAuthority.get(userOrderAccount.user.toString());
42
+ const userPublicKeys = authorityToKeys.get(authority);
43
+ userPublicKeys.userOrders = userOrderAccountPublicKey;
44
+ }
45
+ await Promise.all(users.map((user) => {
46
+ // Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
47
+ const userPublicKeys = authorityToKeys.get(user.authority.toString());
48
+ return user.accountSubscriber.addToAccountLoader(userPublicKeys);
49
+ }));
50
+ await accountLoader.load();
51
+ await Promise.all(users.map(async (user) => {
52
+ return user.subscribe();
53
+ }));
54
+ }
55
+ exports.bulkPollingUserSubscribe = bulkPollingUserSubscribe;
56
+ //# sourceMappingURL=bulkUserSubscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulkUserSubscription.js","sourceRoot":"","sources":["bulkUserSubscription.ts"],"names":[],"mappings":";;;AAOA;;;GAGG;AACI,KAAK,UAAU,wBAAwB,CAC7C,KAA0B,EAC1B,aAAgC;IAEhC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;QACvB,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;QAC3B,OAAO;KACP;IAED,+BAA+B;IAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC;IAC/C,IAAI,mBAAqC,CAAC;IAC1C,IAAI,oBAAsC,CAAC;IAC3C,MAAM,OAAO,CAAC,GAAG,CAAC;QACjB,CAAC,KAAK,IAAI,EAAE;YACX,mBAAmB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACxD,CAAC,CAAC,EAAE;QACJ,CAAC,KAAK,IAAI,EAAE;YACX,oBAAoB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;QAC/D,CAAC,CAAC,EAAE;KACJ,CAAC,CAAC;IAEH,wCAAwC;IACxC,MAAM,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC1D,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,KAAK,MAAM,kBAAkB,IAAI,mBAAmB,EAAE;QACrD,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,SAAS,CAAC;QAC1D,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAsB,CAAC;QAE9D,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE;YACrD,IAAI,EAAE,oBAAoB;YAC1B,aAAa,EAAE,WAAW,CAAC,SAAS;YACpC,UAAU,EAAE,SAAS;SACrB,CAAC,CAAC;QAEH,eAAe,CAAC,GAAG,CAClB,oBAAoB,CAAC,QAAQ,EAAE,EAC/B,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE,CAChC,CAAC;KACF;IACD,KAAK,MAAM,mBAAmB,IAAI,oBAAoB,EAAE;QACvD,MAAM,yBAAyB,GAAG,mBAAmB,CAAC,SAAS,CAAC;QAChE,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,OAA4B,CAAC;QAE1E,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxE,MAAM,cAAc,GAAG,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACtD,cAAc,CAAC,UAAU,GAAG,yBAAyB,CAAC;KACtD;IAED,MAAM,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAClB,0FAA0F;QAC1F,MAAM,cAAc,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtE,OACC,IAAI,CAAC,iBACL,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC,CAAC,CACF,CAAC;IAEF,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;IAE3B,MAAM,OAAO,CAAC,GAAG,CAChB,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACxB,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;IACzB,CAAC,CAAC,CACF,CAAC;AACH,CAAC;AAlED,4DAkEC"}