@drift-labs/sdk 2.85.0-beta.8 → 2.86.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 (53) hide show
  1. package/VERSION +1 -1
  2. package/bun.lockb +0 -0
  3. package/lib/addresses/pda.d.ts +1 -0
  4. package/lib/addresses/pda.js +8 -1
  5. package/lib/adminClient.d.ts +2 -0
  6. package/lib/adminClient.js +22 -0
  7. package/lib/blockhashSubscriber/BlockhashSubscriber.js +22 -15
  8. package/lib/config.d.ts +3 -0
  9. package/lib/config.js +4 -1
  10. package/lib/constants/perpMarkets.d.ts +1 -0
  11. package/lib/constants/perpMarkets.js +57 -0
  12. package/lib/constants/spotMarkets.d.ts +1 -0
  13. package/lib/constants/spotMarkets.js +20 -0
  14. package/lib/driftClient.d.ts +26 -1
  15. package/lib/driftClient.js +157 -31
  16. package/lib/driftClientConfig.d.ts +2 -1
  17. package/lib/idl/drift.json +161 -2
  18. package/lib/math/oracles.d.ts +2 -0
  19. package/lib/math/oracles.js +14 -1
  20. package/lib/oracles/pythPullClient.js +1 -1
  21. package/lib/tx/baseTxSender.js +1 -0
  22. package/lib/tx/blockhashFetcher/baseBlockhashFetcher.d.ts +8 -0
  23. package/lib/tx/blockhashFetcher/baseBlockhashFetcher.js +13 -0
  24. package/lib/tx/blockhashFetcher/cachedBlockhashFetcher.d.ts +28 -0
  25. package/lib/tx/blockhashFetcher/cachedBlockhashFetcher.js +73 -0
  26. package/lib/tx/blockhashFetcher/types.d.ts +4 -0
  27. package/lib/tx/blockhashFetcher/types.js +2 -0
  28. package/lib/tx/txHandler.d.ts +10 -0
  29. package/lib/tx/txHandler.js +16 -7
  30. package/lib/tx/utils.d.ts +2 -0
  31. package/lib/tx/utils.js +10 -0
  32. package/lib/util/pythPullOracleUtils.d.ts +2 -0
  33. package/lib/util/pythPullOracleUtils.js +15 -0
  34. package/package.json +3 -1
  35. package/src/addresses/pda.ts +13 -0
  36. package/src/adminClient.ts +39 -0
  37. package/src/blockhashSubscriber/BlockhashSubscriber.ts +24 -19
  38. package/src/config.ts +6 -0
  39. package/src/constants/perpMarkets.ts +115 -0
  40. package/src/constants/spotMarkets.ts +41 -0
  41. package/src/driftClient.ts +347 -41
  42. package/src/driftClientConfig.ts +2 -1
  43. package/src/idl/drift.json +161 -2
  44. package/src/math/oracles.ts +17 -0
  45. package/src/oracles/pythPullClient.ts +2 -3
  46. package/src/tx/baseTxSender.ts +1 -0
  47. package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +19 -0
  48. package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +90 -0
  49. package/src/tx/blockhashFetcher/types.ts +5 -0
  50. package/src/tx/txHandler.ts +38 -4
  51. package/src/tx/utils.ts +11 -0
  52. package/src/util/pythPullOracleUtils.ts +11 -0
  53. package/tests/tx/cachedBlockhashFetcher.test.ts +96 -0
@@ -14,6 +14,7 @@ exports.DevnetSpotMarkets = [
14
14
  mint: new web3_js_1.PublicKey('8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2'),
15
15
  precision: new __1.BN(10).pow(numericConstants_1.SIX),
16
16
  precisionExp: numericConstants_1.SIX,
17
+ pythFeedId: '0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a',
17
18
  },
