@drift-labs/sdk 2.86.0-beta.8 → 2.87.0-beta.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 (39) hide show
  1. package/VERSION +1 -1
  2. package/lib/addresses/pda.d.ts +1 -0
  3. package/lib/addresses/pda.js +8 -1
  4. package/lib/adminClient.d.ts +8 -4
  5. package/lib/adminClient.js +51 -8
  6. package/lib/bankrun/bankrunConnection.d.ts +1 -0
  7. package/lib/bankrun/bankrunConnection.js +6 -0
  8. package/lib/constants/numericConstants.d.ts +2 -0
  9. package/lib/constants/numericConstants.js +3 -1
  10. package/lib/constants/perpMarkets.js +144 -120
  11. package/lib/constants/spotMarkets.js +50 -38
  12. package/lib/driftClient.d.ts +12 -14
  13. package/lib/driftClient.js +147 -9
  14. package/lib/idl/drift.json +344 -10
  15. package/lib/idl/pyth_solana_receiver.json +628 -0
  16. package/lib/math/fuel.d.ts +1 -0
  17. package/lib/math/fuel.js +12 -2
  18. package/lib/types.d.ts +25 -6
  19. package/lib/types.js +3 -2
  20. package/lib/user.d.ts +6 -5
  21. package/lib/user.js +36 -18
  22. package/package.json +1 -1
  23. package/src/addresses/pda.ts +15 -0
  24. package/src/adminClient.ts +119 -7
  25. package/src/bankrun/bankrunConnection.ts +13 -0
  26. package/src/constants/numericConstants.ts +2 -0
  27. package/src/constants/perpMarkets.ts +148 -120
  28. package/src/constants/spotMarkets.ts +52 -38
  29. package/src/driftClient.ts +203 -16
  30. package/src/idl/drift.json +344 -10
  31. package/src/idl/openbook.json +3854 -0
  32. package/src/idl/pyth_solana_receiver.json +628 -0
  33. package/src/math/fuel.ts +15 -1
  34. package/src/types.ts +28 -7
  35. package/src/user.ts +119 -55
  36. package/tests/ci/verifyConstants.ts +214 -0
  37. package/tests/dlob/helpers.ts +30 -0
  38. package/tests/user/helpers.ts +1 -0
  39. package/tests/user/test.ts +2 -0
