@drift-labs/sdk 0.1.23-master.4 → 0.1.26

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 (61) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +2 -0
  2. package/lib/accounts/bulkAccountLoader.js +24 -0
  3. package/lib/addresses.js +5 -1
  4. package/lib/admin.d.ts +2 -2
  5. package/lib/admin.js +11 -5
  6. package/lib/clearingHouse.js +7 -1
  7. package/lib/clearingHouseUser.d.ts +12 -17
  8. package/lib/clearingHouseUser.js +114 -217
  9. package/lib/constants/markets.d.ts +6 -4
  10. package/lib/constants/markets.js +48 -0
  11. package/lib/constants/numericConstants.d.ts +2 -2
  12. package/lib/constants/numericConstants.js +3 -3
  13. package/lib/factory/oracleClient.d.ts +5 -0
  14. package/lib/factory/oracleClient.js +16 -0
  15. package/lib/idl/clearing_house.json +58 -5
  16. package/lib/idl/switchboard_v2.json +4663 -0
  17. package/lib/index.d.ts +4 -1
  18. package/lib/index.js +9 -2
  19. package/lib/math/funding.d.ts +6 -6
  20. package/lib/math/funding.js +4 -16
  21. package/lib/math/orders.d.ts +1 -0
  22. package/lib/math/orders.js +19 -1
  23. package/lib/mockUSDCFaucet.js +5 -1
  24. package/lib/oracles/pythClient.d.ts +14 -0
  25. package/lib/oracles/pythClient.js +53 -0
  26. package/lib/oracles/switchboardClient.d.ts +13 -0
  27. package/lib/oracles/switchboardClient.js +76 -0
  28. package/lib/oracles/types.d.ts +15 -0
  29. package/lib/oracles/types.js +2 -0
  30. package/lib/orderParams.d.ts +1 -1
  31. package/lib/orderParams.js +2 -2
  32. package/lib/orders.js +1 -1
  33. package/lib/types.d.ts +5 -1
  34. package/package.json +2 -1
  35. package/src/accounts/bulkAccountLoader.ts +32 -0
  36. package/src/accounts/types.js +10 -0
  37. package/src/accounts/utils.js +7 -0
  38. package/src/accounts/webSocketAccountSubscriber.js +76 -0
  39. package/src/addresses.js +83 -0
  40. package/src/admin.ts +15 -4
  41. package/src/clearingHouse.ts +2 -0
  42. package/src/clearingHouseUser.ts +161 -330
  43. package/src/constants/markets.ts +54 -3
  44. package/src/constants/numericConstants.ts +2 -2
  45. package/src/factory/oracleClient.ts +22 -0
  46. package/src/idl/clearing_house.json +58 -5
  47. package/src/idl/switchboard_v2.json +4663 -0
  48. package/src/index.ts +4 -1
  49. package/src/math/funding.ts +9 -25
  50. package/src/math/orders.ts +28 -0
  51. package/src/mockUSDCFaucet.js +171 -0
  52. package/src/oracles/pythClient.ts +49 -0
  53. package/src/oracles/switchboardClient.ts +87 -0
  54. package/src/oracles/types.ts +15 -0
  55. package/src/orderParams.ts +3 -2
  56. package/src/orders.ts +1 -1
  57. package/src/types.js +60 -0
  58. package/src/types.ts +6 -1
  59. package/lib/pythClient.d.ts +0 -7
  60. package/lib/pythClient.js +0 -25
  61. package/src/pythClient.ts +0 -15
package/lib/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import { BN } from '@project-serum/anchor';
2
2
  import { PublicKey } from '@solana/web3.js';
3
3
  export * from './mockUSDCFaucet';
4
- export * from './pythClient';
4
+ export * from './oracles/types';
5
+ export * from './oracles/pythClient';
6
+ export * from './oracles/switchboardClient';
5
7
  export * from './types';
6
8
  export * from './constants/markets';
7
9
  export * from './accounts/webSocketClearingHouseAccountSubscriber';
