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,730 @@
1
+ /**
2
+ * Bonk Protocol Instruction Builder
3
+ *
4
+ * Production-grade instruction builder for Bonk AMM protocol.
5
+ * Supports buy and sell operations with WSOL and USD1 pools.
6
+ * 100% port from Rust: src/instruction/bonk.rs
7
+ */
8
+
9
+ import {
10
+ PublicKey,
11
+ Keypair,
12
+ AccountMeta,
13
+ TransactionInstruction,
14
+ SystemProgram,
15
+ } from "@solana/web3.js";
16
+ import {
17
+ getAssociatedTokenAddressSync,
18
+ createAssociatedTokenAccountInstruction,
19
+ TOKEN_PROGRAM_ID,
20
+ createCloseAccountInstruction,
21
+ NATIVE_MINT,
22
+ createSyncNativeInstruction,
23
+ } from "@solana/spl-token";
24
+
25
+ // ============================================
26
+ // Program IDs and Constants - from Rust src/instruction/utils/bonk.rs
27
+ // ============================================
28
+
29
+ /** Bonk program ID */
30
+ export const BONK_PROGRAM_ID = new PublicKey(
31
+ "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj"
32
+ );
33
+
34
+ /** Bonk Authority */
35
+ export const BONK_AUTHORITY = new PublicKey(
36
+ "WLhv2UAZm6z4KyaaELi5pjdbJh6RESMva1Rnn8pJVVh"
37
+ );
38
+
39
+ /** Bonk Global Config */
40
+ export const BONK_GLOBAL_CONFIG = new PublicKey(
41
+ "6s1xP3hpbAfFoNtUNF8mfHsjr2Bd97JxFJRWLbL6aHuX"
42
+ );
43
+
44
+ /** Bonk USD1 Global Config */
45
+ export const BONK_USD1_GLOBAL_CONFIG = new PublicKey(
46
+ "EPiZbnrThjyLnoQ6QQzkxeFqyL5uyg9RzNHHAudUPxBz"
47
+ );
48
+
49
+ /** Bonk Event Authority */
50
+ export const BONK_EVENT_AUTHORITY = new PublicKey(
51
+ "2DPAtwB8L12vrMRExbLuyGnC7n2J5LNoZQSejeQGpwkr"
52
+ );
53
+
54
+ /** WSOL Token Account (mint) */
55
+ export const WSOL_MINT = new PublicKey(
56
+ "So11111111111111111111111111111111111111112"
57
+ );
58
+
59
+ /** USD1 Token Account (mint) */
60
+ export const USD1_MINT = new PublicKey(
61
+ "USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB"
62
+ );
63
+
64
+ /** USDC Token Account (mint) */
65
+ export const USDC_MINT = new PublicKey(
66
+ "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
67
+ );
68
+
69
+ /** Fee rates - from Rust */
70
+ export const BONK_PLATFORM_FEE_RATE = BigInt(100); // 1%
71
+ export const BONK_PROTOCOL_FEE_RATE = BigInt(25); // 0.25%
72
+ export const BONK_SHARE_FEE_RATE = BigInt(0); // 0%
73
+
74
+ // ============================================
75
+ // Discriminators - from Rust src/instruction/utils/bonk.rs
76
+ // ============================================
77
+
78
+ /** Buy exact in instruction discriminator */
79
+ export const BONK_BUY_EXACT_IN_DISCRIMINATOR: Buffer = Buffer.from([
80
+ 250, 234, 13, 123, 213, 156, 19, 236,
81
+ ]);
82
+
83
+ /** Sell exact in instruction discriminator */
84
+ export const BONK_SELL_EXACT_IN_DISCRIMINATOR: Buffer = Buffer.from([
85
+ 149, 39, 222, 155, 211, 124, 152, 26,
86
+ ]);
87
+
88
+ // ============================================
89
+ // Seeds
90
+ // ============================================
91
+
92
+ export const BONK_POOL_SEED = Buffer.from("pool");
93
+ export const BONK_POOL_VAULT_SEED = Buffer.from("pool_vault");
94
+
95
+ // ============================================
96
+ // PDA Derivation Functions
97
+ // ============================================
98
+
99
+ /**
100
+ * Derive the pool PDA for given base and quote mints
101
+ */
102
+ export function getBonkPoolPda(baseMint: PublicKey, quoteMint: PublicKey): PublicKey {
103
+ const [pda] = PublicKey.findProgramAddressSync(
104
+ [BONK_POOL_SEED, baseMint.toBuffer(), quoteMint.toBuffer()],
105
+ BONK_PROGRAM_ID
106
+ );
107
+ return pda;
108
+ }
109
+
110
+ /**
111
+ * Derive the vault PDA for given pool and mint
112
+ */
113
+ export function getBonkVaultPda(poolState: PublicKey, mint: PublicKey): PublicKey {
114
+ const [pda] = PublicKey.findProgramAddressSync(
115
+ [BONK_POOL_VAULT_SEED, poolState.toBuffer(), mint.toBuffer()],
116
+ BONK_PROGRAM_ID
117
+ );
118
+ return pda;
119
+ }
120
+
121
+ /**
122
+ * Get platform associated account PDA
123
+ */
124
+ export function getBonkPlatformAssociatedAccount(platformConfig: PublicKey): PublicKey {
125
+ const [pda] = PublicKey.findProgramAddressSync(
126
+ [platformConfig.toBuffer(), WSOL_MINT.toBuffer()],
127
+ BONK_PROGRAM_ID
128
+ );
129
+ return pda;
130
+ }
131
+
132
+ /**
133
+ * Get creator associated account PDA
134
+ */
135
+ export function getBonkCreatorAssociatedAccount(creator: PublicKey): PublicKey {
136
+ const [pda] = PublicKey.findProgramAddressSync(
137
+ [creator.toBuffer(), WSOL_MINT.toBuffer()],
138
+ BONK_PROGRAM_ID
139
+ );
140
+ return pda;
141
+ }
142
+
143
+ // ============================================
144
+ // Types
145
+ // ============================================
146
+
147
+ export interface BonkParams {
148
+ poolState: PublicKey;
149
+ baseVault: PublicKey;
150
+ quoteVault: PublicKey;
151
+ virtualBase: bigint;
152
+ virtualQuote: bigint;
153
+ realBase: bigint;
154
+ realQuote: bigint;
155
+ mintTokenProgram: PublicKey;
156
+ platformConfig: PublicKey;
157
+ platformAssociatedAccount: PublicKey;
158
+ creatorAssociatedAccount: PublicKey;
159
+ globalConfig?: PublicKey;
160
+ }
161
+
162
+ export interface BonkBuildBuyParams {
163
+ payer: Keypair | PublicKey;
164
+ outputMint: PublicKey;
165
+ inputAmount: bigint;
166
+ slippageBasisPoints?: bigint;
167
+ fixedOutputAmount?: bigint;
168
+ createInputMintAta?: boolean;
169
+ createOutputMintAta?: boolean;
170
+ closeInputMintAta?: boolean;
171
+ protocolParams: BonkParams;
172
+ }
173
+
174
+ export interface BonkBuildSellParams {
175
+ payer: Keypair | PublicKey;
176
+ inputMint: PublicKey;
177
+ inputAmount: bigint;
178
+ slippageBasisPoints?: bigint;
179
+ fixedOutputAmount?: bigint;
180
+ createOutputMintAta?: boolean;
181
+ closeOutputMintAta?: boolean;
182
+ closeInputMintAta?: boolean;
183
+ protocolParams: BonkParams;
184
+ }
185
+
186
+ // ============================================
187
+ // Helper Functions
188
+ // ============================================
189
+
190
+ function getAmountOut(
191
+ amountIn: bigint,
192
+ protocolFeeRate: bigint,
193
+ platformFeeRate: bigint,
194
+ shareFeeRate: bigint,
195
+ virtualBase: bigint,
196
+ virtualQuote: bigint,
197
+ realBase: bigint,
198
+ realQuote: bigint,
199
+ slippageBps: bigint,
200
+ ): bigint {
201
+ const protocolFee = (amountIn * protocolFeeRate) / BigInt(10000);
202
+ const platformFee = (amountIn * platformFeeRate) / BigInt(10000);
203
+ const shareFee = (amountIn * shareFeeRate) / BigInt(10000);
204
+ const amountInNet = amountIn - protocolFee - platformFee - shareFee;
205
+
206
+ const inputReserve = virtualQuote + realQuote;
207
+ const outputReserve = virtualBase - realBase;
208
+ const numerator = amountInNet * outputReserve;
209
+ const denominator = inputReserve + amountInNet;
210
+ let amountOut = numerator / denominator;
211
+
212
+ amountOut = amountOut - (amountOut * slippageBps) / BigInt(10000);
213
+ return amountOut;
214
+ }
215
+
216
+ // ============================================
217
+ // Instruction Builders
218
+ // ============================================
219
+
220
+ /**
221
+ * Build buy instructions for Bonk protocol
222
+ * 100% port from Rust: src/instruction/bonk.rs build_buy_instructions
223
+ */
224
+ export function buildBonkBuyInstructions(
225
+ params: BonkBuildBuyParams
226
+ ): TransactionInstruction[] {
227
+ const {
228
+ payer,
229
+ outputMint,
230
+ inputAmount,
231
+ slippageBasisPoints = BigInt(1000),
232
+ fixedOutputAmount,
233
+ createInputMintAta = true,
234
+ createOutputMintAta = true,
235
+ closeInputMintAta = false,
236
+ protocolParams,
237
+ } = params;
238
+
239
+ if (inputAmount === BigInt(0)) {
240
+ throw new Error("Amount cannot be zero");
241
+ }
242
+
243
+ const payerPubkey = payer instanceof Keypair ? payer.publicKey : payer;
244
+ const instructions: TransactionInstruction[] = [];
245
+
246
+ const isUsd1Pool = protocolParams.globalConfig?.equals(BONK_USD1_GLOBAL_CONFIG) ?? false;
247
+ const quoteMint = isUsd1Pool ? USD1_MINT : WSOL_MINT;
248
+
249
+ // Get pool state
250
+ const poolState = protocolParams.poolState.equals(PublicKey.default)
251
+ ? getBonkPoolPda(outputMint, quoteMint)
252
+ : protocolParams.poolState;
253
+
254
+ const globalConfig = isUsd1Pool ? BONK_USD1_GLOBAL_CONFIG : BONK_GLOBAL_CONFIG;
255
+
256
+ // Calculate minimum output
257
+ const minimumAmountOut = fixedOutputAmount ?? getAmountOut(
258
+ inputAmount,
259
+ BONK_PROTOCOL_FEE_RATE,
260
+ BONK_PLATFORM_FEE_RATE,
261
+ BONK_SHARE_FEE_RATE,
262
+ protocolParams.virtualBase,
263
+ protocolParams.virtualQuote,
264
+ protocolParams.realBase,
265
+ protocolParams.realQuote,
266
+ slippageBasisPoints,
267
+ );
268
+
269
+ // Derive token accounts
270
+ const userBaseTokenAccount = getAssociatedTokenAddressSync(
271
+ outputMint,
272
+ payerPubkey,
273
+ true,
274
+ protocolParams.mintTokenProgram,
275
+ );
276
+ const userQuoteTokenAccount = getAssociatedTokenAddressSync(
277
+ quoteMint,
278
+ payerPubkey,
279
+ true,
280
+ TOKEN_PROGRAM_ID,
281
+ );
282
+
283
+ // Derive vaults
284
+ const baseVault = protocolParams.baseVault.equals(PublicKey.default)
285
+ ? getBonkVaultPda(poolState, outputMint)
286
+ : protocolParams.baseVault;
287
+ const quoteVault = protocolParams.quoteVault.equals(PublicKey.default)
288
+ ? getBonkVaultPda(poolState, quoteMint)
289
+ : protocolParams.quoteVault;
290
+
291
+ // Handle WSOL wrapping
292
+ if (createInputMintAta && !isUsd1Pool) {
293
+ const wsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, payerPubkey, true, TOKEN_PROGRAM_ID);
294
+ instructions.push(
295
+ createAssociatedTokenAccountInstruction(payerPubkey, wsolAta, payerPubkey, NATIVE_MINT)
296
+ );
297
+ // Transfer SOL
298
+ const transferIx = SystemProgram.transfer({
299
+ fromPubkey: payerPubkey,
300
+ toPubkey: wsolAta,
301
+ lamports: Number(inputAmount),
302
+ });
303
+ instructions.push(transferIx);
304
+ // Sync native
305
+ instructions.push(createSyncNativeInstruction(wsolAta));
306
+ }
307
+
308
+ // Create output ATA
309
+ if (createOutputMintAta) {
310
+ instructions.push(
311
+ createAssociatedTokenAccountInstruction(
312
+ payerPubkey,
313
+ userBaseTokenAccount,
314
+ payerPubkey,
315
+ outputMint,
316
+ protocolParams.mintTokenProgram,
317
+ )
318
+ );
319
+ }
320
+
321
+ // Build instruction data
322
+ const shareFeeRate = BigInt(0);
323
+ const data = Buffer.alloc(32);
324
+ BONK_BUY_EXACT_IN_DISCRIMINATOR.copy(data, 0);
325
+ data.writeBigUInt64LE(inputAmount, 8);
326
+ data.writeBigUInt64LE(minimumAmountOut, 16);
327
+ data.writeBigUInt64LE(shareFeeRate, 24);
328
+
329
+ // Build accounts
330
+ const keys: AccountMeta[] = [
331
+ { pubkey: payerPubkey, isSigner: true, isWritable: true },
332
+ { pubkey: BONK_AUTHORITY, isSigner: false, isWritable: false },
333
+ { pubkey: globalConfig, isSigner: false, isWritable: false },
334
+ { pubkey: protocolParams.platformConfig, isSigner: false, isWritable: false },
335
+ { pubkey: poolState, isSigner: false, isWritable: true },
336
+ { pubkey: userBaseTokenAccount, isSigner: false, isWritable: true },
337
+ { pubkey: userQuoteTokenAccount, isSigner: false, isWritable: true },
338
+ { pubkey: baseVault, isSigner: false, isWritable: true },
339
+ { pubkey: quoteVault, isSigner: false, isWritable: true },
340
+ { pubkey: outputMint, isSigner: false, isWritable: false },
341
+ { pubkey: quoteMint, isSigner: false, isWritable: false },
342
+ { pubkey: protocolParams.mintTokenProgram, isSigner: false, isWritable: false },
343
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
344
+ { pubkey: BONK_EVENT_AUTHORITY, isSigner: false, isWritable: false },
345
+ { pubkey: BONK_PROGRAM_ID, isSigner: false, isWritable: false },
346
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
347
+ { pubkey: protocolParams.platformAssociatedAccount, isSigner: false, isWritable: true },
348
+ { pubkey: protocolParams.creatorAssociatedAccount, isSigner: false, isWritable: true },
349
+ ];
350
+
351
+ instructions.push(
352
+ new TransactionInstruction({
353
+ keys,
354
+ programId: BONK_PROGRAM_ID,
355
+ data,
356
+ })
357
+ );
358
+
359
+ // Close WSOL ATA
360
+ if (closeInputMintAta && !isUsd1Pool) {
361
+ const wsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, payerPubkey, true, TOKEN_PROGRAM_ID);
362
+ instructions.push(
363
+ createCloseAccountInstruction(wsolAta, payerPubkey, payerPubkey)
364
+ );
365
+ }
366
+
367
+ return instructions;
368
+ }
369
+
370
+ /**
371
+ * Build sell instructions for Bonk protocol
372
+ * 100% port from Rust: src/instruction/bonk.rs build_sell_instructions
373
+ */
374
+ export function buildBonkSellInstructions(
375
+ params: BonkBuildSellParams
376
+ ): TransactionInstruction[] {
377
+ const {
378
+ payer,
379
+ inputMint,
380
+ inputAmount,
381
+ slippageBasisPoints = BigInt(1000),
382
+ fixedOutputAmount,
383
+ createOutputMintAta = true,
384
+ closeOutputMintAta = false,
385
+ closeInputMintAta = false,
386
+ protocolParams,
387
+ } = params;
388
+
389
+ if (inputAmount === BigInt(0)) {
390
+ throw new Error("Amount cannot be zero");
391
+ }
392
+
393
+ const payerPubkey = payer instanceof Keypair ? payer.publicKey : payer;
394
+ const instructions: TransactionInstruction[] = [];
395
+
396
+ const isUsd1Pool = protocolParams.globalConfig?.equals(BONK_USD1_GLOBAL_CONFIG) ?? false;
397
+ const quoteMint = isUsd1Pool ? USD1_MINT : WSOL_MINT;
398
+
399
+ // Get pool state
400
+ const poolState = protocolParams.poolState.equals(PublicKey.default)
401
+ ? getBonkPoolPda(inputMint, quoteMint)
402
+ : protocolParams.poolState;
403
+
404
+ const globalConfig = isUsd1Pool ? BONK_USD1_GLOBAL_CONFIG : BONK_GLOBAL_CONFIG;
405
+
406
+ // Calculate minimum output
407
+ const minimumAmountOut = fixedOutputAmount ?? getAmountOut(
408
+ inputAmount,
409
+ BONK_PROTOCOL_FEE_RATE,
410
+ BONK_PLATFORM_FEE_RATE,
411
+ BONK_SHARE_FEE_RATE,
412
+ protocolParams.virtualBase,
413
+ protocolParams.virtualQuote,
414
+ protocolParams.realBase,
415
+ protocolParams.realQuote,
416
+ slippageBasisPoints,
417
+ );
418
+
419
+ // Derive token accounts
420
+ const userBaseTokenAccount = getAssociatedTokenAddressSync(
421
+ inputMint,
422
+ payerPubkey,
423
+ true,
424
+ protocolParams.mintTokenProgram,
425
+ );
426
+ const userQuoteTokenAccount = getAssociatedTokenAddressSync(
427
+ quoteMint,
428
+ payerPubkey,
429
+ true,
430
+ TOKEN_PROGRAM_ID,
431
+ );
432
+
433
+ // Derive vaults
434
+ const baseVault = protocolParams.baseVault.equals(PublicKey.default)
435
+ ? getBonkVaultPda(poolState, inputMint)
436
+ : protocolParams.baseVault;
437
+ const quoteVault = protocolParams.quoteVault.equals(PublicKey.default)
438
+ ? getBonkVaultPda(poolState, quoteMint)
439
+ : protocolParams.quoteVault;
440
+
441
+ // Create output ATA for WSOL
442
+ if (createOutputMintAta && !isUsd1Pool) {
443
+ const wsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, payerPubkey, true, TOKEN_PROGRAM_ID);
444
+ instructions.push(
445
+ createAssociatedTokenAccountInstruction(payerPubkey, wsolAta, payerPubkey, NATIVE_MINT)
446
+ );
447
+ }
448
+
449
+ // Build instruction data
450
+ const shareFeeRate = BigInt(0);
451
+ const data = Buffer.alloc(32);
452
+ BONK_SELL_EXACT_IN_DISCRIMINATOR.copy(data, 0);
453
+ data.writeBigUInt64LE(inputAmount, 8);
454
+ data.writeBigUInt64LE(minimumAmountOut, 16);
455
+ data.writeBigUInt64LE(shareFeeRate, 24);
456
+
457
+ // Build accounts
458
+ const keys: AccountMeta[] = [
459
+ { pubkey: payerPubkey, isSigner: true, isWritable: true },
460
+ { pubkey: BONK_AUTHORITY, isSigner: false, isWritable: false },
461
+ { pubkey: globalConfig, isSigner: false, isWritable: false },
462
+ { pubkey: protocolParams.platformConfig, isSigner: false, isWritable: false },
463
+ { pubkey: poolState, isSigner: false, isWritable: true },
464
+ { pubkey: userBaseTokenAccount, isSigner: false, isWritable: true },
465
+ { pubkey: userQuoteTokenAccount, isSigner: false, isWritable: true },
466
+ { pubkey: baseVault, isSigner: false, isWritable: true },
467
+ { pubkey: quoteVault, isSigner: false, isWritable: true },
468
+ { pubkey: inputMint, isSigner: false, isWritable: false },
469
+ { pubkey: quoteMint, isSigner: false, isWritable: false },
470
+ { pubkey: protocolParams.mintTokenProgram, isSigner: false, isWritable: false },
471
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
472
+ { pubkey: BONK_EVENT_AUTHORITY, isSigner: false, isWritable: false },
473
+ { pubkey: BONK_PROGRAM_ID, isSigner: false, isWritable: false },
474
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
475
+ { pubkey: protocolParams.platformAssociatedAccount, isSigner: false, isWritable: true },
476
+ { pubkey: protocolParams.creatorAssociatedAccount, isSigner: false, isWritable: true },
477
+ ];
478
+
479
+ instructions.push(
480
+ new TransactionInstruction({
481
+ keys,
482
+ programId: BONK_PROGRAM_ID,
483
+ data,
484
+ })
485
+ );
486
+
487
+ // Close WSOL ATA
488
+ if (closeOutputMintAta && !isUsd1Pool) {
489
+ const wsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, payerPubkey, true, TOKEN_PROGRAM_ID);
490
+ instructions.push(
491
+ createCloseAccountInstruction(wsolAta, payerPubkey, payerPubkey)
492
+ );
493
+ }
494
+
495
+ // Close input token account
496
+ if (closeInputMintAta) {
497
+ instructions.push(
498
+ createCloseAccountInstruction(userBaseTokenAccount, payerPubkey, payerPubkey, [], protocolParams.mintTokenProgram)
499
+ );
500
+ }
501
+
502
+ return instructions;
503
+ }
504
+
505
+ // ===== Pool State Decoder - from Rust: src/instruction/utils/bonk_types.rs =====
506
+
507
+ export const BONK_POOL_STATE_SIZE = 421; // 8 + 1*5 + 8*10 + 32*7 + 8*8 + 8*5
508
+
509
+ export interface BonkVestingSchedule {
510
+ totalLockedAmount: bigint;
511
+ cliffPeriod: bigint;
512
+ unlockPeriod: bigint;
513
+ startTime: bigint;
514
+ allocatedShareAmount: bigint;
515
+ }
516
+
517
+ export interface BonkPoolState {
518
+ epoch: bigint;
519
+ authBump: number;
520
+ status: number;
521
+ baseDecimals: number;
522
+ quoteDecimals: number;
523
+ migrateType: number;
524
+ supply: bigint;
525
+ totalBaseSell: bigint;
526
+ virtualBase: bigint;
527
+ virtualQuote: bigint;
528
+ realBase: bigint;
529
+ realQuote: bigint;
530
+ totalQuoteFundRaising: bigint;
531
+ quoteProtocolFee: bigint;
532
+ platformFee: bigint;
533
+ migrateFee: bigint;
534
+ vestingSchedule: BonkVestingSchedule;
535
+ globalConfig: PublicKey;
536
+ platformConfig: PublicKey;
537
+ baseMint: PublicKey;
538
+ quoteMint: PublicKey;
539
+ baseVault: PublicKey;
540
+ quoteVault: PublicKey;
541
+ creator: PublicKey;
542
+ }
543
+
544
+ /**
545
+ * Decode a Bonk pool state from account data
546
+ * 100% from Rust: src/instruction/utils/bonk_types.rs pool_state_decode
547
+ */
548
+ export function decodeBonkPoolState(data: Buffer): BonkPoolState | null {
549
+ if (data.length < BONK_POOL_STATE_SIZE) {
550
+ return null;
551
+ }
552
+
553
+ try {
554
+ let offset = 0;
555
+
556
+ // epoch: u64
557
+ const epoch = data.readBigUInt64LE(offset);
558
+ offset += 8;
559
+
560
+ // auth_bump: u8
561
+ const authBump = data.readUInt8(offset);
562
+ offset += 1;
563
+
564
+ // status: u8
565
+ const status = data.readUInt8(offset);
566
+ offset += 1;
567
+
568
+ // base_decimals: u8
569
+ const baseDecimals = data.readUInt8(offset);
570
+ offset += 1;
571
+
572
+ // quote_decimals: u8
573
+ const quoteDecimals = data.readUInt8(offset);
574
+ offset += 1;
575
+
576
+ // migrate_type: u8
577
+ const migrateType = data.readUInt8(offset);
578
+ offset += 1;
579
+
580
+ // supply: u64
581
+ const supply = data.readBigUInt64LE(offset);
582
+ offset += 8;
583
+
584
+ // total_base_sell: u64
585
+ const totalBaseSell = data.readBigUInt64LE(offset);
586
+ offset += 8;
587
+
588
+ // virtual_base: u64
589
+ const virtualBase = data.readBigUInt64LE(offset);
590
+ offset += 8;
591
+
592
+ // virtual_quote: u64
593
+ const virtualQuote = data.readBigUInt64LE(offset);
594
+ offset += 8;
595
+
596
+ // real_base: u64
597
+ const realBase = data.readBigUInt64LE(offset);
598
+ offset += 8;
599
+
600
+ // real_quote: u64
601
+ const realQuote = data.readBigUInt64LE(offset);
602
+ offset += 8;
603
+
604
+ // total_quote_fund_raising: u64
605
+ const totalQuoteFundRaising = data.readBigUInt64LE(offset);
606
+ offset += 8;
607
+
608
+ // quote_protocol_fee: u64
609
+ const quoteProtocolFee = data.readBigUInt64LE(offset);
610
+ offset += 8;
611
+
612
+ // platform_fee: u64
613
+ const platformFee = data.readBigUInt64LE(offset);
614
+ offset += 8;
615
+
616
+ // migrate_fee: u64
617
+ const migrateFee = data.readBigUInt64LE(offset);
618
+ offset += 8;
619
+
620
+ // vesting_schedule: VestingSchedule (5 * u64)
621
+ const vestingSchedule: BonkVestingSchedule = {
622
+ totalLockedAmount: data.readBigUInt64LE(offset),
623
+ cliffPeriod: data.readBigUInt64LE(offset + 8),
624
+ unlockPeriod: data.readBigUInt64LE(offset + 16),
625
+ startTime: data.readBigUInt64LE(offset + 24),
626
+ allocatedShareAmount: data.readBigUInt64LE(offset + 32),
627
+ };
628
+ offset += 40;
629
+
630
+ // global_config: Pubkey
631
+ const globalConfig = new PublicKey(data.subarray(offset, offset + 32));
632
+ offset += 32;
633
+
634
+ // platform_config: Pubkey
635
+ const platformConfig = new PublicKey(data.subarray(offset, offset + 32));
636
+ offset += 32;
637
+
638
+ // base_mint: Pubkey
639
+ const baseMint = new PublicKey(data.subarray(offset, offset + 32));
640
+ offset += 32;
641
+
642
+ // quote_mint: Pubkey
643
+ const quoteMint = new PublicKey(data.subarray(offset, offset + 32));
644
+ offset += 32;
645
+
646
+ // base_vault: Pubkey
647
+ const baseVault = new PublicKey(data.subarray(offset, offset + 32));
648
+ offset += 32;
649
+
650
+ // quote_vault: Pubkey
651
+ const quoteVault = new PublicKey(data.subarray(offset, offset + 32));
652
+ offset += 32;
653
+
654
+ // creator: Pubkey
655
+ const creator = new PublicKey(data.subarray(offset, offset + 32));
656
+ // offset += 32; // Not needed, last field
657
+
658
+ return {
659
+ epoch,
660
+ authBump,
661
+ status,
662
+ baseDecimals,
663
+ quoteDecimals,
664
+ migrateType,
665
+ supply,
666
+ totalBaseSell,
667
+ virtualBase,
668
+ virtualQuote,
669
+ realBase,
670
+ realQuote,
671
+ totalQuoteFundRaising,
672
+ quoteProtocolFee,
673
+ platformFee,
674
+ migrateFee,
675
+ vestingSchedule,
676
+ globalConfig,
677
+ platformConfig,
678
+ baseMint,
679
+ quoteMint,
680
+ baseVault,
681
+ quoteVault,
682
+ creator,
683
+ };
684
+ } catch {
685
+ return null;
686
+ }
687
+ }
688
+
689
+ // ===== Async Fetch Functions - from Rust: src/instruction/utils/bonk.rs =====
690
+
691
+ /**
692
+ * Fetch a Bonk pool state from RPC.
693
+ * 100% from Rust: src/instruction/utils/bonk.rs fetch_pool_state
694
+ */
695
+ export async function fetchBonkPoolState(
696
+ connection: { getAccountInfo: (pubkey: PublicKey) => Promise<{ value?: { data: Buffer } }> },
697
+ poolAddress: PublicKey
698
+ ): Promise<BonkPoolState | null> {
699
+ const account = await connection.getAccountInfo(poolAddress);
700
+ if (!account?.value?.data) {
701
+ return null;
702
+ }
703
+ return decodeBonkPoolState(account.value.data);
704
+ }
705
+
706
+ /**
707
+ * Get pool PDA for Bonk.
708
+ * Seeds: ["pool", base_mint, quote_mint]
709
+ */
710
+ export function getBonkPoolPDA(baseMint: PublicKey, quoteMint: PublicKey): PublicKey {
711
+ const POOL_SEED = Buffer.from('pool');
712
+ const [pda] = PublicKey.findProgramAddressSync(
713
+ [POOL_SEED, baseMint.toBuffer(), quoteMint.toBuffer()],
714
+ BONK_PROGRAM_ID
715
+ );
716
+ return pda;
717
+ }
718
+
719
+ /**
720
+ * Get vault PDA for Bonk.
721
+ * Seeds: ["pool_vault", pool_state, mint]
722
+ */
723
+ export function getBonkVaultPDA(poolState: PublicKey, mint: PublicKey): PublicKey {
724
+ const POOL_VAULT_SEED = Buffer.from('pool_vault');
725
+ const [pda] = PublicKey.findProgramAddressSync(
726
+ [POOL_VAULT_SEED, poolState.toBuffer(), mint.toBuffer()],
727
+ BONK_PROGRAM_ID
728
+ );
729
+ return pda;
730
+ }