@drift-labs/sdk 0.1.24 → 0.1.25-master.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.
Files changed (63) 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/pollingTokenAccountSubscriber.js +2 -2
  5. package/lib/accounts/pollingUserAccountSubscriber.js +4 -4
  6. package/lib/accounts/webSocketAccountSubscriber.js +2 -2
  7. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +1 -1
  8. package/lib/accounts/webSocketUserAccountSubscriber.js +2 -2
  9. package/lib/addresses.js +5 -1
  10. package/lib/admin.d.ts +1 -1
  11. package/lib/admin.js +15 -10
  12. package/lib/clearingHouse.js +26 -20
  13. package/lib/clearingHouseUser.js +18 -18
  14. package/lib/constants/markets.d.ts +4 -4
  15. package/lib/constants/markets.js +22 -0
  16. package/lib/constants/numericConstants.d.ts +1 -0
  17. package/lib/constants/numericConstants.js +2 -1
  18. package/lib/examples/makeTradeExample.js +6 -6
  19. package/lib/factory/oracleClient.d.ts +5 -0
  20. package/lib/factory/oracleClient.js +16 -0
  21. package/lib/idl/clearing_house.json +11 -1
  22. package/lib/idl/switchboard_v2.json +4663 -0
  23. package/lib/index.d.ts +4 -1
  24. package/lib/index.js +9 -2
  25. package/lib/math/amm.js +12 -12
  26. package/lib/math/conversion.js +1 -1
  27. package/lib/math/funding.d.ts +6 -6
  28. package/lib/math/funding.js +5 -17
  29. package/lib/math/market.js +2 -2
  30. package/lib/math/orders.js +9 -9
  31. package/lib/math/position.js +1 -1
  32. package/lib/math/trade.js +18 -18
  33. package/lib/mockUSDCFaucet.js +5 -1
  34. package/lib/oracles/pythClient.d.ts +14 -0
  35. package/lib/oracles/pythClient.js +53 -0
  36. package/lib/oracles/switchboardClient.d.ts +13 -0
  37. package/lib/oracles/switchboardClient.js +76 -0
  38. package/lib/oracles/types.d.ts +15 -0
  39. package/lib/oracles/types.js +2 -0
  40. package/lib/orderParams.d.ts +1 -1
  41. package/lib/orderParams.js +2 -2
  42. package/lib/orders.js +19 -19
  43. package/lib/tx/retryTxSender.js +1 -1
  44. package/lib/types.d.ts +1 -0
  45. package/package.json +2 -1
  46. package/src/accounts/bulkAccountLoader.ts +19 -0
  47. package/src/admin.ts +2 -0
  48. package/src/clearingHouse.ts +2 -0
  49. package/src/constants/markets.ts +26 -3
  50. package/src/constants/numericConstants.ts +1 -0
  51. package/src/factory/oracleClient.ts +22 -0
  52. package/src/idl/clearing_house.json +11 -1
  53. package/src/idl/switchboard_v2.json +4663 -0
  54. package/src/index.ts +4 -1
  55. package/src/math/funding.ts +9 -25
  56. package/src/oracles/pythClient.ts +49 -0
  57. package/src/oracles/switchboardClient.ts +87 -0
  58. package/src/oracles/types.ts +15 -0
  59. package/src/orderParams.ts +3 -2
  60. package/src/types.ts +1 -0
  61. package/lib/pythClient.d.ts +0 -7
  62. package/lib/pythClient.js +0 -25
  63. package/src/pythClient.ts +0 -15
package/src/index.ts CHANGED
@@ -2,7 +2,9 @@ import { BN } from '@project-serum/anchor';
2
2
  import { PublicKey } from '@solana/web3.js';
3
3
 
4
4
  export * from './mockUSDCFaucet';
5
- export * from './pythClient';
5
+ export * from './oracles/types';
6
+ export * from './oracles/pythClient';
7
+ export * from './oracles/switchboardClient';
6
8
  export * from './types';
7
9
  export * from './constants/markets';
8
10
  export * from './accounts/webSocketClearingHouseAccountSubscriber';
@@ -17,6 +19,7 @@ export * from './clearingHouseUser';
17
19
  export * from './clearingHouse';
18
20
  export * from './factory/clearingHouse';
19
21
  export * from './factory/clearingHouseUser';
22
+ export * from './factory/oracleClient';
20
23
  export * from './math/conversion';
21
24
  export * from './math/funding';
22
25
  export * from './math/insuranceFund';