@@ -16,6 +18,7 @@ export * from './clearingHouseUser';
16
18
  export * from './clearingHouse';
17
19
  export * from './factory/clearingHouse';
18
20
  export * from './factory/clearingHouseUser';
21
+ export * from './factory/oracleClient';
19
22
  export * from './math/conversion';
20
23
  export * from './math/funding';
21
24
  export * from './math/insuranceFund';
package/lib/index.js CHANGED
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -16,7 +20,9 @@ Object.defineProperty(exports, "BN", { enumerable: true, get: function () { retu
16
20
  const web3_js_1 = require("@solana/web3.js");
17
21
  Object.defineProperty(exports, "PublicKey", { enumerable: true, get: function () { return web3_js_1.PublicKey; } });
18
22
  __exportStar(require("./mockUSDCFaucet"), exports);
19
- __exportStar(require("./pythClient"), exports);
23
+ __exportStar(require("./oracles/types"), exports);
24
+ __exportStar(require("./oracles/pythClient"), exports);
25
+ __exportStar(require("./oracles/switchboardClient"), exports);
20
26
  __exportStar(require("./types"), exports);
21
27
  __exportStar(require("./constants/markets"), exports);
22
28
  __exportStar(require("./accounts/webSocketClearingHouseAccountSubscriber"), exports);
@@ -31,6 +37,7 @@ __exportStar(require("./clearingHouseUser"), exports);
31
37
  __exportStar(require("./clearingHouse"), exports);
32
38
  __exportStar(require("./factory/clearingHouse"), exports);
33
39
  __exportStar(require("./factory/clearingHouseUser"), exports);
40
+ __exportStar(require("./factory/oracleClient"), exports);
34
41
  __exportStar(require("./math/conversion"), exports);
35
42
  __exportStar(require("./math/funding"), exports);
36
43
  __exportStar(require("./math/insuranceFund"), exports);
@@ -1,15 +1,15 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { BN } from '@project-serum/anchor';
3
- import { PriceData } from '@pythnetwork/client';
4
3
  import { Market } from '../types';
4
+ import { OraclePriceData } from '../oracles/types';
5
5
  /**
6
6
  *
7
7
  * @param market
8
- * @param pythClient
8
+ * @param oraclePriceData
9
9
  * @param periodAdjustment
10
10
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
11
11
  */
12
- export declare function calculateAllEstimatedFundingRate(market: Market, oraclePriceData: PriceData, periodAdjustment?: BN): Promise<[BN, BN, BN, BN, BN]>;
12
+ export declare function calculateAllEstimatedFundingRate(market: Market, oraclePriceData: OraclePriceData, periodAdjustment?: BN): Promise<[BN, BN, BN, BN, BN]>;
13
13
  /**
14
14
  *
15
15
  * @param market
@@ -18,7 +18,7 @@ export declare function calculateAllEstimatedFundingRate(market: Market, oracleP
18
18
  * @param estimationMethod
19
19
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
20
20
  */
21
- export declare function calculateEstimatedFundingRate(market: Market, oraclePriceData: PriceData, periodAdjustment: BN, estimationMethod: 'interpolated' | 'lowerbound' | 'capped'): Promise<BN>;
21
+ export declare function calculateEstimatedFundingRate(market: Market, oraclePriceData: OraclePriceData, periodAdjustment: BN, estimationMethod: 'interpolated' | 'lowerbound' | 'capped'): Promise<BN>;
22
22
  /**
23
23
  *
24
24
  * @param market
@@ -26,7 +26,7 @@ export declare function calculateEstimatedFundingRate(market: Market, oraclePric
26
26
  * @param periodAdjustment
27
27
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
28
28
  */
29
- export declare function calculateLongShortFundingRate(market: Market, oraclePriceData: PriceData, periodAdjustment?: BN): Promise<[BN, BN]>;
29
+ export declare function calculateLongShortFundingRate(market: Market, oraclePriceData: OraclePriceData, periodAdjustment?: BN): Promise<[BN, BN]>;
30
30
  /**
31
31
  *
32
32
  * @param market
@@ -34,7 +34,7 @@ export declare function calculateLongShortFundingRate(market: Market, oraclePric
34
34
  * @param periodAdjustment
35
35
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
36
36
  */
37
- export declare function calculateLongShortFundingRateAndLiveTwaps(market: Market, oraclePriceData: PriceData, periodAdjustment?: BN): Promise<[BN, BN, BN, BN]>;
37
+ export declare function calculateLongShortFundingRateAndLiveTwaps(market: Market, oraclePriceData: OraclePriceData, periodAdjustment?: BN): Promise<[BN, BN, BN, BN]>;
38
38
  /**
39
39
  *
40
40
  * @param market
@@ -16,7 +16,7 @@ const market_1 = require("./market");
16
16
  /**
17
17
  *
18
18
  * @param market
19
- * @param pythClient
19
+ * @param oraclePriceData
20
20
  * @param periodAdjustment
21
21
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
22
22
  */
@@ -51,21 +51,9 @@ function calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustm
51
51
  const lastOraclePriceTwapTs = market.amm.lastOraclePriceTwapTs;
52
52
  const timeSinceLastOracleTwapUpdate = now.sub(lastOraclePriceTwapTs);
53
53
  const oracleTwapTimeSinceLastUpdate = anchor_1.BN.max(secondsInHour, secondsInHour.sub(timeSinceLastOracleTwapUpdate));
54
- // verify pyth input is positive for live update
55
- let oracleStablePriceNum = 0;
56
- let oracleInputCount = 0;
57
- if (oraclePriceData.price >= 0) {
58
- oracleStablePriceNum += oraclePriceData.price;
59
- oracleInputCount += 1;
60
- }
61
- if (oraclePriceData.previousPrice >= 0) {
62
- oracleStablePriceNum += oraclePriceData.previousPrice;
63
- oracleInputCount += 1;
64
- }
65
- oracleStablePriceNum = oracleStablePriceNum / oracleInputCount;
66
- const oraclePriceStableWithMantissa = new anchor_1.BN(oracleStablePriceNum * numericConstants_1.MARK_PRICE_PRECISION.toNumber());
54
+ const oraclePrice = oraclePriceData.price;
67
55
  let oracleTwapWithMantissa = lastOracleTwapWithMantissa;
68
- const oracleLiveVsTwap = oraclePriceStableWithMantissa
56
+ const oracleLiveVsTwap = oraclePrice
69
57
  .sub(lastOracleTwapWithMantissa)
70
58
  .abs()
71
59
  .mul(numericConstants_1.MARK_PRICE_PRECISION)
@@ -75,7 +63,7 @@ function calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustm
75
63
  if (oracleLiveVsTwap.lte(numericConstants_1.MARK_PRICE_PRECISION.mul(new anchor_1.BN(10)))) {
76
64
  oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
77
65
  .mul(lastOracleTwapWithMantissa)
78
- .add(timeSinceLastMarkChange.mul(oraclePriceStableWithMantissa))
66
+ .add(timeSinceLastMarkChange.mul(oraclePrice))
79
67
  .div(timeSinceLastOracleTwapUpdate.add(oracleTwapTimeSinceLastUpdate));
80
68
  }
81
69
  const twapSpread = lastMarkTwapWithMantissa.sub(lastOracleTwapWithMantissa);
@@ -2,3 +2,4 @@ import { ClearingHouseUser } from '../clearingHouseUser';
2
2
  import { Order } from '../types';
3
3
  export declare function isOrderRiskIncreasing(user: ClearingHouseUser, order: Order): boolean;
4
4
  export declare function isOrderRiskIncreasingInSameDirection(user: ClearingHouseUser, order: Order): boolean;
5
+ export declare function isOrderReduceOnly(user: ClearingHouseUser, order: Order): boolean;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
3
+ exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
4
4
  const types_1 = require("../types");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  function isOrderRiskIncreasing(user, order) {
@@ -52,3 +52,21 @@ function isOrderRiskIncreasingInSameDirection(user, order) {
52
52
  return false;
53
53
  }
54
54
  exports.isOrderRiskIncreasingInSameDirection = isOrderRiskIncreasingInSameDirection;
55
+ function isOrderReduceOnly(user, order) {
56
+ if ((0, types_1.isVariant)(order.status, 'init')) {
57
+ return false;
58
+ }
59
+ const position = user.getUserPosition(order.marketIndex) ||
60
+ user.getEmptyPosition(order.marketIndex);
61
+ // if position is long and order is long
62
+ if (position.baseAssetAmount.gt(numericConstants_1.ZERO) && (0, types_1.isVariant)(order.direction, 'long')) {
63
+ return false;
64
+ }
65
+ // if position is short and order is short
66
+ if (position.baseAssetAmount.lt(numericConstants_1.ZERO) &&
67
+ (0, types_1.isVariant)(order.direction, 'short')) {
68
+ return false;
69
+ }
70
+ return order.baseAssetAmount.abs().lte(position.baseAssetAmount.abs());
71
+ }
72
+ exports.isOrderReduceOnly = isOrderReduceOnly;
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -0,0 +1,14 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="bn.js" />
3
+ import { PriceData } from '@pythnetwork/client';
4
+ import { Connection, PublicKey } from '@solana/web3.js';
5
+ import { OraclePriceData } from './types';
6
+ import { BN } from '@project-serum/anchor';
7
+ export declare class PythClient {
8
+ private connection;
9
+ constructor(connection: Connection);
10
+ getPriceData(pricePublicKey: PublicKey): Promise<PriceData>;
11
+ getOraclePriceData(pricePublicKey: PublicKey): Promise<OraclePriceData>;
12
+ getOraclePriceDataFromBuffer(buffer: Buffer): Promise<OraclePriceData>;
13
+ }
14
+ export declare function convertPythPrice(price: number, exponent: number): BN;
@@ -0,0 +1,53 @@
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.convertPythPrice = exports.PythClient = void 0;
13
+ const client_1 = require("@pythnetwork/client");
14
+ const anchor_1 = require("@project-serum/anchor");
15
+ const numericConstants_1 = require("../constants/numericConstants");
16
+ class PythClient {
17
+ constructor(connection) {
18
+ this.connection = connection;
19
+ }
20
+ getPriceData(pricePublicKey) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ const account = yield this.connection.getAccountInfo(pricePublicKey);
23
+ return (0, client_1.parsePriceData)(account.data);
24
+ });
25
+ }
26
+ getOraclePriceData(pricePublicKey) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ const accountInfo = yield this.connection.getAccountInfo(pricePublicKey);
29
+ return this.getOraclePriceDataFromBuffer(accountInfo.data);
30
+ });
31
+ }
32
+ getOraclePriceDataFromBuffer(buffer) {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ const priceData = (0, client_1.parsePriceData)(buffer);
35
+ return {
36
+ price: convertPythPrice(priceData.price, priceData.exponent),
37
+ slot: new anchor_1.BN(priceData.lastSlot.toString()),
38
+ confidence: convertPythPrice(priceData.confidence, priceData.exponent),
39
+ twap: convertPythPrice(priceData.twap.value, priceData.exponent),
40
+ twapConfidence: convertPythPrice(priceData.twac.value, priceData.exponent),
41
+ };
42
+ });
43
+ }
44
+ }
45
+ exports.PythClient = PythClient;
46
+ function convertPythPrice(price, exponent) {
47
+ exponent = Math.abs(exponent);
48
+ const pythPrecision = numericConstants_1.TEN.pow(new anchor_1.BN(exponent).abs());
49
+ return new anchor_1.BN(price * Math.pow(10, exponent))
50
+ .mul(numericConstants_1.MARK_PRICE_PRECISION)
51
+ .div(pythPrecision);
52
+ }
53
+ exports.convertPythPrice = convertPythPrice;
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ import { Connection, PublicKey } from '@solana/web3.js';
3
+ import { DriftEnv } from '../config';
4
+ import { Program } from '@project-serum/anchor';
5
+ import { OracleClient, OraclePriceData } from './types';
6
+ export declare class SwitchboardClient implements OracleClient {
7
+ connection: Connection;
8
+ env: DriftEnv;
9
+ constructor(connection: Connection, env: DriftEnv);
10
+ getOraclePriceData(pricePublicKey: PublicKey): Promise<OraclePriceData>;
11
+ getOraclePriceDataFromBuffer(buffer: Buffer): Promise<OraclePriceData>;
12
+ getProgram(): Promise<Program>;
13
+ }
@@ -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): 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) {
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,
package/lib/orders.js CHANGED
@@ -137,7 +137,7 @@ function isTriggerConditionSatisfied(market, order) {
137
137
  }
138
138
  }
