sol-trade-sdk 0.1.0 → 0.1.2

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 (50) hide show
  1. package/README.md +12 -5
  2. package/dist/cache/index.d.mts +70 -0
  3. package/dist/cache/index.d.ts +70 -0
  4. package/dist/cache/index.js +259 -0
  5. package/dist/cache/index.mjs +19 -0
  6. package/dist/chunk-64JY4YH6.mjs +227 -0
  7. package/dist/chunk-6BWS3CLP.mjs +16 -0
  8. package/dist/{chunk-NEZDFAYA.mjs → chunk-H4ZUMTTP.mjs} +864 -336
  9. package/dist/{chunk-MMQAMIKR.mjs → chunk-L6RZIXXN.mjs} +4 -11
  10. package/dist/{clients-VITWK7B6.mjs → chunk-V7QDWUXJ.mjs} +39 -39
  11. package/dist/clients-PSG35HN4.mjs +107 -0
  12. package/dist/index-hZh5hrGj.d.mts +3089 -0
  13. package/dist/index-yJ5AsNfm.d.ts +3089 -0
  14. package/dist/index.d.mts +2 -2658
  15. package/dist/index.d.ts +2 -2658
  16. package/dist/index.js +794 -278
  17. package/dist/index.mjs +21 -4
  18. package/dist/perf/index.mjs +2 -1
  19. package/dist/pool/index.d.mts +88 -0
  20. package/dist/pool/index.d.ts +88 -0
  21. package/dist/pool/index.js +262 -0
  22. package/dist/pool/index.mjs +233 -0
  23. package/dist/rpc/index.d.mts +77 -0
  24. package/dist/rpc/index.d.ts +77 -0
  25. package/dist/rpc/index.js +447 -0
  26. package/dist/rpc/index.mjs +223 -0
  27. package/dist/swqos/index.d.mts +416 -0
  28. package/dist/swqos/index.d.ts +416 -0
  29. package/dist/swqos/index.js +3450 -0
  30. package/dist/swqos/index.mjs +1375 -0
  31. package/dist/trading/index.d.mts +998 -0
  32. package/dist/trading/index.d.ts +998 -0
  33. package/dist/trading/index.js +4302 -0
  34. package/dist/trading/index.mjs +2097 -0
  35. package/package.json +5 -4
  36. package/src/__tests__/hotpath.test.ts +33 -0
  37. package/src/__tests__/parser-compat.test.ts +82 -0
  38. package/src/__tests__/protocol-parity.test.ts +242 -0
  39. package/src/__tests__/sdk.test.ts +16 -0
  40. package/src/cache/index.ts +1 -0
  41. package/src/hotpath/executor.ts +25 -18
  42. package/src/index.ts +330 -92
  43. package/src/instruction/meteora_damm_v2_builder.ts +88 -20
  44. package/src/instruction/pumpfun_builder.ts +133 -43
  45. package/src/instruction/raydium_amm_v4_builder.ts +244 -35
  46. package/src/instruction/raydium_cpmm_builder.ts +87 -69
  47. package/src/params/index.ts +38 -5
  48. package/src/pool/index.ts +1 -0
  49. package/src/rpc/index.ts +1 -0
  50. package/src/trading/factory.ts +10 -0
@@ -230,14 +230,15 @@ import {
230
230
  } from "@solana/web3.js";
231
231
  import {
232
232
  getAssociatedTokenAddressSync,
233
- createAssociatedTokenAccountInstruction,
234
233
  createAssociatedTokenAccountIdempotentInstruction,
235
234
  TOKEN_PROGRAM_ID,
236
235
  TOKEN_2022_PROGRAM_ID,
237
236
  ASSOCIATED_TOKEN_PROGRAM_ID as SPL_ASSOCIATED_TOKEN_PROGRAM_ID,
238
237
  createCloseAccountInstruction,
238
+ createSyncNativeInstruction,
239
239
  NATIVE_MINT
240
240
  } from "@solana/spl-token";
241
+ var SOL_TOKEN_ACCOUNT2 = new PublicKey2("So11111111111111111111111111111111111111111");
241
242
  var PUMPFUN_PROGRAM_ID = new PublicKey2(
242
243
  "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
243
244
  );
@@ -489,7 +490,36 @@ function effectivePumpMintTokenProgram(mint, protocolParams) {
489
490
  return TOKEN_2022_PROGRAM_ID;
490
491
  }
491
492
  function effectiveQuoteMint(protocolParams) {
492
- return isUsablePubkey(protocolParams.quoteMint) ? protocolParams.quoteMint : NATIVE_MINT;
493
+ if (!isUsablePubkey(protocolParams.quoteMint) || protocolParams.quoteMint.equals(SOL_TOKEN_ACCOUNT2)) {
494
+ return NATIVE_MINT;
495
+ }
496
+ return protocolParams.quoteMint;
497
+ }
498
+ function usesPumpFunV2Layout(protocolParams) {
499
+ return isUsablePubkey(protocolParams.quoteMint) && !protocolParams.quoteMint.equals(SOL_TOKEN_ACCOUNT2);
500
+ }
501
+ function isSolQuoteMint(mint) {
502
+ return mint.equals(SOL_TOKEN_ACCOUNT2) || mint.equals(NATIVE_MINT);
503
+ }
504
+ function validateV2BuyQuoteMint(inputMint, quoteMint) {
505
+ if (isSolQuoteMint(quoteMint)) {
506
+ if (inputMint.equals(SOL_TOKEN_ACCOUNT2) || inputMint.equals(NATIVE_MINT)) return;
507
+ } else if (inputMint.equals(quoteMint)) {
508
+ return;
509
+ }
510
+ throw new Error(
511
+ `PumpFun V2 buy input_mint ${inputMint.toBase58()} does not match quote_mint ${quoteMint.toBase58()}; USDC quote pools must be bought with USDC, not SOL`
512
+ );
513
+ }
514
+ function validateV2SellQuoteMint(outputMint, quoteMint) {
515
+ if (isSolQuoteMint(quoteMint)) {
516
+ if (outputMint.equals(SOL_TOKEN_ACCOUNT2) || outputMint.equals(NATIVE_MINT)) return;
517
+ } else if (outputMint.equals(quoteMint)) {
518
+ return;
519
+ }
520
+ throw new Error(
521
+ `PumpFun V2 sell output_mint ${outputMint.toBase58()} does not match quote_mint ${quoteMint.toBase58()}; USDC quote pools settle to USDC, not SOL`
522
+ );
493
523
  }
