outsmart 2.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +568 -0
  3. package/dist/cli.d.ts +44 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +1251 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/dex/byreal-clmm.d.ts +16 -0
  8. package/dist/dex/byreal-clmm.d.ts.map +1 -0
  9. package/dist/dex/byreal-clmm.js +39 -0
  10. package/dist/dex/byreal-clmm.js.map +1 -0
  11. package/dist/dex/dflow.d.ts +27 -0
  12. package/dist/dex/dflow.d.ts.map +1 -0
  13. package/dist/dex/dflow.js +200 -0
  14. package/dist/dex/dflow.js.map +1 -0
  15. package/dist/dex/fusion-amm.d.ts +44 -0
  16. package/dist/dex/fusion-amm.d.ts.map +1 -0
  17. package/dist/dex/fusion-amm.js +546 -0
  18. package/dist/dex/fusion-amm.js.map +1 -0
  19. package/dist/dex/futarchy-amm.d.ts +32 -0
  20. package/dist/dex/futarchy-amm.d.ts.map +1 -0
  21. package/dist/dex/futarchy-amm.js +443 -0
  22. package/dist/dex/futarchy-amm.js.map +1 -0
  23. package/dist/dex/futarchy-idl.d.ts +2568 -0
  24. package/dist/dex/futarchy-idl.d.ts.map +1 -0
  25. package/dist/dex/futarchy-idl.js +2570 -0
  26. package/dist/dex/futarchy-idl.js.map +1 -0
  27. package/dist/dex/futarchy-launchpad.d.ts +68 -0
  28. package/dist/dex/futarchy-launchpad.d.ts.map +1 -0
  29. package/dist/dex/futarchy-launchpad.js +377 -0
  30. package/dist/dex/futarchy-launchpad.js.map +1 -0
  31. package/dist/dex/index.d.ts +88 -0
  32. package/dist/dex/index.d.ts.map +1 -0
  33. package/dist/dex/index.js +159 -0
  34. package/dist/dex/index.js.map +1 -0
  35. package/dist/dex/jupiter-ultra.d.ts +27 -0
  36. package/dist/dex/jupiter-ultra.d.ts.map +1 -0
  37. package/dist/dex/jupiter-ultra.js +369 -0
  38. package/dist/dex/jupiter-ultra.js.map +1 -0
  39. package/dist/dex/meteora-damm-v1.d.ts +36 -0
  40. package/dist/dex/meteora-damm-v1.d.ts.map +1 -0
  41. package/dist/dex/meteora-damm-v1.js +314 -0
  42. package/dist/dex/meteora-damm-v1.js.map +1 -0
  43. package/dist/dex/meteora-damm-v2.d.ts +103 -0
  44. package/dist/dex/meteora-damm-v2.d.ts.map +1 -0
  45. package/dist/dex/meteora-damm-v2.js +1146 -0
  46. package/dist/dex/meteora-damm-v2.js.map +1 -0
  47. package/dist/dex/meteora-dbc.d.ts +38 -0
  48. package/dist/dex/meteora-dbc.d.ts.map +1 -0
  49. package/dist/dex/meteora-dbc.js +374 -0
  50. package/dist/dex/meteora-dbc.js.map +1 -0
  51. package/dist/dex/meteora-dlmm.d.ts +79 -0
  52. package/dist/dex/meteora-dlmm.d.ts.map +1 -0
  53. package/dist/dex/meteora-dlmm.js +735 -0
  54. package/dist/dex/meteora-dlmm.js.map +1 -0
  55. package/dist/dex/orca.d.ts +31 -0
  56. package/dist/dex/orca.d.ts.map +1 -0
  57. package/dist/dex/orca.js +536 -0
  58. package/dist/dex/orca.js.map +1 -0
  59. package/dist/dex/pancakeswap-clmm.d.ts +16 -0
  60. package/dist/dex/pancakeswap-clmm.d.ts.map +1 -0
  61. package/dist/dex/pancakeswap-clmm.js +39 -0
  62. package/dist/dex/pancakeswap-clmm.js.map +1 -0
  63. package/dist/dex/pumpfun-amm.d.ts +46 -0
  64. package/dist/dex/pumpfun-amm.d.ts.map +1 -0
  65. package/dist/dex/pumpfun-amm.js +692 -0
  66. package/dist/dex/pumpfun-amm.js.map +1 -0
  67. package/dist/dex/pumpfun.d.ts +41 -0
  68. package/dist/dex/pumpfun.d.ts.map +1 -0
  69. package/dist/dex/pumpfun.js +555 -0
  70. package/dist/dex/pumpfun.js.map +1 -0
  71. package/dist/dex/raydium-amm-v4.d.ts +11 -0
  72. package/dist/dex/raydium-amm-v4.d.ts.map +1 -0
  73. package/dist/dex/raydium-amm-v4.js +649 -0
  74. package/dist/dex/raydium-amm-v4.js.map +1 -0
  75. package/dist/dex/raydium-clmm.d.ts +12 -0
  76. package/dist/dex/raydium-clmm.d.ts.map +1 -0
  77. package/dist/dex/raydium-clmm.js +675 -0
  78. package/dist/dex/raydium-clmm.js.map +1 -0
  79. package/dist/dex/raydium-cpmm.d.ts +10 -0
  80. package/dist/dex/raydium-cpmm.d.ts.map +1 -0
  81. package/dist/dex/raydium-cpmm.js +613 -0
  82. package/dist/dex/raydium-cpmm.js.map +1 -0
  83. package/dist/dex/raydium-launchlab.d.ts +12 -0
  84. package/dist/dex/raydium-launchlab.d.ts.map +1 -0
  85. package/dist/dex/raydium-launchlab.js +530 -0
  86. package/dist/dex/raydium-launchlab.js.map +1 -0
  87. package/dist/dex/shared/clmm-base.d.ts +58 -0
  88. package/dist/dex/shared/clmm-base.d.ts.map +1 -0
  89. package/dist/dex/shared/clmm-base.js +891 -0
  90. package/dist/dex/shared/clmm-base.js.map +1 -0
  91. package/dist/dex/types.d.ts +601 -0
  92. package/dist/dex/types.d.ts.map +1 -0
  93. package/dist/dex/types.js +137 -0
  94. package/dist/dex/types.js.map +1 -0
  95. package/dist/dexscreener/index.d.ts +2 -0
  96. package/dist/dexscreener/index.d.ts.map +1 -0
  97. package/dist/dexscreener/index.js +18 -0
  98. package/dist/dexscreener/index.js.map +1 -0
  99. package/dist/dexscreener/info.d.ts +22 -0
  100. package/dist/dexscreener/info.d.ts.map +1 -0
  101. package/dist/dexscreener/info.js +104 -0
  102. package/dist/dexscreener/info.js.map +1 -0
  103. package/dist/helpers/check_balance.d.ts +10 -0
  104. package/dist/helpers/check_balance.d.ts.map +1 -0
  105. package/dist/helpers/check_balance.js +34 -0
  106. package/dist/helpers/check_balance.js.map +1 -0
  107. package/dist/helpers/config.d.ts +51 -0
  108. package/dist/helpers/config.d.ts.map +1 -0
  109. package/dist/helpers/config.js +118 -0
  110. package/dist/helpers/config.js.map +1 -0
  111. package/dist/helpers/index.d.ts +8 -0
  112. package/dist/helpers/index.d.ts.map +1 -0
  113. package/dist/helpers/index.js +29 -0
  114. package/dist/helpers/index.js.map +1 -0
  115. package/dist/helpers/logger.d.ts +27 -0
  116. package/dist/helpers/logger.d.ts.map +1 -0
  117. package/dist/helpers/logger.js +39 -0
  118. package/dist/helpers/logger.js.map +1 -0
  119. package/dist/helpers/token-2022.d.ts +32 -0
  120. package/dist/helpers/token-2022.d.ts.map +1 -0
  121. package/dist/helpers/token-2022.js +48 -0
  122. package/dist/helpers/token-2022.js.map +1 -0
  123. package/dist/helpers/unwrap_sol.d.ts +2 -0
  124. package/dist/helpers/unwrap_sol.d.ts.map +1 -0
  125. package/dist/helpers/unwrap_sol.js +67 -0
  126. package/dist/helpers/unwrap_sol.js.map +1 -0
  127. package/dist/helpers/util.d.ts +698 -0
  128. package/dist/helpers/util.d.ts.map +1 -0
  129. package/dist/helpers/util.js +181 -0
  130. package/dist/helpers/util.js.map +1 -0
  131. package/dist/helpers/utils.d.ts +10 -0
  132. package/dist/helpers/utils.d.ts.map +1 -0
  133. package/dist/helpers/utils.js +97 -0
  134. package/dist/helpers/utils.js.map +1 -0
  135. package/dist/helpers/wrap_sol.d.ts +3 -0
  136. package/dist/helpers/wrap_sol.d.ts.map +1 -0
  137. package/dist/helpers/wrap_sol.js +88 -0
  138. package/dist/helpers/wrap_sol.js.map +1 -0
  139. package/dist/index.d.ts +14 -0
  140. package/dist/index.d.ts.map +1 -0
  141. package/dist/index.js +32 -0
  142. package/dist/index.js.map +1 -0
  143. package/dist/transactions/bloXroute_tips_tx_executor.d.ts +4 -0
  144. package/dist/transactions/bloXroute_tips_tx_executor.d.ts.map +1 -0
  145. package/dist/transactions/bloXroute_tips_tx_executor.js +70 -0
  146. package/dist/transactions/bloXroute_tips_tx_executor.js.map +1 -0
  147. package/dist/transactions/index.d.ts +6 -0
  148. package/dist/transactions/index.d.ts.map +1 -0
  149. package/dist/transactions/index.js +30 -0
  150. package/dist/transactions/index.js.map +1 -0
  151. package/dist/transactions/jito_tips_tx_executor.d.ts +15 -0
  152. package/dist/transactions/jito_tips_tx_executor.d.ts.map +1 -0
  153. package/dist/transactions/jito_tips_tx_executor.js +99 -0
  154. package/dist/transactions/jito_tips_tx_executor.js.map +1 -0
  155. package/dist/transactions/landing/index.d.ts +30 -0
  156. package/dist/transactions/landing/index.d.ts.map +1 -0
  157. package/dist/transactions/landing/index.js +60 -0
  158. package/dist/transactions/landing/index.js.map +1 -0
  159. package/dist/transactions/landing/nonce-manager.d.ts +116 -0
  160. package/dist/transactions/landing/nonce-manager.d.ts.map +1 -0
  161. package/dist/transactions/landing/nonce-manager.js +393 -0
  162. package/dist/transactions/landing/nonce-manager.js.map +1 -0
  163. package/dist/transactions/landing/orchestrator.d.ts +104 -0
  164. package/dist/transactions/landing/orchestrator.d.ts.map +1 -0
  165. package/dist/transactions/landing/orchestrator.js +329 -0
  166. package/dist/transactions/landing/orchestrator.js.map +1 -0
  167. package/dist/transactions/landing/providers/astralane.d.ts +12 -0
  168. package/dist/transactions/landing/providers/astralane.d.ts.map +1 -0
  169. package/dist/transactions/landing/providers/astralane.js +132 -0
  170. package/dist/transactions/landing/providers/astralane.js.map +1 -0
  171. package/dist/transactions/landing/providers/blockrazor.d.ts +11 -0
  172. package/dist/transactions/landing/providers/blockrazor.d.ts.map +1 -0
  173. package/dist/transactions/landing/providers/blockrazor.js +134 -0
  174. package/dist/transactions/landing/providers/blockrazor.js.map +1 -0
  175. package/dist/transactions/landing/providers/bloxroute.d.ts +12 -0
  176. package/dist/transactions/landing/providers/bloxroute.d.ts.map +1 -0
  177. package/dist/transactions/landing/providers/bloxroute.js +102 -0
  178. package/dist/transactions/landing/providers/bloxroute.js.map +1 -0
  179. package/dist/transactions/landing/providers/flashblock.d.ts +10 -0
  180. package/dist/transactions/landing/providers/flashblock.d.ts.map +1 -0
  181. package/dist/transactions/landing/providers/flashblock.js +102 -0
  182. package/dist/transactions/landing/providers/flashblock.js.map +1 -0
  183. package/dist/transactions/landing/providers/helius-sender.d.ts +11 -0
  184. package/dist/transactions/landing/providers/helius-sender.d.ts.map +1 -0
  185. package/dist/transactions/landing/providers/helius-sender.js +101 -0
  186. package/dist/transactions/landing/providers/helius-sender.js.map +1 -0
  187. package/dist/transactions/landing/providers/jito.d.ts +16 -0
  188. package/dist/transactions/landing/providers/jito.d.ts.map +1 -0
  189. package/dist/transactions/landing/providers/jito.js +110 -0
  190. package/dist/transactions/landing/providers/jito.js.map +1 -0
  191. package/dist/transactions/landing/providers/nextblock.d.ts +11 -0
  192. package/dist/transactions/landing/providers/nextblock.d.ts.map +1 -0
  193. package/dist/transactions/landing/providers/nextblock.js +109 -0
  194. package/dist/transactions/landing/providers/nextblock.js.map +1 -0
  195. package/dist/transactions/landing/providers/node1.d.ts +11 -0
  196. package/dist/transactions/landing/providers/node1.d.ts.map +1 -0
  197. package/dist/transactions/landing/providers/node1.js +101 -0
  198. package/dist/transactions/landing/providers/node1.js.map +1 -0
  199. package/dist/transactions/landing/providers/nozomi.d.ts +11 -0
  200. package/dist/transactions/landing/providers/nozomi.d.ts.map +1 -0
  201. package/dist/transactions/landing/providers/nozomi.js +124 -0
  202. package/dist/transactions/landing/providers/nozomi.js.map +1 -0
  203. package/dist/transactions/landing/providers/soyas.d.ts +16 -0
  204. package/dist/transactions/landing/providers/soyas.d.ts.map +1 -0
  205. package/dist/transactions/landing/providers/soyas.js +192 -0
  206. package/dist/transactions/landing/providers/soyas.js.map +1 -0
  207. package/dist/transactions/landing/providers/stellium.d.ts +11 -0
  208. package/dist/transactions/landing/providers/stellium.d.ts.map +1 -0
  209. package/dist/transactions/landing/providers/stellium.js +102 -0
  210. package/dist/transactions/landing/providers/stellium.js.map +1 -0
  211. package/dist/transactions/landing/providers/zero-slot.d.ts +10 -0
  212. package/dist/transactions/landing/providers/zero-slot.d.ts.map +1 -0
  213. package/dist/transactions/landing/providers/zero-slot.js +92 -0
  214. package/dist/transactions/landing/providers/zero-slot.js.map +1 -0
  215. package/dist/transactions/landing/tip-accounts.d.ts +22 -0
  216. package/dist/transactions/landing/tip-accounts.d.ts.map +1 -0
  217. package/dist/transactions/landing/tip-accounts.js +140 -0
  218. package/dist/transactions/landing/tip-accounts.js.map +1 -0
  219. package/dist/transactions/landing/types.d.ts +98 -0
  220. package/dist/transactions/landing/types.d.ts.map +1 -0
  221. package/dist/transactions/landing/types.js +30 -0
  222. package/dist/transactions/landing/types.js.map +1 -0
  223. package/dist/transactions/nozomi/tx-submission.d.ts +14 -0
  224. package/dist/transactions/nozomi/tx-submission.d.ts.map +1 -0
  225. package/dist/transactions/nozomi/tx-submission.js +107 -0
  226. package/dist/transactions/nozomi/tx-submission.js.map +1 -0
  227. package/dist/transactions/send-rpc.d.ts +54 -0
  228. package/dist/transactions/send-rpc.d.ts.map +1 -0
  229. package/dist/transactions/send-rpc.js +126 -0
  230. package/dist/transactions/send-rpc.js.map +1 -0
  231. package/dist/transactions/simple_tx_executor.d.ts +10 -0
  232. package/dist/transactions/simple_tx_executor.d.ts.map +1 -0
  233. package/dist/transactions/simple_tx_executor.js +33 -0
  234. package/dist/transactions/simple_tx_executor.js.map +1 -0
  235. package/package.json +112 -0
