@drift-labs/sdk 2.152.0-beta.2 → 2.153.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.
@@ -94,6 +94,8 @@ export class TitanClient {
94
94
  url: string;
95
95
  connection: Connection;
96
96
  proxyUrl?: string;
97
+ private lastQuoteData?: SwapQuotes;
98
+ private lastQuoteParams?: string;
97
99
 
98
100
  constructor({
99
101
  connection,
@@ -112,15 +114,12 @@ export class TitanClient {
112
114
  this.proxyUrl = proxyUrl;
113
115
  }
114
116
 
115
- /**
116
- * Get routes for a swap
117
- */
118
- public async getQuote({
117
+ private buildParams({
119
118
  inputMint,
120
119
  outputMint,
121
120
  amount,
122
121
  userPublicKey,
123
- maxAccounts = 50, // 50 is an estimated amount with buffer
122
+ maxAccounts,
124
123
  slippageBps,
125
124
  swapMode,
126
125
  onlyDirectRoutes,
@@ -134,32 +133,78 @@ export class TitanClient {
134
133
  userPublicKey: PublicKey;
135
134
  maxAccounts?: number;
136
135
  slippageBps?: number;
137
- swapMode?: string;
136
+ swapMode?: string | SwapMode;
138
137
  onlyDirectRoutes?: boolean;
139
138
  excludeDexes?: string[];
140
139
  sizeConstraint?: number;
141
140
  accountsLimitWritable?: number;
142
- }): Promise<QuoteResponse> {
143
- const params = new URLSearchParams({
141
+ }): URLSearchParams {
142
+ // Normalize swapMode to enum value
143
+ const normalizedSwapMode =
144
+ swapMode === 'ExactOut' || swapMode === SwapMode.ExactOut
145
+ ? SwapMode.ExactOut
146
+ : SwapMode.ExactIn;
147
+
148
+ return new URLSearchParams({
144
149
  inputMint: inputMint.toString(),
145
150
  outputMint: outputMint.toString(),
146
151
  amount: amount.toString(),
147
152
  userPublicKey: userPublicKey.toString(),
148
153
  ...(slippageBps && { slippageBps: slippageBps.toString() }),
149
- ...(swapMode && {
150
- swapMode:
151
- swapMode === 'ExactOut' ? SwapMode.ExactOut : SwapMode.ExactIn,
152
- }),
154
+ ...(swapMode && { swapMode: normalizedSwapMode.toString() }),
155
+ ...(maxAccounts && { accountsLimitTotal: maxAccounts.toString() }),
156
+ ...(excludeDexes && { excludeDexes: excludeDexes.join(',') }),
153
157
  ...(onlyDirectRoutes && {
154
158
  onlyDirectRoutes: onlyDirectRoutes.toString(),
155
159
  }),
156
- ...(maxAccounts && { accountsLimitTotal: maxAccounts.toString() }),
157
- ...(excludeDexes && { excludeDexes: excludeDexes.join(',') }),
158
160
  ...(sizeConstraint && { sizeConstraint: sizeConstraint.toString() }),
159
161
  ...(accountsLimitWritable && {
160
162
  accountsLimitWritable: accountsLimitWritable.toString(),
161
163
  }),
162
164
  });
165
+ }
166
+
167
+ /**
168
+ * Get routes for a swap
169
+ */
170
+ public async getQuote({
171
+ inputMint,
172
+ outputMint,
173
+ amount,
174
+ userPublicKey,
175
+ maxAccounts = 50, // 50 is an estimated amount with buffer
176
+ slippageBps,
177
+ swapMode,
178
+ onlyDirectRoutes,
179
+ excludeDexes,
180
+ sizeConstraint,
181
+ accountsLimitWritable,
182
+ }: {
183
+ inputMint: PublicKey;
184
+ outputMint: PublicKey;
185
+ amount: BN;
186
+ userPublicKey: PublicKey;
187
+ maxAccounts?: number;
188
+ slippageBps?: number;
189
+ swapMode?: string;
190
+ onlyDirectRoutes?: boolean;
191
+ excludeDexes?: string[];
192
+ sizeConstraint?: number;
193
+ accountsLimitWritable?: number;
194
+ }): Promise<QuoteResponse> {
195
+ const params = this.buildParams({
196
+ inputMint,
197
+ outputMint,
198
+ amount,
199
+ userPublicKey,
200
+ maxAccounts,
201
+ slippageBps,
202
+ swapMode,
203
+ onlyDirectRoutes,
204
+ excludeDexes,
205
+ sizeConstraint,
206
+ accountsLimitWritable,
207
+ });
163
208
 
164
209
  let response: Response;
165
210
 
@@ -195,11 +240,12 @@ export class TitanClient {
195
240
  const buffer = await response.arrayBuffer();
196
241
  const data = decode(buffer) as SwapQuotes;
197
242
 
198
- const route =
199
- data.quotes[
200
- Object.keys(data.quotes).find((key) => key.toLowerCase() === 'titan') ||
201
- ''
202
- ];
243
+ // Cache the quote data and parameters for later use in getSwap
244
+ this.lastQuoteData = data;
245
+ this.lastQuoteParams = params.toString();
246
+
247
+ // We are only querying for the best avaiable route so use that
248
+ const route = data.quotes[Object.keys(data.quotes)[0]];
203
249
 
204
250
  if (!route) {
205
251
  throw new Error('No routes available');
@@ -268,66 +314,32 @@ export class TitanClient {
268
314
  transactionMessage: TransactionMessage;
269
315
  lookupTables: AddressLookupTableAccount[];
270
316
  }> {
271
- const params = new URLSearchParams({
272
- inputMint: inputMint.toString(),
273
- outputMint: outputMint.toString(),
274
- amount: amount.toString(),
275
- userPublicKey: userPublicKey.toString(),
276
- ...(slippageBps && { slippageBps: slippageBps.toString() }),
277
- ...(swapMode && { swapMode: swapMode }),
278
- ...(maxAccounts && { accountsLimitTotal: maxAccounts.toString() }),
279
- ...(excludeDexes && { excludeDexes: excludeDexes.join(',') }),
280
- ...(onlyDirectRoutes && {
281
- onlyDirectRoutes: onlyDirectRoutes.toString(),
282
- }),
283
- ...(sizeConstraint && { sizeConstraint: sizeConstraint.toString() }),
284
- ...(accountsLimitWritable && {
285
- accountsLimitWritable: accountsLimitWritable.toString(),
286
- }),
317
+ const params = this.buildParams({
318
+ inputMint,
319
+ outputMint,
320
+ amount,
321
+ userPublicKey,
322
+ maxAccounts,
323
+ slippageBps,
324
+ swapMode,
325
+ onlyDirectRoutes,
326
+ excludeDexes,
327
+ sizeConstraint,
328
+ accountsLimitWritable,
287
329
  });
288
330
 
289
- let response: Response;
290
-
291
- if (this.proxyUrl) {
292
- // Use proxy route - send parameters in request body
293
- response = await fetch(this.proxyUrl, {
294
- method: 'POST',
295
- headers: {
296
- 'Content-Type': 'application/json',
297
- },
298
- body: JSON.stringify(Object.fromEntries(params.entries())),
299
- });
300
- } else {
301
- // Direct request to Titan API
302
- response = await fetch(
303
- `${this.url}/api/v1/quote/swap?${params.toString()}`,
304
- {
305
- headers: {
306
- Accept: 'application/vnd.msgpack',
307
- 'Accept-Encoding': 'gzip, deflate, br',
308
- Authorization: `Bearer ${this.authToken}`,
309
- },
310
- }
311
- );
312
- }
313
-
314
- if (!response.ok) {
315
- if (response.status === 404) {
316
- throw new Error('No routes available');
317
- }
331
+ // Check if we have cached quote data that matches the current parameters
332
+ if (!this.lastQuoteData || this.lastQuoteParams !== params.toString()) {
318
333
  throw new Error(
319
- `Titan API error: ${response.status} ${response.statusText}`
334
+ 'No matching quote data found. Please get a fresh quote before attempting to swap.'
320
335
  );
321
336
  }
322
337
 
323
- const buffer = await response.arrayBuffer();
324
- const data = decode(buffer) as SwapQuotes;
338
+ // Reuse the cached quote data
339
+ const data = this.lastQuoteData;
325
340
 
326
- const route =
327
- data.quotes[
328
- Object.keys(data.quotes).find((key) => key.toLowerCase() === 'titan') ||
329
- ''
330
- ];
341
+ // We are only querying for the best avaiable route so use that
342
+ const route = data.quotes[Object.keys(data.quotes)[0]];
331
343
 
332
344
  if (!route) {
333
345
  throw new Error('No routes available');
@@ -342,6 +354,10 @@ export class TitanClient {
342
354
  throw new Error(
343
355
  'Something went wrong with creating the Titan swap transaction. Please try again.'
344
356
  );
357
+ } finally {
358
+ // Clear cached quote data after use
359
+ this.lastQuoteData = undefined;
360
+ this.lastQuoteParams = undefined;
345
361
  }
346
362
  }
347
363
  throw new Error('No instructions provided in the route');
package/src/user.ts CHANGED
@@ -4587,7 +4587,7 @@ export class User {
4587
4587
  return calc;
4588
4588
  }
4589
4589
 
4590
- private isPerpPositionIsolated(perpPosition: PerpPosition): boolean {
4590
+ public isPerpPositionIsolated(perpPosition: PerpPosition): boolean {
4591
4591
  return (perpPosition.positionFlag & PositionFlag.IsolatedPosition) !== 0;
4592
4592
  }
4593
4593
  }