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,649 @@
1
+ "use strict";
2
+ /**
3
+ * Raydium AMM V4 DEX Adapter
4
+ *
5
+ * Implements IDexAdapter for Raydium's classic AMM V4 program (675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8).
6
+ * Supports buy, snipe, findPool, getPrice, and buildSwapIxs.
7
+ * No sell — the source module has no sell implementation.
8
+ *
9
+ * Ported from: 100x-algo-bots/trading-modules/raydium-amm-v4/
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ const web3_js_1 = require("@solana/web3.js");
46
+ const spl_token_1 = require("@solana/spl-token");
47
+ const types_1 = require("./types");
48
+ const index_1 = require("./index");
49
+ const config_1 = require("../helpers/config");
50
+ const landing_1 = require("../transactions/landing");
51
+ const send_rpc_1 = require("../transactions/send-rpc");
52
+ // ---------------------------------------------------------------------------
53
+ // Program constants
54
+ // ---------------------------------------------------------------------------
55
+ const RAYDIUM_AMM_V4_PROGRAM_ID = new web3_js_1.PublicKey("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8");
56
+ const SERUM_PROGRAM_ID = new web3_js_1.PublicKey("9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin");
57
+ const TOKEN_PROGRAM_ID_PK = new web3_js_1.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
58
+ const WSOL_MINT_PK = new web3_js_1.PublicKey(types_1.WSOL_MINT);
59
+ const USDC_MINT_PK = new web3_js_1.PublicKey(types_1.USDC_MINT);
60
+ const USDT_MINT_PK = new web3_js_1.PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB");
61
+ const USD1_MINT_PK = new web3_js_1.PublicKey("USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB");
62
+ // Swap instruction discriminator (from Rust: data.push(9))
63
+ const SWAP_DISCRIMINATOR = 9;
64
+ function decodeAmmInfo(data) {
65
+ if (data.length < 752) {
66
+ throw new Error(`AmmInfo data too short: ${data.length} bytes, expected at least 752`);
67
+ }
68
+ const nonceValue = data.readBigUInt64LE(8);
69
+ const nonce = Number(nonceValue & BigInt(0xff));
70
+ return {
71
+ nonce,
72
+ coinVault: new web3_js_1.PublicKey(data.slice(336, 368)),
73
+ pcVault: new web3_js_1.PublicKey(data.slice(368, 400)),
74
+ coinVaultMint: new web3_js_1.PublicKey(data.slice(400, 432)),
75
+ pcVaultMint: new web3_js_1.PublicKey(data.slice(432, 464)),
76
+ openOrders: new web3_js_1.PublicKey(data.slice(496, 528)),
77
+ market: new web3_js_1.PublicKey(data.slice(528, 560)),
78
+ marketProgram: new web3_js_1.PublicKey(data.slice(560, 592)),
79
+ targetOrders: new web3_js_1.PublicKey(data.slice(592, 624)),
80
+ };
81
+ }
82
+ async function fetchAmmInfo(connection, ammId) {
83
+ const accountInfo = await connection.getAccountInfo(ammId);
84
+ if (!accountInfo)
85
+ throw new Error(`AmmInfo account not found: ${ammId.toBase58()}`);
86
+ if (!accountInfo.owner.equals(RAYDIUM_AMM_V4_PROGRAM_ID)) {
87
+ throw new Error(`Invalid account owner for AmmInfo: ${accountInfo.owner.toBase58()}`);
88
+ }
89
+ return decodeAmmInfo(accountInfo.data);
90
+ }
91
+ function decodeMarketInfo(data) {
92
+ if (data.length < 388) {
93
+ throw new Error(`Market data too short: ${data.length} bytes`);
94
+ }
95
+ return {
96
+ bids: new web3_js_1.PublicKey(data.slice(44, 76)),
97
+ asks: new web3_js_1.PublicKey(data.slice(76, 108)),
98
+ eventQueue: new web3_js_1.PublicKey(data.slice(108, 140)),
99
+ coinVault: new web3_js_1.PublicKey(data.slice(140, 172)),
100
+ pcVault: new web3_js_1.PublicKey(data.slice(172, 204)),
101
+ vaultSignerNonce: data.readBigUInt64LE(204),
102
+ };
103
+ }
104
+ async function fetchMarketInfo(connection, marketId) {
105
+ const accountInfo = await connection.getAccountInfo(marketId);
106
+ if (!accountInfo)
107
+ throw new Error(`Market account not found: ${marketId.toBase58()}`);
108
+ return decodeMarketInfo(accountInfo.data);
109
+ }
110
+ function deriveMarketVaultSigner(marketId, marketProgramId) {
111
+ // Try nonces 0-254
112
+ for (let nonce = 0; nonce < 255; nonce++) {
113
+ try {
114
+ const vaultSigner = web3_js_1.PublicKey.createProgramAddressSync([marketId.toBuffer(), Buffer.from(new Uint8Array(new BigUint64Array([BigInt(nonce)]).buffer))], marketProgramId);
115
+ return vaultSigner;
116
+ }
117
+ catch {
118
+ continue;
119
+ }
120
+ }
121
+ throw new Error("Failed to derive market vault signer");
122
+ }
123
+ async function derivePoolAccounts(connection, ammId) {
124
+ const ammInfo = await fetchAmmInfo(connection, ammId);
125
+ // Derive ammAuthority
126
+ const AUTHORITY_AMM_SEED = Buffer.from("amm authority");
127
+ let ammAuthority;
128
+ try {
129
+ ammAuthority = web3_js_1.PublicKey.createProgramAddressSync([AUTHORITY_AMM_SEED, Buffer.from([ammInfo.nonce])], RAYDIUM_AMM_V4_PROGRAM_ID);
130
+ }
131
+ catch {
132
+ const [authority] = web3_js_1.PublicKey.findProgramAddressSync([AUTHORITY_AMM_SEED], RAYDIUM_AMM_V4_PROGRAM_ID);
133
+ ammAuthority = authority;
134
+ }
135
+ // Fetch market info
136
+ const marketInfo = await fetchMarketInfo(connection, ammInfo.market);
137
+ const serumVaultSigner = deriveMarketVaultSigner(ammInfo.market, ammInfo.marketProgram);
138
+ // Detect token programs
139
+ const coinTokenProgram = await getTokenProgramForMint(connection, ammInfo.coinVaultMint);
140
+ const pcTokenProgram = await getTokenProgramForMint(connection, ammInfo.pcVaultMint);
141
+ return {
142
+ ammId,
143
+ ammAuthority,
144
+ ammOpenOrders: ammInfo.openOrders,
145
+ ammTargetOrders: ammInfo.targetOrders,
146
+ poolCoinTokenAccount: ammInfo.coinVault,
147
+ poolPcTokenAccount: ammInfo.pcVault,
148
+ serumMarket: ammInfo.market,
149
+ serumBids: marketInfo.bids,
150
+ serumAsks: marketInfo.asks,
151
+ serumEventQueue: marketInfo.eventQueue,
152
+ serumCoinVaultAccount: marketInfo.coinVault,
153
+ serumPcVaultAccount: marketInfo.pcVault,
154
+ serumVaultSigner,
155
+ coinMint: ammInfo.coinVaultMint,
156
+ pcMint: ammInfo.pcVaultMint,
157
+ coinTokenProgram,
158
+ pcTokenProgram,
159
+ };
160
+ }
161
+ // ---------------------------------------------------------------------------
162
+ // Helpers
163
+ // ---------------------------------------------------------------------------
164
+ async function getTokenProgramForMint(connection, mint) {
165
+ const mintInfo = await connection.getAccountInfo(mint);
166
+ if (!mintInfo)
167
+ throw new Error(`Mint account not found: ${mint.toBase58()}`);
168
+ if (mintInfo.owner.equals(spl_token_1.TOKEN_2022_PROGRAM_ID))
169
+ return spl_token_1.TOKEN_2022_PROGRAM_ID;
170
+ return TOKEN_PROGRAM_ID_PK;
171
+ }
172
+ function isQuoteMint(mint) {
173
+ return (mint.equals(WSOL_MINT_PK) ||
174
+ mint.equals(USDC_MINT_PK) ||
175
+ mint.equals(USDT_MINT_PK) ||
176
+ mint.equals(USD1_MINT_PK));
177
+ }
178
+ // ---------------------------------------------------------------------------
179
+ // SDK instruction builder (ported from raydium-amm-v4/sdk.ts)
180
+ // ---------------------------------------------------------------------------
181
+ function createSwapIx(poolAccounts, payer, userInputAta, userOutputAta, amountIn, minOut, inputTokenProgram) {
182
+ const accounts = [
183
+ { pubkey: inputTokenProgram, isSigner: false, isWritable: false },
184
+ { pubkey: poolAccounts.ammId, isSigner: false, isWritable: true },
185
+ { pubkey: poolAccounts.ammAuthority, isSigner: false, isWritable: false },
186
+ { pubkey: poolAccounts.ammOpenOrders, isSigner: false, isWritable: true },
187
+ { pubkey: poolAccounts.ammTargetOrders, isSigner: false, isWritable: true },
188
+ { pubkey: poolAccounts.poolCoinTokenAccount, isSigner: false, isWritable: true },
189
+ { pubkey: poolAccounts.poolPcTokenAccount, isSigner: false, isWritable: true },
190
+ { pubkey: SERUM_PROGRAM_ID, isSigner: false, isWritable: false },
191
+ { pubkey: poolAccounts.serumMarket, isSigner: false, isWritable: true },
192
+ { pubkey: poolAccounts.serumBids, isSigner: false, isWritable: true },
193
+ { pubkey: poolAccounts.serumAsks, isSigner: false, isWritable: true },
194
+ { pubkey: poolAccounts.serumEventQueue, isSigner: false, isWritable: true },
195
+ { pubkey: poolAccounts.serumCoinVaultAccount, isSigner: false, isWritable: true },
196
+ { pubkey: poolAccounts.serumPcVaultAccount, isSigner: false, isWritable: true },
197
+ { pubkey: poolAccounts.serumVaultSigner, isSigner: false, isWritable: false },
198
+ { pubkey: userInputAta, isSigner: false, isWritable: true },
199
+ { pubkey: userOutputAta, isSigner: false, isWritable: true },
200
+ { pubkey: payer, isSigner: true, isWritable: false },
201
+ ];
202
+ // Data: [9, amount_in (u64 LE), minimum_amount_out (u64 LE)] = 17 bytes
203
+ const data = Buffer.alloc(17);
204
+ data.writeUInt8(SWAP_DISCRIMINATOR, 0);
205
+ data.writeBigUInt64LE(amountIn, 1);
206
+ data.writeBigUInt64LE(minOut, 9);
207
+ return new web3_js_1.TransactionInstruction({
208
+ keys: accounts,
209
+ programId: RAYDIUM_AMM_V4_PROGRAM_ID,
210
+ data,
211
+ });
212
+ }
213
+ // ---------------------------------------------------------------------------
214
+ // Pool discovery via Raydium SDK API
215
+ // ---------------------------------------------------------------------------
216
+ async function discoverAmmV4Pool(connection, tokenMint, quoteMint) {
217
+ // Try fetching via Raydium API
218
+ try {
219
+ const { Raydium } = await Promise.resolve().then(() => __importStar(require("@raydium-io/raydium-sdk-v2")));
220
+ const raydium = await Raydium.load({
221
+ connection,
222
+ disableLoadToken: true,
223
+ });
224
+ const listOfPools = await raydium.api.fetchPoolByMints({
225
+ mint1: quoteMint,
226
+ mint2: tokenMint,
227
+ });
228
+ for (const obj of listOfPools) {
229
+ if (obj.type === "Standard" && obj.programId === RAYDIUM_AMM_V4_PROGRAM_ID.toBase58()) {
230
+ return { poolId: obj.id };
231
+ }
232
+ }
233
+ }
234
+ catch {
235
+ // API unavailable, fallback below
236
+ }
237
+ return null;
238
+ }
239
+ // ---------------------------------------------------------------------------
240
+ // Adapter class
241
+ // ---------------------------------------------------------------------------
242
+ class RaydiumAmmV4Adapter {
243
+ name = "raydium-amm-v4";
244
+ protocol = "amm-v4";
245
+ capabilities = (0, types_1.defaultCapabilities)({
246
+ canBuy: true,
247
+ canSell: true,
248
+ canSnipe: true,
249
+ canFindPool: true,
250
+ canGetPrice: true,
251
+ });
252
+ // ----- Core: buy -----
253
+ async buy(params) {
254
+ const tokenMint = (0, types_1.requireTokenMint)(params, this.name);
255
+ const connection = (0, config_1.getConnection)();
256
+ const wallet = (0, config_1.getWallet)();
257
+ const tokenMintPk = new web3_js_1.PublicKey(tokenMint);
258
+ const quoteMintPk = params.quoteMint ? new web3_js_1.PublicKey(params.quoteMint) : WSOL_MINT_PK;
259
+ const slippageBps = params.opts?.slippageBps ?? types_1.DEFAULT_SLIPPAGE_BPS;
260
+ const priorityFee = params.opts?.priorityFeeMicroLamports ?? types_1.DEFAULT_PRIORITY_FEE_MICRO_LAMPORTS;
261
+ const computeUnits = params.opts?.computeUnitLimit ?? 300_000;
262
+ // Resolve pool
263
+ let poolId;
264
+ if (params.poolAddress) {
265
+ poolId = new web3_js_1.PublicKey(params.poolAddress);
266
+ }
267
+ else {
268
+ const found = await discoverAmmV4Pool(connection, tokenMint, quoteMintPk.toBase58());
269
+ if (!found)
270
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, params.quoteMint);
271
+ poolId = new web3_js_1.PublicKey(found.poolId);
272
+ }
273
+ // Derive all pool accounts
274
+ const poolAccounts = await derivePoolAccounts(connection, poolId);
275
+ // Detect base token program
276
+ const baseTokenProgram = await getTokenProgramForMint(connection, tokenMintPk);
277
+ // Calculate amounts
278
+ const quoteDecimals = quoteMintPk.equals(WSOL_MINT_PK) ? 9 : 6;
279
+ const amountIn = BigInt(Math.floor(params.amountSol * 10 ** quoteDecimals));
280
+ // Compute minOut from reserves
281
+ let minOut = 0n;
282
+ try {
283
+ const [coinBal, pcBal] = await Promise.all([
284
+ connection.getTokenAccountBalance(poolAccounts.poolCoinTokenAccount),
285
+ connection.getTokenAccountBalance(poolAccounts.poolPcTokenAccount),
286
+ ]);
287
+ const coinReserve = BigInt(coinBal.value.amount);
288
+ const pcReserve = BigInt(pcBal.value.amount);
289
+ // Determine direction: if quoteMint == pcMint, swap pc -> coin
290
+ let estOut;
291
+ if (poolAccounts.pcMint.equals(quoteMintPk)) {
292
+ // Buying coinMint with pcMint
293
+ const k = coinReserve * pcReserve;
294
+ const newPc = pcReserve + amountIn;
295
+ estOut = coinReserve - k / newPc;
296
+ }
297
+ else {
298
+ // Buying pcMint with coinMint (reversed pool)
299
+ const k = coinReserve * pcReserve;
300
+ const newCoin = coinReserve + amountIn;
301
+ estOut = pcReserve - k / newCoin;
302
+ }
303
+ minOut = (estOut * BigInt(10000 - slippageBps)) / 10000n;
304
+ }
305
+ catch {
306
+ // zero floor
307
+ }
308
+ // Build ATAs
309
+ const inputAta = await (0, spl_token_1.getAssociatedTokenAddress)(quoteMintPk, wallet.publicKey);
310
+ const outputAta = await (0, spl_token_1.getAssociatedTokenAddress)(tokenMintPk, wallet.publicKey, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID), baseTokenProgram);
311
+ // Determine input token program
312
+ let inputTokenProgram;
313
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
314
+ inputTokenProgram = TOKEN_PROGRAM_ID_PK;
315
+ }
316
+ else if (poolAccounts.pcMint.equals(quoteMintPk)) {
317
+ inputTokenProgram = poolAccounts.pcTokenProgram;
318
+ }
319
+ else {
320
+ inputTokenProgram = poolAccounts.coinTokenProgram;
321
+ }
322
+ // Build instructions
323
+ const ixs = [
324
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits }),
325
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }),
326
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, inputAta, wallet.publicKey, quoteMintPk),
327
+ (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_PK),
328
+ ];
329
+ // WSOL wrapping
330
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
331
+ const lamports = Math.floor(params.amountSol * web3_js_1.LAMPORTS_PER_SOL);
332
+ ixs.push(web3_js_1.SystemProgram.transfer({ fromPubkey: wallet.publicKey, toPubkey: inputAta, lamports }), (0, spl_token_1.createSyncNativeInstruction)(inputAta, TOKEN_PROGRAM_ID_PK));
333
+ }
334
+ // Swap
335
+ ixs.push(createSwapIx(poolAccounts, wallet.publicKey, inputAta, outputAta, amountIn, minOut, inputTokenProgram));
336
+ // Close WSOL
337
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
338
+ ixs.push((0, spl_token_1.createCloseAccountInstruction)(inputAta, wallet.publicKey, wallet.publicKey, [], TOKEN_PROGRAM_ID_PK));
339
+ }
340
+ // Submit via RPC send+confirm
341
+ const result = await (0, send_rpc_1.sendAndConfirmVtx)(connection, ixs, wallet);
342
+ return {
343
+ txSignature: result.txSignature,
344
+ confirmed: result.confirmed,
345
+ amountIn: params.amountSol,
346
+ amountInToken: quoteMintPk.equals(WSOL_MINT_PK) ? "SOL" : quoteMintPk.toBase58(),
347
+ dex: this.name,
348
+ poolAddress: poolId.toBase58(),
349
+ };
350
+ }
351
+ // ----- Core: sell -----
352
+ async sell(params) {
353
+ const tokenMint = (0, types_1.requireTokenMint)(params, this.name);
354
+ const connection = (0, config_1.getConnection)();
355
+ const wallet = (0, config_1.getWallet)();
356
+ const tokenMintPk = new web3_js_1.PublicKey(tokenMint);
357
+ const quoteMintPk = params.quoteMint ? new web3_js_1.PublicKey(params.quoteMint) : WSOL_MINT_PK;
358
+ const slippageBps = params.opts?.slippageBps ?? types_1.DEFAULT_SLIPPAGE_BPS;
359
+ const priorityFee = params.opts?.priorityFeeMicroLamports ?? types_1.DEFAULT_PRIORITY_FEE_MICRO_LAMPORTS;
360
+ const computeUnits = params.opts?.computeUnitLimit ?? 300_000;
361
+ // Resolve pool
362
+ let poolId;
363
+ if (params.poolAddress) {
364
+ poolId = new web3_js_1.PublicKey(params.poolAddress);
365
+ }
366
+ else {
367
+ const found = await discoverAmmV4Pool(connection, tokenMint, quoteMintPk.toBase58());
368
+ if (!found)
369
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, params.quoteMint);
370
+ poolId = new web3_js_1.PublicKey(found.poolId);
371
+ }
372
+ // Derive all pool accounts
373
+ const poolAccounts = await derivePoolAccounts(connection, poolId);
374
+ // Detect base token program
375
+ const baseTokenProgram = await getTokenProgramForMint(connection, tokenMintPk);
376
+ // Get token balance
377
+ const baseAta = await (0, spl_token_1.getAssociatedTokenAddress)(tokenMintPk, wallet.publicKey, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID), baseTokenProgram);
378
+ const tokenAccount = await (0, spl_token_1.getAccount)(connection, baseAta, "confirmed", baseTokenProgram);
379
+ const balance = tokenAccount.amount;
380
+ // Calculate sell amount based on percentage
381
+ const sellAmount = BigInt(Math.floor((Number(balance) * params.percentage) / 100));
382
+ if (sellAmount === 0n) {
383
+ throw new Error(`No balance to sell for ${tokenMint}`);
384
+ }
385
+ // Compute minOut from reserves (reversed direction vs buy)
386
+ let minOut = 0n;
387
+ try {
388
+ const [coinBal, pcBal] = await Promise.all([
389
+ connection.getTokenAccountBalance(poolAccounts.poolCoinTokenAccount),
390
+ connection.getTokenAccountBalance(poolAccounts.poolPcTokenAccount),
391
+ ]);
392
+ const coinReserve = BigInt(coinBal.value.amount);
393
+ const pcReserve = BigInt(pcBal.value.amount);
394
+ // Selling token → receiving quote. Determine direction.
395
+ let estOut;
396
+ if (poolAccounts.coinMint.equals(tokenMintPk)) {
397
+ // Selling coinMint → receiving pcMint
398
+ const k = coinReserve * pcReserve;
399
+ const newCoin = coinReserve + sellAmount;
400
+ estOut = pcReserve - k / newCoin;
401
+ }
402
+ else {
403
+ // Selling pcMint → receiving coinMint
404
+ const k = coinReserve * pcReserve;
405
+ const newPc = pcReserve + sellAmount;
406
+ estOut = coinReserve - k / newPc;
407
+ }
408
+ minOut = (estOut * BigInt(10000 - slippageBps)) / 10000n;
409
+ }
410
+ catch {
411
+ // zero floor
412
+ }
413
+ // Build ATAs — reversed from buy: input is token, output is quote
414
+ const userInputAta = baseAta;
415
+ const quoteTokenProgram = quoteMintPk.equals(WSOL_MINT_PK)
416
+ ? TOKEN_PROGRAM_ID_PK
417
+ : await getTokenProgramForMint(connection, quoteMintPk);
418
+ const userOutputAta = await (0, spl_token_1.getAssociatedTokenAddress)(quoteMintPk, wallet.publicKey);
419
+ // Determine input token program (the token being sold)
420
+ const inputTokenProgram = baseTokenProgram;
421
+ // Build instructions
422
+ const ixs = [
423
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits }),
424
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }),
425
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, userInputAta, wallet.publicKey, tokenMintPk, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID) ? spl_token_1.TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID_PK),
426
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, userOutputAta, wallet.publicKey, quoteMintPk),
427
+ ];
428
+ // WSOL output: create WSOL ATA so we can receive wrapped SOL, then close after
429
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
430
+ // ATA creation already handled above via idempotent instruction
431
+ }
432
+ // Swap — input is token ATA, output is quote ATA
433
+ ixs.push(createSwapIx(poolAccounts, wallet.publicKey, userInputAta, userOutputAta, sellAmount, minOut, inputTokenProgram));
434
+ // Close WSOL output ATA to unwrap back to SOL
435
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
436
+ ixs.push((0, spl_token_1.createCloseAccountInstruction)(userOutputAta, wallet.publicKey, wallet.publicKey, [], TOKEN_PROGRAM_ID_PK));
437
+ }
438
+ // Submit via RPC send+confirm
439
+ const result = await (0, send_rpc_1.sendAndConfirmVtx)(connection, ixs, wallet);
440
+ // Human-readable sell amount
441
+ let tokenDecimals = 9;
442
+ try {
443
+ const mintData = await connection.getTokenSupply(tokenMintPk);
444
+ tokenDecimals = mintData.value.decimals;
445
+ }
446
+ catch { /* fallback to 9 */ }
447
+ const humanAmount = Number(sellAmount) / Math.pow(10, tokenDecimals);
448
+ return {
449
+ txSignature: result.txSignature,
450
+ confirmed: result.confirmed,
451
+ amountIn: humanAmount,
452
+ amountInToken: tokenMint,
453
+ dex: this.name,
454
+ poolAddress: poolId.toBase58(),
455
+ };
456
+ }
457
+ // ----- Snipe -----
458
+ async snipe(params) {
459
+ const connection = (0, config_1.getConnection)();
460
+ const wallet = (0, config_1.getWallet)();
461
+ const tokenMint = new web3_js_1.PublicKey(params.tokenMint);
462
+ const quoteMintPk = params.quoteMint ? new web3_js_1.PublicKey(params.quoteMint) : WSOL_MINT_PK;
463
+ const poolId = new web3_js_1.PublicKey(params.poolAddress);
464
+ const priorityFee = params.opts?.priorityFeeMicroLamports ?? 10_000_000;
465
+ // Derive all pool accounts
466
+ const poolAccounts = await derivePoolAccounts(connection, poolId);
467
+ // Detect base token program
468
+ const baseTokenProgram = await getTokenProgramForMint(connection, tokenMint);
469
+ // Calculate amounts
470
+ const quoteDecimals = quoteMintPk.equals(WSOL_MINT_PK) ? 9 : 6;
471
+ const amountIn = BigInt(Math.floor(params.amountSol * 10 ** quoteDecimals));
472
+ const minOut = 0n; // Unlimited slippage for sniping
473
+ // Build ATAs
474
+ const inputAta = await (0, spl_token_1.getAssociatedTokenAddress)(quoteMintPk, wallet.publicKey);
475
+ const outputAta = await (0, spl_token_1.getAssociatedTokenAddress)(tokenMint, wallet.publicKey, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID), baseTokenProgram);
476
+ // Determine input token program
477
+ let inputTokenProgram;
478
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
479
+ inputTokenProgram = TOKEN_PROGRAM_ID_PK;
480
+ }
481
+ else if (poolAccounts.pcMint.equals(quoteMintPk)) {
482
+ inputTokenProgram = poolAccounts.pcTokenProgram;
483
+ }
484
+ else {
485
+ inputTokenProgram = poolAccounts.coinTokenProgram;
486
+ }
487
+ // Build instructions
488
+ const ixs = [
489
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }),
490
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, inputAta, wallet.publicKey, quoteMintPk),
491
+ (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_PK),
492
+ ];
493
+ // WSOL wrapping
494
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
495
+ const lamports = Math.floor(params.amountSol * web3_js_1.LAMPORTS_PER_SOL);
496
+ ixs.push(web3_js_1.SystemProgram.transfer({ fromPubkey: wallet.publicKey, toPubkey: inputAta, lamports }), (0, spl_token_1.createSyncNativeInstruction)(inputAta, TOKEN_PROGRAM_ID_PK));
497
+ }
498
+ // Swap
499
+ ixs.push(createSwapIx(poolAccounts, wallet.publicKey, inputAta, outputAta, amountIn, minOut, inputTokenProgram));
500
+ // Close WSOL
501
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
502
+ ixs.push((0, spl_token_1.createCloseAccountInstruction)(inputAta, wallet.publicKey, wallet.publicKey, [], TOKEN_PROGRAM_ID_PK));
503
+ }
504
+ // Submit via landing layer
505
+ const { blockhash } = await connection.getLatestBlockhash();
506
+ const results = await (0, landing_1.landTransaction)(ixs, wallet, blockhash, {
507
+ dex: this.name,
508
+ operation: "snipe",
509
+ tipSol: params.tipSol,
510
+ });
511
+ const firstAccepted = results.find((r) => r.accepted);
512
+ return {
513
+ txSignature: firstAccepted?.signature ?? "",
514
+ confirmed: !!firstAccepted?.accepted,
515
+ amountIn: params.amountSol,
516
+ amountInToken: quoteMintPk.equals(WSOL_MINT_PK) ? "SOL" : quoteMintPk.toBase58(),
517
+ dex: this.name,
518
+ poolAddress: poolId.toBase58(),
519
+ };
520
+ }
521
+ // ----- Build swap IXs -----
522
+ async buildSwapIxs(params) {
523
+ if (!("amountSol" in params)) {
524
+ throw new types_1.UnsupportedOperationError(this.name, "buildSwapIxs(sell)");
525
+ }
526
+ const tokenMint = (0, types_1.requireTokenMint)(params, this.name);
527
+ const connection = (0, config_1.getConnection)();
528
+ const wallet = (0, config_1.getWallet)();
529
+ const buyParams = params;
530
+ const tokenMintPk = new web3_js_1.PublicKey(tokenMint);
531
+ const quoteMintPk = buyParams.quoteMint ? new web3_js_1.PublicKey(buyParams.quoteMint) : WSOL_MINT_PK;
532
+ // Resolve pool
533
+ let poolId;
534
+ if (buyParams.poolAddress) {
535
+ poolId = new web3_js_1.PublicKey(buyParams.poolAddress);
536
+ }
537
+ else {
538
+ const found = await discoverAmmV4Pool(connection, tokenMint, quoteMintPk.toBase58());
539
+ if (!found)
540
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, buyParams.quoteMint);
541
+ poolId = new web3_js_1.PublicKey(found.poolId);
542
+ }
543
+ const poolAccounts = await derivePoolAccounts(connection, poolId);
544
+ const baseTokenProgram = await getTokenProgramForMint(connection, tokenMintPk);
545
+ const quoteDecimals = quoteMintPk.equals(WSOL_MINT_PK) ? 9 : 6;
546
+ const amountIn = BigInt(Math.floor(buyParams.amountSol * 10 ** quoteDecimals));
547
+ const inputAta = await (0, spl_token_1.getAssociatedTokenAddress)(quoteMintPk, wallet.publicKey);
548
+ const outputAta = await (0, spl_token_1.getAssociatedTokenAddress)(tokenMintPk, wallet.publicKey, baseTokenProgram.equals(spl_token_1.TOKEN_2022_PROGRAM_ID), baseTokenProgram);
549
+ let inputTokenProgram;
550
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
551
+ inputTokenProgram = TOKEN_PROGRAM_ID_PK;
552
+ }
553
+ else if (poolAccounts.pcMint.equals(quoteMintPk)) {
554
+ inputTokenProgram = poolAccounts.pcTokenProgram;
555
+ }
556
+ else {
557
+ inputTokenProgram = poolAccounts.coinTokenProgram;
558
+ }
559
+ const instructions = [
560
+ (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, inputAta, wallet.publicKey, quoteMintPk),
561
+ (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_PK),
562
+ ];
563
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
564
+ const lamports = Math.floor(buyParams.amountSol * web3_js_1.LAMPORTS_PER_SOL);
565
+ instructions.push(web3_js_1.SystemProgram.transfer({ fromPubkey: wallet.publicKey, toPubkey: inputAta, lamports }), (0, spl_token_1.createSyncNativeInstruction)(inputAta, TOKEN_PROGRAM_ID_PK));
566
+ }
567
+ instructions.push(createSwapIx(poolAccounts, wallet.publicKey, inputAta, outputAta, amountIn, 0n, inputTokenProgram));
568
+ if (quoteMintPk.equals(WSOL_MINT_PK)) {
569
+ instructions.push((0, spl_token_1.createCloseAccountInstruction)(inputAta, wallet.publicKey, wallet.publicKey, [], TOKEN_PROGRAM_ID_PK));
570
+ }
571
+ return { instructions, signers: [] };
572
+ }
573
+ // ----- Pool discovery -----
574
+ async findPool(baseMint, quoteMint) {
575
+ const connection = (0, config_1.getConnection)();
576
+ const quoteMintStr = quoteMint ?? types_1.WSOL_MINT;
577
+ const found = await discoverAmmV4Pool(connection, baseMint, quoteMintStr);
578
+ if (!found)
579
+ return null;
580
+ const poolId = new web3_js_1.PublicKey(found.poolId);
581
+ try {
582
+ const ammInfo = await fetchAmmInfo(connection, poolId);
583
+ const [coinBal, pcBal] = await Promise.all([
584
+ connection.getTokenAccountBalance(ammInfo.coinVault),
585
+ connection.getTokenAccountBalance(ammInfo.pcVault),
586
+ ]);
587
+ return {
588
+ address: found.poolId,
589
+ dex: this.name,
590
+ protocol: this.protocol,
591
+ baseMint: ammInfo.coinVaultMint.toBase58(),
592
+ quoteMint: ammInfo.pcVaultMint.toBase58(),
593
+ baseDecimals: coinBal.value.decimals,
594
+ quoteDecimals: pcBal.value.decimals,
595
+ };
596
+ }
597
+ catch {
598
+ return {
599
+ address: found.poolId,
600
+ dex: this.name,
601
+ protocol: this.protocol,
602
+ baseMint,
603
+ quoteMint: quoteMintStr,
604
+ baseDecimals: 6,
605
+ quoteDecimals: 9,
606
+ };
607
+ }
608
+ }
609
+ // ----- Price -----
610
+ async getPrice(poolAddress) {
611
+ const connection = (0, config_1.getConnection)();
612
+ const poolId = new web3_js_1.PublicKey(poolAddress);
613
+ const ammInfo = await fetchAmmInfo(connection, poolId);
614
+ const [coinBal, pcBal] = await Promise.all([
615
+ connection.getTokenAccountBalance(ammInfo.coinVault),
616
+ connection.getTokenAccountBalance(ammInfo.pcVault),
617
+ ]);
618
+ const coinReserve = Number(coinBal.value.amount) / 10 ** coinBal.value.decimals;
619
+ const pcReserve = Number(pcBal.value.amount) / 10 ** pcBal.value.decimals;
620
+ // Determine which is base vs quote
621
+ const pcIsQuote = isQuoteMint(ammInfo.pcVaultMint);
622
+ let price;
623
+ let baseMint;
624
+ let quoteMintOut;
625
+ if (pcIsQuote) {
626
+ price = coinReserve > 0 ? pcReserve / coinReserve : 0;
627
+ baseMint = ammInfo.coinVaultMint;
628
+ quoteMintOut = ammInfo.pcVaultMint;
629
+ }
630
+ else {
631
+ price = pcReserve > 0 ? coinReserve / pcReserve : 0;
632
+ baseMint = ammInfo.pcVaultMint;
633
+ quoteMintOut = ammInfo.coinVaultMint;
634
+ }
635
+ return {
636
+ price,
637
+ baseMint: baseMint.toBase58(),
638
+ quoteMint: quoteMintOut.toBase58(),
639
+ source: "on-chain",
640
+ poolAddress,
641
+ timestamp: Date.now(),
642
+ };
643
+ }
644
+ }
645
+ // ---------------------------------------------------------------------------
646
+ // Register adapter
647
+ // ---------------------------------------------------------------------------
648
+ (0, index_1.registerAdapter)(new RaydiumAmmV4Adapter());
649
+ //# sourceMappingURL=raydium-amm-v4.js.map