139
139
  function calculateBaseAssetAmountUserCanExecute(market, order, user) {
140
- const maxLeverage = user.getMaxLeverage('Initial');
140
+ const maxLeverage = user.getMaxLeverage(order.marketIndex, 'Initial');
141
141
  const freeCollateral = user.getFreeCollateral();
142
142
  let quoteAssetAmount;
143
143
  if ((0, _1.isOrderRiskIncreasingInSameDirection)(user, order)) {
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;
@@ -272,7 +273,6 @@ export declare type OrderStateAccount = {
272
273
  minOrderQuoteAssetAmount: BN;
273
274
  };
274
275
  export declare type MarketsAccount = {
275
- accountIndex: BN;
276
276
  markets: Market[];
277
277
  };
278
278
  export declare type Market = {
@@ -282,6 +282,9 @@ export declare type Market = {
282
282
  baseAssetAmountShort: BN;
283
283
  initialized: boolean;
284
284
  openInterest: BN;
285
+ marginRatioInitial: number;
286
+ marginRatioMaintenance: number;
287
+ marginRatioPartial: number;
285
288
  };
286
289
  export declare type AMM = {
287
290
  baseAssetReserve: BN;
@@ -434,3 +437,4 @@ export declare type OrderFillerRewardStructure = {
434
437
  rewardDenominator: BN;
435
438
  timeBasedRewardLowerBound: BN;
436
439
  };
440
+ export declare type MarginCategory = 'Initial' | 'Partial' | 'Maintenance';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.1.23-master.4",
3
+ "version": "0.1.26",
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
  },
@@ -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;
@@ -20,6 +22,8 @@ export class BulkAccountLoader {
20
22
  // to handle clients spamming load
21
23
  loadPromise?: Promise<void>;
22
24
  loadPromiseResolver: () => void;
25
+ loggingEnabled = false;
26
+ lastUpdate = Date.now();
23
27
 
24
28
  public constructor(
25
29
  connection: Connection,
@@ -100,6 +104,10 @@ export class BulkAccountLoader {
100
104
  this.loadPromiseResolver = resolver;
101
105
  });
102
106
 
107
+ if (this.loggingEnabled) {
108
+ console.log('Loading accounts');
109
+ }
110
+
103
111
  try {
104
112
  const chunks = this.chunks(
105
113
  Array.from(this.accountsToLoad.values()),
@@ -120,6 +128,20 @@ export class BulkAccountLoader {
120
128
  } finally {
121
129
  this.loadPromiseResolver();
122
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
+ }
123
145
  }
124
146
  }
125
147
 
@@ -161,6 +183,7 @@ export class BulkAccountLoader {
161
183
  buffer: newBuffer,
162
184
  });
163
185
  this.handleAccountCallbacks(accountToLoad, newBuffer);
186
+ this.lastUpdate = Date.now();
164
187
  continue;
165
188
  }
166
189
 
@@ -175,6 +198,7 @@ export class BulkAccountLoader {
175
198
  buffer: newBuffer,
176
199
  });
177
200
  this.handleAccountCallbacks(accountToLoad, newBuffer);
201
+ this.lastUpdate = Date.now();
178
202
  }