18
19
  {
19
20
  symbol: 'SOL',
@@ -25,6 +26,7 @@ exports.DevnetSpotMarkets = [
25
26
  precisionExp: numericConstants_1.LAMPORTS_EXP,
26
27
  serumMarket: new web3_js_1.PublicKey('8N37SsnTu8RYxtjrV9SStjkkwVhmU8aCWhLvwduAPEKW'),
27
28
  phoenixMarket: new web3_js_1.PublicKey('78ehDnHgbkFxqXZwdFxa8HK7saX58GymeX2wNGdkqYLp'),
29
+ pythFeedId: '0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d',
28
30
  },
29
31
  {
30
32
  symbol: 'BTC',
@@ -35,6 +37,7 @@ exports.DevnetSpotMarkets = [
35
37
  precision: new __1.BN(10).pow(numericConstants_1.SIX),
36
38
  precisionExp: numericConstants_1.SIX,
37
39
  serumMarket: new web3_js_1.PublicKey('AGsmbVu3MS9u68GEYABWosQQCZwmLcBHu4pWEuBYH7Za'),
40
+ pythFeedId: '0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43',
38
41
  },
39
42
  ];
40
43
  exports.MainnetSpotMarkets = [
@@ -46,6 +49,7 @@ exports.MainnetSpotMarkets = [
46
49
  mint: new web3_js_1.PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
47
50
  precision: numericConstants_1.QUOTE_PRECISION,
48
51
  precisionExp: numericConstants_1.QUOTE_PRECISION_EXP,
52
+ pythFeedId: '0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a',
49
53
  },
50
54
  {
51
55
  symbol: 'SOL',
@@ -57,6 +61,7 @@ exports.MainnetSpotMarkets = [
57
61
  precisionExp: numericConstants_1.LAMPORTS_EXP,
58
62
  serumMarket: new web3_js_1.PublicKey('8BnEgHoWFysVcuFFX7QztDmzuH8r5ZFvyP3sYwn1XTh6'),
59
63
  phoenixMarket: new web3_js_1.PublicKey('4DoNfFBfF7UokCC2FQzriy7yHK6DY6NVdYpuekQ5pRgg'),
64
+ pythFeedId: '0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d',
60
65
  },
61
66
  {
62
67
  symbol: 'mSOL',
@@ -67,6 +72,7 @@ exports.MainnetSpotMarkets = [
67
72
  precision: new __1.BN(10).pow(numericConstants_1.NINE),
68
73
  precisionExp: numericConstants_1.NINE,
69
74
  serumMarket: new web3_js_1.PublicKey('9Lyhks5bQQxb9EyyX55NtgKQzpM4WK7JCmeaWuQ5MoXD'),
75
+ pythFeedId: '0xc2289a6a43d2ce91c6f55caec370f4acc38a2ed477f58813334c6d03749ff2a4',
70
76
  },
71
77
  {
72
78
  symbol: 'wBTC',
@@ -77,6 +83,7 @@ exports.MainnetSpotMarkets = [
77
83
  precision: new __1.BN(10).pow(numericConstants_1.EIGHT),
78
84
  precisionExp: numericConstants_1.EIGHT,
79
85
  serumMarket: new web3_js_1.PublicKey('3BAKsQd3RuhZKES2DGysMhjBdwjZYKYmxRqnSMtZ4KSN'),
86
+ pythFeedId: '0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43',
80
87
  },
81
88
  {
82
89
  symbol: 'wETH',
@@ -88,6 +95,7 @@ exports.MainnetSpotMarkets = [
88
95
  precisionExp: numericConstants_1.EIGHT,
89
96
  serumMarket: new web3_js_1.PublicKey('BbJgE7HZMaDp5NTYvRh5jZSkQPVDTU8ubPFtpogUkEj4'),
90
97
  phoenixMarket: new web3_js_1.PublicKey('Ew3vFDdtdGrknJAVVfraxCA37uNJtimXYPY4QjnfhFHH'),
98
+ pythFeedId: '0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace',
91
99
  },
92
100
  {
93
101
  symbol: 'USDT',
@@ -98,6 +106,7 @@ exports.MainnetSpotMarkets = [
98
106
  precision: numericConstants_1.QUOTE_PRECISION,
99
107
  precisionExp: numericConstants_1.QUOTE_PRECISION_EXP,
100
108
  serumMarket: new web3_js_1.PublicKey('B2na8Awyd7cpC59iEU43FagJAPLigr3AP3s38KM982bu'),
109
+ pythFeedId: '0x2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b',
101
110
  },
102
111
  {
103
112
  symbol: 'jitoSOL',
@@ -109,6 +118,7 @@ exports.MainnetSpotMarkets = [
109
118
  precisionExp: numericConstants_1.NINE,
110
119
  serumMarket: new web3_js_1.PublicKey('DkbVbMhFxswS32xnn1K2UY4aoBugXooBTxdzkWWDWRkH'),
111
120
  phoenixMarket: new web3_js_1.PublicKey('5LQLfGtqcC5rm2WuGxJf4tjqYmDjsQAbKo2AMLQ8KB7p'),
121
+ pythFeedId: '0x67be9f519b95cf24338801051f9a808eff0a578ccb388db73b7f6fe1de019ffb',
112
122
  },
113
123
  {
114
124
  symbol: 'PYTH',
@@ -120,6 +130,7 @@ exports.MainnetSpotMarkets = [
120
130
  precisionExp: numericConstants_1.SIX,
121
131
  serumMarket: new web3_js_1.PublicKey('4E17F3BxtNVqzVsirxguuqkpYLtFgCR6NfTpccPh82WE'),
122
132
  phoenixMarket: new web3_js_1.PublicKey('2sTMN9A1D1qeZLF95XQgJCUPiKe5DiV52jLfZGqMP46m'),
133
+ pythFeedId: '0x0bbf28e9a841a1cc788f6a361b17ca072d0ea3098a1e5df1c3922d06719579ff',
123
134
  },
124
135
  {
125
136
  symbol: 'bSOL',
@@ -130,6 +141,7 @@ exports.MainnetSpotMarkets = [
130
141
  precision: new __1.BN(10).pow(numericConstants_1.NINE),
131
142
  precisionExp: numericConstants_1.NINE,
132
143
  serumMarket: new web3_js_1.PublicKey('ARjaHVxGCQfTvvKjLd7U7srvk6orthZSE6uqWchCczZc'),
144
+ pythFeedId: '0x89875379e70f8fbadc17aef315adf3a8d5d160b811435537e03c97e8aac97d9c',
133
145
  },
134
146
  {
135
147
  symbol: 'JTO',
@@ -141,6 +153,7 @@ exports.MainnetSpotMarkets = [
141
153
  precisionExp: numericConstants_1.NINE,
142
154
  serumMarket: new web3_js_1.PublicKey('H87FfmHABiZLRGrDsXRZtqq25YpARzaokCzL1vMYGiep'),
143
155
  phoenixMarket: new web3_js_1.PublicKey('BRLLmdtPGuuFn3BU6orYw4KHaohAEptBToi3dwRUnHQZ'),
156
+ pythFeedId: '0xb43660a5f790c69354b0729a5ef9d50d68f1df92107540210b9cccba1f947cc2',
144
157
  },
145
158
  {
146
159
  symbol: 'WIF',
@@ -152,6 +165,7 @@ exports.MainnetSpotMarkets = [
152
165
  precisionExp: numericConstants_1.SIX,
153
166
  serumMarket: new web3_js_1.PublicKey('2BtDHBTCTUxvdur498ZEcMgimasaFrY5GzLv8wS8XgCb'),
154
167
  phoenixMarket: new web3_js_1.PublicKey('6ojSigXF7nDPyhFRgmn3V9ywhYseKF9J32ZrranMGVSX'),
168
+ pythFeedId: '0x4ca4beeca86f0d164160323817a4e42b10010a724c2217c6ee41b54cd4cc61fc',
155
169
  },
156
170
  {
157
171
  symbol: 'JUP',
@@ -163,6 +177,7 @@ exports.MainnetSpotMarkets = [
163
177
  precisionExp: numericConstants_1.SIX,
164
178
  phoenixMarket: new web3_js_1.PublicKey('2pspvjWWaf3dNgt3jsgSzFCNvMGPb7t8FrEYvLGjvcCe'),
165
179
  launchTs: 1706731200000,
180
+ pythFeedId: '0x0a0408d619e9380abad35060f9192039ed5042fa6f82301d0e48bb52be830996',
166
181
  },
167
182
  {
168
183
  symbol: 'RNDR',
@@ -174,6 +189,7 @@ exports.MainnetSpotMarkets = [
174
189
  precisionExp: numericConstants_1.EIGHT,
175
190
  serumMarket: new web3_js_1.PublicKey('2m7ZLEKtxWF29727DSb5D91erpXPUY1bqhRWRC3wQX7u'),
176
191
  launchTs: 1708964021000,
192
+ pythFeedId: '0xab7347771135fc733f8f38db462ba085ed3309955f42554a14fa13e855ac0e2f',
177
193
  },
178
194
  {
179
195
  symbol: 'W',
@@ -185,6 +201,7 @@ exports.MainnetSpotMarkets = [
185
201
  precisionExp: numericConstants_1.SIX,
186
202
  phoenixMarket: new web3_js_1.PublicKey('8dFTCTAbtGuHsdDL8WEPrTU6pXFDrU1QSjBTutw8fwZk'),
187
203
  launchTs: 1712149014000,
204
+ pythFeedId: '0xeff7446475e218517566ea99e72a4abec2e1bd8498b43b7d8331e29dcb059389',
188
205
  },
189
206
  {
190
207
  symbol: 'TNSR',
@@ -196,6 +213,7 @@ exports.MainnetSpotMarkets = [
196
213
  precisionExp: numericConstants_1.NINE,
197
214
  phoenixMarket: new web3_js_1.PublicKey('AbJCZ9TAJiby5AY3cHcXS2gUdENC6mtsm6m7XpC2ZMvE'),
198
215
  launchTs: 1712593532000,
216
+ pythFeedId: '0x05ecd4597cd48fe13d6cc3596c62af4f9675aee06e2e0b94c06d8bee2b659e05',
199
217
  },
200
218
  {
201
219
  symbol: 'DRIFT',
@@ -207,6 +225,7 @@ exports.MainnetSpotMarkets = [
207
225
  precisionExp: numericConstants_1.SIX,
208
226
  phoenixMarket: new web3_js_1.PublicKey('8BV6rrWsUabnTDA3dE6A69oUDJAj3hMhtBHTJyXB7czp'),
209
227
  launchTs: 1715860800000,
228
+ pythFeedId: '0x5c1690b27bb02446db17cdda13ccc2c1d609ad6d2ef5bf4983a85ea8b6f19d07',
210
229
  },
211
230
  {
212
231
  symbol: 'INF',
@@ -217,6 +236,7 @@ exports.MainnetSpotMarkets = [
217
236
  precision: new __1.BN(10).pow(numericConstants_1.NINE),
218
237
  precisionExp: numericConstants_1.NINE,
219
238
  launchTs: 1716595200000,
239
+ pythFeedId: '0xf51570985c642c49c2d6e50156390fdba80bb6d5f7fa389d2f012ced4f7d208f',
220
240
  },
221
241
  {
222
242
  symbol: 'dSOL',
@@ -1,9 +1,10 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="bn.js" />
3
+ /// <reference types="node" />
3
4
  import { AnchorProvider, BN, Program, ProgramAccount } from '@coral-xyz/anchor';
4
5
  import { StateAccount, IWallet, PositionDirection, UserAccount, PerpMarketAccount, OrderParams, Order, SpotMarketAccount, SpotPosition, MakerInfo, TakerInfo, OptionalOrderParams, ReferrerInfo, MarketType, TxParams, SerumV3FulfillmentConfigAccount, ReferrerNameAccount, OrderTriggerCondition, PerpMarketExtendedInfo, UserStatsAccount, PhoenixV1FulfillmentConfigAccount, ModifyOrderPolicy, SwapReduceOnly, SettlePnlMode, SignedTxData, MappedRecord } from './types';
5
6
  import * as anchor from '@coral-xyz/anchor';
6
- import { Connection, PublicKey, TransactionSignature, ConfirmOptions, Transaction, TransactionInstruction, AccountMeta, Signer, AddressLookupTableAccount, TransactionVersion, VersionedTransaction, BlockhashWithExpiryBlockHeight } from '@solana/web3.js';
7
+ import { Connection, PublicKey, TransactionSignature, ConfirmOptions, Transaction, TransactionInstruction, AccountMeta, Keypair, Signer, AddressLookupTableAccount, TransactionVersion, VersionedTransaction, BlockhashWithExpiryBlockHeight } from '@solana/web3.js';
7
8
  import { TokenFaucet } from './tokenFaucet';
8
9
  import { EventEmitter } from 'events';
9
10
  import StrictEventEmitter from 'strict-event-emitter-types';
@@ -18,6 +19,8 @@ import { UserStats } from './userStats';
18
19
  import { JupiterClient, QuoteResponse, Route, SwapMode } from './jupiter/jupiterClient';
19
20
  import { UserStatsSubscriptionConfig } from './userStatsConfig';
20
21
  import { TxHandler } from './tx/txHandler';
22
+ import { WormholeCoreBridgeSolana } from '@pythnetwork/pyth-solana-receiver/lib/idl/wormhole_core_bridge_solana';
23
+ import { PythSolanaReceiver } from '@pythnetwork/pyth-solana-receiver/lib/idl/pyth_solana_receiver';
21
24
  type RemainingAccountParams = {
22
25
  userAccounts: UserAccount[];
23
26
  writablePerpMarketIndexes?: number[];
@@ -60,6 +63,8 @@ export declare class DriftClient {
60
63
  txParams: TxParams;
61
64
  enableMetricsEvents?: boolean;
62
65
  txHandler: TxHandler;
66
+ receiverProgram?: Program<PythSolanaReceiver>;
67
+ wormholeProgram?: Program<WormholeCoreBridgeSolana>;
63
68
  get isSubscribed(): boolean;
64
69
  set isSubscribed(val: boolean);
65
70
  constructor(config: DriftClientConfig);
@@ -221,6 +226,7 @@ export declare class DriftClient {
221
226
  */
222
227
  getAssociatedTokenAccount(marketIndex: number, useNative?: boolean): Promise<PublicKey>;
223
228
  createAssociatedTokenAccountIdempotentInstruction(account: PublicKey, payer: PublicKey, owner: PublicKey, mint: PublicKey): TransactionInstruction;
229
+ createDepositTxn(amount: BN, marketIndex: number, associatedTokenAccount: PublicKey, subAccountId?: number, reduceOnly?: boolean, txParams?: TxParams): Promise<ReturnType<typeof this.buildTransaction>>;
224
230
  /**
225
231
  * Deposit funds into the given spot market
226
232
  *
@@ -240,6 +246,7 @@ export declare class DriftClient {
240
246
  pubkey: PublicKey;
241
247
  }>;
242
248
  getAssociatedTokenAccountCreationIx(tokenMintAddress: PublicKey, associatedTokenAddress: PublicKey): anchor.web3.TransactionInstruction;
249
+ createInitializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, marketIndex?: number, subAccountId?: number, name?: string, fromSubAccountId?: number, referrerInfo?: ReferrerInfo, donateAmount?: BN, txParams?: TxParams, customMaxMarginRatio?: number): Promise<[Transaction | VersionedTransaction, PublicKey]>;
243
250
  /**
244
251
  * Creates the User account for a user, and deposits some initial collateral
245
252
  * @param amount
@@ -703,6 +710,24 @@ export declare class DriftClient {
703
710
  marketIndex: number;
704
711
  marketType: MarketType;
705
712
  } | undefined;
713
+ getReceiverProgram(): Program<PythSolanaReceiver>;
714
+ postPythPullOracleUpdateAtomic(vaaString: string, feedId: string): Promise<TransactionSignature>;
715
+ getPostPythPullOracleUpdateAtomicIxs(vaaString: string, feedId: string, numSignatures?: number): Promise<TransactionInstruction[]>;
716
+ getSinglePostPythPullOracleAtomicIx(params: {
717
+ vaa: Buffer;
718
+ merklePriceUpdate: {
719
+ message: Buffer;
720
+ proof: number[][];
721
+ };
722
+ }, feedId: string, guardianSet: PublicKey): Promise<TransactionInstruction>;
723
+ updatePythPullOracle(vaaString: string, feedId: string): Promise<TransactionSignature>;
724
+ getUpdatePythPullOracleIxs(params: {
725
+ merklePriceUpdate: {
726
+ message: Buffer;
727
+ proof: number[][];
728
+ };
729
+ }, feedId: string, encodedVaaAddress: PublicKey): Promise<TransactionInstruction>;
730
+ getBuildEncodedVaaIxs(vaa: Buffer, guardianSet: PublicKey): Promise<[TransactionInstruction[], Keypair]>;
706
731
  private handleSignedTransaction;
707
732
  private handlePreSignedTransaction;
708
733
  private isVersionedTransaction;
@@ -58,6 +58,12 @@ const utils_1 = require("./math/utils");
58
58
  const txParamProcessor_1 = require("./tx/txParamProcessor");
59
59
  const oracles_1 = require("./math/oracles");
60
60
  const txHandler_1 = require("./tx/txHandler");
61
+ const pyth_solana_receiver_1 = require("@pythnetwork/pyth-solana-receiver");
62
+ const price_service_sdk_1 = require("@pythnetwork/price-service-sdk");
63
+ const address_1 = require("@pythnetwork/pyth-solana-receiver/lib/address");
64
+ const config_2 = require("./config");
65
+ const pythPullOracleUtils_1 = require("./util/pythPullOracleUtils");
66
+ const utils_2 = require("./tx/utils");
61
67
  /**
62
68
  * # DriftClient
63
69
  * This class is the main way to interact with Drift Protocol. It allows you to subscribe to the various accounts where the Market's state is stored, as well as: opening positions, liquidating, settling funding, depositing & withdrawing, and more.
@@ -106,6 +112,7 @@ class DriftClient {
106
112
  onSignedCb: this.handleSignedTransaction.bind(this),
107
113
  preSignedCb: this.handlePreSignedTransaction.bind(this),
108
114
  },
115
+ config: config.txHandlerConfig,
109
116
  });
110
117
  if (config.includeDelegates && config.subAccountIds) {
111
118
  throw new Error('Can only pass one of includeDelegates or subAccountIds. If you want to specify subaccount ids for multiple authorities, pass authoritySubaccountMap instead');
@@ -1061,17 +1068,7 @@ class DriftClient {
1061
1068
  data: Buffer.from([0x1]),
1062
1069
  });
1063
1070
  }
1064
- /**
1065
- * Deposit funds into the given spot market
1066
- *
1067
- * @param amount to deposit
1068
- * @param marketIndex spot market index to deposit into
1069
- * @param associatedTokenAccount can be the wallet public key if using native sol
1070
- * @param subAccountId subaccountId to deposit
1071
- * @param reduceOnly if true, deposit must not increase account risk
1072
- */
1073
- async deposit(amount, marketIndex, associatedTokenAccount, subAccountId, reduceOnly = false, txParams) {
1074
- const additionalSigners = [];
1071
+ async createDepositTxn(amount, marketIndex, associatedTokenAccount, subAccountId, reduceOnly = false, txParams) {
1075
1072
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1076
1073
  const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
1077
1074
  const signerAuthority = this.wallet.publicKey;
@@ -1090,7 +1087,20 @@ class DriftClient {
1090
1087
  }
1091
1088
  txParams = { ...(txParams !== null && txParams !== void 0 ? txParams : this.txParams), computeUnits: 600000 };
1092
1089
  const tx = await this.buildTransaction(instructions, txParams);
1093
- const { txSig, slot } = await this.sendTransaction(tx, additionalSigners, this.opts);
1090
+ return tx;
1091
+ }
1092
+ /**
1093
+ * Deposit funds into the given spot market
1094
+ *
1095
+ * @param amount to deposit
1096
+ * @param marketIndex spot market index to deposit into
1097
+ * @param associatedTokenAccount can be the wallet public key if using native sol
1098
+ * @param subAccountId subaccountId to deposit
1099
+ * @param reduceOnly if true, deposit must not increase account risk
1100
+ */
1101
+ async deposit(amount, marketIndex, associatedTokenAccount, subAccountId, reduceOnly = false, txParams) {
1102
+ const tx = await this.createDepositTxn(amount, marketIndex, associatedTokenAccount, subAccountId, reduceOnly, txParams);
1103
+ const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
1094
1104
  this.spotMarketLastSlotCache.set(marketIndex, slot);
1095
1105
  return txSig;
1096
1106
  }
@@ -1165,23 +1175,9 @@ class DriftClient {
1165
1175
  getAssociatedTokenAccountCreationIx(tokenMintAddress, associatedTokenAddress) {
1166
1176
  return (0, spl_token_1.createAssociatedTokenAccountInstruction)(this.wallet.publicKey, associatedTokenAddress, this.wallet.publicKey, tokenMintAddress);
1167
1177
  }
1168
- /**
1169
- * Creates the User account for a user, and deposits some initial collateral
1170
- * @param amount
1171
- * @param userTokenAccount
1172
- * @param marketIndex
1173
- * @param subAccountId
1174
- * @param name
1175
- * @param fromSubAccountId
1176
- * @param referrerInfo
1177
- * @param donateAmount
1178
- * @param txParams
1179
- * @returns
1180
- */
1181
- async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name, fromSubAccountId, referrerInfo, donateAmount, txParams, customMaxMarginRatio) {
1178
+ async createInitializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name, fromSubAccountId, referrerInfo, donateAmount, txParams, customMaxMarginRatio) {
1182
1179
  const ixs = [];
1183
1180
  const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(subAccountId, name, referrerInfo);
1184
- const additionalSigners = [];
1185
1181
  const spotMarket = this.getSpotMarketAccount(marketIndex);
1186
1182
  const isSolMarket = spotMarket.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
1187
1183
  const authority = this.wallet.publicKey;
@@ -1226,6 +1222,24 @@ class DriftClient {
1226
1222
  ixs.push((0, spl_token_1.createCloseAccountInstruction)(wsolTokenAccount, authority, authority, []));
1227
1223
  }
1228
1224
  const tx = await this.buildTransaction(ixs, txParams);
1225
+ return [tx, userAccountPublicKey];
1226
+ }
1227
+ /**
1228
+ * Creates the User account for a user, and deposits some initial collateral
1229
+ * @param amount
1230
+ * @param userTokenAccount
1231
+ * @param marketIndex
1232
+ * @param subAccountId
1233
+ * @param name
1234
+ * @param fromSubAccountId
1235
+ * @param referrerInfo
1236
+ * @param donateAmount
1237
+ * @param txParams
1238
+ * @returns
1239
+ */
1240
+ async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name, fromSubAccountId, referrerInfo, donateAmount, txParams, customMaxMarginRatio) {
1241
+ const [tx, userAccountPublicKey] = await this.createInitializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex, subAccountId, name, fromSubAccountId, referrerInfo, donateAmount, txParams, customMaxMarginRatio);
1242
+ const additionalSigners = [];
1229
1243
  const { txSig, slot } = await this.sendTransaction(tx, additionalSigners, this.opts);
1230
1244
  this.spotMarketLastSlotCache.set(marketIndex, slot);
1231
1245
  await this.addUser(subAccountId);
@@ -2267,6 +2281,9 @@ class DriftClient {
2267
2281
  async getJupiterSwapIxV6({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, onlyDirectRoutes, quote, reduceOnly, userAccountPublicKey, }) {
2268
2282
  const outMarket = this.getSpotMarketAccount(outMarketIndex);
2269
2283
  const inMarket = this.getSpotMarketAccount(inMarketIndex);
2284
+ const isExactOut = swapMode === 'ExactOut' || quote.swapMode === 'ExactOut';
2285
+ const amountIn = new anchor_1.BN(quote.inAmount);
2286
+ const exactOutBufferedAmountIn = amountIn.muln(1001).divn(1000); // Add 10bp buffer
2270
2287
  if (!quote) {
2271
2288
  const fetchedQuote = await jupiterClient.getQuote({
2272
2289
  inputMint: inMarket.mint,
@@ -2312,7 +2329,7 @@ class DriftClient {
2312
2329
  const { beginSwapIx, endSwapIx } = await this.getSwapIx({
2313
2330
  outMarketIndex,
2314
2331
  inMarketIndex,
2315
- amountIn: new anchor_1.BN(quote.inAmount),
2332
+ amountIn: isExactOut ? exactOutBufferedAmountIn : amountIn,
2316
2333
  inTokenAccount: inAssociatedTokenAccount,
2317
2334
  outTokenAccount: outAssociatedTokenAccount,
2318
2335
  reduceOnly,
@@ -3622,6 +3639,117 @@ class DriftClient {
3622
3639
  }
3623
3640
  return undefined;
3624
3641
  }
3642
+ getReceiverProgram() {
3643
+ if (this.receiverProgram === undefined) {
3644
+ this.receiverProgram = new anchor_1.Program(pyth_solana_receiver_1.pythSolanaReceiverIdl, pyth_solana_receiver_1.DEFAULT_RECEIVER_PROGRAM_ID, this.provider);
3645
+ }
3646
+ return this.receiverProgram;
3647
+ }
3648
+ async postPythPullOracleUpdateAtomic(vaaString, feedId) {
3649
+ const postIxs = await this.getPostPythPullOracleUpdateAtomicIxs(vaaString, feedId);
3650
+ const tx = await this.buildTransaction(postIxs);
3651
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
3652
+ return txSig;
3653
+ }
3654
+ async getPostPythPullOracleUpdateAtomicIxs(vaaString, feedId, numSignatures = 2) {
3655
+ feedId = (0, pythPullOracleUtils_1.trimFeedId)(feedId);
3656
+ const accumulatorUpdateData = (0, price_service_sdk_1.parseAccumulatorUpdateData)(Buffer.from(vaaString, 'base64'));
3657
+ const guardianSetIndex = accumulatorUpdateData.vaa.readUInt32BE(1);
3658
+ const guardianSet = (0, address_1.getGuardianSetPda)(guardianSetIndex, address_1.DEFAULT_WORMHOLE_PROGRAM_ID);
3659
+ const trimmedVaa = (0, oracles_1.trimVaaSignatures)(accumulatorUpdateData.vaa, numSignatures);
3660
+ const postIxs = [];
3661
+ for (const update of accumulatorUpdateData.updates) {
3662
+ postIxs.push(await this.getSinglePostPythPullOracleAtomicIx({
3663
+ vaa: trimmedVaa,
3664
+ merklePriceUpdate: update,
3665
+ }, feedId, guardianSet));
3666
+ }
3667
+ return postIxs;
3668
+ }
3669
+ async getSinglePostPythPullOracleAtomicIx(params, feedId, guardianSet) {
3670
+ const feedIdBuffer = (0, pythPullOracleUtils_1.getFeedIdUint8Array)(feedId);
3671
+ const receiverProgram = this.getReceiverProgram();
3672
+ const encodedParams = receiverProgram.coder.types.encode('PostUpdateAtomicParams', params);
3673
+ return this.program.instruction.postPythPullOracleUpdateAtomic(feedIdBuffer, encodedParams, {
3674
+ accounts: {
3675
+ keeper: this.wallet.publicKey,
3676
+ pythSolanaReceiver: config_2.DRIFT_ORACLE_RECEIVER_ID,
3677
+ guardianSet,
3678
+ priceFeed: (0, pda_1.getPythPullOraclePublicKey)(this.program.programId, feedIdBuffer),
3679
+ },
3680
+ });
3681
+ }
3682
+ async updatePythPullOracle(vaaString, feedId) {
3683
+ feedId = (0, pythPullOracleUtils_1.trimFeedId)(feedId);
3684
+ const accumulatorUpdateData = (0, price_service_sdk_1.parseAccumulatorUpdateData)(Buffer.from(vaaString, 'base64'));
3685
+ const guardianSetIndex = accumulatorUpdateData.vaa.readUInt32BE(1);
3686
+ const guardianSet = (0, address_1.getGuardianSetPda)(guardianSetIndex, address_1.DEFAULT_WORMHOLE_PROGRAM_ID);
3687
+ const [postIxs, encodedVaaAddress] = await this.getBuildEncodedVaaIxs(accumulatorUpdateData.vaa, guardianSet);
3688
+ for (const update of accumulatorUpdateData.updates) {
3689
+ postIxs.push(await this.getUpdatePythPullOracleIxs({
3690
+ merklePriceUpdate: update,
3691
+ }, feedId, encodedVaaAddress.publicKey));
3692
+ }
3693
+ const tx = await this.buildTransaction(postIxs);
3694
+ const { txSig } = await this.sendTransaction(tx, [encodedVaaAddress], this.opts);
3695
+ return txSig;
3696
+ }
3697
+ async getUpdatePythPullOracleIxs(params, feedId, encodedVaaAddress) {
3698
+ const feedIdBuffer = (0, pythPullOracleUtils_1.getFeedIdUint8Array)(feedId);
3699
+ const receiverProgram = this.getReceiverProgram();
3700
+ const encodedParams = receiverProgram.coder.types.encode('PostUpdateParams', params);
3701
+ return this.program.instruction.updatePythPullOracle(feedIdBuffer, encodedParams, {
3702
+ accounts: {
3703
+ keeper: this.wallet.publicKey,
3704
+ pythSolanaReceiver: config_2.DRIFT_ORACLE_RECEIVER_ID,
3705
+ encodedVaa: encodedVaaAddress,
3706
+ priceFeed: (0, pda_1.getPythPullOraclePublicKey)(this.program.programId, feedIdBuffer),
3707
+ },
3708
+ });
3709
+ }
3710
+ async getBuildEncodedVaaIxs(vaa, guardianSet) {
3711
+ const postIxs = [];
3712
+ if (this.wormholeProgram === undefined) {
3713
+ this.wormholeProgram = new anchor_1.Program(pyth_solana_receiver_1.wormholeCoreBridgeIdl, address_1.DEFAULT_WORMHOLE_PROGRAM_ID, this.provider);
3714
+ }
3715
+ const encodedVaaKeypair = new web3_js_1.Keypair();
3716
+ postIxs.push(await this.wormholeProgram.account.encodedVaa.createInstruction(encodedVaaKeypair, vaa.length + 46));
3717
+ // Why do we need this too?
3718
+ postIxs.push(await this.wormholeProgram.methods
3719
+ .initEncodedVaa()
3720
+ .accounts({
3721
+ encodedVaa: encodedVaaKeypair.publicKey,
3722
+ })
3723
+ .instruction());
3724
+ // Split the write into two ixs
3725
+ postIxs.push(await this.wormholeProgram.methods
3726
+ .writeEncodedVaa({
3727
+ index: 0,
3728
+ data: vaa.subarray(0, 755),
3729
+ })
3730
+ .accounts({
3731
+ draftVaa: encodedVaaKeypair.publicKey,
3732
+ })
3733
+ .instruction());
3734
+ postIxs.push(await this.wormholeProgram.methods
3735
+ .writeEncodedVaa({
3736
+ index: 755,
3737
+ data: vaa.subarray(755),
3738
+ })
3739
+ .accounts({
3740
+ draftVaa: encodedVaaKeypair.publicKey,
3741
+ })
3742
+ .instruction());
3743
+ // Verify
3744
+ postIxs.push(await this.wormholeProgram.methods
3745
+ .verifyEncodedVaaV1()
3746
+ .accounts({
3747
+ guardianSet,
3748
+ draftVaa: encodedVaaKeypair.publicKey,
3749
+ })
3750
+ .instruction());
3751
+ return [postIxs, encodedVaaKeypair];
3752
+ }
3625
3753
  handleSignedTransaction(signedTxs) {
3626
3754
  if (this.enableMetricsEvents && this.metricsEventEmitter) {
3627
3755
  this.metricsEventEmitter.emit('txSigned', signedTxs);
@@ -3633,9 +3761,7 @@ class DriftClient {
3633
3761
  }
3634
3762
  }
3635
3763
  isVersionedTransaction(tx) {
3636
- const version = tx === null || tx === void 0 ? void 0 : tx.version;
3637
- const isVersionedTx = tx instanceof web3_js_1.VersionedTransaction || version !== undefined;
3638
- return isVersionedTx;
3764
+ return (0, utils_2.isVersionedTransaction)(tx);
3639
3765
  }
3640
3766
  sendTransaction(tx, additionalSigners, opts, preSigned) {
3641
3767
  const isVersionedTx = this.isVersionedTransaction(tx);
@@ -4,7 +4,7 @@ import { OracleInfo } from './oracles/types';
4
4
  import { BulkAccountLoader } from './accounts/bulkAccountLoader';
5
5
  import { DriftEnv } from './config';
6
6
  import { TxSender } from './tx/types';
7
- import { TxHandler } from './tx/txHandler';
7
+ import { TxHandler, TxHandlerConfig } from './tx/txHandler';
8
8
  export type DriftClientConfig = {
9
9
  connection: Connection;
10
10
  wallet: IWallet;
@@ -28,6 +28,7 @@ export type DriftClientConfig = {
28
28
  txVersion?: TransactionVersion;
29
29
  txParams?: TxParams;
30
30
  enableMetricsEvents?: boolean;
31
+ txHandlerConfig?: TxHandlerConfig;
31
32
  };
32
33
  export type DriftClientSubscriptionConfig = {
33
34
  type: 'websocket';