sol-trade-sdk 0.1.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 (87) hide show
  1. package/README.md +390 -0
  2. package/dist/chunk-MMQAMIKR.mjs +3735 -0
  3. package/dist/chunk-NEZDFAYA.mjs +7744 -0
  4. package/dist/clients-VITWK7B6.mjs +1370 -0
  5. package/dist/index-1BK_FXsW.d.mts +2327 -0
  6. package/dist/index-1BK_FXsW.d.ts +2327 -0
  7. package/dist/index.d.mts +2659 -0
  8. package/dist/index.d.ts +2659 -0
  9. package/dist/index.js +13265 -0
  10. package/dist/index.mjs +562 -0
  11. package/dist/perf/index.d.mts +2 -0
  12. package/dist/perf/index.d.ts +2 -0
  13. package/dist/perf/index.js +3742 -0
  14. package/dist/perf/index.mjs +214 -0
  15. package/package.json +101 -0
  16. package/src/__tests__/complete_sdk.test.ts +354 -0
  17. package/src/__tests__/hotpath.test.ts +486 -0
  18. package/src/__tests__/nonce.test.ts +45 -0
  19. package/src/__tests__/sdk.test.ts +425 -0
  20. package/src/address-lookup/index.ts +197 -0
  21. package/src/cache/cache.ts +308 -0
  22. package/src/calc/index.ts +1058 -0
  23. package/src/calc/pumpfun.ts +124 -0
  24. package/src/common/bonding_curve.ts +272 -0
  25. package/src/common/compute-budget.ts +148 -0
  26. package/src/common/confirm-any-signature.ts +184 -0
  27. package/src/common/fast-timing.ts +481 -0
  28. package/src/common/fast_fn.ts +150 -0
  29. package/src/common/gas-fee-strategy.ts +253 -0
  30. package/src/common/map-pool.ts +23 -0
  31. package/src/common/nonce.ts +40 -0
  32. package/src/common/sdk-log.ts +460 -0
  33. package/src/common/seed.ts +381 -0
  34. package/src/common/spl-token.ts +578 -0
  35. package/src/common/subscription-handle.ts +644 -0
  36. package/src/common/trading-utils.ts +239 -0
  37. package/src/common/wsol-manager.ts +325 -0
  38. package/src/compute/compute_budget_manager.ts +187 -0
  39. package/src/compute/index.ts +21 -0
  40. package/src/constants/index.ts +96 -0
  41. package/src/execution/execution.ts +532 -0
  42. package/src/execution/index.ts +42 -0
  43. package/src/hotpath/executor.ts +464 -0
  44. package/src/hotpath/index.ts +64 -0
  45. package/src/hotpath/state.ts +435 -0
  46. package/src/index.ts +2117 -0
  47. package/src/instruction/bonk_builder.ts +730 -0
  48. package/src/instruction/index.ts +24 -0
  49. package/src/instruction/meteora_damm_v2_builder.ts +509 -0
  50. package/src/instruction/pumpfun_builder.ts +1183 -0
  51. package/src/instruction/pumpswap.ts +1123 -0
  52. package/src/instruction/raydium_amm_v4_builder.ts +692 -0
  53. package/src/instruction/raydium_cpmm_builder.ts +795 -0
  54. package/src/middleware/traits.ts +407 -0
  55. package/src/params/index.ts +483 -0
  56. package/src/perf/compiler-optimization.ts +529 -0
  57. package/src/perf/hardware.ts +631 -0
  58. package/src/perf/index.ts +9 -0
  59. package/src/perf/kernel-bypass.ts +656 -0
  60. package/src/perf/protocol.ts +682 -0
  61. package/src/perf/realtime.ts +592 -0
  62. package/src/perf/simd.ts +668 -0
  63. package/src/perf/syscall-bypass.ts +331 -0
  64. package/src/perf/ultra-low-latency.ts +505 -0
  65. package/src/perf/zero-copy.ts +589 -0
  66. package/src/pool/pool.ts +294 -0
  67. package/src/rpc/client.ts +345 -0
  68. package/src/sdk-errors.ts +13 -0
  69. package/src/security/index.ts +26 -0
  70. package/src/security/secure-key.ts +303 -0
  71. package/src/security/validators.ts +281 -0
  72. package/src/seed/pda.ts +262 -0
  73. package/src/serialization/index.ts +28 -0
  74. package/src/serialization/serialization.ts +288 -0
  75. package/src/swqos/clients.ts +1754 -0
  76. package/src/swqos/index.ts +50 -0
  77. package/src/swqos/providers.ts +1707 -0
  78. package/src/trading/core/async-executor.ts +702 -0
  79. package/src/trading/core/confirmation-monitor.ts +711 -0
  80. package/src/trading/core/index.ts +82 -0
  81. package/src/trading/core/retry-handler.ts +683 -0
  82. package/src/trading/core/transaction-pool.ts +780 -0
  83. package/src/trading/executor.ts +385 -0
  84. package/src/trading/factory.ts +282 -0
  85. package/src/trading/index.ts +30 -0
  86. package/src/types.ts +8 -0
  87. package/src/utils/index.ts +155 -0
