@drift-labs/sdk 2.145.0-beta.0 → 2.145.0-beta.1

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.
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UnifiedSwapClient = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const anchor_1 = require("@coral-xyz/anchor");
6
+ const jupiterClient_1 = require("../jupiter/jupiterClient");
7
+ const titanClient_1 = require("../titan/titanClient");
8
+ class UnifiedSwapClient {
9
+ constructor({ clientType, connection, authToken, url, }) {
10
+ this.clientType = clientType;
11
+ if (clientType === 'jupiter') {
12
+ this.client = new jupiterClient_1.JupiterClient({
13
+ connection,
14
+ url,
15
+ });
16
+ }
17
+ else if (clientType === 'titan') {
18
+ if (!authToken) {
19
+ throw new Error('authToken is required for Titan client');
20
+ }
21
+ this.client = new titanClient_1.TitanClient({
22
+ connection,
23
+ authToken,
24
+ url,
25
+ });
26
+ }
27
+ else {
28
+ throw new Error(`Unsupported client type: ${clientType}`);
29
+ }
30
+ }
31
+ /**
32
+ * Get a swap quote from the underlying client
33
+ */
34
+ async getQuote(params) {
35
+ if (this.clientType === 'jupiter') {
36
+ const jupiterClient = this.client;
37
+ const { userPublicKey: _userPublicKey, // Not needed for Jupiter
38
+ sizeConstraint: _sizeConstraint, // Jupiter-specific params to exclude
39
+ accountsLimitWritable: _accountsLimitWritable, ...jupiterParams } = params;
40
+ return await jupiterClient.getQuote(jupiterParams);
41
+ }
42
+ else {
43
+ const titanClient = this.client;
44
+ const { autoSlippage: _autoSlippage, // Titan-specific params to exclude
45
+ maxAutoSlippageBps: _maxAutoSlippageBps, usdEstimate: _usdEstimate, ...titanParams } = params;
46
+ if (!titanParams.userPublicKey) {
47
+ throw new Error('userPublicKey is required for Titan quotes');
48
+ }
49
+ // Cast to ensure TypeScript knows userPublicKey is defined
50
+ const titanParamsWithUser = {
51
+ ...titanParams,
52
+ userPublicKey: titanParams.userPublicKey,
53
+ swapMode: titanParams.swapMode, // Titan expects string
54
+ };
55
+ return await titanClient.getQuote(titanParamsWithUser);
56
+ }
57
+ }
58
+ /**
59
+ * Get a swap transaction from the underlying client
60
+ */
61
+ async getSwap(params) {
62
+ if (this.clientType === 'jupiter') {
63
+ const jupiterClient = this.client;
64
+ // Cast the quote to Jupiter's QuoteResponse type
65
+ const jupiterParams = {
66
+ ...params,
67
+ quote: params.quote,
68
+ };
69
+ const transaction = await jupiterClient.getSwap(jupiterParams);
70
+ return { transaction };
71
+ }
72
+ else {
73
+ const titanClient = this.client;
74
+ const { quote, userPublicKey, slippageBps } = params;
75
+ // For Titan, we need to reconstruct the parameters from the quote
76
+ const titanQuote = quote;
77
+ const result = await titanClient.getSwap({
78
+ inputMint: new web3_js_1.PublicKey(titanQuote.inputMint),
79
+ outputMint: new web3_js_1.PublicKey(titanQuote.outputMint),
80
+ amount: new anchor_1.BN(titanQuote.inAmount),
81
+ userPublicKey,
82
+ slippageBps: slippageBps || titanQuote.slippageBps,
83
+ swapMode: titanQuote.swapMode,
84
+ });
85
+ return {
86
+ transactionMessage: result.transactionMessage,
87
+ lookupTables: result.lookupTables,
88
+ };
89
+ }
90
+ }
91
+ /**
92
+ * Get swap instructions from the underlying client (Jupiter or Titan)
93
+ * This is the core swap logic without any context preparation
94
+ */
95
+ async getSwapInstructions({ inputMint, outputMint, amount, userPublicKey, slippageBps, swapMode = 'ExactIn', onlyDirectRoutes = false, quote, sizeConstraint, }) {
96
+ const isExactOut = swapMode === 'ExactOut';
97
+ let swapInstructions;
98
+ let lookupTables;
99
+ if (this.clientType === 'jupiter') {
100
+ const jupiterClient = this.client;
101
+ // Get quote if not provided
102
+ let finalQuote = quote;
103
+ if (!finalQuote) {
104
+ finalQuote = await jupiterClient.getQuote({
105
+ inputMint,
106
+ outputMint,
107
+ amount,
108
+ slippageBps,
109
+ swapMode,
110
+ onlyDirectRoutes,
111
+ });
112
+ }
113
+ if (!finalQuote) {
114
+ throw new Error("Could not fetch Jupiter's quote. Please try again.");
115
+ }
116
+ // Get swap transaction and extract instructions
117
+ const transaction = await jupiterClient.getSwap({
118
+ quote: finalQuote,
119
+ userPublicKey,
120
+ slippageBps,
121
+ });
122
+ const { transactionMessage, lookupTables: jupiterLookupTables } = await jupiterClient.getTransactionMessageAndLookupTables({
123
+ transaction,
124
+ });
125
+ swapInstructions = jupiterClient.getJupiterInstructions({
126
+ transactionMessage,
127
+ inputMint,
128
+ outputMint,
129
+ });
130
+ lookupTables = jupiterLookupTables;
131
+ }
132
+ else {
133
+ const titanClient = this.client;
134
+ // For Titan, get swap directly (it handles quote internally)
135
+ const { transactionMessage, lookupTables: titanLookupTables } = await titanClient.getSwap({
136
+ inputMint,
137
+ outputMint,
138
+ amount,
139
+ userPublicKey,
140
+ slippageBps,
141
+ swapMode: isExactOut ? titanClient_1.SwapMode.ExactOut : titanClient_1.SwapMode.ExactIn,
142
+ onlyDirectRoutes,
143
+ sizeConstraint: sizeConstraint || 1280 - 375, // MAX_TX_BYTE_SIZE - buffer for drift instructions
144
+ });
145
+ swapInstructions = titanClient.getTitanInstructions({
146
+ transactionMessage,
147
+ inputMint,
148
+ outputMint,
149
+ });
150
+ lookupTables = titanLookupTables;
151
+ }
152
+ return { instructions: swapInstructions, lookupTables };
153
+ }
154
+ /**
155
+ * Get the underlying client instance
156
+ */
157
+ getClient() {
158
+ return this.client;
159
+ }
160
+ /**
161
+ * Get the client type
162
+ */
163
+ getClientType() {
164
+ return this.clientType;
165
+ }
166
+ /**
167
+ * Check if this is a Jupiter client
168
+ */
169
+ isJupiter() {
170
+ return this.clientType === 'jupiter';
171
+ }
172
+ /**
173
+ * Check if this is a Titan client
174
+ */
175
+ isTitan() {
176
+ return this.clientType === 'titan';
177
+ }
178
+ }
179
+ exports.UnifiedSwapClient = UnifiedSwapClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.145.0-beta.0",
3
+ "version": "2.145.0-beta.1",
4
4
  "main": "lib/node/index.js",