@@ -0,0 +1,613 @@
1
+ "use strict";
2
+ /**
3
+ * Raydium CPMM (Constant Product AMM) DEX Adapter
4
+ *
5
+ * Implements IDexAdapter for Raydium's CPMM program (CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C).
6
+ * Supports buy, sell, snipe, findPool, getPrice, and buildSwapIxs.
7
+ *
8
+ * Ported from: 100x-algo-bots/trading-modules/raydium-cpmm/
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ const web3_js_1 = require("@solana/web3.js");
12
+ const spl_token_1 = require("@solana/spl-token");
13
+ const types_1 = require("./types");
14
+ const index_1 = require("./index");
15
+ const config_1 = require("../helpers/config");
16
+ const landing_1 = require("../transactions/landing");
17
+ const send_rpc_1 = require("../transactions/send-rpc");
18
+ // ---------------------------------------------------------------------------
19
+ // Program constants
20
+ // ---------------------------------------------------------------------------
21
+ const RAYDIUM_CPMM_PROGRAM_ID = new web3_js_1.PublicKey("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C");
22
+ const TOKEN_PROGRAM_ID = new web3_js_1.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
23
+ const WSOL_MINT_PK = new web3_js_1.PublicKey(types_1.WSOL_MINT);
24
+ const USDC_MINT_PK = new web3_js_1.PublicKey(types_1.USDC_MINT);
25
+ // Discriminators from on-chain program
26
+ const SWAP_BASE_IN_DISCRIMINATOR = Uint8Array.from([143, 190, 90, 218, 196, 30, 51, 222]);
27
+ // PDA seeds
28
+ const AUTH_SEED = Buffer.from("vault_and_lp_mint_auth_seed", "utf8");
29
+ const AMM_CONFIG_SEED = Buffer.from("amm_config", "utf8");
30
+ const POOL_SEED = Buffer.from("pool", "utf8");
31
+ const POOL_VAULT_SEED = Buffer.from("pool_vault", "utf8");
32
+ const OBSERVATION_STATE_SEED = Buffer.from("observation", "utf8");
33
+ // ---------------------------------------------------------------------------
34
+ // PDA helpers
35
+ // ---------------------------------------------------------------------------
36
+ function u16ToBytes(num) {
37
+ const arr = new ArrayBuffer(2);
38
+ const view = new DataView(arr);
39
+ view.setUint16(0, num, false);
40
+ return new Uint8Array(arr);
41
+ }
42
+ function getPoolAuthorityPda() {
43
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([AUTH_SEED], RAYDIUM_CPMM_PROGRAM_ID);
44
+ return pda;
45
+ }
46
+ function getAmmConfigPdaByIndex(index) {
47
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([AMM_CONFIG_SEED, Buffer.from(u16ToBytes(index))], RAYDIUM_CPMM_PROGRAM_ID);
48
+ return pda;
49
+ }
50
+ function getPoolPda(ammConfig, mintA, mintB) {
51
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([POOL_SEED, ammConfig.toBuffer(), mintA.toBuffer(), mintB.toBuffer()], RAYDIUM_CPMM_PROGRAM_ID);
52
+ return pda;
53
+ }
54
+ function getPoolPdaSorted(ammConfig, mintA, mintB) {
55
+ const [token0, token1] = [mintA, mintB].sort((a, b) => a.toBase58().localeCompare(b.toBase58()));
56
+ return getPoolPda(ammConfig, token0, token1);
57
+ }
58
+ function getVaultPda(poolState, mint) {
59
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([POOL_VAULT_SEED, poolState.toBuffer(), mint.toBuffer()], RAYDIUM_CPMM_PROGRAM_ID);
60
+ return pda;
61
+ }
62
+ function getObservationStatePda(poolState) {
63
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([OBSERVATION_STATE_SEED, poolState.toBuffer()], RAYDIUM_CPMM_PROGRAM_ID);
64
+ return pda;
65
+ }
66
+ // ---------------------------------------------------------------------------
67
+ // Pool helpers
68
+ // ---------------------------------------------------------------------------
69
+ async function getTokenAccountAmount(connection, tokenAccount) {
70
+ const res = await connection.getTokenAccountBalance(tokenAccount);
71
+ return BigInt(res.value.amount);
72
+ }
73
+ async function getPoolReserves(connection, poolState, baseMint, quoteMint) {
74
+ const baseVault = getVaultPda(poolState, baseMint);
75
+ const quoteVault = getVaultPda(poolState, quoteMint);
76
+ const [base, quote] = await Promise.all([
77
+ getTokenAccountAmount(connection, baseVault),
78
+ getTokenAccountAmount(connection, quoteVault),
79
+ ]);
80
+ return { base, quote };
81
+ }
82
+ function computeSwapOutAmount(xReserve, yReserve, xIn, feeBps = 25n) {
83
+ const feeDen = 10000n;
84
+ const xInAfterFee = (xIn * (feeDen - feeBps)) / feeDen;
85
+ const k = xReserve * yReserve;
86
+ const newX = xReserve + xInAfterFee;
87
+ const newY = k / newX;
88
+ return yReserve - newY;
89
+ }
90
+ async function getTokenProgramForMint(connection, mint) {
91
+ const mintInfo = await connection.getAccountInfo(mint);
92
+ if (!mintInfo)
93
+ throw new Error(`Mint account not found: ${mint.toBase58()}`);
94
+ if (mintInfo.owner.equals(spl_token_1.TOKEN_2022_PROGRAM_ID))
95
+ return spl_token_1.TOKEN_2022_PROGRAM_ID;
96
+ return TOKEN_PROGRAM_ID;
97
+ }
98
+ async function getTokenBalance(connection, mint, owner) {
99
+ const tokenProgram = await getTokenProgramForMint(connection, mint);
100
+ const ata = await (0, spl_token_1.getAssociatedTokenAddress)(mint, owner, tokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID), tokenProgram);
101
+ try {
102
+ const res = await connection.getTokenAccountBalance(ata);
103
+ return {
104
+ amount: BigInt(res.value.amount),
105
+ decimals: res.value.decimals,
106
+ };
107
+ }
108
+ catch {
109
+ return { amount: 0n, decimals: 0 };
110
+ }
111
+ }
112
+ function createCpmmBuyIx(cfg, payer, outputMint, userInputAta, userOutputAta, amountIn, minOut) {
113
+ const obs = getObservationStatePda(cfg.poolState);
114
+ const authority = getPoolAuthorityPda();
115
+ const accounts = [
116
+ { pubkey: payer, isSigner: true, isWritable: true },
117
+ { pubkey: authority, isSigner: false, isWritable: false },
118
+ { pubkey: cfg.ammConfig, isSigner: false, isWritable: false },
119
+ { pubkey: cfg.poolState, isSigner: false, isWritable: true },
120
+ { pubkey: userInputAta, isSigner: false, isWritable: true },
121
+ { pubkey: userOutputAta, isSigner: false, isWritable: true },
122
+ { pubkey: cfg.quoteVault, isSigner: false, isWritable: true },
123
+ { pubkey: cfg.baseVault, isSigner: false, isWritable: true },
124
+ { pubkey: cfg.quoteTokenProgram, isSigner: false, isWritable: false },
125
+ { pubkey: cfg.baseTokenProgram, isSigner: false, isWritable: false },
126
+ { pubkey: cfg.quoteMint, isSigner: false, isWritable: false },
127
+ { pubkey: outputMint, isSigner: false, isWritable: false },
128
+ { pubkey: obs, isSigner: false, isWritable: true },
129
+ ];
130
+ const data = Buffer.alloc(24);
131
+ data.set(SWAP_BASE_IN_DISCRIMINATOR, 0);
132
+ data.writeBigUInt64LE(amountIn, 8);
133
+ data.writeBigUInt64LE(minOut, 16);
134
+ return new web3_js_1.TransactionInstruction({ keys: accounts, programId: RAYDIUM_CPMM_PROGRAM_ID, data });
135
+ }
136
+ function createCpmmSellIx(cfg, payer, inputMint, userInputAta, userOutputAta, amountIn, minOut) {
137
+ const obs = getObservationStatePda(cfg.poolState);
138
+ const authority = getPoolAuthorityPda();
139
+ const accounts = [
140
+ { pubkey: payer, isSigner: true, isWritable: true },
141
+ { pubkey: authority, isSigner: false, isWritable: false },
142
+ { pubkey: cfg.ammConfig, isSigner: false, isWritable: false },
143
+ { pubkey: cfg.poolState, isSigner: false, isWritable: true },
144
+ { pubkey: userInputAta, isSigner: false, isWritable: true },
145
+ { pubkey: userOutputAta, isSigner: false, isWritable: true },
146
+ { pubkey: cfg.baseVault, isSigner: false, isWritable: true },
147
+ { pubkey: cfg.quoteVault, isSigner: false, isWritable: true },
148
+ { pubkey: cfg.baseTokenProgram, isSigner: false, isWritable: false },
149
+ { pubkey: cfg.quoteTokenProgram, isSigner: false, isWritable: false },
150
+ { pubkey: inputMint, isSigner: false, isWritable: false },
151
+ { pubkey: cfg.quoteMint, isSigner: false, isWritable: false },
152
+ { pubkey: obs, isSigner: false, isWritable: true },
153
+ ];
154
+ const data = Buffer.alloc(24);
155
+ data.set(SWAP_BASE_IN_DISCRIMINATOR, 0);
156
+ data.writeBigUInt64LE(amountIn, 8);
157
+ data.writeBigUInt64LE(minOut, 16);
158
+ return new web3_js_1.TransactionInstruction({ keys: accounts, programId: RAYDIUM_CPMM_PROGRAM_ID, data });
159
+ }
160
+ // ---------------------------------------------------------------------------
161
+ // Pool discovery helpers
162
+ // ---------------------------------------------------------------------------
163
+ /** Try known AMM config indices (0 is most common, try others as fallback) */
164
+ const KNOWN_AMM_CONFIG_INDICES = [0, 1, 2, 3];
165
+ async function discoverCpmmPool(connection, baseMint, quoteMint) {
166
+ for (const idx of KNOWN_AMM_CONFIG_INDICES) {
167
+ const ammConfig = getAmmConfigPdaByIndex(idx);
168
+ const candidates = [
169
+ getPoolPda(ammConfig, baseMint, quoteMint),
170
+ getPoolPda(ammConfig, quoteMint, baseMint),
171
+ getPoolPdaSorted(ammConfig, baseMint, quoteMint),
172
+ ];
173
+ for (const poolId of candidates) {
174
+ try {
175
+ const info = await connection.getAccountInfo(poolId);
176
+ if (info && info.owner.equals(RAYDIUM_CPMM_PROGRAM_ID)) {
177
+ return { poolId, ammConfig };
178
+ }
179
+ }
180
+ catch {
181
+ // skip
182
+ }
183
+ }
184
+ }
185
+ return null;
186
+ }
187
+ // ---------------------------------------------------------------------------
188
+ // Decode pool state to get AMM config
189
+ // ---------------------------------------------------------------------------
190
+ /**
191
+ * Decode the ammConfig pubkey from CPMM pool account data.
192
+ * CPMM pool layout: 8-byte discriminator, then amm_config pubkey at offset 8.
193
+ */
194
+ function decodePoolAmmConfig(data) {
195
+ // Skip 8-byte discriminator, ammConfig is at offset 8
196
+ return new web3_js_1.PublicKey(data.slice(8, 40));
197
+ }
198
+ function decodeCpmmPool(data) {
199
+ return {
200
+ ammConfig: new web3_js_1.PublicKey(data.slice(8, 40)),
201
+ token0Mint: new web3_js_1.PublicKey(data.slice(168, 200)),
202
+ token1Mint: new web3_js_1.PublicKey(data.slice(200, 232)),
203
+ token0Program: new web3_js_1.PublicKey(data.slice(232, 264)),
204
+ token1Program: new web3_js_1.PublicKey(data.slice(264, 296)),
205
+ };
206
+ }
207
+ // ---------------------------------------------------------------------------
208
+ // Adapter class
209
+ // ---------------------------------------------------------------------------
210
+ class RaydiumCpmmAdapter {
211
+ name = "raydium-cpmm";
212
+ protocol = "cpmm";
213
+ capabilities = (0, types_1.defaultCapabilities)({
214
+ canBuy: true,
215
+ canSell: true,
216
+ canSnipe: true,
217
+ canFindPool: true,
218
+ canGetPrice: true,
219
+ });
220
+ // ----- Core: buy -----
221
+ async buy(params) {
222
+ const tokenMint = (0, types_1.requireTokenMint)(params, this.name);
223
+ const connection = (0, config_1.getConnection)();
224
+ const wallet = (0, config_1.getWallet)();
225
+ const tokenMintPk = new web3_js_1.PublicKey(tokenMint);
226
+ const quoteMintPk = params.quoteMint ? new web3_js_1.PublicKey(params.quoteMint) : WSOL_MINT_PK;
227
+ const slippageBps = params.opts?.slippageBps ?? types_1.DEFAULT_SLIPPAGE_BPS;
228
+ const priorityFee = params.opts?.priorityFeeMicroLamports ?? types_1.DEFAULT_PRIORITY_FEE_MICRO_LAMPORTS;
229
+ const computeUnits = params.opts?.computeUnitLimit ?? 300_000;
230
+ // Discover or use provided pool
231
+ let poolId;
232
+ let ammConfig;
233
+ if (params.poolAddress) {
234
+ poolId = new web3_js_1.PublicKey(params.poolAddress);
235
+ const poolInfo = await connection.getAccountInfo(poolId);
236
+ if (!poolInfo)
237
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, params.quoteMint);
238
+ ammConfig = decodePoolAmmConfig(poolInfo.data);
239
+ }
240
+ else {
241
+ const result = await discoverCpmmPool(connection, tokenMintPk, quoteMintPk);
242
+ if (!result)
243
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, params.quoteMint);
244
+ poolId = result.poolId;
245
+ ammConfig = result.ammConfig;
246
+ }
247
+ // Detect base token program
248
+ const baseTokenProgram = await getTokenProgramForMint(connection, tokenMintPk);
249
+ // Build SDK config
250
+ const cfg = {
251
+ ammConfig,
252
+ poolState: poolId,
253
+ baseMint: tokenMintPk,
254
+ quoteMint: quoteMintPk,
255
+ baseVault: getVaultPda(poolId, tokenMintPk),
256
+ quoteVault: getVaultPda(poolId, quoteMintPk),
257
+ baseTokenProgram,
258
+ quoteTokenProgram: TOKEN_PROGRAM_ID,
259
+ };
260
+ // Calculate amounts
261
+ const quoteDecimals = quoteMintPk.equals(WSOL_MINT_PK) ? 9 : 6;
262
+ const amountIn = BigInt(Math.floor(params.amountSol * 10 ** quoteDecimals));
263
+ // Get reserves for slippage calculation
264
+ let minOut = 0n;
265
+ try {
266
+ const reserves = await getPoolReserves(connection, poolId, tokenMintPk, quoteMintPk);
267
+ const estOut = computeSwapOutAmount(reserves.quote, reserves.base, amountIn);
268
+ minOut = (estOut * BigInt(10000 - slippageBps)) / 10000n;
269
+ }
270
+ catch {
271
+ // If reserves fail, use zero slippage protection
272
+ }
273
+ // Build ATAs
274
+ const inputAta = await (0, spl_token_1.getAssociatedTokenAddress)(quoteMintPk, wallet.publicKey);
275
+ const outputAta = await (0, spl_token_1.getAssociatedTokenAddress)(tokenMintPk, wallet.publicKey, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID), baseTokenProgram);
276
+ // Build instructions
277
+ const ixs = [
278
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits }),
279
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }),
280
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, inputAta, wallet.publicKey, quoteMintPk),
281
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, outputAta, wallet.publicKey, tokenMintPk, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID) ? spl_token_1.TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID),
282
+ ];
283
+ // WSOL wrapping
284
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
285
+ const lamports = Math.floor(params.amountSol * web3_js_1.LAMPORTS_PER_SOL);
286
+ ixs.push(web3_js_1.SystemProgram.transfer({ fromPubkey: wallet.publicKey, toPubkey: inputAta, lamports }), (0, spl_token_1.createSyncNativeInstruction)(inputAta, TOKEN_PROGRAM_ID));
287
+ }
288
+ // Swap instruction
289
+ ixs.push(createCpmmBuyIx(cfg, wallet.publicKey, tokenMintPk, inputAta, outputAta, amountIn, minOut));
290
+ // Close WSOL ATA after swap
291
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
292
+ ixs.push((0, spl_token_1.createCloseAccountInstruction)(inputAta, wallet.publicKey, wallet.publicKey, [], TOKEN_PROGRAM_ID));
293
+ }
294
+ // Submit via RPC send+confirm
295
+ const result = await (0, send_rpc_1.sendAndConfirmVtx)(connection, ixs, wallet);
296
+ return {
297
+ txSignature: result.txSignature,
298
+ confirmed: result.confirmed,
299
+ amountIn: params.amountSol,
300
+ amountInToken: quoteMintPk.equals(WSOL_MINT_PK) ? "SOL" : quoteMintPk.toBase58(),
301
+ dex: this.name,
302
+ poolAddress: poolId.toBase58(),
303
+ };
304
+ }
305
+ // ----- Core: sell -----
306
+ async sell(params) {
307
+ const tokenMint = (0, types_1.requireTokenMint)(params, this.name);
308
+ const connection = (0, config_1.getConnection)();
309
+ const wallet = (0, config_1.getWallet)();
310
+ const tokenMintPk = new web3_js_1.PublicKey(tokenMint);
311
+ const quoteMintPk = params.quoteMint ? new web3_js_1.PublicKey(params.quoteMint) : WSOL_MINT_PK;
312
+ const slippageBps = params.opts?.slippageBps ?? types_1.DEFAULT_SLIPPAGE_BPS;
313
+ const priorityFee = params.opts?.priorityFeeMicroLamports ?? types_1.DEFAULT_PRIORITY_FEE_MICRO_LAMPORTS;
314
+ const computeUnits = params.opts?.computeUnitLimit ?? 300_000;
315
+ // Discover pool
316
+ let poolId;
317
+ let ammConfig;
318
+ if (params.poolAddress) {
319
+ poolId = new web3_js_1.PublicKey(params.poolAddress);
320
+ const poolInfo = await connection.getAccountInfo(poolId);
321
+ if (!poolInfo)
322
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, params.quoteMint);
323
+ ammConfig = decodePoolAmmConfig(poolInfo.data);
324
+ }
325
+ else {
326
+ const result = await discoverCpmmPool(connection, tokenMintPk, quoteMintPk);
327
+ if (!result)
328
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, params.quoteMint);
329
+ poolId = result.poolId;
330
+ ammConfig = result.ammConfig;
331
+ }
332
+ // Get token balance and compute sell amount
333
+ const baseTokenProgram = await getTokenProgramForMint(connection, tokenMintPk);
334
+ const balance = await getTokenBalance(connection, tokenMintPk, wallet.publicKey);
335
+ const sellAmount = (balance.amount * BigInt(Math.floor(params.percentage))) / 100n;
336
+ if (sellAmount === 0n) {
337
+ return {
338
+ txSignature: "",
339
+ confirmed: false,
340
+ amountIn: 0,
341
+ amountInToken: tokenMint,
342
+ dex: this.name,
343
+ poolAddress: poolId.toBase58(),
344
+ };
345
+ }
346
+ // Compute min out
347
+ let minOut = 0n;
348
+ try {
349
+ const reserves = await getPoolReserves(connection, poolId, tokenMintPk, quoteMintPk);
350
+ const estOut = computeSwapOutAmount(reserves.base, reserves.quote, sellAmount);
351
+ minOut = (estOut * BigInt(10000 - slippageBps)) / 10000n;
352
+ }
353
+ catch {
354
+ // zero floor
355
+ }
356
+ // Build SDK config
357
+ const cfg = {
358
+ ammConfig,
359
+ poolState: poolId,
360
+ baseMint: tokenMintPk,
361
+ quoteMint: quoteMintPk,
362
+ baseVault: getVaultPda(poolId, tokenMintPk),
363
+ quoteVault: getVaultPda(poolId, quoteMintPk),
364
+ baseTokenProgram,
365
+ quoteTokenProgram: TOKEN_PROGRAM_ID,
366
+ };
367
+ // Build ATAs
368
+ const inputAta = await (0, spl_token_1.getAssociatedTokenAddress)(tokenMintPk, wallet.publicKey, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID), baseTokenProgram);
369
+ const outputAta = await (0, spl_token_1.getAssociatedTokenAddress)(quoteMintPk, wallet.publicKey);
370
+ // Build instructions
371
+ const ixs = [
372
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits }),
373
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }),
374
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, outputAta, wallet.publicKey, quoteMintPk),
375
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, inputAta, wallet.publicKey, tokenMintPk, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID) ? spl_token_1.TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID),
376
+ createCpmmSellIx(cfg, wallet.publicKey, tokenMintPk, inputAta, outputAta, sellAmount, minOut),
377
+ ];
378
+ // Submit via RPC send+confirm
379
+ const result = await (0, send_rpc_1.sendAndConfirmVtx)(connection, ixs, wallet);
380
+ const humanSellAmount = Number(sellAmount) / 10 ** balance.decimals;
381
+ return {
382
+ txSignature: result.txSignature,
383
+ confirmed: result.confirmed,
384
+ amountIn: humanSellAmount,
385
+ amountInToken: tokenMint,
386
+ dex: this.name,
387
+ poolAddress: poolId.toBase58(),
388
+ };
389
+ }
390
+ // ----- Snipe -----
391
+ async snipe(params) {
392
+ const connection = (0, config_1.getConnection)();
393
+ const wallet = (0, config_1.getWallet)();
394
+ const tokenMint = new web3_js_1.PublicKey(params.tokenMint);
395
+ const quoteMintPk = params.quoteMint ? new web3_js_1.PublicKey(params.quoteMint) : WSOL_MINT_PK;
396
+ const poolId = new web3_js_1.PublicKey(params.poolAddress);
397
+ const priorityFee = params.opts?.priorityFeeMicroLamports ?? 12_000_000; // Higher for snipe
398
+ // Fetch pool on-chain to determine ammConfig
399
+ const poolInfo = await connection.getAccountInfo(poolId);
400
+ if (!poolInfo || !poolInfo.owner.equals(RAYDIUM_CPMM_PROGRAM_ID)) {
401
+ throw new types_1.PoolNotFoundError(this.name, params.tokenMint, params.quoteMint);
402
+ }
403
+ const poolData = decodeCpmmPool(poolInfo.data);
404
+ const ammConfig = poolData.ammConfig;
405
+ // Detect base token program
406
+ const baseTokenProgram = await getTokenProgramForMint(connection, tokenMint);
407
+ // Build SDK config
408
+ const cfg = {
409
+ ammConfig,
410
+ poolState: poolId,
411
+ baseMint: tokenMint,
412
+ quoteMint: quoteMintPk,
413
+ baseVault: getVaultPda(poolId, tokenMint),
414
+ quoteVault: getVaultPda(poolId, quoteMintPk),
415
+ baseTokenProgram,
416
+ quoteTokenProgram: TOKEN_PROGRAM_ID,
417
+ };
418
+ // Calculate amounts (zero slippage for snipe)
419
+ const quoteDecimals = quoteMintPk.equals(WSOL_MINT_PK) ? 9 : 6;
420
+ const amountIn = BigInt(Math.floor(params.amountSol * 10 ** quoteDecimals));
421
+ const minOut = 0n; // Unlimited slippage for sniping
422
+ // Build ATAs
423
+ const inputAta = await (0, spl_token_1.getAssociatedTokenAddress)(quoteMintPk, wallet.publicKey);
424
+ const outputAta = await (0, spl_token_1.getAssociatedTokenAddress)(tokenMint, wallet.publicKey, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID), baseTokenProgram);
425
+ // Build instruction list
426
+ const ixs = [
427
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }),
428
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, inputAta, wallet.publicKey, quoteMintPk),
429
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, outputAta, wallet.publicKey, tokenMint, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID) ? spl_token_1.TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID),
430
+ ];
431
+ // WSOL wrapping for snipe
432
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
433
+ const lamports = Math.floor(params.amountSol * web3_js_1.LAMPORTS_PER_SOL);
434
+ ixs.push(web3_js_1.SystemProgram.transfer({ fromPubkey: wallet.publicKey, toPubkey: inputAta, lamports }), (0, spl_token_1.createSyncNativeInstruction)(inputAta, TOKEN_PROGRAM_ID));
435
+ }
436
+ // Swap
437
+ ixs.push(createCpmmBuyIx(cfg, wallet.publicKey, tokenMint, inputAta, outputAta, amountIn, minOut));
438
+ // Close WSOL
439
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
440
+ ixs.push((0, spl_token_1.createCloseAccountInstruction)(inputAta, wallet.publicKey, wallet.publicKey, [], TOKEN_PROGRAM_ID));
441
+ }
442
+ // Submit via landing layer (concurrent for snipe)
443
+ const { blockhash } = await connection.getLatestBlockhash();
444
+ const results = await (0, landing_1.landTransaction)(ixs, wallet, blockhash, {
445
+ dex: this.name,
446
+ operation: "snipe",
447
+ tipSol: params.tipSol,
448
+ });
449
+ const firstAccepted = results.find((r) => r.accepted);
450
+ return {
451
+ txSignature: firstAccepted?.signature ?? "",
452
+ confirmed: !!firstAccepted?.accepted,
453
+ amountIn: params.amountSol,
454
+ amountInToken: quoteMintPk.equals(WSOL_MINT_PK) ? "SOL" : quoteMintPk.toBase58(),
455
+ dex: this.name,
456
+ poolAddress: poolId.toBase58(),
457
+ };
458
+ }
459
+ // ----- Build swap instructions (for nonce/orchestrator integration) -----
460
+ async buildSwapIxs(params) {
461
+ const tokenMint = (0, types_1.requireTokenMint)(params, this.name);
462
+ const connection = (0, config_1.getConnection)();
463
+ const wallet = (0, config_1.getWallet)();
464
+ const isBuy = "amountSol" in params;
465
+ const tokenMintPk = new web3_js_1.PublicKey(tokenMint);
466
+ const quoteMintPk = params.quoteMint ? new web3_js_1.PublicKey(params.quoteMint) : WSOL_MINT_PK;
467
+ // Discover pool
468
+ let poolId;
469
+ let ammConfig;
470
+ if (params.poolAddress) {
471
+ poolId = new web3_js_1.PublicKey(params.poolAddress);
472
+ const poolInfo = await connection.getAccountInfo(poolId);
473
+ if (!poolInfo)
474
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, params.quoteMint);
475
+ ammConfig = decodePoolAmmConfig(poolInfo.data);
476
+ }
477
+ else {
478
+ const result = await discoverCpmmPool(connection, tokenMintPk, quoteMintPk);
479
+ if (!result)
480
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, params.quoteMint);
481
+ poolId = result.poolId;
482
+ ammConfig = result.ammConfig;
483
+ }
484
+ const baseTokenProgram = await getTokenProgramForMint(connection, tokenMintPk);
485
+ const cfg = {
486
+ ammConfig,
487
+ poolState: poolId,
488
+ baseMint: tokenMintPk,
489
+ quoteMint: quoteMintPk,
490
+ baseVault: getVaultPda(poolId, tokenMintPk),
491
+ quoteVault: getVaultPda(poolId, quoteMintPk),
492
+ baseTokenProgram,
493
+ quoteTokenProgram: TOKEN_PROGRAM_ID,
494
+ };
495
+ const instructions = [];
496
+ if (isBuy) {
497
+ const buyParams = params;
498
+ const quoteDecimals = quoteMintPk.equals(WSOL_MINT_PK) ? 9 : 6;
499
+ const amountIn = BigInt(Math.floor(buyParams.amountSol * 10 ** quoteDecimals));
500
+ const inputAta = await (0, spl_token_1.getAssociatedTokenAddress)(quoteMintPk, wallet.publicKey);
501
+ const outputAta = await (0, spl_token_1.getAssociatedTokenAddress)(tokenMintPk, wallet.publicKey, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID), baseTokenProgram);
502
+ instructions.push((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, inputAta, wallet.publicKey, quoteMintPk), (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, outputAta, wallet.publicKey, tokenMintPk, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID) ? spl_token_1.TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID));
503
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
504
+ const lamports = Math.floor(buyParams.amountSol * web3_js_1.LAMPORTS_PER_SOL);
505
+ instructions.push(web3_js_1.SystemProgram.transfer({ fromPubkey: wallet.publicKey, toPubkey: inputAta, lamports }), (0, spl_token_1.createSyncNativeInstruction)(inputAta, TOKEN_PROGRAM_ID));
506
+ }
507
+ instructions.push(createCpmmBuyIx(cfg, wallet.publicKey, tokenMintPk, inputAta, outputAta, amountIn, 0n));
508
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
509
+ instructions.push((0, spl_token_1.createCloseAccountInstruction)(inputAta, wallet.publicKey, wallet.publicKey, [], TOKEN_PROGRAM_ID));
510
+ }
511
+ }
512
+ else {
513
+ const sellParams = params;
514
+ const balance = await getTokenBalance(connection, tokenMintPk, wallet.publicKey);
515
+ const sellAmount = (balance.amount * BigInt(Math.floor(sellParams.percentage))) / 100n;
516
+ const inputAta = await (0, spl_token_1.getAssociatedTokenAddress)(tokenMintPk, wallet.publicKey, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID), baseTokenProgram);
517
+ const outputAta = await (0, spl_token_1.getAssociatedTokenAddress)(quoteMintPk, wallet.publicKey);
518
+ instructions.push((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, outputAta, wallet.publicKey, quoteMintPk), createCpmmSellIx(cfg, wallet.publicKey, tokenMintPk, inputAta, outputAta, sellAmount, 0n));
519
+ }
520
+ return { instructions, signers: [] };
521
+ }
522
+ // ----- Pool discovery -----
523
+ async findPool(baseMint, quoteMint) {
524
+ const connection = (0, config_1.getConnection)();
525
+ const baseMintPk = new web3_js_1.PublicKey(baseMint);
526
+ const quoteMintPk = quoteMint ? new web3_js_1.PublicKey(quoteMint) : WSOL_MINT_PK;
527
+ const result = await discoverCpmmPool(connection, baseMintPk, quoteMintPk);
528
+ if (!result)
529
+ return null;
530
+ // Get reserves for price
531
+ try {
532
+ const reserves = await getPoolReserves(connection, result.poolId, baseMintPk, quoteMintPk);
533
+ const quoteDecimals = quoteMintPk.equals(WSOL_MINT_PK) ? 9 : 6;
534
+ // Estimate base decimals from reserves (fallback to 6)
535
+ const baseDecimals = 6;
536
+ const baseReserveHuman = Number(reserves.base) / 10 ** baseDecimals;
537
+ const quoteReserveHuman = Number(reserves.quote) / 10 ** quoteDecimals;
538
+ const price = baseReserveHuman > 0 ? quoteReserveHuman / baseReserveHuman : 0;
539
+ return {
540
+ address: result.poolId.toBase58(),
541
+ dex: this.name,
542
+ protocol: this.protocol,
543
+ baseMint,
544
+ quoteMint: quoteMintPk.toBase58(),
545
+ baseDecimals,
546
+ quoteDecimals,
547
+ price,
548
+ };
549
+ }
550
+ catch {
551
+ return {
552
+ address: result.poolId.toBase58(),
553
+ dex: this.name,
554
+ protocol: this.protocol,
555
+ baseMint,
556
+ quoteMint: quoteMintPk.toBase58(),
557
+ baseDecimals: 6,
558
+ quoteDecimals: quoteMintPk.equals(WSOL_MINT_PK) ? 9 : 6,
559
+ };
560
+ }
561
+ }
562
+ // ----- Price -----
563
+ async getPrice(poolAddress) {
564
+ const connection = (0, config_1.getConnection)();
565
+ const poolId = new web3_js_1.PublicKey(poolAddress);
566
+ const poolInfo = await connection.getAccountInfo(poolId);
567
+ if (!poolInfo || !poolInfo.owner.equals(RAYDIUM_CPMM_PROGRAM_ID)) {
568
+ throw new Error(`Pool not found or not a CPMM pool: ${poolAddress}`);
569
+ }
570
+ const poolData = decodeCpmmPool(poolInfo.data);
571
+ const baseMint = poolData.token0Mint;
572
+ const quoteMint = poolData.token1Mint;
573
+ // Determine which is quote (WSOL/USDC) vs base
574
+ let actualBase;
575
+ let actualQuote;
576
+ if (quoteMint.equals(WSOL_MINT_PK) || quoteMint.equals(USDC_MINT_PK)) {
577
+ actualBase = baseMint;
578
+ actualQuote = quoteMint;
579
+ }
580
+ else if (baseMint.equals(WSOL_MINT_PK) || baseMint.equals(USDC_MINT_PK)) {
581
+ actualBase = quoteMint;
582
+ actualQuote = baseMint;
583
+ }
584
+ else {
585
+ actualBase = baseMint;
586
+ actualQuote = quoteMint;
587
+ }
588
+ const reserves = await getPoolReserves(connection, poolId, actualBase, actualQuote);
589
+ // Fetch actual decimals from mint accounts
590
+ const [baseMintInfo, quoteMintInfo] = await Promise.all([
591
+ connection.getAccountInfo(actualBase),
592
+ connection.getAccountInfo(actualQuote),
593
+ ]);
594
+ const baseDecimals = baseMintInfo ? baseMintInfo.data.readUInt8(44) : 9;
595
+ const quoteDecimals = quoteMintInfo ? quoteMintInfo.data.readUInt8(44) : 9;
596
+ const baseReserveHuman = Number(reserves.base) / 10 ** baseDecimals;
597
+ const quoteReserveHuman = Number(reserves.quote) / 10 ** quoteDecimals;
598
+ const price = baseReserveHuman > 0 ? quoteReserveHuman / baseReserveHuman : 0;
599
+ return {
600
+ price,
601
+ baseMint: actualBase.toBase58(),
602
+ quoteMint: actualQuote.toBase58(),
603
+ source: "on-chain",
604
+ poolAddress,
605
+ timestamp: Date.now(),
606
+ };
607
+ }
608
+ }
609
+ // ---------------------------------------------------------------------------
610
+ // Register adapter
611
+ // ---------------------------------------------------------------------------
612
+ (0, index_1.registerAdapter)(new RaydiumCpmmAdapter());
613
+ //# sourceMappingURL=raydium-cpmm.js.map