179
203
  }
180
204
  }
@@ -195,6 +219,10 @@ export class BulkAccountLoader {
195
219
  return;
196
220
  }
197
221
 
222
+ if (this.loggingEnabled) {
223
+ console.log(`startPolling`);
224
+ }
225
+
198
226
  this.intervalId = setInterval(this.load.bind(this), this.pollingFrequency);
199
227
  }
200
228
 
@@ -202,6 +230,10 @@ export class BulkAccountLoader {
202
230
  if (this.intervalId) {
203
231
  clearInterval(this.intervalId);
204
232
  this.intervalId = undefined;
233
+
234
+ if (this.loggingEnabled) {
235
+ console.log(`stopPolling`);
236
+ }
205
237
  }
206
238
  }
207
239
  }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotSubscribedError = void 0;
4
+ class NotSubscribedError extends Error {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.name = 'NotSubscribedError';
8
+ }
9
+ }
10
+ exports.NotSubscribedError = NotSubscribedError;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.capitalize = void 0;
4
+ function capitalize(value) {
5
+ return value[0].toUpperCase() + value.slice(1);
6
+ }
7
+ exports.capitalize = capitalize;
@@ -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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.WebSocketAccountSubscriber = void 0;
13
+ const utils_1 = require("./utils");
14
+ class WebSocketAccountSubscriber {
15
+ constructor(accountName, program, accountPublicKey) {
16
+ this.accountName = accountName;
17
+ this.program = program;
18
+ this.accountPublicKey = accountPublicKey;
19
+ }
20
+ subscribe(onChange) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ if (this.listenerId) {
23
+ return;
24
+ }
25
+ this.onChange = onChange;
26
+ yield this.fetch();
27
+ this.listenerId = this.program.provider.connection.onAccountChange(this.accountPublicKey, (accountInfo, context) => {
28
+ this.handleRpcResponse(context, accountInfo);
29
+ }, this.program.provider.opts.commitment);
30
+ });
31
+ }
32
+ fetch() {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ const rpcResponse = yield this.program.provider.connection.getAccountInfoAndContext(this.accountPublicKey, this.program.provider.opts.commitment);
35
+ this.handleRpcResponse(rpcResponse.context, rpcResponse === null || rpcResponse === void 0 ? void 0 : rpcResponse.value);
36
+ });
37
+ }
38
+ handleRpcResponse(context, accountInfo) {
39
+ const newSlot = context.slot;
40
+ let newBuffer = undefined;
41
+ if (accountInfo) {
42
+ newBuffer = accountInfo.data;
43
+ }
44
+ if (!this.accountData) {
45
+ this.accountData = {
46
+ buffer: newBuffer,
47
+ slot: newSlot,
48
+ };
49
+ if (newBuffer) {
50
+ this.data = this.program.account[this.accountName].coder.accounts.decode(utils_1.capitalize(this.accountName), newBuffer);
51
+ this.onChange(this.data);
52
+ }
53
+ return;
54
+ }
55
+ if (newSlot <= this.accountData.slot) {
56
+ return;
57
+ }
58
+ const oldBuffer = this.accountData.buffer;
59
+ if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
60
+ this.accountData = {
61
+ buffer: newBuffer,
62
+ slot: newSlot,
63
+ };
64
+ this.data = this.program.account[this.accountName].coder.accounts.decode(utils_1.capitalize(this.accountName), newBuffer);
65
+ this.onChange(this.data);
66
+ }
67
+ }
68
+ unsubscribe() {
69
+ if (this.listenerId) {
70
+ const promise = this.program.provider.connection.removeAccountChangeListener(this.listenerId);
71
+ this.listenerId = undefined;
72
+ return promise;
73
+ }
74
+ }
75
+ }
76
+ exports.WebSocketAccountSubscriber = WebSocketAccountSubscriber;