5
5
  "types": "lib/node/index.d.ts",
6
6
  "module": "./lib/browser/index.js",
@@ -157,11 +157,8 @@ import { isSpotPositionAvailable } from './math/spotPosition';
157
157
  import { calculateMarketMaxAvailableInsurance } from './math/market';
158
158
  import { fetchUserStatsAccount } from './accounts/fetch';
159
159
  import { castNumberToSpotPrecision } from './math/spotMarket';
160
- import {
161
- JupiterClient,
162
- QuoteResponse,
163
- SwapMode,
164
- } from './jupiter/jupiterClient';
160
+ import { JupiterClient, QuoteResponse } from './jupiter/jupiterClient';
161
+ import { SwapMode } from './swap/UnifiedSwapClient';
165
162
  import { getNonIdleUserFilter } from './memcmp';
166
163
  import { UserStatsSubscriptionConfig } from './userStatsConfig';
167
164
  import { getMarinadeDepositIx, getMarinadeFinanceProgram } from './marinade';
@@ -210,9 +207,11 @@ import {
210
207
  isBuilderOrderCompleted,
211
208
  } from './math/builder';
212
209
  import { TitanClient, SwapMode as TitanSwapMode } from './titan/titanClient';
210
+ import { UnifiedSwapClient } from './swap/UnifiedSwapClient';
213
211
 