494
524
  function associatedTokenAddress(mint, owner, tokenProgram) {
495
525
  return getAssociatedTokenAddressSync(
@@ -500,6 +530,28 @@ function associatedTokenAddress(mint, owner, tokenProgram) {
500
530
  SPL_ASSOCIATED_TOKEN_PROGRAM_ID
501
531
  );
502
532
  }
533
+ function pushCreateOrWrapUserTokenAccount(instructions, payer, ata, mint, tokenProgram, amount) {
534
+ instructions.push(
535
+ createAssociatedTokenAccountIdempotentInstruction(
536
+ payer,
537
+ ata,
538
+ payer,
539
+ mint,
540
+ tokenProgram,
541
+ SPL_ASSOCIATED_TOKEN_PROGRAM_ID
542
+ )
543
+ );
544
+ if (mint.equals(NATIVE_MINT)) {
545
+ instructions.push(
546
+ SystemProgram.transfer({
547
+ fromPubkey: payer,
548
+ toPubkey: ata,
549
+ lamports: amount
550
+ })
551
+ );
552
+ instructions.push(createSyncNativeInstruction(ata));
553
+ }
554
+ }
503
555
  function getBuyTokenAmountFromSolAmount(amount, bondingCurve, creator) {
504
556
  if (amount === 0n || bondingCurve.virtualTokenReserves === 0n) {
505
557
  return 0n;
@@ -529,21 +581,23 @@ function getSellSolAmountFromTokenAmount(amount, bondingCurve, creator) {
529
581
  function buildPumpFunBuyInstructions(params) {
530
582
  const {
531
583
  payer,
584
+ inputMint = SOL_TOKEN_ACCOUNT2,
532
585
  outputMint,
533
586
  inputAmount,
534
587
  slippageBasisPoints = BigInt(1e3),
535
588
  fixedOutputAmount,
536
589
  createOutputMintAta = true,
537
590
  createInputMintAta = false,
591
+ closeInputMintAta = false,
538
592
  protocolParams,
539
- useExactSolAmount = true,
540
- usePumpFunV2 = false
593
+ useExactSolAmount = true
541
594
  } = params;
542
- if (usePumpFunV2 || protocolParams.useV2Ix || isUsablePubkey(protocolParams.quoteMint)) {
595
+ if (usesPumpFunV2Layout(protocolParams)) {
543
596
  return buildPumpFunBuyV2Instructions({
544
597
  ...params,
598
+ inputMint,
545
599
  createInputMintAta,
546
- usePumpFunV2: true
600
+ closeInputMintAta
547
601
  });
548
602
  }
549
603
  if (inputAmount === BigInt(0)) {
@@ -567,34 +621,41 @@ function buildPumpFunBuyInstructions(params) {
567
621
  const userVolumeAccumulator = getPumpFunUserVolumeAccumulatorPda(payerPubkey);
568
622
  if (createOutputMintAta) {
569
623
  instructions.push(
570
- createAssociatedTokenAccountInstruction(
624
+ createAssociatedTokenAccountIdempotentInstruction(
571
625
  payerPubkey,
572
626
  userTokenAccount,
573
627
  payerPubkey,
574
628
  outputMint,
575
- tokenProgramId
629
+ tokenProgramId,
630
+ SPL_ASSOCIATED_TOKEN_PROGRAM_ID
576
631
  )
577
632
  );
578
633
  }
579
634
  const feeRecipientPk = pumpFunFeeRecipientMeta(feeRecipient, bondingCurve.isMayhemMode);
580
635
  const bondingCurveV2 = getBondingCurveV2Pda(outputMint);
581
- const trackVolume = bondingCurve.isCashbackCoin ? Buffer.from([1, 1]) : Buffer.from([1, 0]);
636
+ const trackVolume = bondingCurve.isCashbackCoin ? 1 : 0;
582
637
  const buyTokenAmount = fixedOutputAmount ? fixedOutputAmount : getBuyTokenAmountFromSolAmount(inputAmount, bondingCurve, creator);
583
638
  const maxSolCost = calculateWithSlippageBuy(inputAmount, slippageBasisPoints);
584
639
  let data;
585
- if (useExactSolAmount) {
586
- const minTokensOut = fixedOutputAmount ? fixedOutputAmount : calculateWithSlippageSell(buyTokenAmount, slippageBasisPoints);
587
- data = Buffer.alloc(26);
640
+ if (fixedOutputAmount !== void 0) {
641
+ data = Buffer.alloc(25);
642
+ PUMPFUN_BUY_DISCRIMINATOR.copy(data, 0);
643
+ data.writeBigUInt64LE(fixedOutputAmount, 8);
644
+ data.writeBigUInt64LE(inputAmount, 16);
645
+ data[24] = trackVolume;
646
+ } else if (useExactSolAmount) {
647
+ const minTokensOut = calculateWithSlippageSell(buyTokenAmount, slippageBasisPoints);
648
+ data = Buffer.alloc(25);
588
649
  PUMPFUN_BUY_EXACT_SOL_IN_DISCRIMINATOR.copy(data, 0);
589
650
  data.writeBigUInt64LE(inputAmount, 8);
590
651
  data.writeBigUInt64LE(minTokensOut, 16);
591
- trackVolume.copy(data, 24);
652
+ data[24] = trackVolume;
592
653
  } else {
593
- data = Buffer.alloc(26);
654
+ data = Buffer.alloc(25);
594
655
  PUMPFUN_BUY_DISCRIMINATOR.copy(data, 0);
595
656
  data.writeBigUInt64LE(buyTokenAmount, 8);
596
657
  data.writeBigUInt64LE(maxSolCost, 16);
597
- trackVolume.copy(data, 24);
658
+ data[24] = trackVolume;
598
659
  }
599
660
  const keys = [
600
661
  { pubkey: PUMPFUN_GLOBAL_ACCOUNT, isSigner: false, isWritable: false },
@@ -629,19 +690,19 @@ function buildPumpFunSellInstructions(params) {
629
690
  const {
630
691
  payer,
631
692
  inputMint,
693
+ outputMint = SOL_TOKEN_ACCOUNT2,
632
694
  inputAmount,
633
695
  slippageBasisPoints = BigInt(1e3),
634
696
  fixedOutputAmount,
635
697
  createOutputMintAta = false,
636
698
  closeInputMintAta = false,
637
- protocolParams,
638
- usePumpFunV2 = false
699
+ protocolParams
639
700
  } = params;
640
- if (usePumpFunV2 || protocolParams.useV2Ix || isUsablePubkey(protocolParams.quoteMint)) {
701
+ if (usesPumpFunV2Layout(protocolParams)) {
641
702
  return buildPumpFunSellV2Instructions({
642
703
  ...params,
643
- createOutputMintAta,
644
- usePumpFunV2: true
704
+ outputMint,
705
+ createOutputMintAta
645
706
  });
646
707
  }
647
708
  if (inputAmount === BigInt(0)) {
@@ -721,12 +782,14 @@ function buildPumpFunSellInstructions(params) {
721
782
  function buildPumpFunBuyV2Instructions(params) {
722
783
  const {
723
784
  payer,
785
+ inputMint = SOL_TOKEN_ACCOUNT2,
724
786
  outputMint,
725
787
  inputAmount,
726
788
  slippageBasisPoints = BigInt(1e3),
727
789
  fixedOutputAmount,
728
790
  createOutputMintAta = true,
729
791
  createInputMintAta = false,
792
+ closeInputMintAta = false,
730
793
  protocolParams,
731
794
  useExactSolAmount = true
732
795
  } = params;
@@ -741,6 +804,7 @@ function buildPumpFunBuyV2Instructions(params) {
741
804
  const bondingCurveAddr = bondingCurve.account.equals(PublicKey2.default) || !bondingCurve.account ? getBondingCurvePda(outputMint) : bondingCurve.account;
742
805
  const baseTokenProgram = effectivePumpMintTokenProgram(outputMint, protocolParams);
743
806
  const quoteMint = effectiveQuoteMint(protocolParams);
807
+ validateV2BuyQuoteMint(inputMint, quoteMint);
744
808
  const quoteTokenProgram = TOKEN_PROGRAM_ID;
745
809
  const associatedBaseBondingCurve = associatedTokenAddress(
746
810
  outputMint,
@@ -793,32 +857,39 @@ function buildPumpFunBuyV2Instructions(params) {
793
857
  )
794
858
  );
795
859
  }
796
- if (createInputMintAta) {
797
- instructions.push(
798
- createAssociatedTokenAccountIdempotentInstruction(
799
- payerPubkey,
800
- associatedQuoteUser,
801
- payerPubkey,
802
- quoteMint,
803
- quoteTokenProgram,
804
- SPL_ASSOCIATED_TOKEN_PROGRAM_ID
805
- )
806
- );
807
- }
808
860
  const buyTokenAmount = fixedOutputAmount ? fixedOutputAmount : getBuyTokenAmountFromSolAmount(inputAmount, bondingCurve, creator);
809
861
  const maxSolCost = calculateWithSlippageBuy(inputAmount, slippageBasisPoints);
810
862
  let data;
811
- if (useExactSolAmount) {
812
- const minTokensOut = fixedOutputAmount ? fixedOutputAmount : calculateWithSlippageSell(buyTokenAmount, slippageBasisPoints);
863
+ let quoteAmountToFund;
864
+ if (fixedOutputAmount !== void 0) {
865
+ data = Buffer.alloc(24);
866
+ PUMPFUN_BUY_V2_DISCRIMINATOR.copy(data, 0);
867
+ data.writeBigUInt64LE(fixedOutputAmount, 8);
868
+ data.writeBigUInt64LE(inputAmount, 16);
869
+ quoteAmountToFund = inputAmount;
870
+ } else if (useExactSolAmount) {
871
+ const minTokensOut = calculateWithSlippageSell(buyTokenAmount, slippageBasisPoints);
813
872
  data = Buffer.alloc(24);
814
873
  PUMPFUN_BUY_EXACT_QUOTE_IN_V2_DISCRIMINATOR.copy(data, 0);
815
874
  data.writeBigUInt64LE(inputAmount, 8);
816
875
  data.writeBigUInt64LE(minTokensOut, 16);
876
+ quoteAmountToFund = inputAmount;
817
877
  } else {
818
878
  data = Buffer.alloc(24);
819
879
  PUMPFUN_BUY_V2_DISCRIMINATOR.copy(data, 0);
820
880
  data.writeBigUInt64LE(buyTokenAmount, 8);
821
881
  data.writeBigUInt64LE(maxSolCost, 16);
882
+ quoteAmountToFund = maxSolCost;
883
+ }
884
+ if (createInputMintAta) {
885
+ pushCreateOrWrapUserTokenAccount(
886
+ instructions,
887
+ payerPubkey,
888
+ associatedQuoteUser,
889
+ quoteMint,
890
+ quoteTokenProgram,
891
+ quoteAmountToFund
892
+ );
822
893
  }
823
894
  const keys = [
824
895
  { pubkey: PUMPFUN_GLOBAL_ACCOUNT, isSigner: false, isWritable: false },
@@ -856,12 +927,24 @@ function buildPumpFunBuyV2Instructions(params) {
856
927
  data
857
928
  })
858
929
  );
930
+ if (closeInputMintAta && quoteMint.equals(NATIVE_MINT)) {
931
+ instructions.push(
932
+ createCloseAccountInstruction(
933
+ associatedQuoteUser,
934
+ payerPubkey,
935
+ payerPubkey,
936
+ [],
937
+ quoteTokenProgram
938
+ )
939
+ );
940
+ }
859
941
  return instructions;
860
942
  }
861
943
  function buildPumpFunSellV2Instructions(params) {
862
944
  const {
863
945
  payer,
864
946
  inputMint,
947
+ outputMint = SOL_TOKEN_ACCOUNT2,
865
948
  inputAmount,
866
949
  slippageBasisPoints = BigInt(1e3),
867
950
  fixedOutputAmount,
@@ -880,6 +963,7 @@ function buildPumpFunSellV2Instructions(params) {
880
963
  const bondingCurveAddr = bondingCurve.account.equals(PublicKey2.default) || !bondingCurve.account ? getBondingCurvePda(inputMint) : bondingCurve.account;
881
964
  const baseTokenProgram = effectivePumpMintTokenProgram(inputMint, protocolParams);
882
965
  const quoteMint = effectiveQuoteMint(protocolParams);
966
+ validateV2SellQuoteMint(outputMint, quoteMint);
883
967
  const quoteTokenProgram = TOKEN_PROGRAM_ID;
884
968
  const associatedBaseBondingCurve = associatedTokenAddress(
885
969
  inputMint,
@@ -1895,7 +1979,7 @@ import {
1895
1979
  } from "@solana/web3.js";
1896
1980
  import {
1897
1981
  getAssociatedTokenAddressSync as getAssociatedTokenAddressSync2,
1898
- createAssociatedTokenAccountInstruction as createAssociatedTokenAccountInstruction2,
1982
+ createAssociatedTokenAccountInstruction,
1899
1983
  TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID2,
1900
1984
  createCloseAccountInstruction as createCloseAccountInstruction2,
1901
1985
  NATIVE_MINT as NATIVE_MINT2,
@@ -2040,7 +2124,7 @@ function buildBonkBuyInstructions(params) {
2040
2124
  if (createInputMintAta && !isUsd1Pool) {
2041
2125
  const wsolAta = getAssociatedTokenAddressSync2(NATIVE_MINT2, payerPubkey, true, TOKEN_PROGRAM_ID2);
2042
2126
  instructions.push(
2043
- createAssociatedTokenAccountInstruction2(payerPubkey, wsolAta, payerPubkey, NATIVE_MINT2)
2127
+ createAssociatedTokenAccountInstruction(payerPubkey, wsolAta, payerPubkey, NATIVE_MINT2)
2044
2128
  );
2045
2129
  const transferIx = SystemProgram3.transfer({
2046
2130
  fromPubkey: payerPubkey,
@@ -2052,7 +2136,7 @@ function buildBonkBuyInstructions(params) {
2052
2136
  }
2053
2137
  if (createOutputMintAta) {
2054
2138
  instructions.push(
2055
- createAssociatedTokenAccountInstruction2(
2139
+ createAssociatedTokenAccountInstruction(
2056
2140
  payerPubkey,
2057
2141
  userBaseTokenAccount,
2058
2142
  payerPubkey,
@@ -2151,7 +2235,7 @@ function buildBonkSellInstructions(params) {
2151
2235
  if (createOutputMintAta && !isUsd1Pool) {
2152
2236
  const wsolAta = getAssociatedTokenAddressSync2(NATIVE_MINT2, payerPubkey, true, TOKEN_PROGRAM_ID2);
2153
2237
  instructions.push(
2154
- createAssociatedTokenAccountInstruction2(payerPubkey, wsolAta, payerPubkey, NATIVE_MINT2)
2238
+ createAssociatedTokenAccountInstruction(payerPubkey, wsolAta, payerPubkey, NATIVE_MINT2)
2155
2239
  );
2156
2240
  }
2157
2241
  const shareFeeRate = BigInt(0);
@@ -2318,14 +2402,13 @@ function getBonkVaultPDA(poolState, mint) {
2318
2402
  import {
2319
2403
  PublicKey as PublicKey5,
2320
2404
  Keypair as Keypair3,
2321
- TransactionInstruction as TransactionInstruction4
2405
+ TransactionInstruction as TransactionInstruction4,
2406
+ SystemProgram as SystemProgram4
2322
2407
  } from "@solana/web3.js";
2323
2408
  import {
2324
2409
  getAssociatedTokenAddressSync as getAssociatedTokenAddressSync3,
2325
- createAssociatedTokenAccountInstruction as createAssociatedTokenAccountInstruction3,
2326
- TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3,
2410
+ createAssociatedTokenAccountIdempotentInstruction as createAssociatedTokenAccountIdempotentInstruction2,
2327
2411
  createCloseAccountInstruction as createCloseAccountInstruction3,
2328
- NATIVE_MINT as NATIVE_MINT3,
2329
2412
  createSyncNativeInstruction as createSyncNativeInstruction3
2330
2413
  } from "@solana/spl-token";
2331
2414
  var RAYDIUM_CPMM_PROGRAM_ID = new PublicKey5(
@@ -2435,34 +2518,38 @@ function buildRaydiumCpmmBuyInstructions(params) {
2435
2518
  throw new Error("Pool must contain WSOL or USDC");
2436
2519
  }
2437
2520
  const isBaseIn = baseMint.equals(WSOL_TOKEN_ACCOUNT2) || baseMint.equals(USDC_TOKEN_ACCOUNT2);
2438
- const mintTokenProgram = isBaseIn ? quoteTokenProgram : baseTokenProgram;
2521
+ const inputMint = isBaseIn ? baseMint : quoteMint;
2522
+ const inputTokenProgram = isBaseIn ? baseTokenProgram : quoteTokenProgram;
2523
+ const expectedOutputMint = isBaseIn ? quoteMint : baseMint;
2524
+ const outputTokenProgram = isBaseIn ? quoteTokenProgram : baseTokenProgram;
2525
+ if (!outputMint.equals(expectedOutputMint)) {
2526
+ throw new Error(`outputMint must match Raydium CPMM pool side ${expectedOutputMint.toBase58()}`);
2527
+ }
2439
2528
  const poolState = protocolParams.poolState && !protocolParams.poolState.equals(PublicKey5.default) ? protocolParams.poolState : getRaydiumCpmmPoolPda(ammConfig, baseMint, quoteMint);
2440
- const swapResult = computeRaydiumCpmmSwapAmount(
2529
+ const minimumAmountOut = fixedOutputAmount ?? computeRaydiumCpmmSwapAmount(
2441
2530
  baseReserve,
2442
2531
  quoteReserve,
2443
2532
  isBaseIn,
2444
2533
  inputAmount,
2445
2534
  slippageBasisPoints
2446
- );
2447
- const minimumAmountOut = fixedOutputAmount || swapResult.minAmountOut;
2448
- const inputMint = isWsol ? WSOL_TOKEN_ACCOUNT2 : USDC_TOKEN_ACCOUNT2;
2535
+ ).minAmountOut;
2449
2536
  const inputTokenAccount = getAssociatedTokenAddressSync3(
2450
2537
  inputMint,
2451
2538
  payerPubkey,
2452
2539
  true,
2453
- TOKEN_PROGRAM_ID3
2540
+ inputTokenProgram
2454
2541
  );
2455
2542
  const outputTokenAccount = getAssociatedTokenAddressSync3(
2456
2543
  outputMint,
2457
2544
  payerPubkey,
2458
2545
  true,
2459
- mintTokenProgram
2546
+ outputTokenProgram
2460
2547
  );
2461
2548
  const inputVaultAccount = (() => {
2462
- if (isWsol && baseMint.equals(inputMint) && baseVault && !baseVault.equals(PublicKey5.default)) {
2549
+ if (baseMint.equals(inputMint) && baseVault && !baseVault.equals(PublicKey5.default)) {
2463
2550
  return baseVault;
2464
2551
  }
2465
- if (!isWsol && quoteMint.equals(inputMint) && quoteVault && !quoteVault.equals(PublicKey5.default)) {
2552
+ if (quoteMint.equals(inputMint) && quoteVault && !quoteVault.equals(PublicKey5.default)) {
2466
2553
  return quoteVault;
2467
2554
  }
2468
2555
  return getRaydiumCpmmVaultPda(poolState, inputMint);
@@ -2477,34 +2564,43 @@ function buildRaydiumCpmmBuyInstructions(params) {
2477
2564
  return getRaydiumCpmmVaultPda(poolState, outputMint);
2478
2565
  })();
2479
2566
  const observationStateAccount = observationState && !observationState.equals(PublicKey5.default) ? observationState : getRaydiumCpmmObservationStatePda(poolState);
2480
- if (createInputMintAta && isWsol) {
2481
- const wsolAta = getAssociatedTokenAddressSync3(NATIVE_MINT3, payerPubkey, true);
2567
+ if (createInputMintAta) {
2568
+ const isInputWsol = inputMint.equals(WSOL_TOKEN_ACCOUNT2);
2482
2569
  instructions.push(
2483
- createAssociatedTokenAccountInstruction3(
2570
+ createAssociatedTokenAccountIdempotentInstruction2(
2484
2571
  payerPubkey,
2485
- wsolAta,
2572
+ inputTokenAccount,
2486
2573
  payerPubkey,
2487
- NATIVE_MINT3,
2488
- TOKEN_PROGRAM_ID3
2574
+ inputMint,
2575
+ inputTokenProgram
2489
2576
  )
2490
2577
  );
2491
- instructions.push(createSyncNativeInstruction3(wsolAta));
2578
+ if (isInputWsol) {
2579
+ instructions.push(
2580
+ SystemProgram4.transfer({
2581
+ fromPubkey: payerPubkey,
2582
+ toPubkey: inputTokenAccount,
2583
+ lamports: inputAmount
2584
+ })
2585
+ );
2586
+ instructions.push(createSyncNativeInstruction3(inputTokenAccount));
2587
+ }
2492
2588
  }
2493
2589
  if (createOutputMintAta) {
2494
2590
  instructions.push(
2495
- createAssociatedTokenAccountInstruction3(
2591
+ createAssociatedTokenAccountIdempotentInstruction2(
2496
2592
  payerPubkey,
2497
2593
  outputTokenAccount,
2498
2594
  payerPubkey,
2499
2595
  outputMint,
2500
- mintTokenProgram
2596
+ outputTokenProgram
2501
2597
  )
2502
2598
  );
2503
2599
  }
2504
2600
  const data = Buffer.alloc(24);
2505
- RAYDIUM_CPMM_SWAP_BASE_IN_DISCRIMINATOR.copy(data, 0);
2601
+ (fixedOutputAmount !== void 0 ? RAYDIUM_CPMM_SWAP_BASE_OUT_DISCRIMINATOR : RAYDIUM_CPMM_SWAP_BASE_IN_DISCRIMINATOR).copy(data, 0);
2506
2602
  data.writeBigUInt64LE(inputAmount, 8);
2507
- data.writeBigUInt64LE(minimumAmountOut, 16);
2603
+ data.writeBigUInt64LE(fixedOutputAmount ?? minimumAmountOut, 16);
2508
2604
  const accounts = [
2509
2605
  { pubkey: payerPubkey, isSigner: true, isWritable: true },
2510
2606
  { pubkey: RAYDIUM_CPMM_AUTHORITY, isSigner: false, isWritable: false },
@@ -2514,8 +2610,8 @@ function buildRaydiumCpmmBuyInstructions(params) {
2514
2610
  { pubkey: outputTokenAccount, isSigner: false, isWritable: true },
2515
2611
  { pubkey: inputVaultAccount, isSigner: false, isWritable: true },
2516
2612
  { pubkey: outputVaultAccount, isSigner: false, isWritable: true },
2517
- { pubkey: TOKEN_PROGRAM_ID3, isSigner: false, isWritable: false },
2518
- { pubkey: mintTokenProgram, isSigner: false, isWritable: false },
2613
+ { pubkey: inputTokenProgram, isSigner: false, isWritable: false },
2614
+ { pubkey: outputTokenProgram, isSigner: false, isWritable: false },
2519
2615
  { pubkey: inputMint, isSigner: false, isWritable: false },
2520
2616
  { pubkey: outputMint, isSigner: false, isWritable: false },
2521
2617
  { pubkey: observationStateAccount, isSigner: false, isWritable: true }
@@ -2527,10 +2623,9 @@ function buildRaydiumCpmmBuyInstructions(params) {
2527
2623
  data
2528
2624
  })
2529
2625
  );
2530
- if (closeInputMintAta && isWsol) {
2531
- const wsolAta = getAssociatedTokenAddressSync3(NATIVE_MINT3, payerPubkey, true);
2626
+ if (closeInputMintAta && inputMint.equals(WSOL_TOKEN_ACCOUNT2)) {
2532
2627
  instructions.push(
2533
- createCloseAccountInstruction3(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID3)
2628
+ createCloseAccountInstruction3(inputTokenAccount, payerPubkey, payerPubkey, [], inputTokenProgram)
2534
2629
  );
2535
2630
  }
2536
2631
  return instructions;
@@ -2572,28 +2667,32 @@ function buildRaydiumCpmmSellInstructions(params) {
2572
2667
  throw new Error("Pool must contain WSOL or USDC");
2573
2668
  }
2574
2669
  const isQuoteOut = quoteMint.equals(WSOL_TOKEN_ACCOUNT2) || quoteMint.equals(USDC_TOKEN_ACCOUNT2);
2575
- const mintTokenProgram = isQuoteOut ? baseTokenProgram : quoteTokenProgram;
2670
+ const expectedInputMint = isQuoteOut ? baseMint : quoteMint;
2671
+ const inputTokenProgram = isQuoteOut ? baseTokenProgram : quoteTokenProgram;
2672
+ const outputMint = isQuoteOut ? quoteMint : baseMint;
2673
+ const outputTokenProgram = isQuoteOut ? quoteTokenProgram : baseTokenProgram;
2674
+ if (!inputMint.equals(expectedInputMint)) {
2675
+ throw new Error(`inputMint must match Raydium CPMM pool side ${expectedInputMint.toBase58()}`);
2676
+ }
2576
2677
  const poolState = protocolParams.poolState && !protocolParams.poolState.equals(PublicKey5.default) ? protocolParams.poolState : getRaydiumCpmmPoolPda(ammConfig, baseMint, quoteMint);
2577
- const swapResult = computeRaydiumCpmmSwapAmount(
2678
+ const minimumAmountOut = fixedOutputAmount ?? computeRaydiumCpmmSwapAmount(
2578
2679
  baseReserve,
2579
2680
  quoteReserve,
2580
2681
  isQuoteOut,
2581
2682
  inputAmount,
2582
2683
  slippageBasisPoints
2583
- );
2584
- const minimumAmountOut = fixedOutputAmount || swapResult.minAmountOut;
2585
- const outputMint = isWsol ? WSOL_TOKEN_ACCOUNT2 : USDC_TOKEN_ACCOUNT2;
2684
+ ).minAmountOut;
2586
2685
  const inputTokenAccount = getAssociatedTokenAddressSync3(
2587
2686
  inputMint,
2588
2687
  payerPubkey,
2589
2688
  true,
2590
- mintTokenProgram
2689
+ inputTokenProgram
2591
2690
  );
2592
2691
  const outputTokenAccount = getAssociatedTokenAddressSync3(
2593
2692
  outputMint,
2594
2693
  payerPubkey,
2595
2694
  true,
2596
- TOKEN_PROGRAM_ID3
2695
+ outputTokenProgram
2597
2696
  );
2598
2697
  const inputVaultAccount = (() => {
2599
2698
  if (baseMint.equals(inputMint) && baseVault && !baseVault.equals(PublicKey5.default)) {
@@ -2605,31 +2704,30 @@ function buildRaydiumCpmmSellInstructions(params) {
2605
2704
  return getRaydiumCpmmVaultPda(poolState, inputMint);
2606
2705
  })();
2607
2706
  const outputVaultAccount = (() => {
2608
- if (isWsol && baseMint.equals(outputMint) && baseVault && !baseVault.equals(PublicKey5.default)) {
2707
+ if (baseMint.equals(outputMint) && baseVault && !baseVault.equals(PublicKey5.default)) {
2609
2708
  return baseVault;
2610
2709
  }
2611
- if (!isWsol && quoteMint.equals(outputMint) && quoteVault && !quoteVault.equals(PublicKey5.default)) {
2710
+ if (quoteMint.equals(outputMint) && quoteVault && !quoteVault.equals(PublicKey5.default)) {
2612
2711
  return quoteVault;
2613
2712
  }
2614
2713
  return getRaydiumCpmmVaultPda(poolState, outputMint);
2615
2714
  })();
2616
2715
  const observationStateAccount = observationState && !observationState.equals(PublicKey5.default) ? observationState : getRaydiumCpmmObservationStatePda(poolState);
2617
- if (createOutputMintAta && isWsol) {
2618
- const wsolAta = getAssociatedTokenAddressSync3(NATIVE_MINT3, payerPubkey, true);
2716
+ if (createOutputMintAta) {
2619
2717
  instructions.push(
2620
- createAssociatedTokenAccountInstruction3(
2718
+ createAssociatedTokenAccountIdempotentInstruction2(
2621
2719
  payerPubkey,
2622
- wsolAta,
2720
+ outputTokenAccount,
2623
2721
  payerPubkey,
2624
- NATIVE_MINT3,
2625
- TOKEN_PROGRAM_ID3
2722
+ outputMint,
2723
+ outputTokenProgram
2626
2724
  )
2627
2725
  );
2628
2726
  }
2629
2727
  const data = Buffer.alloc(24);
2630
- RAYDIUM_CPMM_SWAP_BASE_IN_DISCRIMINATOR.copy(data, 0);
2728
+ (fixedOutputAmount !== void 0 ? RAYDIUM_CPMM_SWAP_BASE_OUT_DISCRIMINATOR : RAYDIUM_CPMM_SWAP_BASE_IN_DISCRIMINATOR).copy(data, 0);
2631
2729
  data.writeBigUInt64LE(inputAmount, 8);
2632
- data.writeBigUInt64LE(minimumAmountOut, 16);
2730
+ data.writeBigUInt64LE(fixedOutputAmount ?? minimumAmountOut, 16);
2633
2731
  const accounts = [
2634
2732
  { pubkey: payerPubkey, isSigner: true, isWritable: true },
2635
2733
  { pubkey: RAYDIUM_CPMM_AUTHORITY, isSigner: false, isWritable: false },
@@ -2639,8 +2737,8 @@ function buildRaydiumCpmmSellInstructions(params) {
2639
2737
  { pubkey: outputTokenAccount, isSigner: false, isWritable: true },
2640
2738
  { pubkey: inputVaultAccount, isSigner: false, isWritable: true },
2641
2739
  { pubkey: outputVaultAccount, isSigner: false, isWritable: true },
2642
- { pubkey: mintTokenProgram, isSigner: false, isWritable: false },
2643
- { pubkey: TOKEN_PROGRAM_ID3, isSigner: false, isWritable: false },
2740
+ { pubkey: inputTokenProgram, isSigner: false, isWritable: false },
2741
+ { pubkey: outputTokenProgram, isSigner: false, isWritable: false },
2644
2742
  { pubkey: inputMint, isSigner: false, isWritable: false },
2645
2743
  { pubkey: outputMint, isSigner: false, isWritable: false },
2646
2744
  { pubkey: observationStateAccount, isSigner: false, isWritable: true }
@@ -2652,10 +2750,9 @@ function buildRaydiumCpmmSellInstructions(params) {
2652
2750
  data
2653
2751
  })
2654
2752
  );
2655
- if (closeOutputMintAta && isWsol) {
2656
- const wsolAta = getAssociatedTokenAddressSync3(NATIVE_MINT3, payerPubkey, true);
2753
+ if (closeOutputMintAta && outputMint.equals(WSOL_TOKEN_ACCOUNT2)) {
2657
2754
  instructions.push(
2658
- createCloseAccountInstruction3(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID3)
2755
+ createCloseAccountInstruction3(outputTokenAccount, payerPubkey, payerPubkey, [], outputTokenProgram)
2659
2756
  );
2660
2757
  }
2661
2758
  if (closeInputMintAta) {
@@ -2665,7 +2762,7 @@ function buildRaydiumCpmmSellInstructions(params) {
2665
2762
  payerPubkey,
2666
2763
  payerPubkey,
2667
2764
  [],
2668
- mintTokenProgram
2765
+ inputTokenProgram
2669
2766
  )
2670
2767
  );
2671
2768
  }
@@ -2798,16 +2895,18 @@ async function getRaydiumCPMMpoolTokenBalances(connection, poolState, token0Mint
2798
2895
  import {
2799
2896
  PublicKey as PublicKey6,
2800
2897
  Keypair as Keypair4,
2801
- TransactionInstruction as TransactionInstruction5
2898
+ TransactionInstruction as TransactionInstruction5,
2899
+ SystemProgram as SystemProgram5
2802
2900
  } from "@solana/web3.js";
2803
2901
  import {
2804
2902
  getAssociatedTokenAddressSync as getAssociatedTokenAddressSync4,
2805
- createAssociatedTokenAccountInstruction as createAssociatedTokenAccountInstruction4,
2806
- TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4,
2903
+ createAssociatedTokenAccountInstruction as createAssociatedTokenAccountInstruction2,
2904
+ TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3,
2807
2905
  createCloseAccountInstruction as createCloseAccountInstruction4,
2808
- NATIVE_MINT as NATIVE_MINT4,
2906
+ NATIVE_MINT as NATIVE_MINT3,
2809
2907
  createSyncNativeInstruction as createSyncNativeInstruction4
2810
2908
  } from "@solana/spl-token";
2909
+ var SOL_TOKEN_ACCOUNT3 = new PublicKey6("So11111111111111111111111111111111111111111");
2811
2910
  var RAYDIUM_AMM_V4_PROGRAM_ID = new PublicKey6(
2812
2911
  "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"
2813
2912
  );
@@ -2834,10 +2933,44 @@ function computeRaydiumAmmV4SwapAmount(coinReserve, pcReserve, isCoinIn, amountI
2834
2933
  const minAmountOut = amountOut - amountOut * slippageBasisPoints / BigInt(1e4);
2835
2934
  return { amountOut, minAmountOut };
2836
2935
  }
2936
+ function isDefaultPublicKey(pubkey) {
2937
+ return pubkey.equals(PublicKey6.default);
2938
+ }
2939
+ function isMintMatch(requested, expected) {
2940
+ return requested.equals(expected) || expected.equals(NATIVE_MINT3) && requested.equals(SOL_TOKEN_ACCOUNT3);
2941
+ }
2942
+ function ensureExpectedMint(label, requested, expected) {
2943
+ if (!isDefaultPublicKey(requested) && !isMintMatch(requested, expected)) {
2944
+ throw new Error(
2945
+ `${label} must match the Raydium AMM v4 pool side (${expected.toBase58()}), got ${requested.toBase58()}`
2946
+ );
2947
+ }
2948
+ }
2949
+ function ensureMarketAccounts(params) {
2950
+ const required = [
2951
+ ["ammOpenOrders", params.ammOpenOrders],
2952
+ ["ammTargetOrders", params.ammTargetOrders],
2953
+ ["serumProgram", params.serumProgram],
2954
+ ["serumMarket", params.serumMarket],
2955
+ ["serumBids", params.serumBids],
2956
+ ["serumAsks", params.serumAsks],
2957
+ ["serumEventQueue", params.serumEventQueue],
2958
+ ["serumCoinVaultAccount", params.serumCoinVaultAccount],
2959
+ ["serumPcVaultAccount", params.serumPcVaultAccount],
2960
+ ["serumVaultSigner", params.serumVaultSigner]
2961
+ ];
2962
+ for (const [name, account] of required) {
2963
+ if (isDefaultPublicKey(account)) {
2964
+ throw new Error(
2965
+ `Raydium AMM v4 requires ${name}; pass real market accounts from the AMM/market state`
2966
+ );
2967
+ }
2968
+ }
2969
+ }
2837
2970
  function buildRaydiumAmmV4BuyInstructions(params) {
2838
2971
  const {
2839
2972
  payer,
2840
- outputMint,
2973
+ outputMint: requestedOutputMint,
2841
2974
  inputAmount,
2842
2975
  slippageBasisPoints = BigInt(1e3),
2843
2976
  fixedOutputAmount,
@@ -2859,9 +2992,20 @@ function buildRaydiumAmmV4BuyInstructions(params) {
2859
2992
  pcMint,
2860
2993
  tokenCoin,
2861
2994
  tokenPc,
2995
+ ammOpenOrders,
2996
+ ammTargetOrders,
2997
+ serumProgram,
2998
+ serumMarket,
2999
+ serumBids,
3000
+ serumAsks,
3001
+ serumEventQueue,
3002
+ serumCoinVaultAccount,
3003
+ serumPcVaultAccount,
3004
+ serumVaultSigner,
2862
3005
  coinReserve,
2863
3006
  pcReserve
2864
3007
  } = protocolParams;
3008
+ ensureMarketAccounts(protocolParams);
2865
3009
  const isWsol = coinMint.equals(WSOL_TOKEN_ACCOUNT2) || pcMint.equals(WSOL_TOKEN_ACCOUNT2);
2866
3010
  const isUsdc = coinMint.equals(USDC_TOKEN_ACCOUNT2) || pcMint.equals(USDC_TOKEN_ACCOUNT2);
2867
3011
  if (!isWsol && !isUsdc) {
@@ -2875,77 +3019,88 @@ function buildRaydiumAmmV4BuyInstructions(params) {
2875
3019
  inputAmount,
2876
3020
  slippageBasisPoints
2877
3021
  );
2878
- const minimumAmountOut = fixedOutputAmount || swapResult.minAmountOut;
2879
- const inputMint = isWsol ? WSOL_TOKEN_ACCOUNT2 : USDC_TOKEN_ACCOUNT2;
3022
+ const minimumAmountOut = fixedOutputAmount ?? swapResult.minAmountOut;
3023
+ const inputMint = isBaseIn ? coinMint : pcMint;
3024
+ const outputMint = isBaseIn ? pcMint : coinMint;
3025
+ ensureExpectedMint("outputMint", requestedOutputMint, outputMint);
2880
3026
  const userSourceTokenAccount = getAssociatedTokenAddressSync4(
2881
3027
  inputMint,
2882
3028
  payerPubkey,
2883
3029
  true,
2884
- TOKEN_PROGRAM_ID4
3030
+ TOKEN_PROGRAM_ID3
2885
3031
  );
2886
3032
  const userDestinationTokenAccount = getAssociatedTokenAddressSync4(
2887
3033
  outputMint,
2888
3034
  payerPubkey,
2889
3035
  true,
2890
- TOKEN_PROGRAM_ID4
3036
+ TOKEN_PROGRAM_ID3
2891
3037
  );
2892
- if (createInputMintAta && isWsol) {
2893
- const wsolAta = getAssociatedTokenAddressSync4(NATIVE_MINT4, payerPubkey, true);
3038
+ if (createInputMintAta && inputMint.equals(WSOL_TOKEN_ACCOUNT2)) {
3039
+ const wsolAta = getAssociatedTokenAddressSync4(NATIVE_MINT3, payerPubkey, true);
2894
3040
  instructions.push(
2895
- createAssociatedTokenAccountInstruction4(
3041
+ createAssociatedTokenAccountInstruction2(
2896
3042
  payerPubkey,
2897
3043
  wsolAta,
2898
3044
  payerPubkey,
2899
- NATIVE_MINT4,
2900
- TOKEN_PROGRAM_ID4
3045
+ NATIVE_MINT3,
3046
+ TOKEN_PROGRAM_ID3
2901
3047
  )
2902
3048
  );
3049
+ instructions.push(
3050
+ SystemProgram5.transfer({
3051
+ fromPubkey: payerPubkey,
3052
+ toPubkey: wsolAta,
3053
+ lamports: Number(inputAmount)
3054
+ })
3055
+ );
2903
3056
  instructions.push(createSyncNativeInstruction4(wsolAta));
3057
+ } else if (createInputMintAta) {
3058
+ instructions.push(
3059
+ createAssociatedTokenAccountInstruction2(
3060
+ payerPubkey,
3061
+ userSourceTokenAccount,
3062
+ payerPubkey,
3063
+ inputMint,
3064
+ TOKEN_PROGRAM_ID3
3065
+ )
3066
+ );
2904
3067
  }
2905
3068
  if (createOutputMintAta) {
2906
3069
  instructions.push(
2907
- createAssociatedTokenAccountInstruction4(
3070
+ createAssociatedTokenAccountInstruction2(
2908
3071
  payerPubkey,
2909
3072
  userDestinationTokenAccount,
2910
3073
  payerPubkey,
2911
3074
  outputMint,
2912
- TOKEN_PROGRAM_ID4
3075
+ TOKEN_PROGRAM_ID3
2913
3076
  )
2914
3077
  );
2915
3078
  }
2916
3079
  const data = Buffer.alloc(17);
2917
- RAYDIUM_AMM_V4_SWAP_BASE_IN_DISCRIMINATOR.copy(data, 0);
3080
+ (fixedOutputAmount !== void 0 ? RAYDIUM_AMM_V4_SWAP_BASE_OUT_DISCRIMINATOR : RAYDIUM_AMM_V4_SWAP_BASE_IN_DISCRIMINATOR).copy(data, 0);
2918
3081
  data.writeBigUInt64LE(inputAmount, 1);
2919
3082
  data.writeBigUInt64LE(minimumAmountOut, 9);
2920
3083
  const accounts = [
2921
- { pubkey: TOKEN_PROGRAM_ID4, isSigner: false, isWritable: false },
3084
+ { pubkey: TOKEN_PROGRAM_ID3, isSigner: false, isWritable: false },
2922
3085
  { pubkey: amm, isSigner: false, isWritable: true },
2923
3086
  { pubkey: RAYDIUM_AMM_V4_AUTHORITY, isSigner: false, isWritable: false },
2924
- { pubkey: amm, isSigner: false, isWritable: true },
2925
- // Amm Open Orders (same as amm for simplicity)
3087
+ { pubkey: ammOpenOrders, isSigner: false, isWritable: true },
3088
+ { pubkey: ammTargetOrders, isSigner: false, isWritable: true },
2926
3089
  { pubkey: tokenCoin, isSigner: false, isWritable: true },
2927
3090
  // Pool Coin Token Account
2928
3091
  { pubkey: tokenPc, isSigner: false, isWritable: true },
2929
3092
  // Pool Pc Token Account
2930
- { pubkey: amm, isSigner: false, isWritable: false },
2931
- // Serum Program (placeholder)
2932
- { pubkey: amm, isSigner: false, isWritable: false },
2933
- // Serum Market (placeholder)
2934
- { pubkey: amm, isSigner: false, isWritable: false },
2935
- // Serum Bids (placeholder)
2936
- { pubkey: amm, isSigner: false, isWritable: false },
2937
- // Serum Asks (placeholder)
2938
- { pubkey: amm, isSigner: false, isWritable: false },
2939
- // Serum Event Queue (placeholder)
2940
- { pubkey: amm, isSigner: false, isWritable: false },
2941
- // Serum Coin Vault Account (placeholder)
2942
- { pubkey: amm, isSigner: false, isWritable: false },
2943
- // Serum Pc Vault Account (placeholder)
2944
- { pubkey: amm, isSigner: false, isWritable: false },
2945
- // Serum Vault Signer (placeholder)
3093
+ { pubkey: serumProgram, isSigner: false, isWritable: false },
3094
+ { pubkey: serumMarket, isSigner: false, isWritable: true },
3095
+ { pubkey: serumBids, isSigner: false, isWritable: true },
3096
+ { pubkey: serumAsks, isSigner: false, isWritable: true },
3097
+ { pubkey: serumEventQueue, isSigner: false, isWritable: true },
3098
+ { pubkey: serumCoinVaultAccount, isSigner: false, isWritable: true },
3099
+ { pubkey: serumPcVaultAccount, isSigner: false, isWritable: true },
3100
+ { pubkey: serumVaultSigner, isSigner: false, isWritable: false },
2946
3101
  { pubkey: userSourceTokenAccount, isSigner: false, isWritable: true },
2947
3102
  { pubkey: userDestinationTokenAccount, isSigner: false, isWritable: true },
2948
- { pubkey: payerPubkey, isSigner: true, isWritable: true }
3103
+ { pubkey: payerPubkey, isSigner: true, isWritable: false }
2949
3104
  ];
2950
3105
  instructions.push(
2951
3106
  new TransactionInstruction5({
@@ -2954,10 +3109,10 @@ function buildRaydiumAmmV4BuyInstructions(params) {
2954
3109
  data
2955
3110
  })
2956
3111
  );
2957
- if (closeInputMintAta && isWsol) {
2958
- const wsolAta = getAssociatedTokenAddressSync4(NATIVE_MINT4, payerPubkey, true);
3112
+ if (closeInputMintAta && inputMint.equals(WSOL_TOKEN_ACCOUNT2)) {
3113
+ const wsolAta = getAssociatedTokenAddressSync4(NATIVE_MINT3, payerPubkey, true);
2959
3114
  instructions.push(
2960
- createCloseAccountInstruction4(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID4)
3115
+ createCloseAccountInstruction4(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID3)
2961
3116
  );
2962
3117
  }
2963
3118
  return instructions;
@@ -2965,7 +3120,8 @@ function buildRaydiumAmmV4BuyInstructions(params) {
2965
3120
  function buildRaydiumAmmV4SellInstructions(params) {
2966
3121
  const {
2967
3122
  payer,
2968
- inputMint,
3123
+ inputMint: requestedInputMint,
3124
+ outputMint: requestedOutputMint,
2969
3125
  inputAmount,
2970
3126
  slippageBasisPoints = BigInt(1e3),
2971
3127
  fixedOutputAmount,
@@ -2987,9 +3143,20 @@ function buildRaydiumAmmV4SellInstructions(params) {
2987
3143
  pcMint,
2988
3144
  tokenCoin,
2989
3145
  tokenPc,
3146
+ ammOpenOrders,
3147
+ ammTargetOrders,
3148
+ serumProgram,
3149
+ serumMarket,
3150
+ serumBids,
3151
+ serumAsks,
3152
+ serumEventQueue,
3153
+ serumCoinVaultAccount,
3154
+ serumPcVaultAccount,
3155
+ serumVaultSigner,
2990
3156
  coinReserve,
2991
3157
  pcReserve
2992
3158
  } = protocolParams;
3159
+ ensureMarketAccounts(protocolParams);
2993
3160
  const isWsol = coinMint.equals(WSOL_TOKEN_ACCOUNT2) || pcMint.equals(WSOL_TOKEN_ACCOUNT2);
2994
3161
  const isUsdc = coinMint.equals(USDC_TOKEN_ACCOUNT2) || pcMint.equals(USDC_TOKEN_ACCOUNT2);
2995
3162
  if (!isWsol && !isUsdc) {
@@ -3003,65 +3170,72 @@ function buildRaydiumAmmV4SellInstructions(params) {
3003
3170
  inputAmount,
3004
3171
  slippageBasisPoints
3005
3172
  );
3006
- const minimumAmountOut = fixedOutputAmount || swapResult.minAmountOut;
3007
- const outputMint = isWsol ? WSOL_TOKEN_ACCOUNT2 : USDC_TOKEN_ACCOUNT2;
3173
+ const minimumAmountOut = fixedOutputAmount ?? swapResult.minAmountOut;
3174
+ const outputMint = isBaseIn ? pcMint : coinMint;
3175
+ const inputMint = isBaseIn ? coinMint : pcMint;
3176
+ ensureExpectedMint("inputMint", requestedInputMint, inputMint);
3177
+ if (requestedOutputMint) {
3178
+ ensureExpectedMint("outputMint", requestedOutputMint, outputMint);
3179
+ }
3008
3180
  const userSourceTokenAccount = getAssociatedTokenAddressSync4(
3009
3181
  inputMint,
3010
3182
  payerPubkey,
3011
3183
  true,
3012
- TOKEN_PROGRAM_ID4
3184
+ TOKEN_PROGRAM_ID3
3013
3185
  );
3014
3186
  const userDestinationTokenAccount = getAssociatedTokenAddressSync4(
3015
3187
  outputMint,
3016
3188
  payerPubkey,
3017
3189
  true,
3018
- TOKEN_PROGRAM_ID4
3190
+ TOKEN_PROGRAM_ID3
3019
3191
  );
3020
- if (createOutputMintAta && isWsol) {
3021
- const wsolAta = getAssociatedTokenAddressSync4(NATIVE_MINT4, payerPubkey, true);
3192
+ if (createOutputMintAta && outputMint.equals(WSOL_TOKEN_ACCOUNT2)) {
3193
+ const wsolAta = getAssociatedTokenAddressSync4(NATIVE_MINT3, payerPubkey, true);
3022
3194
  instructions.push(
3023
- createAssociatedTokenAccountInstruction4(
3195
+ createAssociatedTokenAccountInstruction2(
3024
3196
  payerPubkey,
3025
3197
  wsolAta,
3026
3198
  payerPubkey,
3027
- NATIVE_MINT4,
3028
- TOKEN_PROGRAM_ID4
3199
+ NATIVE_MINT3,
3200
+ TOKEN_PROGRAM_ID3
3201
+ )
3202
+ );
3203
+ } else if (createOutputMintAta) {
3204
+ instructions.push(
3205
+ createAssociatedTokenAccountInstruction2(
3206
+ payerPubkey,
3207
+ userDestinationTokenAccount,
3208
+ payerPubkey,
3209
+ outputMint,
3210
+ TOKEN_PROGRAM_ID3
3029
3211
  )
3030
3212
  );
3031
3213
  }
3032
3214
  const data = Buffer.alloc(17);
3033
- RAYDIUM_AMM_V4_SWAP_BASE_IN_DISCRIMINATOR.copy(data, 0);
3215
+ (fixedOutputAmount !== void 0 ? RAYDIUM_AMM_V4_SWAP_BASE_OUT_DISCRIMINATOR : RAYDIUM_AMM_V4_SWAP_BASE_IN_DISCRIMINATOR).copy(data, 0);
3034
3216
  data.writeBigUInt64LE(inputAmount, 1);
3035
3217
  data.writeBigUInt64LE(minimumAmountOut, 9);
3036
3218
  const accounts = [
3037
- { pubkey: TOKEN_PROGRAM_ID4, isSigner: false, isWritable: false },
3219
+ { pubkey: TOKEN_PROGRAM_ID3, isSigner: false, isWritable: false },
3038
3220
  { pubkey: amm, isSigner: false, isWritable: true },
3039
3221
  { pubkey: RAYDIUM_AMM_V4_AUTHORITY, isSigner: false, isWritable: false },
3040
- { pubkey: amm, isSigner: false, isWritable: true },
3041
- // Amm Open Orders
3222
+ { pubkey: ammOpenOrders, isSigner: false, isWritable: true },
3223
+ { pubkey: ammTargetOrders, isSigner: false, isWritable: true },
3042
3224
  { pubkey: tokenCoin, isSigner: false, isWritable: true },
3043
3225
  // Pool Coin Token Account
3044
3226
  { pubkey: tokenPc, isSigner: false, isWritable: true },
3045
3227
  // Pool Pc Token Account
3046
- { pubkey: amm, isSigner: false, isWritable: false },
3047
- // Serum Program
3048
- { pubkey: amm, isSigner: false, isWritable: false },
3049
- // Serum Market
3050
- { pubkey: amm, isSigner: false, isWritable: false },
3051
- // Serum Bids
3052
- { pubkey: amm, isSigner: false, isWritable: false },
3053
- // Serum Asks
3054
- { pubkey: amm, isSigner: false, isWritable: false },
3055
- // Serum Event Queue
3056
- { pubkey: amm, isSigner: false, isWritable: false },
3057
- // Serum Coin Vault Account
3058
- { pubkey: amm, isSigner: false, isWritable: false },
3059
- // Serum Pc Vault Account
3060
- { pubkey: amm, isSigner: false, isWritable: false },
3061
- // Serum Vault Signer
3228
+ { pubkey: serumProgram, isSigner: false, isWritable: false },
3229
+ { pubkey: serumMarket, isSigner: false, isWritable: true },
3230
+ { pubkey: serumBids, isSigner: false, isWritable: true },
3231
+ { pubkey: serumAsks, isSigner: false, isWritable: true },
3232
+ { pubkey: serumEventQueue, isSigner: false, isWritable: true },
3233
+ { pubkey: serumCoinVaultAccount, isSigner: false, isWritable: true },
3234
+ { pubkey: serumPcVaultAccount, isSigner: false, isWritable: true },
3235
+ { pubkey: serumVaultSigner, isSigner: false, isWritable: false },
3062
3236
  { pubkey: userSourceTokenAccount, isSigner: false, isWritable: true },
3063
3237
  { pubkey: userDestinationTokenAccount, isSigner: false, isWritable: true },
3064
- { pubkey: payerPubkey, isSigner: true, isWritable: true }
3238
+ { pubkey: payerPubkey, isSigner: true, isWritable: false }
3065
3239
  ];
3066
3240
  instructions.push(
3067
3241
  new TransactionInstruction5({
@@ -3070,10 +3244,10 @@ function buildRaydiumAmmV4SellInstructions(params) {
3070
3244
  data
3071
3245
  })
3072
3246
  );
3073
- if (closeOutputMintAta && isWsol) {
3074
- const wsolAta = getAssociatedTokenAddressSync4(NATIVE_MINT4, payerPubkey, true);
3247
+ if (closeOutputMintAta && outputMint.equals(WSOL_TOKEN_ACCOUNT2)) {
3248
+ const wsolAta = getAssociatedTokenAddressSync4(NATIVE_MINT3, payerPubkey, true);
3075
3249
  instructions.push(
3076
- createCloseAccountInstruction4(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID4)
3250
+ createCloseAccountInstruction4(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID3)
3077
3251
  );
3078
3252
  }
3079
3253
  if (closeInputMintAta) {
@@ -3083,13 +3257,14 @@ function buildRaydiumAmmV4SellInstructions(params) {
3083
3257
  payerPubkey,
3084
3258
  payerPubkey,
3085
3259
  [],
3086
- TOKEN_PROGRAM_ID4
3260
+ TOKEN_PROGRAM_ID3
3087
3261
  )
3088
3262
  );
3089
3263
  }
3090
3264
  return instructions;
3091
3265
  }
3092
3266
  var AMM_INFO_SIZE = 752;
3267
+ var MARKET_STATE_SIZE = 388;
3093
3268
  function decodeAmmInfo(data) {
3094
3269
  if (data.length < AMM_INFO_SIZE) {
3095
3270
  return null;
@@ -3207,6 +3382,65 @@ function decodeAmmInfo(data) {
3207
3382
  return null;
3208
3383
  }
3209
3384
  }
3385
+ function decodeMarketState(data) {
3386
+ if (data.length < MARKET_STATE_SIZE) {
3387
+ return null;
3388
+ }
3389
+ try {
3390
+ let offset = 5;
3391
+ const readU64 = () => {
3392
+ const val = data.readBigUInt64LE(offset);
3393
+ offset += 8;
3394
+ return val;
3395
+ };
3396
+ const readPubkey = () => {
3397
+ const val = new PublicKey6(data.subarray(offset, offset + 32));
3398
+ offset += 32;
3399
+ return val;
3400
+ };
3401
+ readU64();
3402
+ readPubkey();
3403
+ const vaultSignerNonce = readU64();
3404
+ readPubkey();
3405
+ readPubkey();
3406
+ const serumCoinVaultAccount = readPubkey();
3407
+ readU64();
3408
+ readU64();
3409
+ const serumPcVaultAccount = readPubkey();
3410
+ readU64();
3411
+ readU64();
3412
+ readU64();
3413
+ readPubkey();
3414
+ const serumEventQueue = readPubkey();
3415
+ const serumBids = readPubkey();
3416
+ const serumAsks = readPubkey();
3417
+ return {
3418
+ vaultSignerNonce,
3419
+ serumCoinVaultAccount,
3420
+ serumPcVaultAccount,
3421
+ serumEventQueue,
3422
+ serumBids,
3423
+ serumAsks
3424
+ };
3425
+ } catch {
3426
+ return null;
3427
+ }
3428
+ }
3429
+ function deriveSerumVaultSigner(serumProgram, serumMarket, vaultSignerNonce) {
3430
+ const nonce = Buffer.alloc(8);
3431
+ nonce.writeBigUInt64LE(vaultSignerNonce);
3432
+ try {
3433
+ return PublicKey6.createProgramAddressSync(
3434
+ [serumMarket.toBuffer(), nonce],
3435
+ serumProgram
3436
+ );
3437
+ } catch {
3438
+ return PublicKey6.createProgramAddressSync(
3439
+ [serumMarket.toBuffer(), Buffer.from([Number(vaultSignerNonce & 0xffn)])],
3440
+ serumProgram
3441
+ );
3442
+ }
3443
+ }
3210
3444
  async function fetchAmmInfo(connection, amm) {
3211
3445
  const account = await connection.getAccountInfo(amm);
3212
3446
  if (!account?.value?.data) {
@@ -3214,21 +3448,30 @@ async function fetchAmmInfo(connection, amm) {
3214
3448
  }
3215
3449
  return decodeAmmInfo(account.value.data);
3216
3450
  }
3451
+ async function fetchMarketState(connection, market) {
3452
+ const account = await connection.getAccountInfo(market);
3453
+ if (!account?.value?.data) {
3454
+ return null;
3455
+ }
3456
+ return decodeMarketState(account.value.data);
3457
+ }
3217
3458
 
3218
3459
  // src/instruction/meteora_damm_v2_builder.ts
3219
3460
  import {
3220
3461
  PublicKey as PublicKey7,
3221
3462
  Keypair as Keypair5,
3222
- TransactionInstruction as TransactionInstruction6
3463
+ TransactionInstruction as TransactionInstruction6,
3464
+ SystemProgram as SystemProgram6
3223
3465
  } from "@solana/web3.js";
3224
3466
  import {
3225
3467
  getAssociatedTokenAddressSync as getAssociatedTokenAddressSync5,
3226
- createAssociatedTokenAccountInstruction as createAssociatedTokenAccountInstruction5,
3227
- TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID5,
3468
+ createAssociatedTokenAccountInstruction as createAssociatedTokenAccountInstruction3,
3469
+ TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4,
3228
3470
  createCloseAccountInstruction as createCloseAccountInstruction5,
3229
- NATIVE_MINT as NATIVE_MINT5,
3471
+ NATIVE_MINT as NATIVE_MINT4,
3230
3472
  createSyncNativeInstruction as createSyncNativeInstruction5
3231
3473
  } from "@solana/spl-token";
3474
+ var SOL_TOKEN_ACCOUNT4 = new PublicKey7("So11111111111111111111111111111111111111111");
3232
3475
  var METEORA_DAMM_V2_PROGRAM_ID = new PublicKey7(
3233
3476
  "cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG"
3234
3477
  );
@@ -3245,6 +3488,17 @@ var METEORA_DAMM_V2_SWAP_DISCRIMINATOR = Buffer.from([
3245
3488
  135,
3246
3489
  200
3247
3490
  ]);
3491
+ var METEORA_DAMM_V2_SWAP2_DISCRIMINATOR = Buffer.from([
3492
+ 65,
3493
+ 75,
3494
+ 63,
3495
+ 76,
3496
+ 235,
3497
+ 91,
3498
+ 91,
3499
+ 136
3500
+ ]);
3501
+ var METEORA_DAMM_V2_SWAP_MODE_PARTIAL_FILL = 1;
3248
3502
  var METEORA_DAMM_V2_EVENT_AUTHORITY_SEED = Buffer.from("__event_authority");
3249
3503
  function getMeteoraDammV2EventAuthorityPda() {
3250
3504
  const [pda] = PublicKey7.findProgramAddressSync(
@@ -3253,11 +3507,24 @@ function getMeteoraDammV2EventAuthorityPda() {
3253
3507
  );
3254
3508
  return pda;
3255
3509
  }
3510
+ function isDefaultPublicKey2(pubkey) {
3511
+ return pubkey.equals(PublicKey7.default);
3512
+ }
3513
+ function isMintMatch2(requested, expected) {
3514
+ return requested.equals(expected) || expected.equals(NATIVE_MINT4) && requested.equals(SOL_TOKEN_ACCOUNT4);
3515
+ }
3516
+ function ensureExpectedMint2(label, requested, expected) {
3517
+ if (!isDefaultPublicKey2(requested) && !isMintMatch2(requested, expected)) {
3518
+ throw new Error(
3519
+ `${label} must match the Meteora DAMM v2 pool side (${expected.toBase58()}), got ${requested.toBase58()}`
3520
+ );
3521
+ }
3522
+ }
3256
3523
  function buildMeteoraDammV2BuyInstructions(params) {
3257
3524
  const {
3258
3525
  payer,
3259
- inputMint,
3260
- outputMint,
3526
+ inputMint: requestedInputMint,
3527
+ outputMint: requestedOutputMint,
3261
3528
  inputAmount,
3262
3529
  fixedOutputAmount,
3263
3530
  createInputMintAta = true,
@@ -3290,6 +3557,10 @@ function buildMeteoraDammV2BuyInstructions(params) {
3290
3557
  throw new Error("Pool must contain WSOL or USDC");
3291
3558
  }
3292
3559
  const isAIn = tokenAMint.equals(WSOL_TOKEN_ACCOUNT2) || tokenAMint.equals(USDC_TOKEN_ACCOUNT2);
3560
+ const inputMint = isAIn ? tokenAMint : tokenBMint;
3561
+ const outputMint = isAIn ? tokenBMint : tokenAMint;
3562
+ ensureExpectedMint2("inputMint", requestedInputMint, inputMint);
3563
+ ensureExpectedMint2("outputMint", requestedOutputMint, outputMint);
3293
3564
  const inputTokenAccount = getAssociatedTokenAddressSync5(
3294
3565
  inputMint,
3295
3566
  payerPubkey,
@@ -3303,34 +3574,54 @@ function buildMeteoraDammV2BuyInstructions(params) {
3303
3574
  isAIn ? tokenBProgram : tokenAProgram
3304
3575
  );
3305
3576
  const eventAuthority = getMeteoraDammV2EventAuthorityPda();
3306
- if (createInputMintAta && isWsol) {
3307
- const wsolAta = getAssociatedTokenAddressSync5(NATIVE_MINT5, payerPubkey, true);
3577
+ const inputTokenProgram = isAIn ? tokenAProgram : tokenBProgram;
3578
+ const outputTokenProgram = isAIn ? tokenBProgram : tokenAProgram;
3579
+ if (createInputMintAta && inputMint.equals(WSOL_TOKEN_ACCOUNT2)) {
3580
+ const wsolAta = getAssociatedTokenAddressSync5(NATIVE_MINT4, payerPubkey, true);
3308
3581
  instructions.push(
3309
- createAssociatedTokenAccountInstruction5(
3582
+ createAssociatedTokenAccountInstruction3(
3310
3583
  payerPubkey,
3311
3584
  wsolAta,
3312
3585
  payerPubkey,
3313
- NATIVE_MINT5,
3314
- TOKEN_PROGRAM_ID5
3586
+ NATIVE_MINT4,
3587
+ TOKEN_PROGRAM_ID4
3315
3588
  )
3316
3589
  );
3590
+ instructions.push(
3591
+ SystemProgram6.transfer({
3592
+ fromPubkey: payerPubkey,
3593
+ toPubkey: wsolAta,
3594
+ lamports: Number(inputAmount)
3595
+ })
3596
+ );
3317
3597
  instructions.push(createSyncNativeInstruction5(wsolAta));
3598
+ } else if (createInputMintAta) {
3599
+ instructions.push(
3600
+ createAssociatedTokenAccountInstruction3(
3601
+ payerPubkey,
3602
+ inputTokenAccount,
3603
+ payerPubkey,
3604
+ inputMint,
3605
+ inputTokenProgram
3606
+ )
3607
+ );
3318
3608
  }
3319
3609
  if (createOutputMintAta) {
3320
3610
  instructions.push(
3321
- createAssociatedTokenAccountInstruction5(
3611
+ createAssociatedTokenAccountInstruction3(
3322
3612
  payerPubkey,
3323
3613
  outputTokenAccount,
3324
3614
  payerPubkey,
3325
3615
  outputMint,
3326
- TOKEN_PROGRAM_ID5
3616
+ outputTokenProgram
3327
3617
  )
3328
3618
  );
3329
3619
  }
3330
- const data = Buffer.alloc(24);
3331
- METEORA_DAMM_V2_SWAP_DISCRIMINATOR.copy(data, 0);
3620
+ const data = Buffer.alloc(25);
3621
+ METEORA_DAMM_V2_SWAP2_DISCRIMINATOR.copy(data, 0);
3332
3622
  data.writeBigUInt64LE(inputAmount, 8);
3333
3623
  data.writeBigUInt64LE(fixedOutputAmount, 16);
3624
+ data.writeUInt8(METEORA_DAMM_V2_SWAP_MODE_PARTIAL_FILL, 24);
3334
3625
  const accounts = [
3335
3626
  { pubkey: METEORA_DAMM_V2_AUTHORITY, isSigner: false, isWritable: false },
3336
3627
  { pubkey: pool, isSigner: false, isWritable: true },
@@ -3343,8 +3634,6 @@ function buildMeteoraDammV2BuyInstructions(params) {
3343
3634
  { pubkey: payerPubkey, isSigner: true, isWritable: true },
3344
3635
  { pubkey: tokenAProgram, isSigner: false, isWritable: false },
3345
3636
  { pubkey: tokenBProgram, isSigner: false, isWritable: false },
3346
- { pubkey: METEORA_DAMM_V2_PROGRAM_ID, isSigner: false, isWritable: false },
3347
- // Referral Token Account (placeholder)
3348
3637
  { pubkey: eventAuthority, isSigner: false, isWritable: false },
3349
3638
  { pubkey: METEORA_DAMM_V2_PROGRAM_ID, isSigner: false, isWritable: false }
3350
3639
  ];
@@ -3355,10 +3644,10 @@ function buildMeteoraDammV2BuyInstructions(params) {
3355
3644
  data
3356
3645
  })
3357
3646
  );
3358
- if (closeInputMintAta && isWsol) {
3359
- const wsolAta = getAssociatedTokenAddressSync5(NATIVE_MINT5, payerPubkey, true);
3647
+ if (closeInputMintAta && inputMint.equals(WSOL_TOKEN_ACCOUNT2)) {
3648
+ const wsolAta = getAssociatedTokenAddressSync5(NATIVE_MINT4, payerPubkey, true);
3360
3649
  instructions.push(
3361
- createCloseAccountInstruction5(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID5)
3650
+ createCloseAccountInstruction5(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID4)
3362
3651
  );
3363
3652
  }
3364
3653
  return instructions;
@@ -3366,8 +3655,8 @@ function buildMeteoraDammV2BuyInstructions(params) {
3366
3655
  function buildMeteoraDammV2SellInstructions(params) {
3367
3656
  const {
3368
3657
  payer,
3369
- inputMint,
3370
- outputMint,
3658
+ inputMint: requestedInputMint,
3659
+ outputMint: requestedOutputMint,
3371
3660
  inputAmount,
3372
3661
  fixedOutputAmount,
3373
3662
  createOutputMintAta = true,
@@ -3400,6 +3689,10 @@ function buildMeteoraDammV2SellInstructions(params) {
3400
3689
  throw new Error("Pool must contain WSOL or USDC");
3401
3690
  }
3402
3691
  const isAIn = tokenBMint.equals(WSOL_TOKEN_ACCOUNT2) || tokenBMint.equals(USDC_TOKEN_ACCOUNT2);
3692
+ const inputMint = isAIn ? tokenAMint : tokenBMint;
3693
+ const outputMint = isAIn ? tokenBMint : tokenAMint;
3694
+ ensureExpectedMint2("inputMint", requestedInputMint, inputMint);
3695
+ ensureExpectedMint2("outputMint", requestedOutputMint, outputMint);
3403
3696
  const inputTokenAccount = getAssociatedTokenAddressSync5(
3404
3697
  inputMint,
3405
3698
  payerPubkey,
@@ -3413,22 +3706,35 @@ function buildMeteoraDammV2SellInstructions(params) {
3413
3706
  isAIn ? tokenBProgram : tokenAProgram
3414
3707
  );
3415
3708
  const eventAuthority = getMeteoraDammV2EventAuthorityPda();
3416
- if (createOutputMintAta && isWsol) {
3417
- const wsolAta = getAssociatedTokenAddressSync5(NATIVE_MINT5, payerPubkey, true);
3709
+ const inputTokenProgram = isAIn ? tokenAProgram : tokenBProgram;
3710
+ const outputTokenProgram = isAIn ? tokenBProgram : tokenAProgram;
3711
+ if (createOutputMintAta && outputMint.equals(WSOL_TOKEN_ACCOUNT2)) {
3712
+ const wsolAta = getAssociatedTokenAddressSync5(NATIVE_MINT4, payerPubkey, true);
3418
3713
  instructions.push(
3419
- createAssociatedTokenAccountInstruction5(
3714
+ createAssociatedTokenAccountInstruction3(
3420
3715
  payerPubkey,
3421
3716
  wsolAta,
3422
3717
  payerPubkey,
3423
- NATIVE_MINT5,
3424
- TOKEN_PROGRAM_ID5
3718
+ NATIVE_MINT4,
3719
+ TOKEN_PROGRAM_ID4
3720
+ )
3721
+ );
3722
+ } else if (createOutputMintAta) {
3723
+ instructions.push(
3724
+ createAssociatedTokenAccountInstruction3(
3725
+ payerPubkey,
3726
+ outputTokenAccount,
3727
+ payerPubkey,
3728
+ outputMint,
3729
+ outputTokenProgram
3425
3730
  )
3426
3731
  );
3427
3732
  }
3428
- const data = Buffer.alloc(24);
3429
- METEORA_DAMM_V2_SWAP_DISCRIMINATOR.copy(data, 0);
3733
+ const data = Buffer.alloc(25);
3734
+ METEORA_DAMM_V2_SWAP2_DISCRIMINATOR.copy(data, 0);
3430
3735
  data.writeBigUInt64LE(inputAmount, 8);
3431
3736
  data.writeBigUInt64LE(fixedOutputAmount, 16);
3737
+ data.writeUInt8(METEORA_DAMM_V2_SWAP_MODE_PARTIAL_FILL, 24);
3432
3738
  const accounts = [
3433
3739
  { pubkey: METEORA_DAMM_V2_AUTHORITY, isSigner: false, isWritable: false },
3434
3740
  { pubkey: pool, isSigner: false, isWritable: true },
@@ -3441,8 +3747,6 @@ function buildMeteoraDammV2SellInstructions(params) {
3441
3747
  { pubkey: payerPubkey, isSigner: true, isWritable: true },
3442
3748
  { pubkey: tokenAProgram, isSigner: false, isWritable: false },
3443
3749
  { pubkey: tokenBProgram, isSigner: false, isWritable: false },
3444
- { pubkey: METEORA_DAMM_V2_PROGRAM_ID, isSigner: false, isWritable: false },
3445
- // Referral Token Account
3446
3750
  { pubkey: eventAuthority, isSigner: false, isWritable: false },
3447
3751
  { pubkey: METEORA_DAMM_V2_PROGRAM_ID, isSigner: false, isWritable: false }
3448
3752
  ];
@@ -3453,10 +3757,10 @@ function buildMeteoraDammV2SellInstructions(params) {
3453
3757
  data
3454
3758
  })
3455
3759
  );
3456
- if (closeOutputMintAta && isWsol) {
3457
- const wsolAta = getAssociatedTokenAddressSync5(NATIVE_MINT5, payerPubkey, true);
3760
+ if (closeOutputMintAta && outputMint.equals(WSOL_TOKEN_ACCOUNT2)) {
3761
+ const wsolAta = getAssociatedTokenAddressSync5(NATIVE_MINT4, payerPubkey, true);
3458
3762
  instructions.push(
3459
- createCloseAccountInstruction5(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID5)
3763
+ createCloseAccountInstruction5(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID4)
3460
3764
  );
3461
3765
  }
3462
3766
  if (closeInputMintAta) {
@@ -3541,14 +3845,14 @@ import {
3541
3845
  SystemProgram as SystemProgram7,
3542
3846
  SYSVAR_RENT_PUBKEY as SYSVAR_RENT_PUBKEY2
3543
3847
  } from "@solana/web3.js";
3544
- var TOKEN_PROGRAM_ID6 = new PublicKey8("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
3848
+ var TOKEN_PROGRAM_ID5 = new PublicKey8("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
3545
3849
  var TOKEN_2022_PROGRAM_ID2 = new PublicKey8("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
3546
3850
  var ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey8("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
3547
3851
  var TokenInstructionBuilder = class {
3548
3852
  /**
3549
3853
  * Create InitializeMint instruction
3550
3854
  */
3551
- static initializeMint(mint, decimals, mintAuthority, freezeAuthority, tokenProgram = TOKEN_PROGRAM_ID6) {
3855
+ static initializeMint(mint, decimals, mintAuthority, freezeAuthority, tokenProgram = TOKEN_PROGRAM_ID5) {
3552
3856
  const keys = [
3553
3857
  { pubkey: mint, isSigner: false, isWritable: true },
3554
3858
  { pubkey: SYSVAR_RENT_PUBKEY2, isSigner: false, isWritable: false }
@@ -3571,7 +3875,7 @@ var TokenInstructionBuilder = class {
3571
3875
  /**
3572
3876
  * Create InitializeAccount instruction
3573
3877
  */
3574
- static initializeAccount(account, mint, owner, tokenProgram = TOKEN_PROGRAM_ID6) {
3878
+ static initializeAccount(account, mint, owner, tokenProgram = TOKEN_PROGRAM_ID5) {
3575
3879
  const keys = [
3576
3880
  { pubkey: account, isSigner: false, isWritable: true },
3577
3881
  { pubkey: mint, isSigner: false, isWritable: false },
@@ -3588,7 +3892,7 @@ var TokenInstructionBuilder = class {
3588
3892
  /**
3589
3893
  * Create Transfer instruction
3590
3894
  */
3591
- static transfer(source, destination, owner, amount, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID6) {
3895
+ static transfer(source, destination, owner, amount, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID5) {
3592
3896
  const keys = [
3593
3897
  { pubkey: source, isSigner: false, isWritable: true },
3594
3898
  { pubkey: destination, isSigner: false, isWritable: true },
@@ -3611,7 +3915,7 @@ var TokenInstructionBuilder = class {
3611
3915
  /**
3612
3916
  * Create TransferChecked instruction
3613
3917
  */
3614
- static transferChecked(source, mint, destination, owner, amount, decimals, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID6) {
3918
+ static transferChecked(source, mint, destination, owner, amount, decimals, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID5) {
3615
3919
  const keys = [
3616
3920
  { pubkey: source, isSigner: false, isWritable: true },
3617
3921
  { pubkey: mint, isSigner: false, isWritable: false },
@@ -3636,7 +3940,7 @@ var TokenInstructionBuilder = class {
3636
3940
  /**
3637
3941
  * Create MintTo instruction
3638
3942
  */
3639
- static mintTo(mint, destination, authority, amount, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID6) {
3943
+ static mintTo(mint, destination, authority, amount, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID5) {
3640
3944
  const keys = [
3641
3945
  { pubkey: mint, isSigner: false, isWritable: true },
3642
3946
  { pubkey: destination, isSigner: false, isWritable: true },
@@ -3659,7 +3963,7 @@ var TokenInstructionBuilder = class {
3659
3963
  /**
3660
3964
  * Create Burn instruction
3661
3965
  */
3662
- static burn(account, mint, owner, amount, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID6) {
3966
+ static burn(account, mint, owner, amount, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID5) {
3663
3967
  const keys = [
3664
3968
  { pubkey: account, isSigner: false, isWritable: true },
3665
3969
  { pubkey: mint, isSigner: false, isWritable: true },
@@ -3682,7 +3986,7 @@ var TokenInstructionBuilder = class {
3682
3986
  /**
3683
3987
  * Create Approve instruction
3684
3988
  */
3685
- static approve(account, delegate, owner, amount, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID6) {
3989
+ static approve(account, delegate, owner, amount, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID5) {
3686
3990
  const keys = [
3687
3991
  { pubkey: account, isSigner: false, isWritable: true },
3688
3992
  { pubkey: delegate, isSigner: false, isWritable: false },
@@ -3705,7 +4009,7 @@ var TokenInstructionBuilder = class {
3705
4009
  /**
3706
4010
  * Create Revoke instruction
3707
4011
  */
3708
- static revoke(account, owner, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID6) {
4012
+ static revoke(account, owner, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID5) {
3709
4013
  const keys = [
3710
4014
  { pubkey: account, isSigner: false, isWritable: true },
3711
4015
  { pubkey: owner, isSigner: multiSigners.length === 0, isWritable: false },
@@ -3725,7 +4029,7 @@ var TokenInstructionBuilder = class {
3725
4029
  /**
3726
4030
  * Create CloseAccount instruction
3727
4031
  */
3728
- static closeAccount(account, destination, owner, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID6) {
4032
+ static closeAccount(account, destination, owner, multiSigners = [], tokenProgram = TOKEN_PROGRAM_ID5) {
3729
4033
  const keys = [
3730
4034
  { pubkey: account, isSigner: false, isWritable: true },
3731
4035
  { pubkey: destination, isSigner: false, isWritable: true },
@@ -3746,7 +4050,7 @@ var TokenInstructionBuilder = class {
3746
4050
  /**
3747
4051
  * Create SyncNative instruction (for WSOL accounts)
3748
4052
  */
3749
- static syncNative(nativeAccount, tokenProgram = TOKEN_PROGRAM_ID6) {
4053
+ static syncNative(nativeAccount, tokenProgram = TOKEN_PROGRAM_ID5) {
3750
4054
  const keys = [{ pubkey: nativeAccount, isSigner: false, isWritable: true }];
3751
4055
  const data = Buffer.from([17 /* SyncNative */]);
3752
4056
  return new TransactionInstruction7({
@@ -3760,7 +4064,7 @@ var TokenUtil = class {
3760
4064
  /**
3761
4065
  * Calculate associated token account address
3762
4066
  */
3763
- static async getAssociatedTokenAddress(mint, owner, _allowOwnerOffCurve = false, tokenProgram = TOKEN_PROGRAM_ID6, associatedTokenProgram = ASSOCIATED_TOKEN_PROGRAM_ID) {
4067
+ static async getAssociatedTokenAddress(mint, owner, _allowOwnerOffCurve = false, tokenProgram = TOKEN_PROGRAM_ID5, associatedTokenProgram = ASSOCIATED_TOKEN_PROGRAM_ID) {
3764
4068
  const [address] = await PublicKey8.findProgramAddress(
3765
4069
  [owner.toBuffer(), tokenProgram.toBuffer(), mint.toBuffer()],
3766
4070
  associatedTokenProgram
@@ -3770,7 +4074,7 @@ var TokenUtil = class {
3770
4074
  /**
3771
4075
  * Create associated token account idempotent instruction
3772
4076
  */
3773
- static createAssociatedTokenAccountIdempotentInstruction(payer, associatedToken, owner, mint, tokenProgram = TOKEN_PROGRAM_ID6, associatedTokenProgram = ASSOCIATED_TOKEN_PROGRAM_ID) {
4077
+ static createAssociatedTokenAccountIdempotentInstruction(payer, associatedToken, owner, mint, tokenProgram = TOKEN_PROGRAM_ID5, associatedTokenProgram = ASSOCIATED_TOKEN_PROGRAM_ID) {
3774
4078
  const keys = [
3775
4079
  { pubkey: payer, isSigner: true, isWritable: true },
3776
4080
  { pubkey: associatedToken, isSigner: false, isWritable: true },
@@ -3790,7 +4094,7 @@ var TokenUtil = class {
3790
4094
  /**
3791
4095
  * Create associated token account instruction
3792
4096
  */
3793
- static createAssociatedTokenAccountInstruction(payer, associatedToken, owner, mint, tokenProgram = TOKEN_PROGRAM_ID6, associatedTokenProgram = ASSOCIATED_TOKEN_PROGRAM_ID) {
4097
+ static createAssociatedTokenAccountInstruction(payer, associatedToken, owner, mint, tokenProgram = TOKEN_PROGRAM_ID5, associatedTokenProgram = ASSOCIATED_TOKEN_PROGRAM_ID) {
3794
4098
  const keys = [
3795
4099
  { pubkey: payer, isSigner: true, isWritable: true },
3796
4100
  { pubkey: associatedToken, isSigner: false, isWritable: true },
@@ -3836,7 +4140,7 @@ var TokenUtil = class {
3836
4140
  }
3837
4141
  };
3838
4142
  var WSOL_MINT2 = new PublicKey8("So11111111111111111111111111111111111111112");
3839
- var NATIVE_MINT6 = new PublicKey8("So11111111111111111111111111111111111111111");
4143
+ var NATIVE_MINT5 = new PublicKey8("So11111111111111111111111111111111111111111");
3840
4144
  var USDC_MINT2 = new PublicKey8("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
3841
4145
  var USDT_MINT = new PublicKey8("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB");
3842
4146
 
@@ -4075,23 +4379,6 @@ async function confirmAnyTransactionSignature(connection, signatures, options) {
4075
4379
  );
4076
4380
  }
4077
4381
 
4078
- // src/common/map-pool.ts
4079
- async function mapWithConcurrencyLimit(items, concurrency, fn) {
4080
- if (items.length === 0) return [];
4081
- const limit = Math.max(1, Math.min(concurrency, items.length));
4082
- const results = new Array(items.length);
4083
- let next = 0;
4084
- const worker = async () => {
4085
- for (; ; ) {
4086
- const i = next++;
4087
- if (i >= items.length) return;
4088
- results[i] = await fn(items[i], i);
4089
- }
4090
- };
4091
- await Promise.all(Array.from({ length: limit }, () => worker()));
4092
- return results;
4093
- }
4094
-
4095
4382
  // src/execution/execution.ts
4096
4383
  var BYTES_PER_ACCOUNT = 32;
4097
4384
  var MAX_INSTRUCTIONS_WARN = 64;
@@ -4517,12 +4804,22 @@ var RaydiumCpmmParams = class _RaydiumCpmmParams {
4517
4804
  }
4518
4805
  };
4519
4806
  var RaydiumAmmV4Params = class _RaydiumAmmV4Params {
4520
- constructor(amm, coinMint, pcMint, tokenCoin, tokenPc, coinReserve, pcReserve) {
4807
+ constructor(amm, coinMint, pcMint, tokenCoin, tokenPc, ammOpenOrders, ammTargetOrders, serumProgram, serumMarket, serumBids, serumAsks, serumEventQueue, serumCoinVaultAccount, serumPcVaultAccount, serumVaultSigner, coinReserve, pcReserve) {
4521
4808
  this.amm = amm;
4522
4809
  this.coinMint = coinMint;
4523
4810
  this.pcMint = pcMint;
4524
4811
  this.tokenCoin = tokenCoin;
4525
4812
  this.tokenPc = tokenPc;
4813
+ this.ammOpenOrders = ammOpenOrders;
4814
+ this.ammTargetOrders = ammTargetOrders;
4815
+ this.serumProgram = serumProgram;
4816
+ this.serumMarket = serumMarket;
4817
+ this.serumBids = serumBids;
4818
+ this.serumAsks = serumAsks;
4819
+ this.serumEventQueue = serumEventQueue;
4820
+ this.serumCoinVaultAccount = serumCoinVaultAccount;
4821
+ this.serumPcVaultAccount = serumPcVaultAccount;
4822
+ this.serumVaultSigner = serumVaultSigner;
4526
4823
  this.coinReserve = coinReserve;
4527
4824
  this.pcReserve = pcReserve;
4528
4825
  }
@@ -4531,6 +4828,16 @@ var RaydiumAmmV4Params = class _RaydiumAmmV4Params {
4531
4828
  pcMint;
4532
4829
  tokenCoin;
4533
4830
  tokenPc;
4831
+ ammOpenOrders;
4832
+ ammTargetOrders;
4833
+ serumProgram;
4834
+ serumMarket;
4835
+ serumBids;
4836
+ serumAsks;
4837
+ serumEventQueue;
4838
+ serumCoinVaultAccount;
4839
+ serumPcVaultAccount;
4840
+ serumVaultSigner;
4534
4841
  coinReserve;
4535
4842
  pcReserve;
4536
4843
  static async fromAmmAddressByRpc(connection, amm) {
@@ -4538,16 +4845,35 @@ var RaydiumAmmV4Params = class _RaydiumAmmV4Params {
4538
4845
  if (!ammInfo) {
4539
4846
  throw new Error("Raydium AMM account not found");
4540
4847
  }
4848
+ const marketState = await fetchMarketState(wrapConnection(connection), ammInfo.market);
4849
+ if (!marketState) {
4850
+ throw new Error("Raydium AMM market account not found");
4851
+ }
4852
+ const serumVaultSigner = deriveSerumVaultSigner(
4853
+ ammInfo.serumDex,
4854
+ ammInfo.market,
4855
+ marketState.vaultSignerNonce
4856
+ );
4541
4857
  const coinBal = await connection.getTokenAccountBalance(ammInfo.tokenCoin);
4542
4858
  const pcBal = await connection.getTokenAccountBalance(ammInfo.tokenPc);
4543
- const coinReserve = Number(coinBal.value.amount);
4544
- const pcReserve = Number(pcBal.value.amount);
4859
+ const coinReserve = BigInt(coinBal.value.amount);
4860
+ const pcReserve = BigInt(pcBal.value.amount);
4545
4861
  return new _RaydiumAmmV4Params(
4546
4862
  amm,
4547
4863
  ammInfo.coinMint,
4548
4864
  ammInfo.pcMint,
4549
4865
  ammInfo.tokenCoin,
4550
4866
  ammInfo.tokenPc,
4867
+ ammInfo.openOrders,
4868
+ ammInfo.targetOrders,
4869
+ ammInfo.serumDex,
4870
+ ammInfo.market,
4871
+ marketState.serumBids,
4872
+ marketState.serumAsks,
4873
+ marketState.serumEventQueue,
4874
+ marketState.serumCoinVaultAccount,
4875
+ marketState.serumPcVaultAccount,
4876
+ serumVaultSigner,
4551
4877
  coinReserve,
4552
4878
  pcReserve
4553
4879
  );
@@ -5148,20 +5474,30 @@ var HotPathExecutor = class {
5148
5474
  }
5149
5475
  };
5150
5476
  const promises = clients.map(submitToClient);
5151
- try {
5152
- const result = await Promise.any(promises);
5153
- return result;
5154
- } catch {
5155
- const results = await Promise.allSettled(promises);
5156
- const errors = results.filter((r) => r.status === "rejected").map((r) => r.reason);
5157
- return {
5158
- signature: "",
5159
- success: false,
5160
- error: `All parallel submissions failed: ${errors.join(", ")}`,
5161
- latencyMs: 0,
5162
- blockhashUsed: ""
5163
- };
5477
+ const pending = new Map(
5478
+ promises.map((promise, index) => [
5479
+ index,
5480
+ promise.then((result) => ({ index, result }))
5481
+ ])
5482
+ );
5483
+ const errors = [];
5484
+ while (pending.size > 0) {
5485
+ const { index, result } = await Promise.race(pending.values());
5486
+ pending.delete(index);
5487
+ if (result.success) {
5488
+ return result;
5489
+ }
5490
+ if (result.error) {
5491
+ errors.push(`${result.swqosType ?? "unknown"}: ${result.error}`);
5492
+ }
5164
5493
  }
5494
+ return {
5495
+ signature: "",
5496
+ success: false,
5497
+ error: `All parallel submissions failed${errors.length ? `: ${errors.join(", ")}` : ""}`,
5498
+ latencyMs: 0,
5499
+ blockhashUsed: ""
5500
+ };
5165
5501
  }
5166
5502
  /**
5167
5503
  * Submit to SWQoS clients sequentially - NO RPC
@@ -5253,6 +5589,23 @@ function createHotPathExecutor(connection, swqosClients, config) {
5253
5589
  return executor;
5254
5590
  }
5255
5591
 
5592
+ // src/common/map-pool.ts
5593
+ async function mapWithConcurrencyLimit(items, concurrency, fn) {
5594
+ if (items.length === 0) return [];
5595
+ const limit = Math.max(1, Math.min(concurrency, items.length));
5596
+ const results = new Array(items.length);
5597
+ let next = 0;
5598
+ const worker = async () => {
5599
+ for (; ; ) {
5600
+ const i = next++;
5601
+ if (i >= items.length) return;
5602
+ results[i] = await fn(items[i], i);
5603
+ }
5604
+ };
5605
+ await Promise.all(Array.from({ length: limit }, () => worker()));
5606
+ return results;
5607
+ }
5608
+
5256
5609
  // src/common/nonce.ts
5257
5610
  import { PublicKey as PublicKey15 } from "@solana/web3.js";
5258
5611
  import bs58 from "bs58";
@@ -5790,6 +6143,22 @@ var AddressLookupTableCache = class {
5790
6143
  var addressLookupTableCache = new AddressLookupTableCache();
5791
6144
 
5792
6145
  // src/trading/factory.ts
6146
+ var DexType = /* @__PURE__ */ ((DexType3) => {
6147
+ DexType3["PumpFun"] = "PumpFun";
6148
+ DexType3["PumpSwap"] = "PumpSwap";
6149
+ DexType3["Bonk"] = "Bonk";
6150
+ DexType3["RaydiumCpmm"] = "RaydiumCpmm";
6151
+ DexType3["RaydiumAmmV4"] = "RaydiumAmmV4";
6152
+ DexType3["MeteoraDammV2"] = "MeteoraDammV2";
6153
+ return DexType3;
6154
+ })(DexType || {});
6155
+ var TradeType = /* @__PURE__ */ ((TradeType4) => {
6156
+ TradeType4["Buy"] = "Buy";
6157
+ TradeType4["Sell"] = "Sell";
6158
+ TradeType4["Create"] = "Create";
6159
+ TradeType4["CreateAndBuy"] = "CreateAndBuy";
6160
+ return TradeType4;
6161
+ })(TradeType || {});
5793
6162
  function defaultTradeExecuteOptions() {
5794
6163
  return {
5795
6164
  waitConfirmation: true,
@@ -6138,15 +6507,15 @@ function withAllBuiltinMiddlewares() {
6138
6507
  }
6139
6508
 
6140
6509
  // src/index.ts
6141
- var DexType = /* @__PURE__ */ ((DexType2) => {
6142
- DexType2["PumpFun"] = "PumpFun";
6143
- DexType2["PumpSwap"] = "PumpSwap";
6144
- DexType2["Bonk"] = "Bonk";
6145
- DexType2["RaydiumCpmm"] = "RaydiumCpmm";
6146
- DexType2["RaydiumAmmV4"] = "RaydiumAmmV4";
6147
- DexType2["MeteoraDammV2"] = "MeteoraDammV2";
6148
- return DexType2;
6149
- })(DexType || {});
6510
+ var DexType2 = /* @__PURE__ */ ((DexType3) => {
6511
+ DexType3["PumpFun"] = "PumpFun";
6512
+ DexType3["PumpSwap"] = "PumpSwap";
6513
+ DexType3["Bonk"] = "Bonk";
6514
+ DexType3["RaydiumCpmm"] = "RaydiumCpmm";
6515
+ DexType3["RaydiumAmmV4"] = "RaydiumAmmV4";
6516
+ DexType3["MeteoraDammV2"] = "MeteoraDammV2";
6517
+ return DexType3;
6518
+ })(DexType2 || {});
6150
6519
  var TradeTokenType = /* @__PURE__ */ ((TradeTokenType2) => {
6151
6520
  TradeTokenType2["SOL"] = "SOL";
6152
6521
  TradeTokenType2["WSOL"] = "WSOL";
@@ -6154,11 +6523,11 @@ var TradeTokenType = /* @__PURE__ */ ((TradeTokenType2) => {
6154
6523
  TradeTokenType2["USDC"] = "USDC";
6155
6524
  return TradeTokenType2;
6156
6525
  })(TradeTokenType || {});
6157
- var TradeType2 = /* @__PURE__ */ ((TradeType3) => {
6158
- TradeType3["Buy"] = "Buy";
6159
- TradeType3["Sell"] = "Sell";
6160
- return TradeType3;
6161
- })(TradeType2 || {});
6526
+ var TradeType3 = /* @__PURE__ */ ((TradeType4) => {
6527
+ TradeType4["Buy"] = "Buy";
6528
+ TradeType4["Sell"] = "Sell";
6529
+ return TradeType4;
6530
+ })(TradeType3 || {});
6162
6531
  var SwqosRegion = /* @__PURE__ */ ((SwqosRegion2) => {
6163
6532
  SwqosRegion2["Frankfurt"] = "Frankfurt";
6164
6533
  SwqosRegion2["NewYork"] = "NewYork";
@@ -6207,6 +6576,88 @@ var AstralaneTransport = /* @__PURE__ */ ((AstralaneTransport2) => {
6207
6576
  AstralaneTransport2["Quic"] = "Quic";
6208
6577
  return AstralaneTransport2;
6209
6578
  })(AstralaneTransport || {});
6579
+ function normalizeSwqosConfigs(rpcUrl, configs) {
6580
+ if (configs.length === 0 || configs.some((c) => c.type === "Default" /* Default */)) {
6581
+ return configs;
6582
+ }
6583
+ return [
6584
+ ...configs,
6585
+ {
6586
+ type: "Default" /* Default */,
6587
+ region: "Default" /* Default */,
6588
+ apiKey: "",
6589
+ customUrl: rpcUrl
6590
+ }
6591
+ ];
6592
+ }
6593
+ function parserPublicKey(value) {
6594
+ if (!value) return PublicKey20.default;
6595
+ if (value instanceof PublicKey20) return value;
6596
+ if (value === PublicKey20.default.toBase58()) return PublicKey20.default;
6597
+ return new PublicKey20(value);
6598
+ }
6599
+ function pumpFunQuoteMintForLayout(quoteMint) {
6600
+ if (quoteMint.equals(PublicKey20.default) || quoteMint.equals(CONSTANTS.SOL_TOKEN_ACCOUNT)) {
6601
+ return PublicKey20.default;
6602
+ }
6603
+ return quoteMint;
6604
+ }
6605
+ function parserU64(value) {
6606
+ if (value === void 0 || value === null || value === "") return 0;
6607
+ const n = typeof value === "bigint" ? value : BigInt(value);
6608
+ if (n > BigInt(Number.MAX_SAFE_INTEGER)) {
6609
+ throw new TradeError(106, `parser u64 value ${n.toString()} exceeds JavaScript safe integer range`);
6610
+ }
6611
+ return Number(n);
6612
+ }
6613
+ function pumpFunParamsFromParserTrade(event, closeTokenAccountWhenSell) {
6614
+ const quoteMint = parserPublicKey(event.quote_mint);
6615
+ const legacySolQuote = quoteMint.equals(PublicKey20.default) || quoteMint.equals(CONSTANTS.SOL_TOKEN_ACCOUNT);
6616
+ const hasVirtualQuote = event.virtual_quote_reserves !== void 0;
6617
+ const hasRealQuote = event.real_quote_reserves !== void 0;
6618
+ const virtualQuote = !legacySolQuote && hasVirtualQuote ? parserU64(event.virtual_quote_reserves) : parserU64(event.virtual_sol_reserves);
6619
+ const realQuote = !legacySolQuote && hasRealQuote ? parserU64(event.real_quote_reserves) : parserU64(event.real_sol_reserves);
6620
+ const creator = parserPublicKey(event.creator);
6621
+ return {
6622
+ bondingCurve: {
6623
+ discriminator: 0,
6624
+ account: parserPublicKey(event.bonding_curve),
6625
+ virtualTokenReserves: parserU64(event.virtual_token_reserves),
6626
+ virtualSolReserves: virtualQuote,
6627
+ realTokenReserves: parserU64(event.real_token_reserves),
6628
+ realSolReserves: realQuote,
6629
+ tokenTotalSupply: 0,
6630
+ complete: false,
6631
+ creator,
6632
+ isMayhemMode: !!event.mayhem_mode,
6633
+ isCashbackCoin: !!event.is_cashback_coin
6634
+ },
6635
+ associatedBondingCurve: parserPublicKey(event.associated_bonding_curve),
6636
+ creatorVault: parserPublicKey(event.creator_vault),
6637
+ tokenProgram: parserPublicKey(event.token_program),
6638
+ closeTokenAccountWhenSell,
6639
+ feeRecipient: parserPublicKey(event.fee_recipient),
6640
+ quoteMint: pumpFunQuoteMintForLayout(quoteMint),
6641
+ observedTradeCreator: creator.equals(PublicKey20.default) ? void 0 : creator
6642
+ };
6643
+ }
6644
+ function pumpSwapParamsFromParserTrade(event) {
6645
+ return {
6646
+ pool: parserPublicKey(event.pool),
6647
+ baseMint: parserPublicKey(event.base_mint),
6648
+ quoteMint: parserPublicKey(event.quote_mint),
6649
+ poolBaseTokenAccount: parserPublicKey(event.pool_base_token_account),
6650
+ poolQuoteTokenAccount: parserPublicKey(event.pool_quote_token_account),
6651
+ poolBaseTokenReserves: parserU64(event.pool_base_token_reserves),
6652
+ poolQuoteTokenReserves: parserU64(event.pool_quote_token_reserves),
6653
+ coinCreatorVaultAta: parserPublicKey(event.coin_creator_vault_ata),
6654
+ coinCreatorVaultAuthority: parserPublicKey(event.coin_creator_vault_authority),
6655
+ baseTokenProgram: parserPublicKey(event.base_token_program),
6656
+ quoteTokenProgram: parserPublicKey(event.quote_token_program),
6657
+ isMayhemMode: !!event.is_mayhem_mode,
6658
+ isCashbackCoin: !!event.is_cashback_coin
6659
+ };
6660
+ }
6210
6661
  var TradeConfigBuilder = class _TradeConfigBuilder {
6211
6662
  _rpcUrl;
6212
6663
  _swqosConfigs = [];
@@ -6215,7 +6666,6 @@ var TradeConfigBuilder = class _TradeConfigBuilder {
6215
6666
  _checkMinTip = false;
6216
6667
  _mevProtection = false;
6217
6668
  _useSeedOptimize = true;
6218
- _usePumpfunV2 = false;
6219
6669
  _swqosCoresFromEnd = true;
6220
6670
  _createWsolAtaOnStartup = false;
6221
6671
  _gasFeeStrategy;
@@ -6229,7 +6679,7 @@ var TradeConfigBuilder = class _TradeConfigBuilder {
6229
6679
  return new _TradeConfigBuilder(rpcUrl);
6230
6680
  }
6231
6681
  swqosConfigs(configs) {
6232
- this._swqosConfigs = configs;
6682
+ this._swqosConfigs = normalizeSwqosConfigs(this._rpcUrl, configs);
6233
6683
  return this;
6234
6684
  }
6235
6685
  commitment(commitment) {
@@ -6258,10 +6708,6 @@ var TradeConfigBuilder = class _TradeConfigBuilder {
6258
6708
  this._useSeedOptimize = enabled;
6259
6709
  return this;
6260
6710
  }
6261
- usePumpfunV2(enabled) {
6262
- this._usePumpfunV2 = enabled;
6263
- return this;
6264
- }
6265
6711
  swqosCoresFromEnd(enabled) {
6266
6712
  this._swqosCoresFromEnd = enabled;
6267
6713
  return this;
@@ -6293,13 +6739,12 @@ var TradeConfigBuilder = class _TradeConfigBuilder {
6293
6739
  build() {
6294
6740
  return {
6295
6741
  rpcUrl: this._rpcUrl,
6296
- swqosConfigs: this._swqosConfigs,
6742
+ swqosConfigs: normalizeSwqosConfigs(this._rpcUrl, this._swqosConfigs),
6297
6743
  commitment: this._commitment,
6298
6744
  logEnabled: this._logEnabled,
6299
6745
  checkMinTip: this._checkMinTip,
6300
6746
  mevProtection: this._mevProtection,
6301
6747
  useSeedOptimize: this._useSeedOptimize,
6302
- usePumpfunV2: this._usePumpfunV2,
6303
6748
  swqosCoresFromEnd: this._swqosCoresFromEnd,
6304
6749
  createWsolAtaOnStartup: this._createWsolAtaOnStartup,
6305
6750
  gasFeeStrategy: this._gasFeeStrategy,
@@ -6346,8 +6791,7 @@ function mapPumpFunParams(p) {
6346
6791
  feeSharingCreatorVaultIfActive: p.feeSharingCreatorVaultIfActive,
6347
6792
  closeTokenAccountWhenSell: p.closeTokenAccountWhenSell,
6348
6793
  feeRecipient: p.feeRecipient,
6349
- quoteMint: p.quoteMint,
6350
- useV2Ix: p.useV2Ix
6794
+ quoteMint: p.quoteMint
6351
6795
  };
6352
6796
  }
6353
6797
  async function findPoolByMint2(connection, mint, dexType) {
@@ -6371,7 +6815,7 @@ async function findPoolByMint2(connection, mint, dexType) {
6371
6815
  }
6372
6816
  return found.poolAddress;
6373
6817
  }
6374
- var SWQOS_SUBMIT_TIMEOUT_MS_WHEN_NO_CONFIRM = 2e3;
6818
+ var SWQOS_SUBMIT_TIMEOUT_MS_WHEN_NO_CONFIRM = 5e3;
6375
6819
  var RUST_PARITY_SIMULATE_CONFIG = {
6376
6820
  sigVerify: false,
6377
6821
  replaceRecentBlockhash: false,
@@ -6448,7 +6892,24 @@ function gasConfigFromStrategyValue(value, tradeType) {
6448
6892
  sellTipLamports: !isBuy ? tipLam : 0
6449
6893
  };
6450
6894
  }
6451
- function expandSwqosGasTasks(effectiveSwqos, tradeType, execGas, configGas, gasStrategy, useStrategyRowMinTip, checkMinTip, withTip, swqosMod, mevProtection, rpcUrl, logEnabled) {
6895
+ async function collectUntilFirstSuccess(promises, isSuccess) {
6896
+ if (promises.length === 0) return [];
6897
+ const results = [];
6898
+ const pending = new Map(
6899
+ promises.map((promise, index) => [
6900
+ index,
6901
+ promise.then((result) => ({ index, result }))
6902
+ ])
6903
+ );
6904
+ while (pending.size > 0) {
6905
+ const { index, result } = await Promise.race(pending.values());
6906
+ pending.delete(index);
6907
+ results.push(result);
6908
+ if (isSuccess(result)) return results;
6909
+ }
6910
+ return results;
6911
+ }
6912
+ function expandSwqosGasTasks(effectiveSwqos, tradeType, execGas, configGas, gasStrategy, useStrategyRowMinTip, checkMinTip, withTip, swqosMod, mevProtection, rpcUrl, logEnabled, getClient) {
6452
6913
  const out = [];
6453
6914
  if (execGas || configGas) {
6454
6915
  for (const cfg of effectiveSwqos) {
@@ -6473,10 +6934,7 @@ function expandSwqosGasTasks(effectiveSwqos, tradeType, execGas, configGas, gasS
6473
6934
  for (const row of matching) {
6474
6935
  const tipLamports = Math.floor(row.value.tip * 1e9);
6475
6936
  if (checkMinTip && withTip && cfg.type !== "Default" /* Default */) {
6476
- const client = swqosMod.ClientFactory.createClient(
6477
- mapSwqosToClientConfig(cfg, mevProtection),
6478
- rpcUrl
6479
- );
6937
+ const client = getClient?.(cfg) ?? swqosMod.ClientFactory.createClient(mapSwqosToClientConfig(cfg, mevProtection), rpcUrl);
6480
6938
  const minLamports = Math.ceil(client.minTipSol() * 1e9);
6481
6939
  if (tipLamports < minLamports) {
6482
6940
  if (logEnabled) {
@@ -6514,7 +6972,7 @@ function filterSwqosConfigsForWithTip(configs, withTip) {
6514
6972
  if (withTip) return configs;
6515
6973
  return configs.filter((c) => c.type === "Default" /* Default */);
6516
6974
  }
6517
- function filterSwqosConfigsByMinTip(swqosMod, configs, tradeType, gas, mevProtection, rpcUrl, logEnabled) {
6975
+ function filterSwqosConfigsByMinTip(swqosMod, configs, tradeType, gas, mevProtection, rpcUrl, logEnabled, getClient) {
6518
6976
  const tipLamports = gas ? tradeType === "Buy" /* Buy */ ? gas.buyTipLamports : gas.sellTipLamports : 0;
6519
6977
  const out = [];
6520
6978
  for (const cfg of configs) {
@@ -6522,10 +6980,7 @@ function filterSwqosConfigsByMinTip(swqosMod, configs, tradeType, gas, mevProtec
6522
6980
  out.push(cfg);
6523
6981
  continue;
6524
6982
  }
6525
- const client = swqosMod.ClientFactory.createClient(
6526
- mapSwqosToClientConfig(cfg, mevProtection),
6527
- rpcUrl
6528
- );
6983
+ const client = getClient?.(cfg) ?? swqosMod.ClientFactory.createClient(mapSwqosToClientConfig(cfg, mevProtection), rpcUrl);
6529
6984
  const minLamports = Math.ceil(client.minTipSol() * 1e9);
6530
6985
  if (tipLamports < minLamports) {
6531
6986
  if (logEnabled) {
@@ -6539,13 +6994,10 @@ function filterSwqosConfigsByMinTip(swqosMod, configs, tradeType, gas, mevProtec
6539
6994
  }
6540
6995
  return out;
6541
6996
  }
6542
- function resolveTipRecipientPubkey(swqosMod, configs, mevProtection, rpcUrl) {
6997
+ function resolveTipRecipientPubkey(swqosMod, configs, mevProtection, rpcUrl, getClient) {
6543
6998
  const preferred = configs.find((c) => c.type !== "Default" /* Default */) ?? configs[0];
6544
6999
  if (!preferred) return null;
6545
- const client = swqosMod.ClientFactory.createClient(
6546
- mapSwqosToClientConfig(preferred, mevProtection),
6547
- rpcUrl
6548
- );
7000
+ const client = getClient?.(preferred) ?? swqosMod.ClientFactory.createClient(mapSwqosToClientConfig(preferred, mevProtection), rpcUrl);
6549
7001
  const acc = client.getTipAccount();
6550
7002
  if (!acc) return null;
6551
7003
  try {
@@ -6560,14 +7012,48 @@ var TradingClient = class {
6560
7012
  _config;
6561
7013
  middlewares = [];
6562
7014
  _logEnabled;
7015
+ _swqosModulePromise;
7016
+ _swqosClientCache = /* @__PURE__ */ new Map();
6563
7017
  constructor(payer, config) {
6564
7018
  this.payer = payer;
6565
- this._config = config;
7019
+ this._config = {
7020
+ ...config,
7021
+ swqosConfigs: normalizeSwqosConfigs(config.rpcUrl, config.swqosConfigs ?? [])
7022
+ };
6566
7023
  this.connection = new Connection6(config.rpcUrl, {
6567
7024
  commitment: config.commitment ?? "confirmed"
6568
7025
  });
6569
7026
  this._logEnabled = config.logEnabled ?? true;
6570
7027
  }
7028
+ getSwqosModule() {
7029
+ this._swqosModulePromise ??= import("./clients-PSG35HN4.mjs");
7030
+ return this._swqosModulePromise;
7031
+ }
7032
+ swqosClientCacheKey(cfg) {
7033
+ return JSON.stringify([
7034
+ this._config.rpcUrl,
7035
+ this._config.mevProtection ?? false,
7036
+ cfg.type,
7037
+ cfg.region ?? null,
7038
+ cfg.customUrl ?? null,
7039
+ cfg.apiKey ?? null,
7040
+ cfg.transport ?? null,
7041
+ cfg.astralaneTransport ?? null,
7042
+ cfg.swqosOnly ?? null,
7043
+ cfg.mevProtection ?? null
7044
+ ]);
7045
+ }
7046
+ getSwqosClient(swqosMod, cfg) {
7047
+ const key = this.swqosClientCacheKey(cfg);
7048
+ const cached = this._swqosClientCache.get(key);
7049
+ if (cached) return cached;
7050
+ const client = swqosMod.ClientFactory.createClient(
7051
+ mapSwqosToClientConfig(cfg, this._config.mevProtection),
7052
+ this._config.rpcUrl
7053
+ );
7054
+ this._swqosClientCache.set(key, client);
7055
+ return client;
7056
+ }
6571
7057
  /** Get the current configuration */
6572
7058
  get config() {
6573
7059
  return this._config;
@@ -6802,9 +7288,10 @@ var TradingClient = class {
6802
7288
  fixedOutputAmount: params.fixedOutputTokenAmount !== void 0 ? BigInt(params.fixedOutputTokenAmount) : void 0,
6803
7289
  createOutputMintAta: params.createMintAta ?? true,
6804
7290
  createInputMintAta: params.createInputTokenAta ?? false,
7291
+ closeInputMintAta: params.closeInputTokenAta ?? false,
6805
7292
  protocolParams: mapPumpFunParams(ext.params),
6806
7293
  useExactSolAmount: params.useExactSolAmount ?? true,
6807
- usePumpFunV2: this._config.usePumpfunV2 ?? ext.params.useV2Ix ?? false
7294
+ inputMint: this.getInputMint(params.inputTokenType)
6808
7295
  });
6809
7296
  }
6810
7297
  case "PumpSwap" /* PumpSwap */: {
@@ -6903,8 +7390,18 @@ var TradingClient = class {
6903
7390
  pcMint: p.pcMint,
6904
7391
  tokenCoin: p.tokenCoin,
6905
7392
  tokenPc: p.tokenPc,
6906
- coinReserve: BigInt(p.coinReserve),
6907
- pcReserve: BigInt(p.pcReserve)
7393
+ ammOpenOrders: p.ammOpenOrders,
7394
+ ammTargetOrders: p.ammTargetOrders,
7395
+ serumProgram: p.serumProgram,
7396
+ serumMarket: p.serumMarket,
7397
+ serumBids: p.serumBids,
7398
+ serumAsks: p.serumAsks,
7399
+ serumEventQueue: p.serumEventQueue,
7400
+ serumCoinVaultAccount: p.serumCoinVaultAccount,
7401
+ serumPcVaultAccount: p.serumPcVaultAccount,
7402
+ serumVaultSigner: p.serumVaultSigner,
7403
+ coinReserve: p.coinReserve,
7404
+ pcReserve: p.pcReserve
6908
7405
  };
6909
7406
  return buildRaydiumAmmV4BuyInstructions({
6910
7407
  payer: this.payer.publicKey,
@@ -6970,7 +7467,7 @@ var TradingClient = class {
6970
7467
  closeInputMintAta: params.closeMintTokenAta ?? false,
6971
7468
  createOutputMintAta: params.createOutputTokenAta ?? false,
6972
7469
  protocolParams: mapPumpFunParams(ext.params),
6973
- usePumpFunV2: this._config.usePumpfunV2 ?? ext.params.useV2Ix ?? false
7470
+ outputMint: this.getOutputMint(params.outputTokenType)
6974
7471
  });
6975
7472
  }
6976
7473
  case "PumpSwap" /* PumpSwap */: {
@@ -7068,12 +7565,23 @@ var TradingClient = class {
7068
7565
  pcMint: p.pcMint,
7069
7566
  tokenCoin: p.tokenCoin,
7070
7567
  tokenPc: p.tokenPc,
7071
- coinReserve: BigInt(p.coinReserve),
7072
- pcReserve: BigInt(p.pcReserve)
7568
+ ammOpenOrders: p.ammOpenOrders,
7569
+ ammTargetOrders: p.ammTargetOrders,
7570
+ serumProgram: p.serumProgram,
7571
+ serumMarket: p.serumMarket,
7572
+ serumBids: p.serumBids,
7573
+ serumAsks: p.serumAsks,
7574
+ serumEventQueue: p.serumEventQueue,
7575
+ serumCoinVaultAccount: p.serumCoinVaultAccount,
7576
+ serumPcVaultAccount: p.serumPcVaultAccount,
7577
+ serumVaultSigner: p.serumVaultSigner,
7578
+ coinReserve: p.coinReserve,
7579
+ pcReserve: p.pcReserve
7073
7580
  };
7074
7581
  return buildRaydiumAmmV4SellInstructions({
7075
7582
  payer: this.payer.publicKey,
7076
7583
  inputMint: params.mint,
7584
+ outputMint: this.getOutputMint(params.outputTokenType),
7077
7585
  inputAmount: inputAmt,
7078
7586
  slippageBasisPoints: slippage,
7079
7587
  fixedOutputAmount: params.fixedOutputTokenAmount !== void 0 ? BigInt(params.fixedOutputTokenAmount) : void 0,
@@ -7149,11 +7657,23 @@ var TradingClient = class {
7149
7657
  return result;
7150
7658
  }
7151
7659
  async executeTransaction(instructions, recentBlockhash, lookupTableAccount, waitConfirmed, simulate, execCtx) {
7152
- const blockhash = recentBlockhash ?? execCtx?.durableNonce?.nonceHash ?? (await this.connection.getLatestBlockhash(this.rpcCommitment())).blockhash;
7660
+ const blockhash = recentBlockhash ?? execCtx?.durableNonce?.nonceHash;
7661
+ if (!blockhash) {
7662
+ return {
7663
+ success: false,
7664
+ signatures: [],
7665
+ error: new TradeError(
7666
+ 105,
7667
+ "recentBlockhash or durableNonce.nonceHash is required; trade execution hot path does not query RPC for blockhash"
7668
+ ),
7669
+ timings: []
7670
+ };
7671
+ }
7153
7672
  const swqosList = this._config.swqosConfigs ?? [];
7154
7673
  const tradeType = execCtx?.tradeType ?? "Buy" /* Buy */;
7155
7674
  const withTip = execCtx?.withTip ?? true;
7156
- const swqosMod = swqosList.length > 0 ? await import("./clients-VITWK7B6.mjs") : null;
7675
+ const swqosMod = swqosList.length > 0 ? await this.getSwqosModule() : null;
7676
+ const swqosClientForConfig = swqosMod ? (cfg) => this.getSwqosClient(swqosMod, cfg) : void 0;
7157
7677
  let effectiveSwqos = swqosList;
7158
7678
  if (swqosMod && !withTip) {
7159
7679
  effectiveSwqos = filterSwqosConfigsForWithTip(swqosList, withTip);
@@ -7185,7 +7705,8 @@ var TradingClient = class {
7185
7705
  gasMerged,
7186
7706
  this._config.mevProtection,
7187
7707
  this._config.rpcUrl,
7188
- this._logEnabled
7708
+ this._logEnabled,
7709
+ swqosClientForConfig
7189
7710
  );
7190
7711
  if (effectiveSwqos.length === 0) {
7191
7712
  return {
@@ -7219,7 +7740,8 @@ var TradingClient = class {
7219
7740
  swqosMod,
7220
7741
  this._config.mevProtection,
7221
7742
  this._config.rpcUrl,
7222
- this._logEnabled
7743
+ this._logEnabled,
7744
+ swqosClientForConfig
7223
7745
  );
7224
7746
  if (swqosTasks.length === 0) {
7225
7747
  return {
@@ -7281,7 +7803,8 @@ var TradingClient = class {
7281
7803
  swqosMod,
7282
7804
  [t.cfg],
7283
7805
  this._config.mevProtection,
7284
- this._config.rpcUrl
7806
+ this._config.rpcUrl,
7807
+ swqosClientForConfig
7285
7808
  ) : null;
7286
7809
  const txSim2 = buildSignedVersionedTransaction(
7287
7810
  this.payer,
@@ -7336,17 +7859,15 @@ var TradingClient = class {
7336
7859
  if (swqosMod) {
7337
7860
  const timings = [];
7338
7861
  const signatures = [];
7339
- const submitConcurrency = this._config.maxSwqosSubmitConcurrency ?? swqosTasks.length;
7340
- const results = await mapWithConcurrencyLimit(
7341
- swqosTasks,
7342
- submitConcurrency,
7343
- async (task) => {
7344
- const t0 = performance.now();
7862
+ const submitTask = async (task) => {
7863
+ const t0 = performance.now();
7864
+ try {
7345
7865
  const tipPk = withTip ? resolveTipRecipientPubkey(
7346
7866
  swqosMod,
7347
7867
  [task.cfg],
7348
7868
  this._config.mevProtection,
7349
- this._config.rpcUrl
7869
+ this._config.rpcUrl,
7870
+ swqosClientForConfig
7350
7871
  ) : null;
7351
7872
  const tx = buildSignedVersionedTransaction(
7352
7873
  this.payer,
@@ -7355,33 +7876,30 @@ var TradingClient = class {
7355
7876
  lookupTableAccount
7356
7877
  );
7357
7878
  const raw = Buffer.from(tx.serialize());
7358
- const client = swqosMod.ClientFactory.createClient(
7359
- mapSwqosToClientConfig(task.cfg, this._config.mevProtection),
7360
- this._config.rpcUrl
7361
- );
7362
- try {
7363
- const pending = client.sendTransaction(tradeType, raw, false);
7364
- const sig = await (!waitConfirmed ? Promise.race([
7365
- pending,
7366
- new Promise(
7367
- (_, reject) => setTimeout(
7368
- () => reject(
7369
- new Error(
7370
- `SWQOS submit timed out after ${SWQOS_SUBMIT_TIMEOUT_MS_WHEN_NO_CONFIRM}ms`
7371
- )
7372
- ),
7373
- SWQOS_SUBMIT_TIMEOUT_MS_WHEN_NO_CONFIRM
7374
- )
7879
+ const client = swqosClientForConfig(task.cfg);
7880
+ const pending = client.sendTransaction(tradeType, raw, false);
7881
+ const sig = await (!waitConfirmed ? Promise.race([
7882
+ pending,
7883
+ new Promise(
7884
+ (_, reject) => setTimeout(
7885
+ () => reject(
7886
+ new Error(
7887
+ `SWQOS submit timed out after ${SWQOS_SUBMIT_TIMEOUT_MS_WHEN_NO_CONFIRM}ms`
7888
+ )
7889
+ ),
7890
+ SWQOS_SUBMIT_TIMEOUT_MS_WHEN_NO_CONFIRM
7375
7891
  )
7376
- ]) : pending);
7377
- const duration = Math.round((performance.now() - t0) * 1e3);
7378
- return { ok: true, sig, task, duration };
7379
- } catch (e) {
7380
- const duration = Math.round((performance.now() - t0) * 1e3);
7381
- return { ok: false, err: e, task, duration };
7382
- }
7892
+ )
7893
+ ]) : pending);
7894
+ const duration = Math.round((performance.now() - t0) * 1e3);
7895
+ return { ok: true, sig, task, duration };
7896
+ } catch (e) {
7897
+ const duration = Math.round((performance.now() - t0) * 1e3);
7898
+ return { ok: false, err: e, task, duration };
7383
7899
  }
7384
- );
7900
+ };
7901
+ const submitPromises = swqosTasks.map((task) => submitTask(task));
7902
+ const results = waitConfirmed ? await Promise.all(submitPromises) : await collectUntilFirstSuccess(submitPromises, (result) => result.ok);
7385
7903
  for (const v of results) {
7386
7904
  timings.push({
7387
7905
  swqosType: v.task.cfg.type,
@@ -7389,7 +7907,7 @@ var TradingClient = class {
7389
7907
  gasFeeStrategyType: v.task.strategyType
7390
7908
  });
7391
7909
  if (v.ok) {
7392
- signatures.push(v.sig);
7910
+ if (v.sig) signatures.push(v.sig);
7393
7911
  }
7394
7912
  }
7395
7913
  const success = signatures.length > 0;
@@ -7456,7 +7974,7 @@ function createTradeConfig(rpcUrl, swqosConfigs = [], options) {
7456
7974
  const { commitment, logEnabled, ...rest } = options ?? {};
7457
7975
  return {
7458
7976
  rpcUrl,
7459
- swqosConfigs,
7977
+ swqosConfigs: normalizeSwqosConfigs(rpcUrl, swqosConfigs),
7460
7978
  ...rest,
7461
7979
  commitment: commitment ?? "confirmed",
7462
7980
  logEnabled: logEnabled ?? true
@@ -7638,11 +8156,17 @@ export {
7638
8156
  buildRaydiumAmmV4BuyInstructions,
7639
8157
  buildRaydiumAmmV4SellInstructions,
7640
8158
  AMM_INFO_SIZE,
8159
+ MARKET_STATE_SIZE,
7641
8160
  decodeAmmInfo,
8161
+ decodeMarketState,
8162
+ deriveSerumVaultSigner,
7642
8163
  fetchAmmInfo,
8164
+ fetchMarketState,
7643
8165
  METEORA_DAMM_V2_PROGRAM_ID,
7644
8166
  METEORA_DAMM_V2_AUTHORITY,
7645
8167
  METEORA_DAMM_V2_SWAP_DISCRIMINATOR,
8168
+ METEORA_DAMM_V2_SWAP2_DISCRIMINATOR,
8169
+ METEORA_DAMM_V2_SWAP_MODE_PARTIAL_FILL,
7646
8170
  METEORA_DAMM_V2_EVENT_AUTHORITY_SEED,
7647
8171
  getMeteoraDammV2EventAuthorityPda,
7648
8172
  buildMeteoraDammV2BuyInstructions,
@@ -7655,7 +8179,6 @@ export {
7655
8179
  extractHintsFromLogs,
7656
8180
  instructionErrorCodeFromMetaErr,
7657
8181
  confirmAnyTransactionSignature,
7658
- mapWithConcurrencyLimit,
7659
8182
  BYTES_PER_ACCOUNT,
7660
8183
  MAX_INSTRUCTIONS_WARN,
7661
8184
  Prefetch,
@@ -7691,6 +8214,7 @@ export {
7691
8214
  HotPathExecutor,
7692
8215
  TransactionBuilder,
7693
8216
  createHotPathExecutor,
8217
+ mapWithConcurrencyLimit,
7694
8218
  fetchDurableNonceInfo,
7695
8219
  SecureKeyError,
7696
8220
  KeyNotAvailableError,
@@ -7710,6 +8234,8 @@ export {
7710
8234
  parseAddressLookupTable,
7711
8235
  AddressLookupTableCache,
7712
8236
  addressLookupTableCache,
8237
+ DexType,
8238
+ TradeType,
7713
8239
  defaultTradeExecuteOptions,
7714
8240
  BaseExecutor,
7715
8241
  PumpFunExecutor,
@@ -7727,13 +8253,15 @@ export {
7727
8253
  MetricsMiddleware,
7728
8254
  withStandardMiddlewares,
7729
8255
  withAllBuiltinMiddlewares,
7730
- DexType,
8256
+ DexType2,
7731
8257
  TradeTokenType,
7732
- TradeType2 as TradeType,
8258
+ TradeType3 as TradeType2,
7733
8259
  SwqosRegion,
7734
8260
  SwqosType,
7735
8261
  SwqosTransport,
7736
8262
  AstralaneTransport,
8263
+ pumpFunParamsFromParserTrade,
8264
+ pumpSwapParamsFromParserTrade,
7737
8265
  TradeConfigBuilder,
7738
8266
  recommendedSenderThreadCoreIndices,
7739
8267
  findPoolByMint2 as findPoolByMint,