@@ -0,0 +1,464 @@
1
+ /**
2
+ * Hot Path Executor for Sol Trade SDK
3
+ *
4
+ * Executes trades with ZERO RPC calls in the hot path.
5
+ * All data must be prefetched before execution.
6
+ *
7
+ * Key principle: Prepare everything, then execute with minimal latency.
8
+ */
9
+
10
+ import { Connection, PublicKey, Transaction, TransactionInstruction } from '@solana/web3.js';
11
+ import {
12
+ HotPathState,
13
+ HotPathConfig,
14
+ TradingContext,
15
+ StaleBlockhashError,
16
+ defaultHotPathConfig,
17
+ } from './state';
18
+ import { SwqosClient } from '../swqos/clients';
19
+ import { SwqosType, TradeType } from '../index';
20
+
21
+ // ===== Types =====
22
+
23
+ export interface ExecuteOptions {
24
+ parallelSubmit: boolean;
25
+ timeoutMs: number;
26
+ skipBlockhashValidation: boolean;
27
+ maxRetries: number;
28
+ }
29
+
30
+ export function defaultExecuteOptions(): ExecuteOptions {
31
+ return {
32
+ parallelSubmit: true,
33
+ timeoutMs: 10000,
34
+ skipBlockhashValidation: false,
35
+ maxRetries: 3,
36
+ };
37
+ }
38
+
39
+ export interface ExecuteResult {
40
+ signature: string;
41
+ success: boolean;
42
+ error?: string;
43
+ latencyMs: number;
44
+ swqosType?: SwqosType;
45
+ blockhashUsed: string;
46
+ }
47
+
48
+ export interface GasFeeConfig {
49
+ computeUnitLimit: number;
50
+ computeUnitPrice: number;
51
+ }
52
+
53
+ // ===== Metrics =====
54
+
55
+ export class HotPathMetrics {
56
+ private totalTrades = 0;
57
+ private successTrades = 0;
58
+ private failedTrades = 0;
59
+ private totalLatencyMs = 0;
60
+
61
+ record(success: boolean, latencyMs: number): void {
62
+ this.totalTrades++;
63
+ if (success) {
64
+ this.successTrades++;
65
+ } else {
66
+ this.failedTrades++;
67
+ }
68
+ this.totalLatencyMs += latencyMs;
69
+ }
70
+
71
+ getStats(): {
72
+ totalTrades: number;
73
+ successTrades: number;
74
+ failedTrades: number;
75
+ avgLatencyMs: number;
76
+ } {
77
+ return {
78
+ totalTrades: this.totalTrades,
79
+ successTrades: this.successTrades,
80
+ failedTrades: this.failedTrades,
81
+ avgLatencyMs: this.totalTrades > 0 ? this.totalLatencyMs / this.totalTrades : 0,
82
+ };
83
+ }
84
+ }
85
+
86
+ // ===== Hot Path Executor =====
87
+
88
+ /**
89
+ * Executes trades with ZERO RPC calls in the hot path.
90
+ *
91
+ * Usage:
92
+ * 1. Create executor with RPC connection
93
+ * 2. Call start() to begin background prefetching
94
+ * 3. Prefetch required accounts/pools BEFORE trading
95
+ * 4. Build transaction with prefetched blockhash
96
+ * 5. Execute - no RPC calls during this phase
97
+ */
98
+ export class HotPathExecutor {
99
+ private state: HotPathState;
100
+ private config: HotPathConfig;
101
+ private connection: Connection;
102
+
103
+ // SWQoS clients for transaction submission
104
+ private swqosClients: Map<SwqosType, SwqosClient> = new Map();
105
+
106
+ // Metrics
107
+ private metrics = new HotPathMetrics();
108
+
109
+ constructor(connection: Connection, config?: Partial<HotPathConfig>) {
110
+ this.config = { ...defaultHotPathConfig(), ...config };
111
+ this.connection = connection;
112
+ this.state = new HotPathState(connection, config);
113
+ }
114
+
115
+ /**
116
+ * Add a SWQoS client for transaction submission
117
+ */
118
+ addSwqosClient(client: SwqosClient): void {
119
+ this.swqosClients.set(client.getSwqosType(), client);
120
+ }
121
+
122
+ /**
123
+ * Remove a SWQoS client
124
+ */
125
+ removeSwqosClient(swqosType: SwqosType): void {
126
+ this.swqosClients.delete(swqosType);
127
+ }
128
+
129
+ /**
130
+ * Get SWQoS client by type
131
+ */
132
+ getSwqosClient(swqosType: SwqosType): SwqosClient | undefined {
133
+ return this.swqosClients.get(swqosType);
134
+ }
135
+
136
+ /**
137
+ * Start background prefetching
138
+ */
139
+ async start(): Promise<void> {
140
+ await this.state.start();
141
+ }
142
+
143
+ /**
144
+ * Stop background prefetching
145
+ */
146
+ stop(): void {
147
+ this.state.stop();
148
+ }
149
+
150
+ /**
151
+ * Get hot path state for external access
152
+ */
153
+ getState(): HotPathState {
154
+ return this.state;
155
+ }
156
+
157
+ /**
158
+ * Check if executor is ready for hot path execution
159
+ */
160
+ isReady(): boolean {
161
+ return this.state.isDataFresh() && this.swqosClients.size > 0;
162
+ }
163
+
164
+ /**
165
+ * Wait until executor is ready
166
+ */
167
+ async waitForReady(
168
+ checkIntervalMs: number = 100,
169
+ timeoutMs: number = 30000
170
+ ): Promise<boolean> {
171
+ const startTime = Date.now();
172
+ while (Date.now() - startTime < timeoutMs) {
173
+ if (this.isReady()) {
174
+ return true;
175
+ }
176
+ await this.sleep(checkIntervalMs);
177
+ }
178
+ return false;
179
+ }
180
+
181
+ /**
182
+ * Prefetch accounts - call BEFORE hot path execution
183
+ */
184
+ async prefetchAccounts(pubkeys: string[]): Promise<void> {
185
+ await this.state.prefetchAccounts(pubkeys);
186
+ }
187
+
188
+ /**
189
+ * Create trading context with prefetched data - NO RPC
190
+ */
191
+ createTradingContext(payer: string): TradingContext {
192
+ return new TradingContext(this.state, payer);
193
+ }
194
+
195
+ /**
196
+ * Execute a pre-signed transaction - NO RPC CALLS
197
+ *
198
+ * Transaction must already be signed with valid blockhash.
199
+ * All state should be prefetched before calling this.
200
+ */
201
+ async execute(
202
+ tradeType: TradeType,
203
+ transactionBytes: Buffer,
204
+ opts: ExecuteOptions = defaultExecuteOptions()
205
+ ): Promise<ExecuteResult> {
206
+ const startTime = Date.now();
207
+
208
+ // Validate blockhash is fresh (no RPC, just check cache age)
209
+ if (!opts.skipBlockhashValidation && !this.state.isDataFresh()) {
210
+ return {
211
+ signature: '',
212
+ success: false,
213
+ error: 'Stale blockhash - prefetch required',
214
+ latencyMs: 0,
215
+ blockhashUsed: '',
216
+ };
217
+ }
218
+
219
+ // Get current blockhash for tracking
220
+ const blockhashData = this.state.getBlockhash();
221
+ const blockhashUsed = blockhashData?.blockhash || '';
222
+
223
+ // Get clients
224
+ const clients = Array.from(this.swqosClients.values());
225
+ if (clients.length === 0) {
226
+ return {
227
+ signature: '',
228
+ success: false,
229
+ error: 'No SWQoS clients configured',
230
+ latencyMs: 0,
231
+ blockhashUsed,
232
+ };
233
+ }
234
+
235
+ // Submit transaction
236
+ let result: ExecuteResult;
237
+ if (opts.parallelSubmit && clients.length > 1) {
238
+ result = await this.executeParallel(tradeType, transactionBytes, clients, opts);
239
+ } else {
240
+ result = await this.executeSequential(tradeType, transactionBytes, clients, opts);
241
+ }
242
+
243
+ result.latencyMs = Date.now() - startTime;
244
+ result.blockhashUsed = blockhashUsed;
245
+
246
+ // Update metrics
247
+ this.metrics.record(result.success, result.latencyMs);
248
+
249
+ return result;
250
+ }
251
+
252
+ /**
253
+ * Submit to all SWQoS clients in parallel - NO RPC
254
+ */
255
+ private async executeParallel(
256
+ tradeType: TradeType,
257
+ txBytes: Buffer,
258
+ clients: SwqosClient[],
259
+ opts: ExecuteOptions
260
+ ): Promise<ExecuteResult> {
261
+ const submitToClient = async (client: SwqosClient): Promise<ExecuteResult> => {
262
+ try {
263
+ const signature = await Promise.race([
264
+ client.sendTransaction(tradeType, txBytes, false),
265
+ new Promise<never>((_, reject) =>
266
+ setTimeout(() => reject(new Error('Timeout')), opts.timeoutMs)
267
+ ),
268
+ ]);
269
+ return {
270
+ signature,
271
+ success: true,
272
+ swqosType: client.getSwqosType(),
273
+ latencyMs: 0,
274
+ blockhashUsed: '',
275
+ };
276
+ } catch (error) {
277
+ return {
278
+ signature: '',
279
+ success: false,
280
+ error: error instanceof Error ? error.message : 'Unknown error',
281
+ swqosType: client.getSwqosType(),
282
+ latencyMs: 0,
283
+ blockhashUsed: '',
284
+ };
285
+ }
286
+ };
287
+
288
+ // Race all submissions - first success wins
289
+ const promises = clients.map(submitToClient);
290
+
291
+ try {
292
+ // Use Promise.any for first-success-wins
293
+ const result = await Promise.any(promises);
294
+ return result;
295
+ } catch {
296
+ // All failed - aggregate errors
297
+ const results = await Promise.allSettled(promises);
298
+ const errors = results
299
+ .filter((r): r is PromiseRejectedResult => r.status === 'rejected')
300
+ .map((r) => r.reason);
301
+ return {
302
+ signature: '',
303
+ success: false,
304
+ error: `All parallel submissions failed: ${errors.join(', ')}`,
305
+ latencyMs: 0,
306
+ blockhashUsed: '',
307
+ };
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Submit to SWQoS clients sequentially - NO RPC
313
+ */
314
+ private async executeSequential(
315
+ tradeType: TradeType,
316
+ txBytes: Buffer,
317
+ clients: SwqosClient[],
318
+ opts: ExecuteOptions
319
+ ): Promise<ExecuteResult> {
320
+ let lastError = 'No clients available';
321
+
322
+ for (let retry = 0; retry < opts.maxRetries; retry++) {
323
+ for (const client of clients) {
324
+ try {
325
+ const signature = await Promise.race([
326
+ client.sendTransaction(tradeType, txBytes, false),
327
+ new Promise<never>((_, reject) =>
328
+ setTimeout(() => reject(new Error('Timeout')), opts.timeoutMs)
329
+ ),
330
+ ]);
331
+ return {
332
+ signature,
333
+ success: true,
334
+ swqosType: client.getSwqosType(),
335
+ latencyMs: 0,
336
+ blockhashUsed: '',
337
+ };
338
+ } catch (error) {
339
+ lastError = error instanceof Error ? error.message : 'Unknown error';
340
+ }
341
+ }
342
+ }
343
+
344
+ return {
345
+ signature: '',
346
+ success: false,
347
+ error: `All sequential submissions failed after ${opts.maxRetries} retries: ${lastError}`,
348
+ latencyMs: 0,
349
+ blockhashUsed: '',
350
+ };
351
+ }
352
+
353
+ /**
354
+ * Execute multiple transactions in parallel
355
+ */
356
+ async executeMultiple(
357
+ tradeType: TradeType,
358
+ transactions: Buffer[],
359
+ opts: ExecuteOptions = defaultExecuteOptions()
360
+ ): Promise<ExecuteResult[]> {
361
+ return Promise.all((transactions).map((tx) => this.execute(tradeType, tx, opts)));
362
+ }
363
+
364
+ /**
365
+ * Get cached blockhash - NO RPC CALL
366
+ * Use this to build transactions before execution
367
+ */
368
+ getBlockhash(): { blockhash: string; lastValidBlockHeight: number } | null {
369
+ return this.state.getBlockhash();
370
+ }
371
+
372
+ /**
373
+ * Get execution metrics
374
+ */
375
+ getMetrics(): ReturnType<HotPathMetrics['getStats']> {
376
+ return this.metrics.getStats();
377
+ }
378
+
379
+ private sleep(ms: number): Promise<void> {
380
+ return new Promise((resolve) => setTimeout(resolve, ms));
381
+ }
382
+ }
383
+
384
+ // ===== Transaction Builder Helper =====
385
+
386
+ /**
387
+ * Builds transactions using prefetched data - NO RPC CALLS
388
+ *
389
+ * Use this to construct transactions before hot path execution.
390
+ */
391
+ export class TransactionBuilder {
392
+ constructor(private executor: HotPathExecutor) {}
393
+
394
+ /**
395
+ * Build a transaction using prefetched blockhash - NO RPC
396
+ */
397
+ async buildTransaction(
398
+ payer: PublicKey,
399
+ instructions: TransactionInstruction[],
400
+ signers: any[], // Keypair[]
401
+ gasConfig?: GasFeeConfig
402
+ ): Promise<Transaction | null> {
403
+ // Get blockhash from cache
404
+ const blockhashData = this.executor.getBlockhash();
405
+ if (!blockhashData) {
406
+ throw new StaleBlockhashError('Stale blockhash - prefetch required');
407
+ }
408
+
409
+ // Build transaction
410
+ const tx = new Transaction();
411
+
412
+ // Add compute budget instructions if gas config provided
413
+ if (gasConfig) {
414
+ // Add compute budget instructions
415
+ // These would use the compute budget program
416
+ }
417
+
418
+ // Add main instructions
419
+ tx.add(...instructions);
420
+
421
+ // Set blockhash and payer
422
+ tx.recentBlockhash = blockhashData.blockhash;
423
+ tx.feePayer = payer;
424
+
425
+ // Sign transaction
426
+ tx.sign(...signers);
427
+
428
+ return tx;
429
+ }
430
+ }
431
+
432
+ // ===== Convenience Factory =====
433
+
434
+ /**
435
+ * Create a hot path executor with default configuration.
436
+ *
437
+ * Usage:
438
+ * const executor = createHotPathExecutor(
439
+ * connection,
440
+ * [jitoClient, bloxrouteClient]
441
+ * );
442
+ * await executor.start();
443
+ *
444
+ * // Prefetch required data
445
+ * await executor.prefetchAccounts([tokenAccountPubkey]);
446
+ *
447
+ * // Now ready for hot path execution
448
+ * const result = await executor.execute('buy', txBytes);
449
+ */
450
+ export function createHotPathExecutor(
451
+ connection: Connection,
452
+ swqosClients?: SwqosClient[],
453
+ config?: Partial<HotPathConfig>
454
+ ): HotPathExecutor {
455
+ const executor = new HotPathExecutor(connection, config);
456
+
457
+ if (swqosClients) {
458
+ for (const client of swqosClients) {
459
+ executor.addSwqosClient(client);
460
+ }
461
+ }
462
+
463
+ return executor;
464
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Hot Path Module for Sol Trade SDK
3
+ *
4
+ * Provides optimized trading execution with ZERO RPC calls in the hot path.
5
+ * All data is prefetched before trading to minimize latency.
6
+ *
7
+ * Key Components:
8
+ * - HotPathState: Manages prefetched blockchain state
9
+ * - HotPathExecutor: Executes trades using cached data only
10
+ * - TradingContext: Context object for a single trade with all required data
11
+ *
12
+ * Usage:
13
+ * ```typescript
14
+ * const executor = new HotPathExecutor(connection);
15
+ * await executor.start();
16
+ *
17
+ * // Prefetch required data BEFORE trading
18
+ * await executor.prefetchAccounts([tokenAccountPubkey]);
19
+ *
20
+ * // Build transaction with cached blockhash
21
+ * const blockhash = executor.getBlockhash();
22
+ * // ... build transaction ...
23
+ *
24
+ * // Execute - NO RPC calls during this phase
25
+ * const result = await executor.execute('buy', txBytes);
26
+ * ```
27
+ */
28
+
29
+ export {
30
+ // State management
31
+ HotPathState,
32
+ TradingContext,
33
+ defaultHotPathConfig,
34
+ } from './state';
35
+
36
+ export type {
37
+ HotPathConfig,
38
+ PrefetchedData,
39
+ AccountState,
40
+ PoolState,
41
+ } from './state';
42
+
43
+ export type {
44
+ ExecuteOptions,
45
+ ExecuteResult,
46
+ GasFeeConfig,
47
+ } from './executor';
48
+
49
+ export {
50
+ // Execution
51
+ HotPathExecutor,
52
+ HotPathMetrics,
53
+ TransactionBuilder,
54
+ defaultExecuteOptions,
55
+ createHotPathExecutor,
56
+ } from './executor';
57
+
58
+ export {
59
+ // Errors
60
+ HotPathError,
61
+ StaleBlockhashError,
62
+ MissingAccountError,
63
+ ContextExpiredError,
64
+ } from './state';