@@ -1,5 +1,4 @@
1
1
  import { BN } from '@project-serum/anchor';
2
- import { PriceData } from '@pythnetwork/client';
3
2
  import {
4
3
  AMM_RESERVE_PRECISION,
5
4
  MARK_PRICE_PRECISION,
@@ -8,17 +7,18 @@ import {
8
7
  } from '../constants/numericConstants';
9
8
  import { Market } from '../types';
10
9
  import { calculateMarkPrice } from './market';
10
+ import { OraclePriceData } from '../oracles/types';
11
11
 
12
12
  /**
13
13
  *
14
14
  * @param market
15
- * @param pythClient
15
+ * @param oraclePriceData
16
16
  * @param periodAdjustment
17
17
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
18
18
  */
19
19
  export async function calculateAllEstimatedFundingRate(
20
20
  market: Market,
21
- oraclePriceData: PriceData,
21
+ oraclePriceData: OraclePriceData,
22
22
  periodAdjustment: BN = new BN(1)
23
23
  ): Promise<[BN, BN, BN, BN, BN]> {
24
24
  // periodAdjustment
@@ -65,26 +65,10 @@ export async function calculateAllEstimatedFundingRate(
65
65
  secondsInHour.sub(timeSinceLastOracleTwapUpdate)
66
66
  );
67
67
 
68
- // verify pyth input is positive for live update
69
- let oracleStablePriceNum = 0;
70
- let oracleInputCount = 0;
71
- if (oraclePriceData.price >= 0) {
72
- oracleStablePriceNum += oraclePriceData.price;
73
- oracleInputCount += 1;
74
- }
75
- if (oraclePriceData.previousPrice >= 0) {
76
- oracleStablePriceNum += oraclePriceData.previousPrice;
77
- oracleInputCount += 1;
78
- }
79
-
80
- oracleStablePriceNum = oracleStablePriceNum / oracleInputCount;
81
- const oraclePriceStableWithMantissa = new BN(
82
- oracleStablePriceNum * MARK_PRICE_PRECISION.toNumber()
83
- );
84
-
68
+ const oraclePrice = oraclePriceData.price;
85
69
  let oracleTwapWithMantissa = lastOracleTwapWithMantissa;
86
70
 
87
- const oracleLiveVsTwap = oraclePriceStableWithMantissa
71
+ const oracleLiveVsTwap = oraclePrice
88
72
  .sub(lastOracleTwapWithMantissa)
89
73
  .abs()
90
74
  .mul(MARK_PRICE_PRECISION)
@@ -95,7 +79,7 @@ export async function calculateAllEstimatedFundingRate(
95
79
  if (oracleLiveVsTwap.lte(MARK_PRICE_PRECISION.mul(new BN(10)))) {
96
80
  oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
97
81
  .mul(lastOracleTwapWithMantissa)
98
- .add(timeSinceLastMarkChange.mul(oraclePriceStableWithMantissa))
82
+ .add(timeSinceLastMarkChange.mul(oraclePrice))
99
83
  .div(timeSinceLastOracleTwapUpdate.add(oracleTwapTimeSinceLastUpdate));
100
84
  }
101
85
 
@@ -203,7 +187,7 @@ export async function calculateAllEstimatedFundingRate(
203
187
  */
204
188
  export async function calculateEstimatedFundingRate(
205
189
  market: Market,
206
- oraclePriceData: PriceData,
190
+ oraclePriceData: OraclePriceData,
207
191
  periodAdjustment: BN = new BN(1),
208
192
  estimationMethod: 'interpolated' | 'lowerbound' | 'capped'
209
193
  ): Promise<BN> {
@@ -233,7 +217,7 @@ export async function calculateEstimatedFundingRate(
233
217
  */
234
218
  export async function calculateLongShortFundingRate(
235
219
  market: Market,
236
- oraclePriceData: PriceData,
220
+ oraclePriceData: OraclePriceData,
237
221
  periodAdjustment: BN = new BN(1)
238
222
  ): Promise<[BN, BN]> {
239
223
  const [_1, _2, _, cappedAltEst, interpEst] =
@@ -261,7 +245,7 @@ export async function calculateLongShortFundingRate(
261
245
  */
262
246
  export async function calculateLongShortFundingRateAndLiveTwaps(
263
247
  market: Market,
264
- oraclePriceData: PriceData,
248
+ oraclePriceData: OraclePriceData,
265
249
  periodAdjustment: BN = new BN(1)
266
250
  ): Promise<[BN, BN, BN, BN]> {
267
251
  const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] =
@@ -0,0 +1,49 @@
1
+ import { parsePriceData, PriceData } from '@pythnetwork/client';
2
+ import { Connection, PublicKey } from '@solana/web3.js';
3
+ import { OraclePriceData } from './types';
4
+ import { BN } from '@project-serum/anchor';
5
+ import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
6
+
7
+ export class PythClient {
8
+ private connection: Connection;
9
+
10
+ public constructor(connection: Connection) {
11
+ this.connection = connection;
12
+ }
13
+
14
+ public async getPriceData(pricePublicKey: PublicKey): Promise<PriceData> {
15
+ const account = await this.connection.getAccountInfo(pricePublicKey);
16
+ return parsePriceData(account.data);
17
+ }
18
+
19
+ public async getOraclePriceData(
20
+ pricePublicKey: PublicKey
21
+ ): Promise<OraclePriceData> {
22
+ const accountInfo = await this.connection.getAccountInfo(pricePublicKey);
23
+ return this.getOraclePriceDataFromBuffer(accountInfo.data);
24
+ }
25
+
26
+ public async getOraclePriceDataFromBuffer(
27
+ buffer: Buffer
28
+ ): Promise<OraclePriceData> {
29
+ const priceData = parsePriceData(buffer);
30
+ return {
31
+ price: convertPythPrice(priceData.price, priceData.exponent),
32
+ slot: new BN(priceData.lastSlot.toString()),
33
+ confidence: convertPythPrice(priceData.confidence, priceData.exponent),
34
+ twap: convertPythPrice(priceData.twap.value, priceData.exponent),
35
+ twapConfidence: convertPythPrice(
36
+ priceData.twac.value,
37
+ priceData.exponent
38
+ ),
39
+ };
40
+ }
41
+ }
42
+
43
+ export function convertPythPrice(price: number, exponent: number): BN {
44
+ exponent = Math.abs(exponent);
45
+ const pythPrecision = TEN.pow(new BN(exponent).abs());
46
+ return new BN(price * Math.pow(10, exponent))
47
+ .mul(MARK_PRICE_PRECISION)
48
+ .div(pythPrecision);
49
+ }
@@ -0,0 +1,87 @@
1
+ import {
2
+ getSwitchboardPid,
3
+ SwitchboardDecimal,
4
+ } from '@switchboard-xyz/switchboard-v2';
5
+ import { Connection, Keypair, PublicKey } from '@solana/web3.js';
6
+ import { DriftEnv } from '../config';
7
+ import { BN, Provider, Program, Idl } from '@project-serum/anchor';
8
+ import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
9
+ import { OracleClient, OraclePriceData } from './types';
10
+ import { Wallet } from '../wallet';
11
+ import switchboardV2Idl from '../idl/switchboard_v2.json';
12
+
13
+ // cache switchboard program for every client object since itll always be the same
14
+ const programMap = new Map<string, Program>();
15
+
16
+ export class SwitchboardClient implements OracleClient {
17
+ connection: Connection;
18
+ env: DriftEnv;
19
+
20
+ public constructor(connection: Connection, env: DriftEnv) {
21
+ this.connection = connection;
22
+ this.env = env;
23
+ }
24
+
25
+ public async getOraclePriceData(
26
+ pricePublicKey: PublicKey
27
+ ): Promise<OraclePriceData> {
28
+ const accountInfo = await this.connection.getAccountInfo(pricePublicKey);
29
+ return this.getOraclePriceDataFromBuffer(accountInfo.data);
30
+ }
31
+
32
+ public async getOraclePriceDataFromBuffer(
33
+ buffer: Buffer
34
+ ): Promise<OraclePriceData> {
35
+ const program = await this.getProgram();
36
+
37
+ const aggregatorAccountData =
38
+ program.account.aggregatorAccountData.coder.accounts.decode(
39
+ 'AggregatorAccountData',
40
+ buffer
41
+ );
42
+ const price = convertSwitchboardDecimal(
43
+ aggregatorAccountData.latestConfirmedRound.result as SwitchboardDecimal
44
+ );
45
+
46
+ const confidence = convertSwitchboardDecimal(
47
+ aggregatorAccountData.latestConfirmedRound
48
+ .stdDeviation as SwitchboardDecimal
49
+ );
50
+
51
+ const slot: BN = aggregatorAccountData.latestConfirmedRound.roundOpenSlot;
52
+ return {
53
+ price,
54
+ slot,
55
+ confidence,
56
+ };
57
+ }
58
+
59
+ public async getProgram(): Promise<Program> {
60
+ if (programMap.has(this.env)) {
61
+ return programMap.get(this.env);
62
+ }
63
+
64
+ const program = await getSwitchboardProgram(this.env, this.connection);
65
+ programMap.set(this.env, program);
66
+ return program;
67
+ }
68
+ }
69
+
70
+ async function getSwitchboardProgram(
71
+ env: DriftEnv,
72
+ connection: Connection
73
+ ): Promise<Program> {
74
+ const DEFAULT_KEYPAIR = Keypair.fromSeed(new Uint8Array(32).fill(1));
75
+ const programId = getSwitchboardPid(env);
76
+ const wallet = new Wallet(DEFAULT_KEYPAIR);
77
+ const provider = new Provider(connection, wallet, {});
78
+
79
+ return new Program(switchboardV2Idl as Idl, programId, provider);
80
+ }
81
+
82
+ function convertSwitchboardDecimal(switchboardDecimal: SwitchboardDecimal): BN {
83
+ const switchboardPrecision = TEN.pow(new BN(switchboardDecimal.scale));
84
+ return switchboardDecimal.mantissa
85
+ .mul(MARK_PRICE_PRECISION)
86
+ .div(switchboardPrecision);
87
+ }
@@ -0,0 +1,15 @@
1
+ import { BN } from '@project-serum/anchor';
2
+ import { PublicKey } from '@solana/web3.js';
3
+
4
+ export type OraclePriceData = {
5
+ price: BN;
6
+ slot: BN;
7
+ confidence: BN;
8
+ twap?: BN;
9
+ twapConfidence?: BN;
10
+ };
11
+
12
+ export interface OracleClient {
13
+ getOraclePriceDataFromBuffer(buffer: Buffer): Promise<OraclePriceData>;
14
+ getOraclePriceData(publicKey: PublicKey): Promise<OraclePriceData>;
15
+ }
@@ -15,7 +15,8 @@ export function getLimitOrderParams(
15
15
  reduceOnly: boolean,
16
16
  discountToken = false,
17
17
  referrer = false,
18
- userOrderId = 0
18
+ userOrderId = 0,
19
+ postOnly = false
19
20
  ): OrderParams {
20
21
  return {
21
22
  orderType: OrderType.LIMIT,
@@ -26,7 +27,7 @@ export function getLimitOrderParams(
26
27
  baseAssetAmount,
27
28
  price,
28
29
  reduceOnly,
29
- postOnly: false,
30
+ postOnly,
30
31
  immediateOrCancel: false,
31
32
  positionLimit: ZERO,
32
33
  padding0: true,
package/src/types.ts CHANGED
@@ -217,6 +217,7 @@ export type OrderRecord = {
217
217
  fee: BN;
218
218
  fillerReward: BN;
219
219
  tradeRecordId: BN;
220
+ quoteAssetAmountSurplus: BN;
220
221
  };
221
222
 
222
223
  export type StateAccount = {
@@ -1,7 +0,0 @@
1
- import { PriceData } from '@pythnetwork/client';
2
- import { Connection, PublicKey } from '@solana/web3.js';
3
- export declare class PythClient {
4
- private connection;
5
- constructor(connection: Connection);
6
- getPriceData(pricePublicKey: PublicKey): Promise<PriceData>;
7
- }
package/lib/pythClient.js DELETED
@@ -1,25 +0,0 @@
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.PythClient = void 0;
13
- const client_1 = require("@pythnetwork/client");
14
- class PythClient {
15
- constructor(connection) {
16
- this.connection = connection;
17
- }
18
- getPriceData(pricePublicKey) {
19
- return __awaiter(this, void 0, void 0, function* () {
20
- const account = yield this.connection.getAccountInfo(pricePublicKey);
21
- return client_1.parsePriceData(account.data);
22
- });
23
- }
24
- }
25
- exports.PythClient = PythClient;
package/src/pythClient.ts DELETED
@@ -1,15 +0,0 @@
1
- import { parsePriceData, PriceData } from '@pythnetwork/client';
2
- import { Connection, PublicKey } from '@solana/web3.js';
3
-
4
- export class PythClient {
5
- private connection: Connection;
6
-
7
- public constructor(connection: Connection) {
8
- this.connection = connection;
9
- }
10
-
11
- public async getPriceData(pricePublicKey: PublicKey): Promise<PriceData> {
12
- const account = await this.connection.getAccountInfo(pricePublicKey);
13
- return parsePriceData(account.data);
14
- }
15
- }