@drift-labs/sdk 0.1.18-orders.0 → 0.1.18-orders.4

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 (93) hide show
  1. package/README.md +2 -1
  2. package/lib/accounts/bulkAccountLoader.d.ts +31 -0
  3. package/lib/accounts/bulkAccountLoader.js +175 -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 +34 -25
  13. package/lib/accounts/utils.d.ts +1 -0
  14. package/lib/accounts/utils.js +7 -0
  15. package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -2
  16. package/lib/accounts/webSocketAccountSubscriber.js +43 -12
  17. package/lib/accounts/{defaultClearingHouseAccountSubscriber.d.ts → webSocketClearingHouseAccountSubscriber.d.ts} +6 -4
  18. package/lib/accounts/{defaultClearingHouseAccountSubscriber.js → webSocketClearingHouseAccountSubscriber.js} +5 -4
  19. package/lib/accounts/{defaultUserAccountSubscriber.d.ts → webSocketUserAccountSubscriber.d.ts} +3 -1
  20. package/lib/accounts/{defaultUserAccountSubscriber.js → webSocketUserAccountSubscriber.js} +10 -7
  21. package/lib/addresses.d.ts +2 -2
  22. package/lib/addresses.js +4 -4
  23. package/lib/admin.d.ts +3 -0
  24. package/lib/admin.js +61 -13
  25. package/lib/clearingHouse.d.ts +20 -4
  26. package/lib/clearingHouse.js +90 -10
  27. package/lib/clearingHouseUser.d.ts +12 -4
  28. package/lib/clearingHouseUser.js +35 -25
  29. package/lib/config.js +1 -1
  30. package/lib/constants/markets.d.ts +2 -1
  31. package/lib/constants/markets.js +35 -14
  32. package/lib/constants/numericConstants.d.ts +3 -1
  33. package/lib/constants/numericConstants.js +15 -17
  34. package/lib/examples/makeTradeExample.js +1 -1
  35. package/lib/factory/clearingHouse.d.ts +25 -0
  36. package/lib/factory/clearingHouse.js +64 -0
  37. package/lib/factory/clearingHouseUser.d.ts +19 -0
  38. package/lib/factory/clearingHouseUser.js +34 -0
  39. package/lib/idl/clearing_house.json +366 -17
  40. package/lib/index.d.ts +9 -3
  41. package/lib/index.js +10 -3
  42. package/lib/math/conversion.d.ts +1 -1
  43. package/lib/math/funding.js +4 -1
  44. package/lib/math/insuranceFund.d.ts +2 -1
  45. package/lib/math/insuranceFund.js +3 -6
  46. package/lib/math/position.d.ts +2 -1
  47. package/lib/math/position.js +2 -5
  48. package/lib/math/utils.d.ts +2 -1
  49. package/lib/math/utils.js +3 -3
  50. package/lib/mockUSDCFaucet.d.ts +2 -1
  51. package/lib/orderParams.d.ts +3 -3
  52. package/lib/orderParams.js +28 -8
  53. package/lib/orders.d.ts +2 -1
  54. package/lib/token/index.d.ts +3 -0
  55. package/lib/token/index.js +38 -0
  56. package/lib/types.d.ts +20 -8
  57. package/lib/types.js +2 -2
  58. package/package.json +11 -3
  59. package/src/accounts/bulkAccountLoader.ts +215 -0
  60. package/src/accounts/bulkUserSubscription.ts +28 -0
  61. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +326 -0
  62. package/src/accounts/pollingTokenAccountSubscriber.ts +99 -0
  63. package/src/accounts/pollingUserAccountSubscriber.ts +186 -0
  64. package/src/accounts/types.ts +40 -30
  65. package/src/accounts/utils.ts +3 -0
  66. package/src/accounts/webSocketAccountSubscriber.ts +67 -17
  67. package/src/accounts/{defaultClearingHouseAccountSubscriber.ts → webSocketClearingHouseAccountSubscriber.ts} +9 -6
  68. package/src/accounts/{defaultUserAccountSubscriber.ts → webSocketUserAccountSubscriber.ts} +10 -5
  69. package/src/addresses.ts +6 -4
  70. package/src/admin.ts +73 -20
  71. package/src/clearingHouse.ts +125 -25
  72. package/src/clearingHouseUser.ts +28 -8
  73. package/src/config.ts +1 -1
  74. package/src/constants/markets.ts +25 -1
  75. package/src/constants/numericConstants.ts +2 -1
  76. package/src/examples/makeTradeExample.ts +4 -1
  77. package/src/factory/clearingHouse.ts +125 -0
  78. package/src/factory/clearingHouseUser.ts +73 -0
  79. package/src/idl/clearing_house.json +366 -17
  80. package/src/index.ts +9 -3
  81. package/src/math/conversion.ts +1 -1
  82. package/src/math/funding.ts +5 -1
  83. package/src/math/insuranceFund.ts +1 -1
  84. package/src/math/position.ts +1 -1
  85. package/src/math/utils.ts +1 -1
  86. package/src/mockUSDCFaucet.ts +1 -1
  87. package/src/orderParams.ts +30 -7
  88. package/src/orders.ts +1 -1
  89. package/src/token/index.ts +37 -0
  90. package/src/types.ts +17 -6
  91. package/lib/accounts/defaultHistoryAccountSubscriber.d.ts +0 -28
  92. package/lib/accounts/defaultHistoryAccountSubscriber.js +0 -110
  93. package/src/accounts/defaultHistoryAccountSubscriber.ts +0 -176
