@drift-labs/sdk 0.1.18-orders.1 → 0.1.18-orders.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +2 -1
  2. package/lib/accounts/bulkAccountLoader.d.ts +32 -0
  3. package/lib/accounts/bulkAccountLoader.js +156 -0
  4. package/lib/accounts/bulkUserSubscription.d.ts +7 -0
  5. package/lib/accounts/bulkUserSubscription.js +28 -0
  6. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +49 -0
  7. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +228 -0
  8. package/lib/accounts/pollingTokenAccountSubscriber.d.ts +25 -0
  9. package/lib/accounts/pollingTokenAccountSubscriber.js +79 -0
  10. package/lib/accounts/pollingUserAccountSubscriber.d.ts +32 -0
  11. package/lib/accounts/pollingUserAccountSubscriber.js +133 -0
  12. package/lib/accounts/types.d.ts +30 -25
  13. package/lib/accounts/utils.d.ts +1 -0
  14. package/lib/accounts/utils.js +7 -0
  15. package/lib/accounts/{defaultClearingHouseAccountSubscriber.d.ts → webSocketClearingHouseAccountSubscriber.d.ts} +6 -4
  16. package/lib/accounts/{defaultClearingHouseAccountSubscriber.js → webSocketClearingHouseAccountSubscriber.js} +5 -4
  17. package/lib/accounts/{defaultUserAccountSubscriber.d.ts → webSocketUserAccountSubscriber.d.ts} +3 -1
  18. package/lib/accounts/{defaultUserAccountSubscriber.js → webSocketUserAccountSubscriber.js} +10 -7
  19. package/lib/addresses.d.ts +2 -2
  20. package/lib/addresses.js +4 -4
  21. package/lib/admin.d.ts +3 -0
  22. package/lib/admin.js +61 -13
  23. package/lib/clearingHouse.d.ts +16 -4
  24. package/lib/clearingHouse.js +50 -10
  25. package/lib/clearingHouseUser.d.ts +9 -1
  26. package/lib/clearingHouseUser.js +19 -5
  27. package/lib/config.js +1 -1
  28. package/lib/constants/markets.js +16 -0
  29. package/lib/factory/clearingHouse.d.ts +25 -0
  30. package/lib/factory/clearingHouse.js +64 -0
  31. package/lib/factory/clearingHouseUser.d.ts +19 -0
  32. package/lib/factory/clearingHouseUser.js +34 -0
  33. package/lib/idl/clearing_house.json +360 -15
  34. package/lib/index.d.ts +9 -4
  35. package/lib/index.js +14 -5
  36. package/lib/math/funding.js +4 -1
  37. package/lib/math/utils.d.ts +2 -2
  38. package/lib/math/utils.js +6 -3
  39. package/lib/orderParams.d.ts +3 -3
  40. package/lib/orderParams.js +23 -3
  41. package/lib/token/index.d.ts +3 -0
  42. package/lib/token/index.js +38 -0
  43. package/lib/types.d.ts +13 -3
  44. package/package.json +3 -3
  45. package/src/accounts/bulkAccountLoader.ts +195 -0
  46. package/src/accounts/bulkUserSubscription.ts +28 -0
  47. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +326 -0
  48. package/src/accounts/pollingTokenAccountSubscriber.ts +99 -0
  49. package/src/accounts/pollingUserAccountSubscriber.ts +186 -0
  50. package/src/accounts/types.ts +35 -30
  51. package/src/accounts/utils.ts +3 -0
  52. package/src/accounts/{defaultClearingHouseAccountSubscriber.ts → webSocketClearingHouseAccountSubscriber.ts} +9 -6
  53. package/src/accounts/{defaultUserAccountSubscriber.ts → webSocketUserAccountSubscriber.ts} +10 -5
  54. package/src/addresses.ts +6 -4
  55. package/src/admin.ts +73 -20
  56. package/src/clearingHouse.ts +69 -25
  57. package/src/clearingHouseUser.ts +26 -6
  58. package/src/config.ts +1 -1
  59. package/src/constants/markets.ts +16 -0
  60. package/src/factory/clearingHouse.ts +125 -0
  61. package/src/factory/clearingHouseUser.ts +73 -0
  62. package/src/idl/clearing_house.json +360 -15
  63. package/src/index.ts +9 -4
  64. package/src/math/funding.ts +5 -1
  65. package/src/math/utils.ts +1 -1
  66. package/src/orderParams.ts +26 -3
  67. package/src/token/index.ts +37 -0
  68. package/src/types.ts +13 -3
  69. package/lib/accounts/defaultHistoryAccountSubscriber.d.ts +0 -28
  70. package/lib/accounts/defaultHistoryAccountSubscriber.js +0 -110
  71. package/src/accounts/defaultHistoryAccountSubscriber.ts +0 -176
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getMarketOrderParams = exports.getStopLimitOrderParams = exports.getStopOrderParams = 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) {
6
+ function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
7
7
  return {
8
8
  orderType: types_1.OrderType.LIMIT,
9
+ userOrderId,
9
10
  marketIndex,
10
11
  direction,
11
12
  quoteAssetAmount: numericConstants_1.ZERO,
@@ -14,18 +15,23 @@ function getLimitOrderParams(marketIndex, direction, baseAssetAmount, price, red
14
15
  reduceOnly,
15
16
  postOnly: false,
16
17
  immediateOrCancel: false,
18
+ positionLimit: numericConstants_1.ZERO,
19
+ padding0: true,
20
+ padding1: numericConstants_1.ZERO,
17
21
  optionalAccounts: {
18
22
  discountToken,
19
23
  referrer,
20
24
  },
21
25
  triggerCondition: types_1.OrderTriggerCondition.ABOVE,
22
26
  triggerPrice: numericConstants_1.ZERO,
27
+ oraclePriceOffset: numericConstants_1.ZERO,
23
28
  };
24
29
  }
25
30
  exports.getLimitOrderParams = getLimitOrderParams;
26
- function getStopOrderParams(marketIndex, direction, baseAssetAmount, triggerPrice, triggerCondition, reduceOnly, discountToken = false, referrer = false) {
31
+ function getStopOrderParams(marketIndex, direction, baseAssetAmount, triggerPrice, triggerCondition, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
27
32
  return {
28
33
  orderType: types_1.OrderType.STOP,
34
+ userOrderId,
29
35
  marketIndex,
30
36
  direction,
31
37
  quoteAssetAmount: numericConstants_1.ZERO,
@@ -34,18 +40,23 @@ function getStopOrderParams(marketIndex, direction, baseAssetAmount, triggerPric
34
40
  reduceOnly,
35
41
  postOnly: false,
36
42
  immediateOrCancel: false,
43
+ positionLimit: numericConstants_1.ZERO,
44
+ padding0: true,
45
+ padding1: numericConstants_1.ZERO,
37
46
  optionalAccounts: {
38
47
  discountToken,
39
48
  referrer,
40
49
  },
41
50
  triggerCondition,
42
51
  triggerPrice,
52
+ oraclePriceOffset: numericConstants_1.ZERO,
43
53
  };
44
54
  }
45
55
  exports.getStopOrderParams = getStopOrderParams;
46
- function getStopLimitOrderParams(marketIndex, direction, baseAssetAmount, price, triggerPrice, triggerCondition, reduceOnly, discountToken = false, referrer = false) {
56
+ function getStopLimitOrderParams(marketIndex, direction, baseAssetAmount, price, triggerPrice, triggerCondition, reduceOnly, discountToken = false, referrer = false, userOrderId = 0) {
47
57
  return {
48
58
  orderType: types_1.OrderType.STOP_LIMIT,
59
+ userOrderId,
49
60
  marketIndex,
50
61
  direction,
51
62
  quoteAssetAmount: numericConstants_1.ZERO,
@@ -54,12 +65,16 @@ function getStopLimitOrderParams(marketIndex, direction, baseAssetAmount, price,
54
65
  reduceOnly,
55
66
  postOnly: false,
56
67
  immediateOrCancel: false,
68
+ positionLimit: numericConstants_1.ZERO,
69
+ padding0: true,
70
+ padding1: numericConstants_1.ZERO,
57
71
  optionalAccounts: {
58
72
  discountToken,
59
73
  referrer,
60
74
  },
61
75
  triggerCondition,
62
76
  triggerPrice,
77
+ oraclePriceOffset: numericConstants_1.ZERO,
63
78
  };
64
79
  }
65
80
  exports.getStopLimitOrderParams = getStopLimitOrderParams;
@@ -69,6 +84,7 @@ function getMarketOrderParams(marketIndex, direction, quoteAssetAmount, baseAsse
69
84
  }
70
85
  return {
71
86
  orderType: types_1.OrderType.MARKET,
87
+ userOrderId: 0,
72
88
  marketIndex,
73
89
  direction,
74
90
  quoteAssetAmount,
@@ -77,12 +93,16 @@ function getMarketOrderParams(marketIndex, direction, quoteAssetAmount, baseAsse
77
93
  reduceOnly,
78
94
  postOnly: false,
79
95
  immediateOrCancel: false,
96
+ positionLimit: numericConstants_1.ZERO,
97
+ padding0: true,
98
+ padding1: numericConstants_1.ZERO,
80
99
  optionalAccounts: {
81
100
  discountToken,
82
101
  referrer,
83
102
  },
84
103
  triggerCondition: types_1.OrderTriggerCondition.ABOVE,
85
104
  triggerPrice: numericConstants_1.ZERO,
105
+ oraclePriceOffset: numericConstants_1.ZERO,
86
106
  };
87
107
  }
88
108
  exports.getMarketOrderParams = getMarketOrderParams;
@@ -0,0 +1,3 @@
1
+ /// <reference types="node" />
2
+ import { AccountInfo } from '@solana/spl-token';
3
+ export declare function parseTokenAccount(data: Buffer): AccountInfo;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTokenAccount = void 0;
4
+ const spl_token_1 = require("@solana/spl-token");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ function parseTokenAccount(data) {
7
+ const accountInfo = spl_token_1.AccountLayout.decode(data);
8
+ accountInfo.mint = new web3_js_1.PublicKey(accountInfo.mint);
9
+ accountInfo.owner = new web3_js_1.PublicKey(accountInfo.owner);
10
+ accountInfo.amount = spl_token_1.u64.fromBuffer(accountInfo.amount);
11
+ if (accountInfo.delegateOption === 0) {
12
+ accountInfo.delegate = null;
13
+ // eslint-disable-next-line new-cap
14
+ accountInfo.delegatedAmount = new spl_token_1.u64(0);
15
+ }
16
+ else {
17
+ accountInfo.delegate = new web3_js_1.PublicKey(accountInfo.delegate);
18
+ accountInfo.delegatedAmount = spl_token_1.u64.fromBuffer(accountInfo.delegatedAmount);
19
+ }
20
+ accountInfo.isInitialized = accountInfo.state !== 0;
21
+ accountInfo.isFrozen = accountInfo.state === 2;
22
+ if (accountInfo.isNativeOption === 1) {
23
+ accountInfo.rentExemptReserve = spl_token_1.u64.fromBuffer(accountInfo.isNative);
24
+ accountInfo.isNative = true;
25
+ }
26
+ else {
27
+ accountInfo.rentExemptReserve = null;
28
+ accountInfo.isNative = false;
29
+ }
30
+ if (accountInfo.closeAuthorityOption === 0) {
31
+ accountInfo.closeAuthority = null;
32
+ }
33
+ else {
34
+ accountInfo.closeAuthority = new web3_js_1.PublicKey(accountInfo.closeAuthority);
35
+ }
36
+ return accountInfo;
37
+ }
38
+ exports.parseTokenAccount = parseTokenAccount;
package/lib/types.d.ts CHANGED
@@ -97,9 +97,9 @@ export declare type DepositHistoryAccount = {
97
97
  head: BN;
98
98
  depositRecords: DepositRecord[];
99
99
  };
100
- export declare type CurveHistoryAccount = {
100
+ export declare type ExtendedCurveHistoryAccount = {
101
101
  head: BN;
102
- curveRecords: CurveRecord[];
102
+ curveRecords: ExtendedCurveRecord[];
103
103
  };
104
104
  export declare type FundingRateHistoryAccount = {
105
105
  head: BN;
@@ -131,7 +131,7 @@ export declare type DepositRecord = {
131
131
  cumulativeDepositsBefore: BN;
132
132
  amount: BN;
133
133
  };
134
- export declare type CurveRecord = {
134
+ export declare type ExtendedCurveRecord = {
135
135
  ts: BN;
136
136
  recordId: BN;
137
137
  marketIndex: BN;
@@ -147,6 +147,8 @@ export declare type CurveRecord = {
147
147
  baseAssetAmountShort: BN;
148
148
  baseAssetAmount: BN;
149
149
  openInterest: BN;
150
+ oraclePrice: BN;
151
+ tradeId: BN;
150
152
  };
151
153
  export declare type TradeRecord = {
152
154
  ts: BN;
@@ -261,6 +263,7 @@ export declare type StateAccount = {
261
263
  oracleGuardRails: OracleGuardRails;
262
264
  maxDeposit: BN;
263
265
  orderState: PublicKey;
266
+ extendedCurveHistory: PublicKey;
264
267
  };
265
268
  export declare type OrderStateAccount = {
266
269
  orderHistory: PublicKey;
@@ -303,6 +306,7 @@ export declare type AMM = {
303
306
  totalFee: BN;
304
307
  minimumQuoteAssetTradeSize: BN;
305
308
  minimumBaseAssetTradeSize: BN;
309
+ lastOraclePrice: BN;
306
310
  };
307
311
  export declare type UserPosition = {
308
312
  baseAssetAmount: BN;
@@ -334,6 +338,7 @@ export declare type Order = {
334
338
  orderType: OrderType;
335
339
  ts: BN;
336
340
  orderId: BN;
341
+ userOrderId: number;
337
342
  marketIndex: BN;
338
343
  price: BN;
339
344
  baseAssetAmount: BN;
@@ -352,6 +357,7 @@ export declare type Order = {
352
357
  };
353
358
  export declare type OrderParams = {
354
359
  orderType: OrderType;
360
+ userOrderId: number;
355
361
  direction: PositionDirection;
356
362
  quoteAssetAmount: BN;
357
363
  baseAssetAmount: BN;
@@ -362,6 +368,10 @@ export declare type OrderParams = {
362
368
  immediateOrCancel: boolean;
363
369
  triggerPrice: BN;
364
370
  triggerCondition: OrderTriggerCondition;
371
+ positionLimit: BN;
372
+ oraclePriceOffset: BN;
373
+ padding0: boolean;
374
+ padding1: BN;
365
375
  optionalAccounts: {
366
376
  discountToken: boolean;
367
377
  referrer: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.1.18-orders.1",
3
+ "version": "0.1.18-orders.2",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -31,8 +31,8 @@
31
31
  "@pythnetwork/client": "^2.5.1",
32
32
  "@solana/spl-token": "^0.1.6",
33
33
  "@solana/web3.js": "^1.22.0",
34
- "@types/bn.js": "^5.1.0",
35
- "strict-event-emitter-types": "^2.0.0"
34
+ "strict-event-emitter-types": "^2.0.0",
35
+ "uuid": "^8.3.2"
36
36
  },
37
37
  "description": "SDK for Drift Protocol v1",
38
38
  "engines": {
@@ -0,0 +1,195 @@
1
+ import { Commitment, Connection, PublicKey } from '@solana/web3.js';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+
4
+ type AccountToLoad = {
5
+ publicKey: PublicKey;
6
+ callbacks: Map<string, (buffer: Buffer) => void>;
7
+ };
8
+
9
+ type AccountData = {
10
+ slot: number;
11
+ buffer: Buffer | undefined;
12
+ };
13
+
14
+ const GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = 99;
15
+
16
+ export class BulkAccountLoader {
17
+ connection: Connection;
18
+ commitment: Commitment;
19
+ pollingFrequency: number;
20
+ accountsToLoad = new Map<string, AccountToLoad>();
21
+ accountData = new Map<string, AccountData>();
22
+ errorCallbacks = new Map<string, (e) => void>();
23
+ intervalId?: NodeJS.Timer;
24
+
25
+ public constructor(
26
+ connection: Connection,
27
+ commitment: Commitment,
28
+ pollingFrequency: number
29
+ ) {
30
+ this.connection = connection;
31
+ this.commitment = commitment;
32
+ this.pollingFrequency = pollingFrequency;
33
+ }
34
+
35
+ public addAccount(
36
+ publicKey: PublicKey,
37
+ callback: (buffer: Buffer) => void
38
+ ): string {
39
+ const existingSize = this.accountsToLoad.size;
40
+
41
+ const callbackId = uuidv4();
42
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
43
+ if (existingAccountToLoad) {
44
+ existingAccountToLoad.callbacks.set(callbackId, callback);
45
+ } else {
46
+ const callbacks = new Map<string, (buffer: Buffer) => void>();
47
+ callbacks.set(callbackId, callback);
48
+ const newAccountToLoad = {
49
+ publicKey,
50
+ callbacks,
51
+ };
52
+ this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
53
+ }
54
+
55
+ if (existingSize === 0) {
56
+ this.startPolling();
57
+ }
58
+
59
+ return callbackId;
60
+ }
61
+
62
+ public removeAccount(publicKey: PublicKey, callbackId: string): void {
63
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
64
+ if (existingAccountToLoad) {
65
+ existingAccountToLoad.callbacks.delete(callbackId);
66
+ if (existingAccountToLoad.callbacks.size === 0) {
67
+ this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString());
68
+ }
69
+ }
70
+
71
+ if (this.accountsToLoad.size === 0) {
72
+ this.stopPolling();
73
+ }
74
+ }
75
+
76
+ public addErrorCallbacks(callback: (error: Error) => void): string {
77
+ const callbackId = uuidv4();
78
+ this.errorCallbacks.set(callbackId, callback);
79
+ return callbackId;
80
+ }
81
+
82
+ public removeErrorCallbacks(callbackId: string): void {
83
+ this.errorCallbacks.delete(callbackId);
84
+ }
85
+
86
+ chunks<T>(array: readonly T[], size: number): T[][] {
87
+ return new Array(Math.ceil(array.length / size))
88
+ .fill(null)
89
+ .map((_, index) => index * size)
90
+ .map((begin) => array.slice(begin, begin + size));
91
+ }
92
+
93
+ public async load(): Promise<void> {
94
+ const chunks = this.chunks(
95
+ Array.from(this.accountsToLoad.values()),
96
+ GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE
97
+ );
98
+
99
+ await Promise.all(
100
+ chunks.map((chunk) => {
101
+ return this.loadChunk(chunk);
102
+ })
103
+ );
104
+ }
105
+
106
+ async loadChunk(accountsToLoad: AccountToLoad[]): Promise<void> {
107
+ if (accountsToLoad.length === 0) {
108
+ return;
109
+ }
110
+
111
+ const args = [
112
+ accountsToLoad.map((accountToLoad) => {
113
+ return accountToLoad.publicKey.toBase58();
114
+ }),
115
+ { commitment: this.commitment },
116
+ ];
117
+
118
+ let rpcResponse;
119
+ try {
120
+ // @ts-ignore
121
+ rpcResponse = await this.connection._rpcRequest(
122
+ 'getMultipleAccounts',
123
+ args
124
+ );
125
+ } catch (e) {
126
+ for (const [_, callback] of this.errorCallbacks) {
127
+ callback(e);
128
+ }
129
+ return;
130
+ }
131
+
132
+ const newSlot = rpcResponse.result.context.slot;
133
+
134
+ for (const i in accountsToLoad) {
135
+ const accountToLoad = accountsToLoad[i];
136
+ const key = accountToLoad.publicKey.toString();
137
+ const oldRPCResponse = this.accountData.get(key);
138
+
139
+ let newBuffer: Buffer | undefined = undefined;
140
+ if (rpcResponse.result.value[i]) {
141
+ const raw: string = rpcResponse.result.value[i].data[0];
142
+ const dataType = rpcResponse.result.value[i].data[1];
143
+ newBuffer = Buffer.from(raw, dataType);
144
+ }
145
+
146
+ if (!oldRPCResponse) {
147
+ this.accountData.set(key, {
148
+ slot: newSlot,
149
+ buffer: newBuffer,
150
+ });
151
+ this.handleAccountCallbacks(accountToLoad, newBuffer);
152
+ continue;
153
+ }
154
+
155
+ if (newSlot <= oldRPCResponse.slot) {
156
+ continue;
157
+ }
158
+
159
+ const oldBuffer = oldRPCResponse.buffer;
160
+ if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
161
+ this.accountData.set(key, {
162
+ slot: newSlot,
163
+ buffer: newBuffer,
164
+ });
165
+ this.handleAccountCallbacks(accountToLoad, newBuffer);
166
+ }
167
+ }
168
+ }
169
+
170
+ handleAccountCallbacks(accountToLoad: AccountToLoad, buffer: Buffer): void {
171
+ for (const [_, callback] of accountToLoad.callbacks) {
172
+ callback(buffer);
173
+ }
174
+ }
175
+
176
+ public getAccountData(publicKey: PublicKey): Buffer | undefined {
177
+ const accountData = this.accountData.get(publicKey.toString());
178
+ return accountData?.buffer;
179
+ }
180
+
181
+ public startPolling(): void {
182
+ if (this.intervalId) {
183
+ return;
184
+ }
185
+
186
+ this.intervalId = setInterval(this.load.bind(this), this.pollingFrequency);
187
+ }
188
+
189
+ public stopPolling(): void {
190
+ if (this.intervalId) {
191
+ clearInterval(this.intervalId);
192
+ this.intervalId = undefined;
193
+ }
194
+ }
195
+ }
@@ -0,0 +1,28 @@
1
+ import { ClearingHouseUser } from '../clearingHouseUser';
2
+ import { BulkAccountLoader } from './bulkAccountLoader';
3
+ import { PollingUserAccountSubscriber } from './pollingUserAccountSubscriber';
4
+
5
+ /**
6
+ * @param users
7
+ * @param accountLoader
8
+ */
9
+ export async function bulkPollingUserSubscribe(
10
+ users: ClearingHouseUser[],
11
+ accountLoader: BulkAccountLoader
12
+ ): Promise<void> {
13
+ await Promise.all(
14
+ users.map((user) => {
15
+ return (
16
+ user.accountSubscriber as PollingUserAccountSubscriber
17
+ ).addToAccountLoader();
18
+ })
19
+ );
20
+
21
+ await accountLoader.load();
22
+
23
+ await Promise.all(
24
+ users.map(async (user) => {
25
+ return user.subscribe();
26
+ })
27
+ );
28
+ }