214
212
  /**
215
- * Union type for swap clients (Titan and Jupiter)
213
+ * Union type for swap clients (Titan and Jupiter) - Legacy type
214
+ * @deprecated Use UnifiedSwapClient class instead
216
215
  */
217
216
  export type SwapClient = TitanClient | JupiterClient;
218
217
 
@@ -5772,7 +5771,7 @@ export class DriftClient {
5772
5771
  quote,
5773
5772
  onlyDirectRoutes = false,
5774
5773
  }: {
5775
- swapClient: SwapClient;
5774
+ swapClient: UnifiedSwapClient | SwapClient;
5776
5775
  outMarketIndex: number;
5777
5776
  inMarketIndex: number;
5778
5777
  outAssociatedTokenAccount?: PublicKey;
@@ -5793,7 +5792,23 @@ export class DriftClient {
5793
5792
  lookupTables: AddressLookupTableAccount[];
5794
5793
  };
5795
5794
 
5796
- if (swapClient instanceof TitanClient) {
5795
+ // Use unified SwapClient if available
5796
+ if (swapClient instanceof UnifiedSwapClient) {
5797
+ res = await this.getSwapIxV2({
5798
+ swapClient,
5799
+ outMarketIndex,
5800
+ inMarketIndex,
5801
+ outAssociatedTokenAccount,
5802
+ inAssociatedTokenAccount,
5803
+ amount,
5804
+ slippageBps,
5805
+ swapMode,
5806
+ onlyDirectRoutes,
5807
+ reduceOnly,
5808
+ quote,
5809
+ v6,
5810
+ });
5811
+ } else if (swapClient instanceof TitanClient) {
5797
5812
  res = await this.getTitanSwapIx({
5798
5813
  titanClient: swapClient,
5799
5814
  outMarketIndex,
@@ -5823,7 +5838,7 @@ export class DriftClient {
5823
5838
  });
5824
5839
  } else {
5825
5840
  throw new Error(
5826
- 'Invalid swap client type. Must be TitanClient or JupiterClient.'
5841
+ 'Invalid swap client type. Must be SwapClient, TitanClient, or JupiterClient.'
5827
5842
  );
5828
5843
  }
5829
5844
 
@@ -6243,6 +6258,134 @@ export class DriftClient {
6243
6258
  return { beginSwapIx, endSwapIx };
6244
6259
  }
6245
6260
 
6261
+ public async getSwapIxV2({
6262
+ swapClient,
6263
+ outMarketIndex,
6264
+ inMarketIndex,
6265
+ outAssociatedTokenAccount,
6266
+ inAssociatedTokenAccount,
6267
+ amount,
6268
+ slippageBps,
6269
+ swapMode,
6270
+ onlyDirectRoutes,
6271
+ reduceOnly,
6272
+ quote,
6273
+ v6,
6274
+ }: {
6275
+ swapClient: UnifiedSwapClient;
6276
+ outMarketIndex: number;
6277
+ inMarketIndex: number;
6278
+ outAssociatedTokenAccount?: PublicKey;
6279
+ inAssociatedTokenAccount?: PublicKey;
6280
+ amount: BN;
6281
+ slippageBps?: number;
6282
+ swapMode?: SwapMode;
6283
+ onlyDirectRoutes?: boolean;
6284
+ reduceOnly?: SwapReduceOnly;
6285
+ quote?: QuoteResponse;
6286
+ v6?: {
6287
+ quote?: QuoteResponse;
6288
+ };
6289
+ }): Promise<{
6290
+ ixs: TransactionInstruction[];
6291
+ lookupTables: AddressLookupTableAccount[];
6292
+ }> {
6293
+ // Get market accounts to determine mints
6294
+ const outMarket = this.getSpotMarketAccount(outMarketIndex);
6295
+ const inMarket = this.getSpotMarketAccount(inMarketIndex);
6296
+
6297
+ const isExactOut = swapMode === 'ExactOut';
6298
+ const exactOutBufferedAmountIn = amount.muln(1001).divn(1000); // Add 10bp buffer
6299
+
6300
+ const preInstructions: TransactionInstruction[] = [];
6301
+
6302
+ // Handle token accounts if not provided
6303
+ let finalOutAssociatedTokenAccount = outAssociatedTokenAccount;
6304
+ let finalInAssociatedTokenAccount = inAssociatedTokenAccount;
6305
+
6306
+ if (!finalOutAssociatedTokenAccount) {
6307
+ const tokenProgram = this.getTokenProgramForSpotMarket(outMarket);
6308
+ finalOutAssociatedTokenAccount = await this.getAssociatedTokenAccount(
6309
+ outMarket.marketIndex,
6310
+ false,
6311
+ tokenProgram
6312
+ );
6313
+
6314
+ const accountInfo = await this.connection.getAccountInfo(
6315
+ finalOutAssociatedTokenAccount
6316
+ );
6317
+ if (!accountInfo) {
6318
+ preInstructions.push(
6319
+ this.createAssociatedTokenAccountIdempotentInstruction(
6320
+ finalOutAssociatedTokenAccount,
6321
+ this.provider.wallet.publicKey,
6322
+ this.provider.wallet.publicKey,
6323
+ outMarket.mint,
6324
+ tokenProgram
6325
+ )
6326
+ );
6327
+ }
6328
+ }
6329
+
6330
+ if (!finalInAssociatedTokenAccount) {
6331
+ const tokenProgram = this.getTokenProgramForSpotMarket(inMarket);
6332
+ finalInAssociatedTokenAccount = await this.getAssociatedTokenAccount(
6333
+ inMarket.marketIndex,
6334
+ false,
6335
+ tokenProgram
6336
+ );
6337
+
6338
+ const accountInfo = await this.connection.getAccountInfo(
6339
+ finalInAssociatedTokenAccount
6340
+ );
6341
+ if (!accountInfo) {
6342
+ preInstructions.push(
6343
+ this.createAssociatedTokenAccountIdempotentInstruction(
6344
+ finalInAssociatedTokenAccount,
6345
+ this.provider.wallet.publicKey,
6346
+ this.provider.wallet.publicKey,
6347
+ inMarket.mint,
6348
+ tokenProgram
6349
+ )
6350
+ );
6351
+ }
6352
+ }
6353
+
6354
+ // Get drift swap instructions for begin and end
6355
+ const { beginSwapIx, endSwapIx } = await this.getSwapIx({
6356
+ outMarketIndex,
6357
+ inMarketIndex,
6358
+ amountIn: isExactOut ? exactOutBufferedAmountIn : amount,
6359
+ inTokenAccount: finalInAssociatedTokenAccount,
6360
+ outTokenAccount: finalOutAssociatedTokenAccount,
6361
+ reduceOnly,
6362
+ });
6363
+
6364
+ // Get core swap instructions from SwapClient
6365
+ const swapResult = await swapClient.getSwapInstructions({
6366
+ inputMint: inMarket.mint,
6367
+ outputMint: outMarket.mint,
6368
+ amount,
6369
+ userPublicKey: this.provider.wallet.publicKey,
6370
+ slippageBps,
6371
+ swapMode,
6372
+ onlyDirectRoutes,
6373
+ quote: quote ?? v6?.quote,
6374
+ });
6375
+
6376
+ const allInstructions = [
6377
+ ...preInstructions,
6378
+ beginSwapIx,
6379
+ ...swapResult.instructions,
6380
+ endSwapIx,
6381
+ ];
6382
+
6383
+ return {
6384
+ ixs: allInstructions,
6385
+ lookupTables: swapResult.lookupTables,
6386
+ };
6387
+ }
6388
+
6246
6389
  public async stakeForMSOL({ amount }: { amount: BN }): Promise<TxSigAndSlot> {
6247
6390
  const ixs = await this.getStakeForMSOLIx({ amount });
6248
6391
  const tx = await this.buildTransaction(ixs);
package/src/index.ts CHANGED
@@ -53,7 +53,8 @@ export * from './events/webSocketLogProvider';
53
53
  export * from './events/parse';
54
54
  export * from './events/pollingLogProvider';
55
55
  export * from './jupiter/jupiterClient';
56
- export { TitanClient } from './titan/titanClient';
56
+ // Primary swap client interface - use this for all swap operations
57
+ export * from './swap/UnifiedSwapClient';
57
58
  export * from './math/auction';
58
59
  export * from './math/builder';
59
60
  export * from './math/spotMarket';
@@ -8,8 +8,7 @@ import {
8
8
  } from '@solana/web3.js';
9
9
  import fetch from 'node-fetch';
10
10
  import { BN } from '@coral-xyz/anchor';
11
-
12
- export type SwapMode = 'ExactIn' | 'ExactOut';
11
+ import { SwapMode } from '../swap/UnifiedSwapClient';
13
12
 
14
13
  export interface MarketInfo {
15
14
  id: string;
@@ -0,0 +1,293 @@
1
+ import {
2
+ Connection,
3
+ PublicKey,
4
+ TransactionMessage,
5
+ AddressLookupTableAccount,
6
+ VersionedTransaction,
7
+ TransactionInstruction,
8
+ } from '@solana/web3.js';
9
+ import { BN } from '@coral-xyz/anchor';
10
+ import {
11
+ JupiterClient,
12
+ QuoteResponse as JupiterQuoteResponse,
13
+ } from '../jupiter/jupiterClient';
14
+ import {
15
+ TitanClient,
16
+ QuoteResponse as TitanQuoteResponse,
17
+ SwapMode as TitanSwapMode,
18
+ } from '../titan/titanClient';
19
+
20
+ export type SwapMode = 'ExactIn' | 'ExactOut';
21
+ export type SwapClientType = 'jupiter' | 'titan';
22
+
23
+ export type UnifiedQuoteResponse = JupiterQuoteResponse | TitanQuoteResponse;
24
+
25
+ export interface SwapQuoteParams {
26
+ inputMint: PublicKey;
27
+ outputMint: PublicKey;
28
+ amount: BN;
29
+ userPublicKey?: PublicKey; // Required for Titan, optional for Jupiter
30
+ maxAccounts?: number;
31
+ slippageBps?: number;
32
+ swapMode?: SwapMode;
33
+ onlyDirectRoutes?: boolean;
34
+ excludeDexes?: string[];
35
+ sizeConstraint?: number; // Titan-specific
36
+ accountsLimitWritable?: number; // Titan-specific
37
+ autoSlippage?: boolean; // Jupiter-specific
38
+ maxAutoSlippageBps?: number; // Jupiter-specific
39
+ usdEstimate?: number; // Jupiter-specific
40
+ }
41
+
42
+ export interface SwapTransactionParams {
43
+ quote: UnifiedQuoteResponse;
44
+ userPublicKey: PublicKey;
45
+ slippageBps?: number;
46
+ }
47
+
48
+ export interface SwapTransactionResult {
49
+ transaction?: VersionedTransaction; // Jupiter returns this
50
+ transactionMessage?: TransactionMessage; // Titan returns this
51
+ lookupTables?: AddressLookupTableAccount[]; // Titan returns this
52
+ }
53
+
54
+ export class UnifiedSwapClient {
55
+ private client: JupiterClient | TitanClient;
56
+ private clientType: SwapClientType;
57
+
58
+ constructor({
59
+ clientType,
60
+ connection,
61
+ authToken,
62
+ url,
63
+ }: {
64
+ clientType: SwapClientType;
65
+ connection: Connection;
66
+ authToken?: string; // Required for Titan, optional for Jupiter
67
+ url?: string; // Optional custom URL
68
+ }) {
69
+ this.clientType = clientType;
70
+
71
+ if (clientType === 'jupiter') {
72
+ this.client = new JupiterClient({
73
+ connection,
74
+ url,
75
+ });
76
+ } else if (clientType === 'titan') {
77
+ if (!authToken) {
78
+ throw new Error('authToken is required for Titan client');
79
+ }
80
+ this.client = new TitanClient({
81
+ connection,
82
+ authToken,
83
+ url,
84
+ });
85
+ } else {
86
+ throw new Error(`Unsupported client type: ${clientType}`);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Get a swap quote from the underlying client
92
+ */
93
+ public async getQuote(
94
+ params: SwapQuoteParams
95
+ ): Promise<UnifiedQuoteResponse> {
96
+ if (this.clientType === 'jupiter') {
97
+ const jupiterClient = this.client as JupiterClient;
98
+ const {
99
+ userPublicKey: _userPublicKey, // Not needed for Jupiter
100
+ sizeConstraint: _sizeConstraint, // Jupiter-specific params to exclude
101
+ accountsLimitWritable: _accountsLimitWritable,
102
+ ...jupiterParams
103
+ } = params;
104
+
105
+ return await jupiterClient.getQuote(jupiterParams);
106
+ } else {
107
+ const titanClient = this.client as TitanClient;
108
+ const {
109
+ autoSlippage: _autoSlippage, // Titan-specific params to exclude
110
+ maxAutoSlippageBps: _maxAutoSlippageBps,
111
+ usdEstimate: _usdEstimate,
112
+ ...titanParams
113
+ } = params;
114
+
115
+ if (!titanParams.userPublicKey) {
116
+ throw new Error('userPublicKey is required for Titan quotes');
117
+ }
118
+
119
+ // Cast to ensure TypeScript knows userPublicKey is defined
120
+ const titanParamsWithUser = {
121
+ ...titanParams,
122
+ userPublicKey: titanParams.userPublicKey,
123
+ swapMode: titanParams.swapMode as string, // Titan expects string
124
+ };
125
+
126
+ return await titanClient.getQuote(titanParamsWithUser);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Get a swap transaction from the underlying client
132
+ */
133
+ public async getSwap(
134
+ params: SwapTransactionParams
135
+ ): Promise<SwapTransactionResult> {
136
+ if (this.clientType === 'jupiter') {
137
+ const jupiterClient = this.client as JupiterClient;
138
+ // Cast the quote to Jupiter's QuoteResponse type
139
+ const jupiterParams = {
140
+ ...params,
141
+ quote: params.quote as JupiterQuoteResponse,
142
+ };
143
+ const transaction = await jupiterClient.getSwap(jupiterParams);
144
+ return { transaction };
145
+ } else {
146
+ const titanClient = this.client as TitanClient;
147
+ const { quote, userPublicKey, slippageBps } = params;
148
+
149
+ // For Titan, we need to reconstruct the parameters from the quote
150
+ const titanQuote = quote as TitanQuoteResponse;
151
+ const result = await titanClient.getSwap({
152
+ inputMint: new PublicKey(titanQuote.inputMint),
153
+ outputMint: new PublicKey(titanQuote.outputMint),
154
+ amount: new BN(titanQuote.inAmount),
155
+ userPublicKey,
156
+ slippageBps: slippageBps || titanQuote.slippageBps,
157
+ swapMode: titanQuote.swapMode,
158
+ });
159
+
160
+ return {
161
+ transactionMessage: result.transactionMessage,
162
+ lookupTables: result.lookupTables,
163
+ };
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Get swap instructions from the underlying client (Jupiter or Titan)
169
+ * This is the core swap logic without any context preparation
170
+ */
171
+ public async getSwapInstructions({
172
+ inputMint,
173
+ outputMint,
174
+ amount,
175
+ userPublicKey,
176
+ slippageBps,
177
+ swapMode = 'ExactIn',
178
+ onlyDirectRoutes = false,
179
+ quote,
180
+ sizeConstraint,
181
+ }: {
182
+ inputMint: PublicKey;
183
+ outputMint: PublicKey;
184
+ amount: BN;
185
+ userPublicKey: PublicKey;
186
+ slippageBps?: number;
187
+ swapMode?: SwapMode;
188
+ onlyDirectRoutes?: boolean;
189
+ quote?: UnifiedQuoteResponse;
190
+ sizeConstraint?: number;
191
+ }): Promise<{
192
+ instructions: TransactionInstruction[];
193
+ lookupTables: AddressLookupTableAccount[];
194
+ }> {
195
+ const isExactOut = swapMode === 'ExactOut';
196
+ let swapInstructions: TransactionInstruction[];
197
+ let lookupTables: AddressLookupTableAccount[];
198
+
199
+ if (this.clientType === 'jupiter') {
200
+ const jupiterClient = this.client as JupiterClient;
201
+
202
+ // Get quote if not provided
203
+ let finalQuote = quote as JupiterQuoteResponse;
204
+ if (!finalQuote) {
205
+ finalQuote = await jupiterClient.getQuote({
206
+ inputMint,
207
+ outputMint,
208
+ amount,
209
+ slippageBps,
210
+ swapMode,
211
+ onlyDirectRoutes,
212
+ });
213
+ }
214
+
215
+ if (!finalQuote) {
216
+ throw new Error("Could not fetch Jupiter's quote. Please try again.");
217
+ }
218
+
219
+ // Get swap transaction and extract instructions
220
+ const transaction = await jupiterClient.getSwap({
221
+ quote: finalQuote,
222
+ userPublicKey,
223
+ slippageBps,
224
+ });
225
+
226
+ const { transactionMessage, lookupTables: jupiterLookupTables } =
227
+ await jupiterClient.getTransactionMessageAndLookupTables({
228
+ transaction,
229
+ });
230
+
231
+ swapInstructions = jupiterClient.getJupiterInstructions({
232
+ transactionMessage,
233
+ inputMint,
234
+ outputMint,
235
+ });
236
+
237
+ lookupTables = jupiterLookupTables;
238
+ } else {
239
+ const titanClient = this.client as TitanClient;
240
+
241
+ // For Titan, get swap directly (it handles quote internally)
242
+ const { transactionMessage, lookupTables: titanLookupTables } =
243
+ await titanClient.getSwap({
244
+ inputMint,
245
+ outputMint,
246
+ amount,
247
+ userPublicKey,
248
+ slippageBps,
249
+ swapMode: isExactOut ? TitanSwapMode.ExactOut : TitanSwapMode.ExactIn,
250
+ onlyDirectRoutes,
251
+ sizeConstraint: sizeConstraint || 1280 - 375, // MAX_TX_BYTE_SIZE - buffer for drift instructions
252
+ });
253
+
254
+ swapInstructions = titanClient.getTitanInstructions({
255
+ transactionMessage,
256
+ inputMint,
257
+ outputMint,
258
+ });
259
+
260
+ lookupTables = titanLookupTables;
261
+ }
262
+
263
+ return { instructions: swapInstructions, lookupTables };
264
+ }
265
+
266
+ /**
267
+ * Get the underlying client instance
268
+ */
269
+ public getClient(): JupiterClient | TitanClient {
270
+ return this.client;
271
+ }
272
+
273
+ /**
274
+ * Get the client type
275
+ */
276
+ public getClientType(): SwapClientType {
277
+ return this.clientType;
278
+ }
279
+
280
+ /**
281
+ * Check if this is a Jupiter client
282
+ */
283
+ public isJupiter(): boolean {
284
+ return this.clientType === 'jupiter';
285
+ }
286
+
287
+ /**
288
+ * Check if this is a Titan client
289
+ */
290
+ public isTitan(): boolean {
291
+ return this.clientType === 'titan';
292
+ }
293
+ }