@@ -0,0 +1,186 @@
1
+ import {
2
+ AccountToPoll,
3
+ NotSubscribedError,
4
+ UserAccountEvents,
5
+ UserAccountSubscriber,
6
+ } from './types';
7
+ import { Program } from '@project-serum/anchor';
8
+ import StrictEventEmitter from 'strict-event-emitter-types';
9
+ import { EventEmitter } from 'events';
10
+ import { PublicKey } from '@solana/web3.js';
11
+ import {
12
+ getUserAccountPublicKey,
13
+ getUserOrdersAccountPublicKey,
14
+ } from '../addresses';
15
+ import { UserAccount, UserOrdersAccount, UserPositionsAccount } from '../types';
16
+ import { BulkAccountLoader } from './bulkAccountLoader';
17
+ import { capitalize } from './utils';
18
+ import { ClearingHouseConfigType } from '../factory/clearingHouse';
19
+
20
+ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
21
+ isSubscribed: boolean;
22
+ program: Program;
23
+ eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
24
+ authority: PublicKey;
25
+
26
+ accountLoader: BulkAccountLoader;
27
+ accountsToPoll = new Map<string, AccountToPoll>();
28
+ errorCallbackId?: string;
29
+
30
+ user?: UserAccount;
31
+ userPositions?: UserPositionsAccount;
32
+ userOrders?: UserOrdersAccount;
33
+
34
+ type: ClearingHouseConfigType = 'polling';
35
+
36
+ public constructor(
37
+ program: Program,
38
+ authority: PublicKey,
39
+ accountLoader: BulkAccountLoader
40
+ ) {
41
+ this.isSubscribed = false;
42
+ this.program = program;
43
+ this.authority = authority;
44
+ this.accountLoader = accountLoader;
45
+ this.eventEmitter = new EventEmitter();
46
+ }
47
+
48
+ async subscribe(): Promise<boolean> {
49
+ if (this.isSubscribed) {
50
+ return true;
51
+ }
52
+
53
+ await this.addToAccountLoader();
54
+ await this.fetchIfUnloaded();
55
+ this.eventEmitter.emit('update');
56
+
57
+ this.isSubscribed = true;
58
+ return true;
59
+ }
60
+
61
+ async addToAccountLoader(): Promise<void> {
62
+ if (this.accountsToPoll.size > 0) {
63
+ return;
64
+ }
65
+
66
+ const userPublicKey = await getUserAccountPublicKey(
67
+ this.program.programId,
68
+ this.authority
69
+ );
70
+
71
+ const userAccount = (await this.program.account.user.fetch(
72
+ userPublicKey
73
+ )) as UserAccount;
74
+
75
+ this.accountsToPoll.set(userPublicKey.toString(), {
76
+ key: 'user',
77
+ publicKey: userPublicKey,
78
+ eventType: 'userAccountData',
79
+ });
80
+
81
+ this.accountsToPoll.set(userAccount.positions.toString(), {
82
+ key: 'userPositions',
83
+ publicKey: userAccount.positions,
84
+ eventType: 'userPositionsData',
85
+ });
86
+
87
+ const userOrdersPublicKey = await getUserOrdersAccountPublicKey(
88
+ this.program.programId,
89
+ userPublicKey
90
+ );
91
+
92
+ this.accountsToPoll.set(userOrdersPublicKey.toString(), {
93
+ key: 'userOrders',
94
+ publicKey: userOrdersPublicKey,
95
+ eventType: 'userOrdersData',
96
+ });
97
+
98
+ for (const [_, accountToPoll] of this.accountsToPoll) {
99
+ accountToPoll.callbackId = this.accountLoader.addAccount(
100
+ accountToPoll.publicKey,
101
+ (buffer) => {
102
+ const account = this.program.account[
103
+ accountToPoll.key
104
+ ].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
105
+ this[accountToPoll.key] = account;
106
+ // @ts-ignore
107
+ this.eventEmitter.emit(accountToPoll.eventType, account);
108
+ this.eventEmitter.emit('update');
109
+ }
110
+ );
111
+ }
112
+
113
+ this.errorCallbackId = this.accountLoader.addErrorCallbacks((error) => {
114
+ this.eventEmitter.emit('error', error);
115
+ });
116
+ }
117
+
118
+ async fetchIfUnloaded(): Promise<void> {
119
+ let shouldFetch = false;
120
+ for (const [_, accountToPoll] of this.accountsToPoll) {
121
+ if (this[accountToPoll.key] === undefined) {
122
+ shouldFetch = true;
123
+ break;
124
+ }
125
+ }
126
+
127
+ if (shouldFetch) {
128
+ await this.fetch();
129
+ }
130
+ }
131
+
132
+ async fetch(): Promise<void> {
133
+ await this.accountLoader.load();
134
+ for (const [_, accountToPoll] of this.accountsToPoll) {
135
+ const buffer = this.accountLoader.getAccountData(accountToPoll.publicKey);
136
+ if (buffer) {
137
+ this[accountToPoll.key] = this.program.account[
138
+ accountToPoll.key
139
+ ].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
140
+ }
141
+ }
142
+ }
143
+
144
+ async unsubscribe(): Promise<void> {
145
+ if (!this.isSubscribed) {
146
+ return;
147
+ }
148
+
149
+ for (const [_, accountToPoll] of this.accountsToPoll) {
150
+ this.accountLoader.removeAccount(
151
+ accountToPoll.publicKey,
152
+ accountToPoll.callbackId
153
+ );
154
+ }
155
+
156
+ this.accountLoader.removeErrorCallbacks(this.errorCallbackId);
157
+ this.errorCallbackId = undefined;
158
+
159
+ this.accountsToPoll.clear();
160
+
161
+ this.isSubscribed = false;
162
+ }
163
+
164
+ assertIsSubscribed(): void {
165
+ if (!this.isSubscribed) {
166
+ throw new NotSubscribedError(
167
+ 'You must call `subscribe` before using this function'
168
+ );
169
+ }
170
+ }
171
+
172
+ public getUserAccount(): UserAccount {
173
+ this.assertIsSubscribed();
174
+ return this.user;
175
+ }
176
+
177
+ public getUserPositionsAccount(): UserPositionsAccount {
178
+ this.assertIsSubscribed();
179
+ return this.userPositions;
180
+ }
181
+
182
+ public getUserOrdersAccount(): UserOrdersAccount {
183
+ this.assertIsSubscribed();
184
+ return this.userOrders;
185
+ }
186
+ }
@@ -1,6 +1,6 @@
1
1
  import {
2
- CurveHistoryAccount,
3
2
  DepositHistoryAccount,
3
+ ExtendedCurveHistoryAccount,
4
4
  FundingPaymentHistoryAccount,
5
5
  FundingRateHistoryAccount,
6
6
  LiquidationHistoryAccount,
@@ -15,12 +15,15 @@ import {
15
15
  } from '../types';
16
16
  import StrictEventEmitter from 'strict-event-emitter-types';
17
17
  import { EventEmitter } from 'events';
18
+ import { PublicKey } from '@solana/web3.js';
19
+ import { AccountInfo } from '@solana/spl-token';
20
+ import { ClearingHouseConfigType, ClearingHouseUserConfigType } from '..';
18
21
 
19
22
  export interface AccountSubscriber<T> {
20
23
  data?: T;
21
24
  subscribe(onChange: (data: T) => void): Promise<void>;
22
25
  fetch(): Promise<void>;
23
- unsubscribe(): void;
26
+ unsubscribe(): Promise<void>;
24
27
  }
25
28
 
26
29
  export class NotSubscribedError extends Error {
@@ -37,10 +40,11 @@ export interface ClearingHouseAccountEvents {
37
40
  tradeHistoryAccountUpdate: (payload: TradeHistoryAccount) => void;
38
41
  liquidationHistoryAccountUpdate: (payload: LiquidationHistoryAccount) => void;
39
42
  depositHistoryAccountUpdate: (payload: DepositHistoryAccount) => void;
40
- curveHistoryAccountUpdate: (payload: CurveHistoryAccount) => void;
43
+ curveHistoryAccountUpdate: (payload: ExtendedCurveHistoryAccount) => void;
41
44
  orderHistoryAccountUpdate: (payload: OrderHistoryAccount) => void;
42
45
  orderStateAccountUpdate: (payload: OrderStateAccount) => void;
43
46
  update: void;
47
+ error: (e: Error) => void;
44
48
  }
45
49
 
46
50
  export type ClearingHouseAccountTypes =
@@ -70,37 +74,12 @@ export interface ClearingHouseAccountSubscriber {
70
74
  getDepositHistoryAccount(): DepositHistoryAccount;
71
75
  getFundingPaymentHistoryAccount(): FundingPaymentHistoryAccount;
72
76
  getFundingRateHistoryAccount(): FundingRateHistoryAccount;
73
- getCurveHistoryAccount(): CurveHistoryAccount;
77
+ getCurveHistoryAccount(): ExtendedCurveHistoryAccount;
74
78
  getLiquidationHistoryAccount(): LiquidationHistoryAccount;
75
79
  getOrderStateAccount(): OrderStateAccount;
76
80
  getOrderHistoryAccount(): OrderHistoryAccount;
77
- }
78
-
79
- export interface HistoryAccountEvents {
80
- fundingPaymentHistoryAccountUpdate: (
81
- payload: FundingPaymentHistoryAccount
82
- ) => void;
83
- fundingRateHistoryAccountUpdate: (payload: FundingRateHistoryAccount) => void;
84
- tradeHistoryAccountUpdate: (payload: TradeHistoryAccount) => void;
85
- liquidationHistoryAccountUpdate: (payload: LiquidationHistoryAccount) => void;
86
- depositHistoryAccountUpdate: (payload: DepositHistoryAccount) => void;
87
- curveHistoryAccountUpdate: (payload: CurveHistoryAccount) => void;
88
- update: void;
89
- }
90
-
91
- export interface HistoryAccountSubscriber {
92
- eventEmitter: StrictEventEmitter<EventEmitter, HistoryAccountEvents>;
93
- isSubscribed: boolean;
94
-
95
- subscribe(): Promise<boolean>;
96
- unsubscribe(): Promise<void>;
97
81
 
98
- getTradeHistoryAccount(): TradeHistoryAccount;
99
- getDepositHistoryAccount(): DepositHistoryAccount;
100
- getFundingPaymentHistoryAccount(): FundingPaymentHistoryAccount;
101
- getFundingRateHistoryAccount(): FundingRateHistoryAccount;
102
- getCurveHistoryAccount(): CurveHistoryAccount;
103
- getLiquidationHistoryAccount(): LiquidationHistoryAccount;
82
+ type: ClearingHouseConfigType;
104
83
  }
105
84
 
106
85
  export interface UserAccountEvents {
@@ -108,6 +87,7 @@ export interface UserAccountEvents {
108
87
  userPositionsData: (payload: UserPositionsAccount) => void;
109
88
  userOrdersData: (payload: UserOrdersAccount) => void;
110
89
  update: void;
90
+ error: (e: Error) => void;
111
91
  }
112
92
 
113
93
  export interface UserAccountSubscriber {
@@ -121,4 +101,34 @@ export interface UserAccountSubscriber {
121
101
  getUserAccount(): UserAccount;
122
102
  getUserPositionsAccount(): UserPositionsAccount;
123
103
  getUserOrdersAccount(): UserOrdersAccount;
104
+ type: ClearingHouseUserConfigType;
124
105
  }
106
+
107
+ export interface TokenAccountEvents {
108
+ tokenAccountUpdate: (payload: AccountInfo) => void;
109
+ update: void;
110
+ error: (e: Error) => void;
111
+ }
112
+
113
+ export interface TokenAccountSubscriber {
114
+ eventEmitter: StrictEventEmitter<EventEmitter, TokenAccountEvents>;
115
+ isSubscribed: boolean;
116
+
117
+ subscribe(): Promise<boolean>;
118
+ fetch(): Promise<void>;
119
+ unsubscribe(): Promise<void>;
120
+
121
+ getTokenAccount(): AccountInfo;
122
+ }
123
+
124
+ export type AccountToPoll = {
125
+ key: string;
126
+ publicKey: PublicKey;
127
+ eventType: string;
128
+ callbackId?: string;
129
+ };
130
+
131
+ export type AccountData = {
132
+ slot: number;
133
+ buffer: Buffer | undefined;
134
+ };
@@ -0,0 +1,3 @@
1
+ export function capitalize(value: string): string {
2
+ return value[0].toUpperCase() + value.slice(1);
3
+ }
@@ -1,13 +1,17 @@
1
- import { AccountSubscriber } from './types';
1
+ import { AccountData, AccountSubscriber } from './types';
2
2
  import { Program } from '@project-serum/anchor';
3
- import { PublicKey } from '@solana/web3.js';
3
+ import { AccountInfo, Context, PublicKey } from '@solana/web3.js';
4
+ import { capitalize } from './utils';
5
+ import * as Buffer from 'buffer';
4
6
 
5
7
  export class WebSocketAccountSubscriber<T> implements AccountSubscriber<T> {
6
8
  data?: T;
9
+ accountData?: AccountData;
7
10
  accountName: string;
8
11
  program: Program;
9
12
  accountPublicKey: PublicKey;
10
13
  onChange: (data: T) => void;
14
+ listenerId?: number;
11
15
 
12
16
  public constructor(
13
17
  accountName: string,
@@ -20,32 +24,78 @@ export class WebSocketAccountSubscriber<T> implements AccountSubscriber<T> {
20
24
  }
21
25
 
22
26
  async subscribe(onChange: (data: T) => void): Promise<void> {
27
+ if (this.listenerId) {
28
+ return;
29
+ }
30
+
23
31
  this.onChange = onChange;
24
32
  await this.fetch();
25
33
 
26
- this.program.account[this.accountName]
27
- .subscribe(this.accountPublicKey, this.program.provider.opts.commitment)
28
- .on('change', async (data: T) => {
29
- this.data = data;
30
- this.onChange(data);
31
- });
34
+ this.listenerId = this.program.provider.connection.onAccountChange(
35
+ this.accountPublicKey,
36
+ (accountInfo, context) => {
37
+ this.handleRpcResponse(context, accountInfo);
38
+ },
39
+ this.program.provider.opts.commitment
40
+ );
32
41
  }
33
42
 
34
43
  async fetch(): Promise<void> {
35
- const newData = (await this.program.account[this.accountName].fetch(
36
- this.accountPublicKey
37
- )) as T;
44
+ const rpcResponse =
45
+ await this.program.provider.connection.getAccountInfoAndContext(
46
+ this.accountPublicKey,
47
+ this.program.provider.opts.commitment
48
+ );
49
+ this.handleRpcResponse(rpcResponse.context, rpcResponse?.value);
50
+ }
51
+
52
+ handleRpcResponse(context: Context, accountInfo?: AccountInfo<Buffer>): void {
53
+ const newSlot = context.slot;
54
+ let newBuffer: Buffer | undefined = undefined;
55
+ if (accountInfo) {
56
+ newBuffer = accountInfo.data;
57
+ }
38
58
 
39
- // if data has changed trigger update
40
- if (JSON.stringify(newData) !== JSON.stringify(this.data)) {
41
- this.data = newData;
59
+ if (!this.accountData) {
60
+ this.accountData = {
61
+ buffer: newBuffer,
62
+ slot: newSlot,
63
+ };
64
+ if (newBuffer) {
65
+ this.data = this.program.account[
66
+ this.accountName
67
+ ].coder.accounts.decode(capitalize(this.accountName), newBuffer);
68
+ this.onChange(this.data);
69
+ }
70
+ return;
71
+ }
72
+
73
+ if (newSlot <= this.accountData.slot) {
74
+ return;
75
+ }
76
+
77
+ const oldBuffer = this.accountData.buffer;
78
+ if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
79
+ this.accountData = {
80
+ buffer: newBuffer,
81
+ slot: newSlot,
82
+ };
83
+ this.data = this.program.account[this.accountName].coder.accounts.decode(
84
+ capitalize(this.accountName),
85
+ newBuffer
86
+ );
42
87
  this.onChange(this.data);
43
88
  }
44
89
  }
45
90
 
46
91
  unsubscribe(): Promise<void> {
47
- return this.program.account[this.accountName].unsubscribe(
48
- this.accountPublicKey
49
- );
92
+ if (this.listenerId) {
93
+ const promise =
94
+ this.program.provider.connection.removeAccountChangeListener(
95
+ this.listenerId
96
+ );
97
+ this.listenerId = undefined;
98
+ return promise;
99
+ }
50
100
  }
51
101
  }
@@ -5,8 +5,8 @@ import {
5
5
  } from './types';
6
6
  import { AccountSubscriber, NotSubscribedError } from './types';
7
7
  import {
8
- CurveHistoryAccount,
9
8
  DepositHistoryAccount,
9
+ ExtendedCurveHistoryAccount,
10
10
  FundingPaymentHistoryAccount,
11
11
  FundingRateHistoryAccount,
12
12
  LiquidationHistoryAccount,
@@ -21,8 +21,9 @@ import StrictEventEmitter from 'strict-event-emitter-types';
21
21
  import { EventEmitter } from 'events';
22
22
  import { getClearingHouseStateAccountPublicKey } from '../addresses';
23
23
  import { WebSocketAccountSubscriber } from './webSocketAccountSubscriber';
24
+ import { ClearingHouseConfigType } from '../factory/clearingHouse';
24
25
 
25
- export class DefaultClearingHouseAccountSubscriber
26
+ export class WebSocketClearingHouseAccountSubscriber
26
27
  implements ClearingHouseAccountSubscriber
27
28
  {
28
29
  isSubscribed: boolean;
@@ -34,13 +35,15 @@ export class DefaultClearingHouseAccountSubscriber
34
35
  depositHistoryAccountSubscriber?: AccountSubscriber<DepositHistoryAccount>;
35
36
  fundingPaymentHistoryAccountSubscriber?: AccountSubscriber<FundingPaymentHistoryAccount>;
36
37
  fundingRateHistoryAccountSubscriber?: AccountSubscriber<FundingRateHistoryAccount>;
37
- curveHistoryAccountSubscriber?: AccountSubscriber<CurveHistoryAccount>;
38
+ curveHistoryAccountSubscriber?: AccountSubscriber<ExtendedCurveHistoryAccount>;
38
39
  liquidationHistoryAccountSubscriber?: AccountSubscriber<LiquidationHistoryAccount>;
39
40
  orderStateAccountSubscriber?: AccountSubscriber<OrderStateAccount>;
40
41
  orderHistoryAccountSubscriber?: AccountSubscriber<OrderHistoryAccount>;
41
42
 
42
43
  optionalExtraSubscriptions: ClearingHouseAccountTypes[] = [];
43
44
 
45
+ type: ClearingHouseConfigType = 'websocket';
46
+
44
47
  private isSubscribing = false;
45
48
  private subscriptionPromise: Promise<boolean>;
46
49
  private subscriptionPromiseResolver: (val: boolean) => void;
@@ -145,9 +148,9 @@ export class DefaultClearingHouseAccountSubscriber
145
148
  );
146
149
 
147
150
  this.curveHistoryAccountSubscriber = new WebSocketAccountSubscriber(
148
- 'curveHistory',
151
+ 'extendedCurveHistory',
149
152
  this.program,
150
- state.curveHistory
153
+ state.extendedCurveHistory
151
154
  );
152
155
 
153
156
  this.orderHistoryAccountSubscriber = new WebSocketAccountSubscriber(
@@ -343,7 +346,7 @@ export class DefaultClearingHouseAccountSubscriber
343
346
  return this.fundingRateHistoryAccountSubscriber.data;
344
347
  }
345
348
 
346
- public getCurveHistoryAccount(): CurveHistoryAccount {
349
+ public getCurveHistoryAccount(): ExtendedCurveHistoryAccount {
347
350
  this.assertIsSubscribed();
348
351
  this.assertOptionalIsSubscribed('curveHistoryAccount');
349
352
  return this.curveHistoryAccountSubscriber.data;
@@ -14,8 +14,9 @@ import {
14
14
  } from '../addresses';
15
15
  import { WebSocketAccountSubscriber } from './webSocketAccountSubscriber';
16
16
  import { UserAccount, UserOrdersAccount, UserPositionsAccount } from '../types';
17
+ import { ClearingHouseConfigType } from '../factory/clearingHouse';
17
18
 
18
- export class DefaultUserAccountSubscriber implements UserAccountSubscriber {
19
+ export class WebSocketUserAccountSubscriber implements UserAccountSubscriber {
19
20
  isSubscribed: boolean;
20
21
  program: Program;
21
22
  eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
@@ -25,6 +26,8 @@ export class DefaultUserAccountSubscriber implements UserAccountSubscriber {
25
26
  userPositionsAccountSubscriber: AccountSubscriber<UserPositionsAccount>;
26
27
  userOrdersAccountSubscriber: AccountSubscriber<UserOrdersAccount>;
27
28
 
29
+ type: ClearingHouseConfigType = 'websocket';
30
+
28
31
  public constructor(program: Program, authority: PublicKey) {
29
32
  this.isSubscribed = false;
30
33
  this.program = program;
@@ -67,7 +70,7 @@ export class DefaultUserAccountSubscriber implements UserAccountSubscriber {
67
70
 
68
71
  const userOrdersPublicKey = await getUserOrdersAccountPublicKey(
69
72
  this.program.programId,
70
- this.authority
73
+ userPublicKey
71
74
  );
72
75
 
73
76
  this.userOrdersAccountSubscriber = new WebSocketAccountSubscriber(
@@ -100,9 +103,11 @@ export class DefaultUserAccountSubscriber implements UserAccountSubscriber {
100
103
  return;
101
104
  }
102
105
 
103
- this.userDataAccountSubscriber.unsubscribe();
104
- this.userPositionsAccountSubscriber.unsubscribe();
105
- this.userOrdersAccountSubscriber.unsubscribe();
106
+ await Promise.all([
107
+ this.userDataAccountSubscriber.unsubscribe(),
108
+ this.userPositionsAccountSubscriber.unsubscribe(),
109
+ await this.userOrdersAccountSubscriber.unsubscribe(),
110
+ ]);
106
111
 
107
112
  this.isSubscribed = false;
108
113
  }
package/src/addresses.ts CHANGED
@@ -50,12 +50,12 @@ export async function getUserAccountPublicKey(
50
50
 
51
51
  export async function getUserOrdersAccountPublicKeyAndNonce(
52
52
  programId: PublicKey,
53
- authority: PublicKey
53
+ userAccount: PublicKey
54
54
  ): Promise<[PublicKey, number]> {
55
55
  return anchor.web3.PublicKey.findProgramAddress(
56
56
  [
57
57
  Buffer.from(anchor.utils.bytes.utf8.encode('user_orders')),
58
- authority.toBuffer(),
58
+ userAccount.toBuffer(),
59
59
  ],
60
60
  programId
61
61
  );
@@ -63,7 +63,9 @@ export async function getUserOrdersAccountPublicKeyAndNonce(
63
63
 
64
64
  export async function getUserOrdersAccountPublicKey(
65
65
  programId: PublicKey,
66
- authority: PublicKey
66
+ userAccount: PublicKey
67
67
  ): Promise<PublicKey> {
68
- return (await getUserOrdersAccountPublicKeyAndNonce(programId, authority))[0];
68
+ return (
69
+ await getUserOrdersAccountPublicKeyAndNonce(programId, userAccount)
70
+ )[0];
69
71
  }
package/src/admin.ts CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  OracleSource,
13
13
  OrderFillerRewardStructure,
14
14
  } from './types';
15
- import { BN, Idl, Program, Provider } from '@project-serum/anchor';
15
+ import { BN, Provider } from '@project-serum/anchor';
16
16
  import * as anchor from '@project-serum/anchor';
17
17
  import {
18
18
  getClearingHouseStateAccountPublicKey,
@@ -22,11 +22,12 @@ import {
22
22
  import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
23
23
  import { ClearingHouse } from './clearingHouse';
24
24
  import { PEG_PRECISION } from './constants/numericConstants';
25
- import clearingHouseIDL from './idl/clearing_house.json';
26
- import { DefaultClearingHouseAccountSubscriber } from './accounts/defaultClearingHouseAccountSubscriber';
27
- import { DefaultTxSender } from './tx/defaultTxSender';
28
25
  import { calculateTargetPriceTrade } from './math/trade';
29
26
  import { calculateAmmReservesAfterSwap, getSwapDirection } from './math/amm';
27
+ import {
28
+ getAdmin,
29
+ getWebSocketClearingHouseConfig,
30
+ } from './factory/clearingHouse';
30
31
 
31
32
  export class Admin extends ClearingHouse {
32
33
  public static from(
@@ -35,24 +36,13 @@ export class Admin extends ClearingHouse {
35
36
  clearingHouseProgramId: PublicKey,
36
37
  opts: ConfirmOptions = Provider.defaultOptions()
37
38
  ): Admin {
38
- const provider = new Provider(connection, wallet, opts);
39
- const program = new Program(
40
- clearingHouseIDL as Idl,
41
- clearingHouseProgramId,
42
- provider
43
- );
44
- const accountSubscriber = new DefaultClearingHouseAccountSubscriber(
45
- program
46
- );
47
- const txSender = new DefaultTxSender(provider);
48
- return new Admin(
39
+ const config = getWebSocketClearingHouseConfig(
49
40
  connection,
50
41
  wallet,
51
- program,
52
- accountSubscriber,
53
- txSender,
42
+ clearingHouseProgramId,
54
43
  opts
55
44
  );
45
+ return getAdmin(config);
56
46
  }
57
47
 
58
48
  public async initialize(
@@ -165,7 +155,7 @@ export class Admin extends ClearingHouse {
165
155
  await this.program.account.depositHistory.createInstruction(
166
156
  depositHistory
167
157
  ),
168
- await this.program.account.curveHistory.createInstruction(
158
+ await this.program.account.extendedCurveHistory.createInstruction(
169
159
  curveHistory
170
160
  ),
171
161
  ],
@@ -275,13 +265,38 @@ export class Admin extends ClearingHouse {
275
265
  marketIndex: BN
276
266
  ): Promise<TransactionSignature> {
277
267
  const state = this.getStateAccount();
268
+ const markets = this.getMarketsAccount();
269
+ const marketData = markets.markets[marketIndex.toNumber()];
270
+ const ammData = marketData.amm;
271
+
278
272
  return await this.program.rpc.updateK(sqrtK, marketIndex, {
279
273
  accounts: {
280
274
  state: await this.getStatePublicKey(),
281
275
  admin: this.wallet.publicKey,
282
276
  markets: state.markets,
277
+ curveHistory: state.extendedCurveHistory,
278
+ oracle: ammData.oracle,
279
+ },
280
+ });
281
+ }
282
+
283
+ public async updateCurveHistory(): Promise<TransactionSignature> {
284
+ const extendedCurveHistory = anchor.web3.Keypair.generate();
285
+
286
+ const state = this.getStateAccount();
287
+ return await this.program.rpc.updateCurveHistory({
288
+ accounts: {
289
+ state: await this.getStatePublicKey(),
290
+ admin: this.wallet.publicKey,
283
291
  curveHistory: state.curveHistory,
292
+ extendedCurveHistory: extendedCurveHistory.publicKey,
284
293
  },
294
+ instructions: [
295
+ await this.program.account.extendedCurveHistory.createInstruction(
296
+ extendedCurveHistory
297
+ ),
298
+ ],
299
+ signers: [extendedCurveHistory],
285
300
  });
286
301
  }
287
302
 
@@ -334,7 +349,45 @@ export class Admin extends ClearingHouse {
334
349
  admin: this.wallet.publicKey,
335
350
  oracle: ammData.oracle,
336
351
  markets: state.markets,
337
- curveHistory: state.curveHistory,
352
+ curveHistory: state.extendedCurveHistory,
353
+ },
354
+ });
355
+ }
356
+
357
+ public async updateAmmOracleTwap(
358
+ marketIndex: BN
359
+ ): Promise<TransactionSignature> {
360
+ const state = this.getStateAccount();
361
+ const markets = this.getMarketsAccount();
362
+ const marketData = markets.markets[marketIndex.toNumber()];
363
+ const ammData = marketData.amm;
364
+
365
+ return await this.program.rpc.updateAmmOracleTwap(marketIndex, {
366
+ accounts: {
367
+ state: await this.getStatePublicKey(),
368
+ admin: this.wallet.publicKey,
369
+ oracle: ammData.oracle,
370
+ markets: state.markets,
371
+ curveHistory: state.extendedCurveHistory,
372
+ },
373
+ });
374
+ }
375
+
376
+ public async resetAmmOracleTwap(
377
+ marketIndex: BN
378
+ ): Promise<TransactionSignature> {
379
+ const state = this.getStateAccount();
380
+ const markets = this.getMarketsAccount();
381
+ const marketData = markets.markets[marketIndex.toNumber()];
382
+ const ammData = marketData.amm;
383
+
384
+ return await this.program.rpc.resetAmmOracleTwap(marketIndex, {
385
+ accounts: {
386
+ state: await this.getStatePublicKey(),
387
+ admin: this.wallet.publicKey,
388
+ oracle: ammData.oracle,
389
+ markets: state.markets,
390
+ curveHistory: state.extendedCurveHistory,
338
391
  },
339
392
  });
340
393
  }