@@ -73,8 +73,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
73
73
  {
74
74
  symbol: 'USDC',
75
75
  marketIndex: 0,
76
- oracle: new PublicKey('Gnt27xtC473ZT2Mw5u8wZ68Z3gULkSTb5DuxJy7eJotD'),
77
- oracleSource: OracleSource.PYTH_STABLE_COIN,
76
+ oracle: new PublicKey('En8hkHLkRe9d9DraYmBTrus518BvmVH448YcvmrFM6Ce'),
77
+ oracleSource: OracleSource.PYTH_STABLE_COIN_PULL,
78
78
  mint: new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
79
79
  precision: QUOTE_PRECISION,
80
80
  precisionExp: QUOTE_PRECISION_EXP,
@@ -84,8 +84,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
84
84
  {
85
85
  symbol: 'SOL',
86
86
  marketIndex: 1,
87
- oracle: new PublicKey('H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG'),
88
- oracleSource: OracleSource.PYTH,
87
+ oracle: new PublicKey('BAtFj4kQttZRVep3UZS2aZRDixkGYgWsbqTBVDbnSsPF'),
88
+ oracleSource: OracleSource.PYTH_PULL,
89
89
  mint: new PublicKey(WRAPPED_SOL_MINT),
90
90
  precision: LAMPORTS_PRECISION,
91
91
  precisionExp: LAMPORTS_EXP,
@@ -99,8 +99,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
99
99
  {
100
100
  symbol: 'mSOL',
101
101
  marketIndex: 2,
102
- oracle: new PublicKey('E4v1BBgoso9s64TQvmyownAVJbhbEPGyzA3qn4n46qj9'),
103
- oracleSource: OracleSource.PYTH,
102
+ oracle: new PublicKey('FAq7hqjn7FWGXKDwJHzsXGgBcydGTcK4kziJpAGWXjDb'),
103
+ oracleSource: OracleSource.PYTH_PULL,
104
104
  mint: new PublicKey('mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So'),
105
105
  precision: new BN(10).pow(NINE),
106
106
  precisionExp: NINE,
@@ -111,8 +111,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
111
111
  {
112
112
  symbol: 'wBTC',
113
113
  marketIndex: 3,
114
- oracle: new PublicKey('GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU'),
115
- oracleSource: OracleSource.PYTH,
114
+ oracle: new PublicKey('486kr3pmFPfTsS4aZgcsQ7kS4i9rjMsYYZup6HQNSTT4'),
115
+ oracleSource: OracleSource.PYTH_PULL,
116
116
  mint: new PublicKey('3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh'),
117
117
  precision: new BN(10).pow(EIGHT),
118
118
  precisionExp: EIGHT,
@@ -123,8 +123,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
123
123
  {
124
124
  symbol: 'wETH',
125
125
  marketIndex: 4,
126
- oracle: new PublicKey('JBu1AL4obBcCMqKBBxhpWCNUt136ijcuMZLFvTP7iWdB'),
127
- oracleSource: OracleSource.PYTH,
126
+ oracle: new PublicKey('6bEp2MiyoiiiDxcVqE8rUHQWwHirXUXtKfAEATTVqNzT'),
127
+ oracleSource: OracleSource.PYTH_PULL,
128
128
  mint: new PublicKey('7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs'),
129
129
  precision: new BN(10).pow(EIGHT),
130
130
  precisionExp: EIGHT,
@@ -138,8 +138,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
138
138
  {
139
139
  symbol: 'USDT',
140
140
  marketIndex: 5,
141
- oracle: new PublicKey('3vxLXJqLqF3JG5TCbYycbKWRBbCJQLxQmBGCkyqEEefL'),
142
- oracleSource: OracleSource.PYTH_STABLE_COIN,
141
+ oracle: new PublicKey('BekJ3P5G3iFeC97sXHuKnUHofCFj9Sbo7uyF2fkKwvit'),
142
+ oracleSource: OracleSource.PYTH_STABLE_COIN_PULL,
143
143
  mint: new PublicKey('Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'),
144
144
  precision: QUOTE_PRECISION,
145
145
  precisionExp: QUOTE_PRECISION_EXP,
@@ -150,8 +150,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
150
150
  {
151
151
  symbol: 'jitoSOL',
152
152
  marketIndex: 6,
153
- oracle: new PublicKey('7yyaeuJ1GGtVBLT2z2xub5ZWYKaNhF28mj1RdV4VDFVk'),
154
- oracleSource: OracleSource.PYTH,
153
+ oracle: new PublicKey('9QE1P5EfzthYDgoQ9oPeTByCEKaRJeZbVVqKJfgU9iau'),
154
+ oracleSource: OracleSource.PYTH_PULL,
155
155
  mint: new PublicKey('J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn'),
156
156
  precision: new BN(10).pow(NINE),
157
157
  precisionExp: NINE,
@@ -165,8 +165,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
165
165
  {
166
166
  symbol: 'PYTH',
167
167
  marketIndex: 7,
168
- oracle: new PublicKey('nrYkQQQur7z8rYTST3G9GqATviK5SxTDkrqd21MW6Ue'),
169
- oracleSource: OracleSource.PYTH,
168
+ oracle: new PublicKey('GqkCu7CbsPVz1H6W6AAHuReqbJckYG59TXz7Y5HDV7hr'),
169
+ oracleSource: OracleSource.PYTH_PULL,
170
170
  mint: new PublicKey('HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3'),
171
171
  precision: new BN(10).pow(SIX),
172
172
  precisionExp: SIX,
@@ -180,8 +180,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
180
180
  {
181
181
  symbol: 'bSOL',
182
182
  marketIndex: 8,
183
- oracle: new PublicKey('AFrYBhb5wKQtxRS9UA9YRS4V3dwFm7SqmS6DHKq6YVgo'),
184
- oracleSource: OracleSource.PYTH,
183
+ oracle: new PublicKey('BmDWPMsytWmYkh9n6o7m79eVshVYf2B5GVaqQ2EWKnGH'),
184
+ oracleSource: OracleSource.PYTH_PULL,
185
185
  mint: new PublicKey('bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1'),
186
186
  precision: new BN(10).pow(NINE),
187
187
  precisionExp: NINE,
@@ -192,8 +192,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
192
192
  {
193
193
  symbol: 'JTO',
194
194
  marketIndex: 9,
195
- oracle: new PublicKey('D8UUgr8a3aR3yUeHLu7v8FWK7E8Y5sSU7qrYBXUJXBQ5'),
196
- oracleSource: OracleSource.PYTH,
195
+ oracle: new PublicKey('Ffq6ACJ17NAgaxC6ocfMzVXL3K61qxB2xHg6WUawWPfP'),
196
+ oracleSource: OracleSource.PYTH_PULL,
197
197
  mint: new PublicKey('jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL'),
198
198
  precision: new BN(10).pow(NINE),
199
199
  precisionExp: NINE,
@@ -207,8 +207,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
207
207
  {
208
208
  symbol: 'WIF',
209
209
  marketIndex: 10,
210
- oracle: new PublicKey('6ABgrEZk8urs6kJ1JNdC1sspH5zKXRqxy8sg3ZG2cQps'),
211
- oracleSource: OracleSource.PYTH,
210
+ oracle: new PublicKey('6x6KfE7nY2xoLCRSMPT1u83wQ5fpGXoKNBqFjrCwzsCQ'),
211
+ oracleSource: OracleSource.PYTH_PULL,
212
212
  mint: new PublicKey('EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm'),
213
213
  precision: new BN(10).pow(SIX),
214
214
  precisionExp: SIX,
@@ -222,8 +222,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
222
222
  {
223
223
  symbol: 'JUP',
224
224
  marketIndex: 11,
225
- oracle: new PublicKey('g6eRCbboSwK4tSWngn773RCMexr1APQr4uA9bGZBYfo'),
226
- oracleSource: OracleSource.PYTH,
225
+ oracle: new PublicKey('AwqRpfJ36jnSZQykyL1jYY35mhMteeEAjh7o8LveRQin'),
226
+ oracleSource: OracleSource.PYTH_PULL,
227
227
  mint: new PublicKey('JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN'),
228
228
  precision: new BN(10).pow(SIX),
229
229
  precisionExp: SIX,
@@ -237,8 +237,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
237
237
  {
238
238
  symbol: 'RNDR',
239
239
  marketIndex: 12,
240
- oracle: new PublicKey('CYGfrBJB9HgLf9iZyN4aH5HvUAi2htQ4MjPxeXMf4Egn'),
241
- oracleSource: OracleSource.PYTH,
240
+ oracle: new PublicKey('F3mPHRtJqqq57JPDBmUwUVhpyPLmjE5dAzDfpVgpFkug'),
241
+ oracleSource: OracleSource.PYTH_PULL,
242
242
  mint: new PublicKey('rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof'),
243
243
  precision: new BN(10).pow(EIGHT),
244
244
  precisionExp: EIGHT,
@@ -250,8 +250,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
250
250
  {
251
251
  symbol: 'W',
252
252
  marketIndex: 13,
253
- oracle: new PublicKey('H9j8CT1bFiWHaZUPMooEaxMRHdWdJ5T9CzFn41z96JHW'),
254
- oracleSource: OracleSource.PYTH,
253
+ oracle: new PublicKey('4HbitGsdcFbtFotmYscikQFAAKJ3nYx4t7sV7fTvsk8U'),
254
+ oracleSource: OracleSource.PYTH_PULL,
255
255
  mint: new PublicKey('85VBFQZC9TZkfaptBWjvUw7YbZjy52A6mjtPGjstQAmQ'),
256
256
  precision: new BN(10).pow(SIX),
257
257
  precisionExp: SIX,
@@ -265,8 +265,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
265
265
  {
266
266
  symbol: 'TNSR',
267
267
  marketIndex: 14,
268
- oracle: new PublicKey('7Cfyymx49ipGsgEsCA2XygAB2DUsan4C6Cyb5c8oR5st'),
269
- oracleSource: OracleSource.SWITCHBOARD,
268
+ oracle: new PublicKey('13jpjpVyU5hGpjsZ4HzCcmBo85wze4N8Au7U6cC3GMip'),
269
+ oracleSource: OracleSource.PYTH_PULL,
270
270
  mint: new PublicKey('TNSRxcUxoT9xBG3de7PiJyTDYu7kskLqcpddxnEJAS6'),
271
271
  precision: new BN(10).pow(NINE),
272
272
  precisionExp: NINE,
@@ -280,8 +280,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
280
280
  {
281
281
  symbol: 'DRIFT',
282
282
  marketIndex: 15,
283
- oracle: new PublicKey('PeNpQeGEm9UEFJ6MBCMauY4WW4h3YxoESPWbsqVKucE'),
284
- oracleSource: OracleSource.SWITCHBOARD,
283
+ oracle: new PublicKey('23KmX7SNikmUr2axSCy6Zer7XPBnvmVcASALnDGqBVRR'),
284
+ oracleSource: OracleSource.PYTH_PULL,
285
285
  mint: new PublicKey('DriFtupJYLTosbwoN8koMbEYSx54aFAVLddWsbksjwg7'),
286
286
  precision: new BN(10).pow(SIX),
287
287
  precisionExp: SIX,
@@ -295,8 +295,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
295
295
  {
296
296
  symbol: 'INF',
297
297
  marketIndex: 16,
298
- oracle: new PublicKey('81SuhCcCQri9w4yPyv56ErtpXuncVyFCDT3fYehceG1M'),
299
- oracleSource: OracleSource.SWITCHBOARD,
298
+ oracle: new PublicKey('B7RUYg2zF6UdUSHv2RmpnriPVJccYWojgFydNS1NY5F8'),
299
+ oracleSource: OracleSource.PYTH_PULL,
300
300
  mint: new PublicKey('5oVNBeEEQvYi1cX3ir8Dx5n1P7pdxydbGF2X4TxVusJm'),
301
301
  precision: new BN(10).pow(NINE),
302
302
  precisionExp: NINE,
@@ -317,12 +317,14 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
317
317
  {
318
318
  symbol: 'USDY',
319
319
  marketIndex: 18,
320
- oracle: new PublicKey('DiqUGbq5CV8Tjcae1whjrX97qPo6gU7BKAvKNFc2vrX8'),
321
- oracleSource: OracleSource.SWITCHBOARD,
320
+ oracle: new PublicKey('BPTQgHV4y2x4jvKPPkkd9aS8jY7L3DGZBwjEZC8Vm27o'),
321
+ oracleSource: OracleSource.PYTH_PULL,
322
322
  mint: new PublicKey('A1KLoBrKBde8Ty9qtNQUtq3C2ortoC3u7twggz7sEto6'),
323
323
  precision: new BN(10).pow(SIX),
324
324
  precisionExp: SIX,
325
325
  launchTs: 1718811089000,
326
+ pythFeedId:
327
+ '0xe393449f6aff8a4b6d3e1165a7c9ebec103685f3b41e60db4277b5b6d10e7326',
326
328
  },
327
329
  {
328
330
  symbol: 'JLP',
@@ -337,8 +339,8 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
337
339
  {
338
340
  symbol: 'POPCAT',
339
341
  marketIndex: 20,
340
- oracle: new PublicKey('3GjpjC8TWsPqjyFSiR7saGxgzD8zqYJNsBnWpenZPEBy'),
341
- oracleSource: OracleSource.SWITCHBOARD,
342
+ oracle: new PublicKey('H3pn43tkNvsG5z3qzmERguSvKoyHZvvY6VPmNrJqiW5X'),
343
+ oracleSource: OracleSource.PYTH_PULL,
342
344
  mint: new PublicKey('7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr'),
343
345
  precision: new BN(10).pow(NINE),
344
346
  precisionExp: NINE,
@@ -346,6 +348,18 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
346
348
  phoenixMarket: new PublicKey(
347
349
  '31XgvAQ1HgFQEk31KdszbPkVXKaQqB1bgYZPoDrFpSR2'
348
350
  ),
351
+ pythFeedId:
352
+ '0xb9312a7ee50e189ef045aa3c7842e099b061bd9bdc99ac645956c3b660dc8cce',
353
+ },
354
+ {
355
+ symbol: 'CLOUD',
356
+ marketIndex: 21,
357
+ oracle: new PublicKey('4FG7UyPkszGvcSVCCKaLSZsArGjyxitwhJeQhYu2bFTS'),
358
+ oracleSource: OracleSource.SWITCHBOARD,
359
+ mint: new PublicKey('CLoUDKc4Ane7HeQcPpE3YHnznRxhMimJ4MyaUqyHFzAu'),
360
+ precision: new BN(10).pow(NINE),
361
+ precisionExp: NINE,
362
+ launchTs: 1721316817000,
349
363
  },
350
364
  ];
351
365
 
@@ -45,6 +45,7 @@ import {
45
45
  SettlePnlMode,
46
46
  SignedTxData,
47
47
  MappedRecord,
48
+ OpenbookV2FulfillmentConfigAccount,
48
49
  } from './types';
49
50
  import * as anchor from '@coral-xyz/anchor';
50
51
  import driftIDL from './idl/drift.json';
@@ -74,6 +75,7 @@ import {
74
75
  getDriftSignerPublicKey,
75
76
  getDriftStateAccountPublicKey,
76
77
  getInsuranceFundStakeAccountPublicKey,
78
+ getOpenbookV2FulfillmentConfigPublicKey,
77
79
  getPerpMarketPublicKey,
78
80
  getPhoenixFulfillmentConfigPublicKey,
79
81
  getPythPullOraclePublicKey,
@@ -132,7 +134,6 @@ import { isOracleValid, trimVaaSignatures } from './math/oracles';
132
134
  import { TxHandler } from './tx/txHandler';
133
135
  import {
134
136
  wormholeCoreBridgeIdl,
135
- pythSolanaReceiverIdl,
136
137
  DEFAULT_RECEIVER_PROGRAM_ID,
137
138
  } from '@pythnetwork/pyth-solana-receiver';
138
139
  import { parseAccumulatorUpdateData } from '@pythnetwork/price-service-sdk';
@@ -145,6 +146,7 @@ import { WormholeCoreBridgeSolana } from '@pythnetwork/pyth-solana-receiver/lib/
145
146
  import { PythSolanaReceiver } from '@pythnetwork/pyth-solana-receiver/lib/idl/pyth_solana_receiver';
146
147
  import { getFeedIdUint8Array, trimFeedId } from './util/pythPullOracleUtils';
147
148
  import { isVersionedTransaction } from './tx/utils';
149
+ import pythSolanaReceiverIdl from './idl/pyth_solana_receiver.json';
148
150
 
149
151
  type RemainingAccountParams = {
150
152
  userAccounts: UserAccount[];
@@ -575,6 +577,28 @@ export class DriftClient {
575
577
  ) as PhoenixV1FulfillmentConfigAccount[];
576
578
  }
577
579
 
580
+ public async getOpenbookV2FulfillmentConfig(
581
+ openbookMarket: PublicKey
582
+ ): Promise<OpenbookV2FulfillmentConfigAccount> {
583
+ const address = getOpenbookV2FulfillmentConfigPublicKey(
584
+ this.program.programId,
585
+ openbookMarket
586
+ );
587
+ return (await this.program.account.openbookV2FulfillmentConfig.fetch(
588
+ address
589
+ )) as OpenbookV2FulfillmentConfigAccount;
590
+ }
591
+
592
+ public async getOpenbookV2FulfillmentConfigs(): Promise<
593
+ OpenbookV2FulfillmentConfigAccount[]
594
+ > {
595
+ const accounts =
596
+ await this.program.account.openbookV2FulfillmentConfig.all();
597
+ return accounts.map(
598
+ (account) => account.account
599
+ ) as OpenbookV2FulfillmentConfigAccount[];
600
+ }
601
+
578
602
  public async fetchMarketLookupTableAccount(): Promise<AddressLookupTableAccount> {
579
603
  if (this.lookupTableAccount) return this.lookupTableAccount;
580
604
 
@@ -3635,7 +3659,8 @@ export class DriftClient {
3635
3659
  order?: Order,
3636
3660
  fulfillmentConfig?:
3637
3661
  | SerumV3FulfillmentConfigAccount
3638
- | PhoenixV1FulfillmentConfigAccount,
3662
+ | PhoenixV1FulfillmentConfigAccount
3663
+ | OpenbookV2FulfillmentConfigAccount,
3639
3664
  makerInfo?: MakerInfo | MakerInfo[],
3640
3665
  referrerInfo?: ReferrerInfo,
3641
3666
  txParams?: TxParams
@@ -3664,7 +3689,8 @@ export class DriftClient {
3664
3689
  order?: Order,
3665
3690
  fulfillmentConfig?:
3666
3691
  | SerumV3FulfillmentConfigAccount
3667
- | PhoenixV1FulfillmentConfigAccount,
3692
+ | PhoenixV1FulfillmentConfigAccount
3693
+ | OpenbookV2FulfillmentConfigAccount,
3668
3694
  makerInfo?: MakerInfo | MakerInfo[],
3669
3695
  referrerInfo?: ReferrerInfo,
3670
3696
  fillerPublicKey?: PublicKey
@@ -3743,6 +3769,7 @@ export class DriftClient {
3743
3769
  fulfillmentConfig?:
3744
3770
  | SerumV3FulfillmentConfigAccount
3745
3771
  | PhoenixV1FulfillmentConfigAccount
3772
+ | OpenbookV2FulfillmentConfigAccount
3746
3773
  ): void {
3747
3774
  if (fulfillmentConfig) {
3748
3775
  if ('serumProgramId' in fulfillmentConfig) {
@@ -3757,6 +3784,12 @@ export class DriftClient {
3757
3784
  remainingAccounts,
3758
3785
  fulfillmentConfig
3759
3786
  );
3787
+ } else if ('openbookV2ProgramId' in fulfillmentConfig) {
3788
+ this.addOpenbookRemainingAccounts(
3789
+ marketIndex,
3790
+ remainingAccounts,
3791
+ fulfillmentConfig
3792
+ );
3760
3793
  } else {
3761
3794
  throw Error('Invalid fulfillment config type');
3762
3795
  }
@@ -3922,6 +3955,103 @@ export class DriftClient {
3922
3955
  });
3923
3956
  }
3924
3957
 
3958
+ addOpenbookRemainingAccounts(
3959
+ marketIndex: number,
3960
+ remainingAccounts: AccountMeta[],
3961
+ fulfillmentConfig: OpenbookV2FulfillmentConfigAccount
3962
+ ): void {
3963
+ remainingAccounts.push({
3964
+ pubkey: fulfillmentConfig.pubkey,
3965
+ isWritable: false,
3966
+ isSigner: false,
3967
+ });
3968
+ remainingAccounts.push({
3969
+ pubkey: this.getSignerPublicKey(),
3970
+ isWritable: true,
3971
+ isSigner: false,
3972
+ });
3973
+ remainingAccounts.push({
3974
+ pubkey: fulfillmentConfig.openbookV2ProgramId,
3975
+ isWritable: false,
3976
+ isSigner: false,
3977
+ });
3978
+ remainingAccounts.push({
3979
+ pubkey: fulfillmentConfig.openbookV2Market,
3980
+ isWritable: true,
3981
+ isSigner: false,
3982
+ });
3983
+ remainingAccounts.push({
3984
+ pubkey: fulfillmentConfig.openbookV2MarketAuthority,
3985
+ isWritable: false,
3986
+ isSigner: false,
3987
+ });
3988
+ remainingAccounts.push({
3989
+ pubkey: fulfillmentConfig.openbookV2EventHeap,
3990
+ isWritable: true,
3991
+ isSigner: false,
3992
+ });
3993
+ remainingAccounts.push({
3994
+ pubkey: fulfillmentConfig.openbookV2Bids,
3995
+ isWritable: true,
3996
+ isSigner: false,
3997
+ });
3998
+ remainingAccounts.push({
3999
+ pubkey: fulfillmentConfig.openbookV2Asks,
4000
+ isWritable: true,
4001
+ isSigner: false,
4002
+ });
4003
+ remainingAccounts.push({
4004
+ pubkey: fulfillmentConfig.openbookV2BaseVault,
4005
+ isWritable: true,
4006
+ isSigner: false,
4007
+ });
4008
+ remainingAccounts.push({
4009
+ pubkey: fulfillmentConfig.openbookV2QuoteVault,
4010
+ isWritable: true,
4011
+ isSigner: false,
4012
+ });
4013
+ remainingAccounts.push({
4014
+ pubkey: this.getSpotMarketAccount(marketIndex).vault,
4015
+ isWritable: true,
4016
+ isSigner: false,
4017
+ });
4018
+ remainingAccounts.push({
4019
+ pubkey: this.getQuoteSpotMarketAccount().vault,
4020
+ isWritable: true,
4021
+ isSigner: false,
4022
+ });
4023
+ remainingAccounts.push({
4024
+ pubkey: TOKEN_PROGRAM_ID,
4025
+ isWritable: false,
4026
+ isSigner: false,
4027
+ });
4028
+ remainingAccounts.push({
4029
+ pubkey: SystemProgram.programId,
4030
+ isWritable: false,
4031
+ isSigner: false,
4032
+ });
4033
+ remainingAccounts.push({
4034
+ pubkey: this.getSpotMarketAccount(marketIndex).pubkey,
4035
+ isWritable: true,
4036
+ isSigner: false,
4037
+ });
4038
+ remainingAccounts.push({
4039
+ pubkey: this.getQuoteSpotMarketAccount().pubkey,
4040
+ isWritable: true,
4041
+ isSigner: false,
4042
+ });
4043
+
4044
+ if (fulfillmentConfig.remainingAccounts) {
4045
+ for (const remainingAccount of fulfillmentConfig.remainingAccounts) {
4046
+ remainingAccounts.push({
4047
+ pubkey: remainingAccount,
4048
+ isWritable: true,
4049
+ isSigner: false,
4050
+ });
4051
+ }
4052
+ }
4053
+ }
4054
+
3925
4055
  /**
3926
4056
  * Swap tokens in drift account using jupiter
3927
4057
  * @param jupiterClient jupiter client to find routes and jupiter instructions
@@ -4180,10 +4310,6 @@ export class DriftClient {
4180
4310
  const outMarket = this.getSpotMarketAccount(outMarketIndex);
4181
4311
  const inMarket = this.getSpotMarketAccount(inMarketIndex);
4182
4312
 
4183
- const isExactOut = swapMode === 'ExactOut' || quote.swapMode === 'ExactOut';
4184
- const amountIn = new BN(quote.inAmount);
4185
- const exactOutBufferedAmountIn = amountIn.muln(1001).divn(1000); // Add 10bp buffer
4186
-
4187
4313
  if (!quote) {
4188
4314
  const fetchedQuote = await jupiterClient.getQuote({
4189
4315
  inputMint: inMarket.mint,
@@ -4201,6 +4327,10 @@ export class DriftClient {
4201
4327
  throw new Error("Could not fetch Jupiter's quote. Please try again.");
4202
4328
  }
4203
4329
 
4330
+ const isExactOut = swapMode === 'ExactOut' || quote.swapMode === 'ExactOut';
4331
+ const amountIn = new BN(quote.inAmount);
4332
+ const exactOutBufferedAmountIn = amountIn.muln(1001).divn(1000); // Add 10bp buffer
4333
+
4204
4334
  const transaction = await jupiterClient.getSwap({
4205
4335
  quote,
4206
4336
  userPublicKey: this.provider.wallet.publicKey,
@@ -6457,6 +6587,12 @@ export class DriftClient {
6457
6587
 
6458
6588
  let tokenAccount;
6459
6589
 
6590
+ if (
6591
+ !(await this.checkIfAccountExists(this.getUserStatsAccountPublicKey()))
6592
+ ) {
6593
+ addIfStakeIxs.push(await this.getInitializeUserStatsIx());
6594
+ }
6595
+
6460
6596
  if (createWSOLTokenAccount) {
6461
6597
  const { ixs, pubkey } = await this.getWrappedSolAccountCreationIxs(
6462
6598
  amount,
@@ -6913,7 +7049,7 @@ export class DriftClient {
6913
7049
  public getReceiverProgram(): Program<PythSolanaReceiver> {
6914
7050
  if (this.receiverProgram === undefined) {
6915
7051
  this.receiverProgram = new Program(
6916
- pythSolanaReceiverIdl,
7052
+ pythSolanaReceiverIdl as PythSolanaReceiver,
6917
7053
  DEFAULT_RECEIVER_PROGRAM_ID,
6918
7054
  this.provider
6919
7055
  );
@@ -6935,12 +7071,25 @@ export class DriftClient {
6935
7071
  return txSig;
6936
7072
  }
6937
7073
 
7074
+ public async postMultiPythPullOracleUpdatesAtomic(
7075
+ vaaString: string,
7076
+ feedIds: string[]
7077
+ ): Promise<TransactionSignature> {
7078
+ const postIxs = await this.getPostPythPullOracleUpdateAtomicIxs(
7079
+ vaaString,
7080
+ feedIds
7081
+ );
7082
+ const tx = await this.buildTransaction(postIxs);
7083
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
7084
+
7085
+ return txSig;
7086
+ }
7087
+
6938
7088
  public async getPostPythPullOracleUpdateAtomicIxs(
6939
7089
  vaaString: string,
6940
- feedId: string,
7090
+ feedIds: string | string[],
6941
7091
  numSignatures = 2
6942
7092
  ): Promise<TransactionInstruction[]> {
6943
- feedId = trimFeedId(feedId);
6944
7093
  const accumulatorUpdateData = parseAccumulatorUpdateData(
6945
7094
  Buffer.from(vaaString, 'base64')
6946
7095
  );
@@ -6955,23 +7104,61 @@ export class DriftClient {
6955
7104
  );
6956
7105
 
6957
7106
  const postIxs: TransactionInstruction[] = [];
6958
- for (const update of accumulatorUpdateData.updates) {
7107
+ if (accumulatorUpdateData.updates.length > 1) {
7108
+ const encodedParams = this.getReceiverProgram().coder.types.encode(
7109
+ 'PostMultiUpdatesAtomicParams',
7110
+ {
7111
+ vaa: trimmedVaa,
7112
+ merklePriceUpdates: accumulatorUpdateData.updates,
7113
+ }
7114
+ );
7115
+ const feedIdsToUse: string[] =
7116
+ typeof feedIds === 'string' ? [feedIds] : feedIds;
7117
+ const pubkeys = feedIdsToUse.map((feedId) => {
7118
+ return getPythPullOraclePublicKey(
7119
+ this.program.programId,
7120
+ getFeedIdUint8Array(feedId)
7121
+ );
7122
+ });
7123
+
7124
+ const remainingAccounts: Array<AccountMeta> = pubkeys.map((pubkey) => {
7125
+ return {
7126
+ pubkey,
7127
+ isSigner: false,
7128
+ isWritable: true,
7129
+ };
7130
+ });
7131
+ postIxs.push(
7132
+ this.program.instruction.postMultiPythPullOracleUpdatesAtomic(
7133
+ encodedParams,
7134
+ {
7135
+ accounts: {
7136
+ keeper: this.wallet.publicKey,
7137
+ pythSolanaReceiver: DRIFT_ORACLE_RECEIVER_ID,
7138
+ guardianSet,
7139
+ },
7140
+ remainingAccounts,
7141
+ }
7142
+ )
7143
+ );
7144
+ } else {
7145
+ let feedIdToUse = typeof feedIds === 'string' ? feedIds : feedIds[0];
7146
+ feedIdToUse = trimFeedId(feedIdToUse);
6959
7147
  postIxs.push(
6960
7148
  await this.getSinglePostPythPullOracleAtomicIx(
6961
7149
  {
6962
7150
  vaa: trimmedVaa,
6963
- merklePriceUpdate: update,
7151
+ merklePriceUpdate: accumulatorUpdateData.updates[0],
6964
7152
  },
6965
- feedId,
7153
+ feedIdToUse,
6966
7154
  guardianSet
6967
7155
  )
6968
7156
  );
6969
7157
  }
6970
-
6971
7158
  return postIxs;
6972
7159
  }
6973
7160
 
6974
- public async getSinglePostPythPullOracleAtomicIx(
7161
+ private async getSinglePostPythPullOracleAtomicIx(
6975
7162
  params: {
6976
7163
  vaa: Buffer;
6977
7164
  merklePriceUpdate: {
@@ -7083,7 +7270,7 @@ export class DriftClient {
7083
7270
  );
7084
7271
  }
7085
7272
 
7086
- public async getBuildEncodedVaaIxs(
7273
+ private async getBuildEncodedVaaIxs(
7087
7274
  vaa: Buffer,
7088
7275
  guardianSet: PublicKey
7089
7276
  ): Promise<[TransactionInstruction[], Keypair]> {