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,692 @@
1
+ "use strict";
2
+ /**
3
+ * PumpFun AMM (PumpSwap) — IDexAdapter Implementation
4
+ *
5
+ * Program ID: pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA
6
+ *
7
+ * A constant-product AMM that tokens graduate to after their bonding curve
8
+ * completes on pump.fun. Also supports user-created pools.
9
+ *
10
+ * Supports:
11
+ * - buy: Buy base tokens from a pool (SOL → token)
12
+ * - sell: Sell base tokens to a pool (token → SOL)
13
+ * - createPool: Create a new AMM pool with initial liquidity
14
+ * - getPrice: Read pool reserves to compute price
15
+ * - snipe: Competitive buy via landing layer
16
+ *
17
+ * Pool PDA: ["pool", index(u16 LE), creator, baseMint, quoteMint]
18
+ * LP Mint PDA: ["pool_lp_mint", pool]
19
+ *
20
+ * Fees: LP fee 20 bps + protocol fee 5 bps = 25 bps total.
21
+ * Protocol fee recipients (8) should be randomly selected per TX.
22
+ *
23
+ * IDL source: https://github.com/pump-fun/pump-public-docs/blob/main/idl/pump_amm.json
24
+ */
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.PumpFunAmmAdapter = void 0;
30
+ const bn_js_1 = __importDefault(require("bn.js"));
31
+ const web3_js_1 = require("@solana/web3.js");
32
+ const spl_token_1 = require("@solana/spl-token");
33
+ const config_1 = require("../helpers/config");
34
+ const landing_1 = require("../transactions/landing");
35
+ const send_rpc_1 = require("../transactions/send-rpc");
36
+ const types_1 = require("./types");
37
+ const index_1 = require("./index");
38
+ // ---------------------------------------------------------------------------
39
+ // Program constants
40
+ // ---------------------------------------------------------------------------
41
+ const PUMP_AMM_PROGRAM_ID = new web3_js_1.PublicKey("pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA");
42
+ const PUMP_AMM_GLOBAL_CONFIG = new web3_js_1.PublicKey("ADyA8hdefvWN2dbGGWFotbzWxrAvLW83WG6QCVXvJKqw");
43
+ const PUMP_FEE_PROGRAM = new web3_js_1.PublicKey("pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ");
44
+ const PUMP_PROGRAM_ID = new web3_js_1.PublicKey("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P");
45
+ // Protocol fee recipients — randomly pick one per TX
46
+ const PROTOCOL_FEE_RECIPIENTS = [
47
+ new web3_js_1.PublicKey("62qc2CNXwrYqQScmEdiZFFAnJR262PxWEuNQtxfafNgV"),
48
+ new web3_js_1.PublicKey("7VtfL8fvgNfhz17qKRMjzQEXgbdpnHHHQRh54R9jP2RJ"),
49
+ new web3_js_1.PublicKey("7hTckgnGnLQR6sdH7YkqFTAA7VwTfYFaZ6EhEsU3saCX"),
50
+ new web3_js_1.PublicKey("9rPYyANsfQZw3DnDmKE3YCQF5E8oD89UXoHn9JFEhJUz"),
51
+ new web3_js_1.PublicKey("AVmoTthdrX6tKt4nDjco2D775W2YK3sDhxPcMmzUAmTY"),
52
+ new web3_js_1.PublicKey("FWsW1xNtWscwNmKv6wVsU1iTzRN6wmmk3MjxRP5tT7hz"),
53
+ new web3_js_1.PublicKey("G5UZAVbAf46s7cKWoyKu8kYTip9DGTpbLZ2qa9Aq69dP"),
54
+ new web3_js_1.PublicKey("JCRGumoE9Qi5BBgULTgdgTLjSgkCMSbF62ZZfGs84JeU"),
55
+ ];
56
+ // Instruction discriminators (from IDL)
57
+ const BUY_DISCRIMINATOR = Buffer.from([102, 6, 61, 18, 1, 218, 235, 234]);
58
+ const SELL_DISCRIMINATOR = Buffer.from([51, 230, 133, 164, 1, 127, 131, 173]);
59
+ const CREATE_POOL_DISCRIMINATOR = Buffer.from([233, 146, 209, 142, 207, 104, 64, 188]);
60
+ // Pool account discriminator
61
+ const POOL_DISCRIMINATOR = Buffer.from([241, 154, 109, 4, 17, 177, 109, 188]);
62
+ // All pump.fun tokens are 6 decimals. Quote (WSOL) is 9.
63
+ const PUMP_TOKEN_DECIMALS = 6;
64
+ function deserializePool(data) {
65
+ let offset = 8; // skip discriminator
66
+ const poolBump = data.readUInt8(offset);
67
+ offset += 1;
68
+ const index = data.readUInt16LE(offset);
69
+ offset += 2;
70
+ const creator = new web3_js_1.PublicKey(data.subarray(offset, offset + 32));
71
+ offset += 32;
72
+ const baseMint = new web3_js_1.PublicKey(data.subarray(offset, offset + 32));
73
+ offset += 32;
74
+ const quoteMint = new web3_js_1.PublicKey(data.subarray(offset, offset + 32));
75
+ offset += 32;
76
+ const lpMint = new web3_js_1.PublicKey(data.subarray(offset, offset + 32));
77
+ offset += 32;
78
+ const poolBaseTokenAccount = new web3_js_1.PublicKey(data.subarray(offset, offset + 32));
79
+ offset += 32;
80
+ const poolQuoteTokenAccount = new web3_js_1.PublicKey(data.subarray(offset, offset + 32));
81
+ offset += 32;
82
+ const lpSupply = data.readBigUInt64LE(offset);
83
+ offset += 8;
84
+ const coinCreator = new web3_js_1.PublicKey(data.subarray(offset, offset + 32));
85
+ offset += 32;
86
+ return {
87
+ poolBump, index, creator, baseMint, quoteMint, lpMint,
88
+ poolBaseTokenAccount, poolQuoteTokenAccount, lpSupply, coinCreator,
89
+ };
90
+ }
91
+ // ---------------------------------------------------------------------------
92
+ // PDA derivation helpers
93
+ // ---------------------------------------------------------------------------
94
+ function getEventAuthorityPda() {
95
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("__event_authority")], PUMP_AMM_PROGRAM_ID);
96
+ return pda;
97
+ }
98
+ function getCreatorVaultAuthorityPda(coinCreator) {
99
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("creator_vault"), coinCreator.toBuffer()], PUMP_AMM_PROGRAM_ID);
100
+ return pda;
101
+ }
102
+ function getGlobalVolumeAccumulatorPda() {
103
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("global_volume_accumulator")], PUMP_AMM_PROGRAM_ID);
104
+ return pda;
105
+ }
106
+ function getUserVolumeAccumulatorPda(user) {
107
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("user_volume_accumulator"), user.toBuffer()], PUMP_AMM_PROGRAM_ID);
108
+ return pda;
109
+ }
110
+ function getFeeConfigPda() {
111
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fee_config"), PUMP_AMM_PROGRAM_ID.toBuffer()], PUMP_FEE_PROGRAM);
112
+ return pda;
113
+ }
114
+ function getPoolPda(index, creator, baseMint, quoteMint) {
115
+ const indexBuf = Buffer.alloc(2);
116
+ indexBuf.writeUInt16LE(index);
117
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("pool"), indexBuf, creator.toBuffer(), baseMint.toBuffer(), quoteMint.toBuffer()], PUMP_AMM_PROGRAM_ID);
118
+ return pda;
119
+ }
120
+ function getLpMintPda(pool) {
121
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("pool_lp_mint"), pool.toBuffer()], PUMP_AMM_PROGRAM_ID);
122
+ return pda;
123
+ }
124
+ /** Pick a random protocol fee recipient */
125
+ function randomProtocolFeeRecipient() {
126
+ return PROTOCOL_FEE_RECIPIENTS[Math.floor(Math.random() * PROTOCOL_FEE_RECIPIENTS.length)];
127
+ }
128
+ /** Detect token program from on-chain account owner */
129
+ async function detectTokenProgram(mint) {
130
+ const connection = (0, config_1.getConnection)();
131
+ const accountInfo = await connection.getAccountInfo(mint);
132
+ if (!accountInfo)
133
+ throw new Error(`Mint account not found: ${mint.toBase58()}`);
134
+ return accountInfo.owner.equals(spl_token_1.TOKEN_2022_PROGRAM_ID)
135
+ ? spl_token_1.TOKEN_2022_PROGRAM_ID
136
+ : spl_token_1.TOKEN_PROGRAM_ID;
137
+ }
138
+ // ---------------------------------------------------------------------------
139
+ // Instruction builders
140
+ // ---------------------------------------------------------------------------
141
+ /**
142
+ * Build a PumpSwap AMM BUY instruction.
143
+ *
144
+ * buy(base_amount_out, max_quote_amount_in, track_volume)
145
+ */
146
+ function buildBuyInstruction(pool, poolState, user, baseAmountOut, maxQuoteAmountIn, baseTokenProgram, quoteTokenProgram) {
147
+ const userBaseTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.baseMint, user, false, baseTokenProgram);
148
+ const userQuoteTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.quoteMint, user, false, quoteTokenProgram);
149
+ const protocolFeeRecipient = randomProtocolFeeRecipient();
150
+ const protocolFeeRecipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.quoteMint, protocolFeeRecipient, true, quoteTokenProgram);
151
+ const coinCreatorVaultAuthority = getCreatorVaultAuthorityPda(poolState.coinCreator);
152
+ const coinCreatorVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.quoteMint, coinCreatorVaultAuthority, true, quoteTokenProgram);
153
+ const eventAuthority = getEventAuthorityPda();
154
+ const globalVolumeAccumulator = getGlobalVolumeAccumulatorPda();
155
+ const userVolumeAccumulator = getUserVolumeAccumulatorPda(user);
156
+ const feeConfig = getFeeConfigPda();
157
+ // Encode args: base_amount_out (u64) + max_quote_amount_in (u64)
158
+ const data = Buffer.alloc(8 + 8 + 8);
159
+ BUY_DISCRIMINATOR.copy(data, 0);
160
+ data.writeBigUInt64LE(BigInt(baseAmountOut.toString()), 8);
161
+ data.writeBigUInt64LE(BigInt(maxQuoteAmountIn.toString()), 16);
162
+ return new web3_js_1.TransactionInstruction({
163
+ programId: PUMP_AMM_PROGRAM_ID,
164
+ keys: [
165
+ { pubkey: pool, isSigner: false, isWritable: true },
166
+ { pubkey: user, isSigner: true, isWritable: true },
167
+ { pubkey: PUMP_AMM_GLOBAL_CONFIG, isSigner: false, isWritable: false },
168
+ { pubkey: poolState.baseMint, isSigner: false, isWritable: false },
169
+ { pubkey: poolState.quoteMint, isSigner: false, isWritable: false },
170
+ { pubkey: userBaseTokenAccount, isSigner: false, isWritable: true },
171
+ { pubkey: userQuoteTokenAccount, isSigner: false, isWritable: true },
172
+ { pubkey: poolState.poolBaseTokenAccount, isSigner: false, isWritable: true },
173
+ { pubkey: poolState.poolQuoteTokenAccount, isSigner: false, isWritable: true },
174
+ { pubkey: protocolFeeRecipient, isSigner: false, isWritable: false },
175
+ { pubkey: protocolFeeRecipientTokenAccount, isSigner: false, isWritable: true },
176
+ { pubkey: baseTokenProgram, isSigner: false, isWritable: false },
177
+ { pubkey: quoteTokenProgram, isSigner: false, isWritable: false },
178
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
179
+ { pubkey: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
180
+ { pubkey: eventAuthority, isSigner: false, isWritable: false },
181
+ { pubkey: PUMP_AMM_PROGRAM_ID, isSigner: false, isWritable: false },
182
+ { pubkey: coinCreatorVaultAta, isSigner: false, isWritable: true },
183
+ { pubkey: coinCreatorVaultAuthority, isSigner: false, isWritable: false },
184
+ { pubkey: globalVolumeAccumulator, isSigner: false, isWritable: true },
185
+ { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true },
186
+ { pubkey: feeConfig, isSigner: false, isWritable: false },
187
+ { pubkey: PUMP_FEE_PROGRAM, isSigner: false, isWritable: false },
188
+ ],
189
+ data,
190
+ });
191
+ }
192
+ /**
193
+ * Build a PumpSwap AMM SELL instruction.
194
+ *
195
+ * sell(base_amount_in, min_quote_amount_out)
196
+ */
197
+ function buildSellInstruction(pool, poolState, user, baseAmountIn, minQuoteAmountOut, baseTokenProgram, quoteTokenProgram) {
198
+ const userBaseTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.baseMint, user, false, baseTokenProgram);
199
+ const userQuoteTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.quoteMint, user, false, quoteTokenProgram);
200
+ const protocolFeeRecipient = randomProtocolFeeRecipient();
201
+ const protocolFeeRecipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.quoteMint, protocolFeeRecipient, true, quoteTokenProgram);
202
+ const coinCreatorVaultAuthority = getCreatorVaultAuthorityPda(poolState.coinCreator);
203
+ const coinCreatorVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.quoteMint, coinCreatorVaultAuthority, true, quoteTokenProgram);
204
+ const eventAuthority = getEventAuthorityPda();
205
+ const feeConfig = getFeeConfigPda();
206
+ // Encode args: base_amount_in (u64) + min_quote_amount_out (u64)
207
+ const data = Buffer.alloc(8 + 8 + 8);
208
+ SELL_DISCRIMINATOR.copy(data, 0);
209
+ data.writeBigUInt64LE(BigInt(baseAmountIn.toString()), 8);
210
+ data.writeBigUInt64LE(BigInt(minQuoteAmountOut.toString()), 16);
211
+ return new web3_js_1.TransactionInstruction({
212
+ programId: PUMP_AMM_PROGRAM_ID,
213
+ keys: [
214
+ { pubkey: pool, isSigner: false, isWritable: true },
215
+ { pubkey: user, isSigner: true, isWritable: true },
216
+ { pubkey: PUMP_AMM_GLOBAL_CONFIG, isSigner: false, isWritable: false },
217
+ { pubkey: poolState.baseMint, isSigner: false, isWritable: false },
218
+ { pubkey: poolState.quoteMint, isSigner: false, isWritable: false },
219
+ { pubkey: userBaseTokenAccount, isSigner: false, isWritable: true },
220
+ { pubkey: userQuoteTokenAccount, isSigner: false, isWritable: true },
221
+ { pubkey: poolState.poolBaseTokenAccount, isSigner: false, isWritable: true },
222
+ { pubkey: poolState.poolQuoteTokenAccount, isSigner: false, isWritable: true },
223
+ { pubkey: protocolFeeRecipient, isSigner: false, isWritable: false },
224
+ { pubkey: protocolFeeRecipientTokenAccount, isSigner: false, isWritable: true },
225
+ { pubkey: baseTokenProgram, isSigner: false, isWritable: false },
226
+ { pubkey: quoteTokenProgram, isSigner: false, isWritable: false },
227
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
228
+ { pubkey: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
229
+ { pubkey: eventAuthority, isSigner: false, isWritable: false },
230
+ { pubkey: PUMP_AMM_PROGRAM_ID, isSigner: false, isWritable: false },
231
+ { pubkey: coinCreatorVaultAta, isSigner: false, isWritable: true },
232
+ { pubkey: coinCreatorVaultAuthority, isSigner: false, isWritable: false },
233
+ { pubkey: feeConfig, isSigner: false, isWritable: false },
234
+ { pubkey: PUMP_FEE_PROGRAM, isSigner: false, isWritable: false },
235
+ ],
236
+ data,
237
+ });
238
+ }
239
+ /**
240
+ * Build a PumpSwap AMM CREATE_POOL instruction.
241
+ *
242
+ * create_pool(index, base_amount_in, quote_amount_in, coin_creator, is_mayhem_mode, is_cashback_coin)
243
+ */
244
+ function buildCreatePoolInstruction(creator, baseMint, quoteMint, index, baseAmountIn, quoteAmountIn, coinCreator, baseTokenProgram, quoteTokenProgram) {
245
+ const pool = getPoolPda(index, creator, baseMint, quoteMint);
246
+ const lpMint = getLpMintPda(pool);
247
+ const userBaseTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(baseMint, creator, false, baseTokenProgram);
248
+ const userQuoteTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(quoteMint, creator, false, quoteTokenProgram);
249
+ // LP mint uses Token-2022
250
+ const userPoolTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(lpMint, creator, false, spl_token_1.TOKEN_2022_PROGRAM_ID);
251
+ const poolBaseTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(baseMint, pool, true, baseTokenProgram);
252
+ const poolQuoteTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(quoteMint, pool, true, quoteTokenProgram);
253
+ const eventAuthority = getEventAuthorityPda();
254
+ // Encode args:
255
+ // index: u16
256
+ // base_amount_in: u64
257
+ // quote_amount_in: u64
258
+ // coin_creator: pubkey (32 bytes)
259
+ // is_mayhem_mode: bool (1 byte)
260
+ // is_cashback_coin: OptionBool (1 byte, None = 0)
261
+ const data = Buffer.alloc(8 + 2 + 8 + 8 + 32 + 1 + 1);
262
+ let offset = 0;
263
+ CREATE_POOL_DISCRIMINATOR.copy(data, offset);
264
+ offset += 8;
265
+ data.writeUInt16LE(index, offset);
266
+ offset += 2;
267
+ data.writeBigUInt64LE(BigInt(baseAmountIn.toString()), offset);
268
+ offset += 8;
269
+ data.writeBigUInt64LE(BigInt(quoteAmountIn.toString()), offset);
270
+ offset += 8;
271
+ coinCreator.toBuffer().copy(data, offset);
272
+ offset += 32;
273
+ data.writeUInt8(0, offset);
274
+ offset += 1; // is_mayhem_mode = false
275
+ data.writeUInt8(0, offset);
276
+ offset += 1; // is_cashback_coin = None
277
+ return new web3_js_1.TransactionInstruction({
278
+ programId: PUMP_AMM_PROGRAM_ID,
279
+ keys: [
280
+ { pubkey: pool, isSigner: false, isWritable: true },
281
+ { pubkey: PUMP_AMM_GLOBAL_CONFIG, isSigner: false, isWritable: false },
282
+ { pubkey: creator, isSigner: true, isWritable: true },
283
+ { pubkey: baseMint, isSigner: false, isWritable: false },
284
+ { pubkey: quoteMint, isSigner: false, isWritable: false },
285
+ { pubkey: lpMint, isSigner: false, isWritable: true },
286
+ { pubkey: userBaseTokenAccount, isSigner: false, isWritable: true },
287
+ { pubkey: userQuoteTokenAccount, isSigner: false, isWritable: true },
288
+ { pubkey: userPoolTokenAccount, isSigner: false, isWritable: true },
289
+ { pubkey: poolBaseTokenAccount, isSigner: false, isWritable: true },
290
+ { pubkey: poolQuoteTokenAccount, isSigner: false, isWritable: true },
291
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
292
+ { pubkey: spl_token_1.TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false },
293
+ { pubkey: baseTokenProgram, isSigner: false, isWritable: false },
294
+ { pubkey: quoteTokenProgram, isSigner: false, isWritable: false },
295
+ { pubkey: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
296
+ { pubkey: eventAuthority, isSigner: false, isWritable: false },
297
+ { pubkey: PUMP_AMM_PROGRAM_ID, isSigner: false, isWritable: false },
298
+ ],
299
+ data,
300
+ });
301
+ }
302
+ // ---------------------------------------------------------------------------
303
+ // AMM math (constant product)
304
+ // ---------------------------------------------------------------------------
305
+ /**
306
+ * Calculate base tokens out for a given quote input on AMM.
307
+ * Constant product: base_out = (base_reserves * quote_in) / (quote_reserves + quote_in)
308
+ * Fees: LP fee 20 bps + protocol fee 5 bps = 25 bps total.
309
+ * Fee is deducted from quote input before the swap.
310
+ */
311
+ function calculateBuyBaseOut(baseReserves, quoteReserves, quoteAmountIn) {
312
+ // Total fee: 25 bps (0.25%)
313
+ const feeNumerator = 25n;
314
+ const feeDenominator = 10000n;
315
+ const fee = (quoteAmountIn * feeNumerator) / feeDenominator;
316
+ const netQuote = quoteAmountIn - fee;
317
+ return (baseReserves * netQuote) / (quoteReserves + netQuote);
318
+ }
319
+ /**
320
+ * Calculate quote output for a given base input on AMM.
321
+ */
322
+ function calculateSellQuoteOut(baseReserves, quoteReserves, baseAmountIn) {
323
+ const grossQuote = (quoteReserves * baseAmountIn) / (baseReserves + baseAmountIn);
324
+ // Total fee: 25 bps deducted from quote output
325
+ const feeNumerator = 25n;
326
+ const feeDenominator = 10000n;
327
+ const fee = (grossQuote * feeNumerator) / feeDenominator;
328
+ return grossQuote - fee;
329
+ }
330
+ // ---------------------------------------------------------------------------
331
+ // Adapter
332
+ // ---------------------------------------------------------------------------
333
+ class PumpFunAmmAdapter {
334
+ name = "pumpfun-amm";
335
+ protocol = "pump-amm";
336
+ capabilities = (0, types_1.defaultCapabilities)({
337
+ canBuy: true,
338
+ canSell: true,
339
+ canSnipe: true,
340
+ canGetPrice: true,
341
+ });
342
+ // ----- Core: buy -----
343
+ async buy(params) {
344
+ const tokenMint = (0, types_1.requireTokenMint)(params, this.name);
345
+ const { amountSol, poolAddress, opts } = params;
346
+ const connection = (0, config_1.getConnection)();
347
+ const wallet = (0, config_1.getWallet)();
348
+ if (!poolAddress)
349
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, types_1.WSOL_MINT);
350
+ const poolPk = new web3_js_1.PublicKey(poolAddress);
351
+ // Fetch pool state
352
+ const accountInfo = await connection.getAccountInfo(poolPk);
353
+ if (!accountInfo)
354
+ throw new Error(`Pool not found: ${poolAddress}`);
355
+ const poolState = deserializePool(accountInfo.data);
356
+ // Detect token programs
357
+ const baseTokenProgram = await detectTokenProgram(poolState.baseMint);
358
+ const quoteTokenProgram = poolState.quoteMint.toBase58() === types_1.WSOL_MINT
359
+ ? spl_token_1.TOKEN_PROGRAM_ID
360
+ : await detectTokenProgram(poolState.quoteMint);
361
+ // Read pool reserves
362
+ const [baseBalance, quoteBalance] = await Promise.all([
363
+ connection.getTokenAccountBalance(poolState.poolBaseTokenAccount),
364
+ connection.getTokenAccountBalance(poolState.poolQuoteTokenAccount),
365
+ ]);
366
+ const baseReserves = BigInt(baseBalance.value.amount);
367
+ const quoteReserves = BigInt(quoteBalance.value.amount);
368
+ const quoteAmountIn = BigInt(Math.floor(amountSol * web3_js_1.LAMPORTS_PER_SOL));
369
+ const baseAmountOut = calculateBuyBaseOut(baseReserves, quoteReserves, quoteAmountIn);
370
+ if (baseAmountOut === 0n)
371
+ throw new Error("Buy amount too small — would receive 0 tokens");
372
+ const computeLimit = opts?.computeUnitLimit ?? types_1.DEFAULT_COMPUTE_UNIT_LIMIT;
373
+ const priorityFee = opts?.priorityFeeMicroLamports ?? types_1.DEFAULT_PRIORITY_FEE_MICRO_LAMPORTS;
374
+ // Ensure user has ATAs for both base and quote tokens
375
+ const userBaseAta = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.baseMint, wallet.publicKey, false, baseTokenProgram);
376
+ const userQuoteAta = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.quoteMint, wallet.publicKey, false, quoteTokenProgram);
377
+ const createBaseAta = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, userBaseAta, wallet.publicKey, poolState.baseMint, baseTokenProgram);
378
+ const createQuoteAta = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, userQuoteAta, wallet.publicKey, poolState.quoteMint, quoteTokenProgram);
379
+ // max_quote_amount_in with 30% slippage buffer (AMM fee rounding + price movement)
380
+ const maxQuoteAmountIn = quoteAmountIn + quoteAmountIn * 30n / 100n;
381
+ // For WSOL: need to wrap SOL into the WSOL ATA (wrap max to cover slippage buffer)
382
+ const wrapIxs = [];
383
+ if (poolState.quoteMint.toBase58() === types_1.WSOL_MINT) {
384
+ wrapIxs.push(web3_js_1.SystemProgram.transfer({
385
+ fromPubkey: wallet.publicKey,
386
+ toPubkey: userQuoteAta,
387
+ lamports: maxQuoteAmountIn,
388
+ }),
389
+ // syncNative to update WSOL balance
390
+ new web3_js_1.TransactionInstruction({
391
+ programId: spl_token_1.TOKEN_PROGRAM_ID,
392
+ keys: [{ pubkey: userQuoteAta, isSigner: false, isWritable: true }],
393
+ data: Buffer.from([17]), // SyncNative instruction
394
+ }));
395
+ }
396
+ const buyIx = buildBuyInstruction(poolPk, poolState, wallet.publicKey, new bn_js_1.default(baseAmountOut.toString()), new bn_js_1.default(maxQuoteAmountIn.toString()), baseTokenProgram, quoteTokenProgram);
397
+ // Close WSOL ATA after swap to recover SOL
398
+ const closeIxs = [];
399
+ if (poolState.quoteMint.toBase58() === types_1.WSOL_MINT) {
400
+ closeIxs.push(new web3_js_1.TransactionInstruction({
401
+ programId: spl_token_1.TOKEN_PROGRAM_ID,
402
+ keys: [
403
+ { pubkey: userQuoteAta, isSigner: false, isWritable: true },
404
+ { pubkey: wallet.publicKey, isSigner: false, isWritable: true },
405
+ { pubkey: wallet.publicKey, isSigner: true, isWritable: false },
406
+ ],
407
+ data: Buffer.from([9]), // CloseAccount instruction
408
+ }));
409
+ }
410
+ const ixs = [
411
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: computeLimit }),
412
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }),
413
+ createBaseAta,
414
+ createQuoteAta,
415
+ ...wrapIxs,
416
+ buyIx,
417
+ ...closeIxs,
418
+ ];
419
+ const result = await (0, send_rpc_1.sendAndConfirmVtx)(connection, ixs, wallet);
420
+ const baseDecimals = baseBalance.value.decimals;
421
+ return {
422
+ txSignature: result.txSignature,
423
+ confirmed: result.confirmed,
424
+ amountIn: amountSol,
425
+ amountInToken: "SOL",
426
+ amountOut: Number(baseAmountOut) / Math.pow(10, baseDecimals),
427
+ amountOutToken: poolState.baseMint.toBase58(),
428
+ dex: this.name,
429
+ poolAddress,
430
+ };
431
+ }
432
+ // ----- Core: sell -----
433
+ async sell(params) {
434
+ const tokenMint = (0, types_1.requireTokenMint)(params, this.name);
435
+ const { percentage, poolAddress, opts } = params;
436
+ const connection = (0, config_1.getConnection)();
437
+ const wallet = (0, config_1.getWallet)();
438
+ if (!poolAddress)
439
+ throw new types_1.PoolNotFoundError(this.name, tokenMint, types_1.WSOL_MINT);
440
+ const poolPk = new web3_js_1.PublicKey(poolAddress);
441
+ // Fetch pool state
442
+ const accountInfo = await connection.getAccountInfo(poolPk);
443
+ if (!accountInfo)
444
+ throw new Error(`Pool not found: ${poolAddress}`);
445
+ const poolState = deserializePool(accountInfo.data);
446
+ const baseTokenProgram = await detectTokenProgram(poolState.baseMint);
447
+ const quoteTokenProgram = poolState.quoteMint.toBase58() === types_1.WSOL_MINT
448
+ ? spl_token_1.TOKEN_PROGRAM_ID
449
+ : await detectTokenProgram(poolState.quoteMint);
450
+ // Get user's base token balance
451
+ const userBaseAta = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.baseMint, wallet.publicKey, false, baseTokenProgram);
452
+ const tokenAccount = await (0, spl_token_1.getAccount)(connection, userBaseAta, "confirmed", baseTokenProgram);
453
+ const sellAmount = BigInt(Math.floor((Number(tokenAccount.amount) * percentage) / 100));
454
+ if (sellAmount === 0n)
455
+ throw new Error(`No balance to sell for ${tokenMint}`);
456
+ const computeLimit = opts?.computeUnitLimit ?? types_1.DEFAULT_COMPUTE_UNIT_LIMIT;
457
+ const priorityFee = opts?.priorityFeeMicroLamports ?? types_1.DEFAULT_PRIORITY_FEE_MICRO_LAMPORTS;
458
+ // Ensure user has quote ATA (for receiving SOL/WSOL)
459
+ const userQuoteAta = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.quoteMint, wallet.publicKey, false, quoteTokenProgram);
460
+ const createQuoteAta = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, userQuoteAta, wallet.publicKey, poolState.quoteMint, quoteTokenProgram);
461
+ const sellIx = buildSellInstruction(poolPk, poolState, wallet.publicKey, new bn_js_1.default(sellAmount.toString()), new bn_js_1.default(0), // min_quote_amount_out = 0 (no slippage protection)
462
+ baseTokenProgram, quoteTokenProgram);
463
+ // Close WSOL ATA to unwrap SOL
464
+ const closeIxs = [];
465
+ if (poolState.quoteMint.toBase58() === types_1.WSOL_MINT) {
466
+ closeIxs.push(new web3_js_1.TransactionInstruction({
467
+ programId: spl_token_1.TOKEN_PROGRAM_ID,
468
+ keys: [
469
+ { pubkey: userQuoteAta, isSigner: false, isWritable: true },
470
+ { pubkey: wallet.publicKey, isSigner: false, isWritable: true },
471
+ { pubkey: wallet.publicKey, isSigner: true, isWritable: false },
472
+ ],
473
+ data: Buffer.from([9]), // CloseAccount instruction
474
+ }));
475
+ }
476
+ const ixs = [
477
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: computeLimit }),
478
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }),
479
+ createQuoteAta,
480
+ sellIx,
481
+ ...closeIxs,
482
+ ];
483
+ const result = await (0, send_rpc_1.sendAndConfirmVtx)(connection, ixs, wallet);
484
+ // Human-readable sell amount
485
+ let tokenDecimals = PUMP_TOKEN_DECIMALS;
486
+ try {
487
+ const mintData = await connection.getTokenSupply(poolState.baseMint);
488
+ tokenDecimals = mintData.value.decimals;
489
+ }
490
+ catch { /* fallback to 6 */ }
491
+ const humanSellAmount = Number(sellAmount) / Math.pow(10, tokenDecimals);
492
+ return {
493
+ txSignature: result.txSignature,
494
+ confirmed: result.confirmed,
495
+ amountIn: humanSellAmount,
496
+ amountInToken: tokenMint,
497
+ dex: this.name,
498
+ poolAddress,
499
+ };
500
+ }
501
+ // ----- Snipe -----
502
+ async snipe(params) {
503
+ const { tokenMint, amountSol, poolAddress, tipSol, opts } = params;
504
+ const connection = (0, config_1.getConnection)();
505
+ const wallet = (0, config_1.getWallet)();
506
+ const poolPk = new web3_js_1.PublicKey(poolAddress);
507
+ const accountInfo = await connection.getAccountInfo(poolPk);
508
+ if (!accountInfo)
509
+ throw new Error(`Pool not found: ${poolAddress}`);
510
+ const poolState = deserializePool(accountInfo.data);
511
+ const baseTokenProgram = await detectTokenProgram(poolState.baseMint);
512
+ const quoteTokenProgram = poolState.quoteMint.toBase58() === types_1.WSOL_MINT
513
+ ? spl_token_1.TOKEN_PROGRAM_ID
514
+ : await detectTokenProgram(poolState.quoteMint);
515
+ // Read pool reserves
516
+ const [baseBalance, quoteBalance] = await Promise.all([
517
+ connection.getTokenAccountBalance(poolState.poolBaseTokenAccount),
518
+ connection.getTokenAccountBalance(poolState.poolQuoteTokenAccount),
519
+ ]);
520
+ const baseReserves = BigInt(baseBalance.value.amount);
521
+ const quoteReserves = BigInt(quoteBalance.value.amount);
522
+ const quoteAmountIn = BigInt(Math.floor(amountSol * web3_js_1.LAMPORTS_PER_SOL));
523
+ const baseAmountOut = calculateBuyBaseOut(baseReserves, quoteReserves, quoteAmountIn);
524
+ const computeLimit = opts?.computeUnitLimit ?? types_1.DEFAULT_COMPUTE_UNIT_LIMIT;
525
+ const priorityFee = opts?.priorityFeeMicroLamports ?? 40_000_000;
526
+ const userBaseAta = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.baseMint, wallet.publicKey, false, baseTokenProgram);
527
+ const userQuoteAta = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.quoteMint, wallet.publicKey, false, quoteTokenProgram);
528
+ const createBaseAta = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, userBaseAta, wallet.publicKey, poolState.baseMint, baseTokenProgram);
529
+ const createQuoteAta = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(wallet.publicKey, userQuoteAta, wallet.publicKey, poolState.quoteMint, quoteTokenProgram);
530
+ // max_quote_amount_in with 30% slippage buffer
531
+ const maxQuoteAmountIn = quoteAmountIn + quoteAmountIn * 30n / 100n;
532
+ // WSOL wrapping
533
+ const wrapIxs = [];
534
+ if (poolState.quoteMint.toBase58() === types_1.WSOL_MINT) {
535
+ wrapIxs.push(web3_js_1.SystemProgram.transfer({
536
+ fromPubkey: wallet.publicKey,
537
+ toPubkey: userQuoteAta,
538
+ lamports: maxQuoteAmountIn,
539
+ }), new web3_js_1.TransactionInstruction({
540
+ programId: spl_token_1.TOKEN_PROGRAM_ID,
541
+ keys: [{ pubkey: userQuoteAta, isSigner: false, isWritable: true }],
542
+ data: Buffer.from([17]), // SyncNative
543
+ }));
544
+ }
545
+ const buyIx = buildBuyInstruction(poolPk, poolState, wallet.publicKey, new bn_js_1.default(baseAmountOut.toString()), new bn_js_1.default(maxQuoteAmountIn.toString()), baseTokenProgram, quoteTokenProgram);
546
+ const ixs = [
547
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: computeLimit }),
548
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }),
549
+ createBaseAta,
550
+ createQuoteAta,
551
+ ...wrapIxs,
552
+ buyIx,
553
+ ];
554
+ const blockhash = await connection.getLatestBlockhash();
555
+ const results = await (0, landing_1.landTransaction)(ixs, wallet, blockhash, {
556
+ dex: this.name,
557
+ operation: "snipe",
558
+ tipSol,
559
+ });
560
+ const accepted = results.find((r) => r.accepted);
561
+ return {
562
+ txSignature: accepted?.signature ?? "",
563
+ confirmed: !!accepted?.accepted,
564
+ amountIn: amountSol,
565
+ amountInToken: "SOL",
566
+ dex: this.name,
567
+ poolAddress,
568
+ };
569
+ }
570
+ // ----- buildSwapIxs -----
571
+ async buildSwapIxs(params) {
572
+ const connection = (0, config_1.getConnection)();
573
+ const wallet = (0, config_1.getWallet)();
574
+ if ("percentage" in params) {
575
+ const p = params;
576
+ if (!p.poolAddress)
577
+ throw new Error("poolAddress required for pumpfun-amm buildSwapIxs");
578
+ const poolPk = new web3_js_1.PublicKey(p.poolAddress);
579
+ const accountInfo = await connection.getAccountInfo(poolPk);
580
+ if (!accountInfo)
581
+ throw new Error("Pool not found");
582
+ const poolState = deserializePool(accountInfo.data);
583
+ const baseTokenProgram = await detectTokenProgram(poolState.baseMint);
584
+ const quoteTokenProgram = poolState.quoteMint.toBase58() === types_1.WSOL_MINT
585
+ ? spl_token_1.TOKEN_PROGRAM_ID : await detectTokenProgram(poolState.quoteMint);
586
+ const userBaseAta = (0, spl_token_1.getAssociatedTokenAddressSync)(poolState.baseMint, wallet.publicKey, false, baseTokenProgram);
587
+ const tokenAccount = await (0, spl_token_1.getAccount)(connection, userBaseAta, "confirmed", baseTokenProgram);
588
+ const sellAmount = BigInt(Math.floor((Number(tokenAccount.amount) * p.percentage) / 100));
589
+ const sellIx = buildSellInstruction(poolPk, poolState, wallet.publicKey, new bn_js_1.default(sellAmount.toString()), new bn_js_1.default(0), baseTokenProgram, quoteTokenProgram);
590
+ return { instructions: [sellIx], signers: [] };
591
+ }
592
+ // Buy
593
+ const p = params;
594
+ if (!p.poolAddress)
595
+ throw new Error("poolAddress required for pumpfun-amm buildSwapIxs");
596
+ const poolPk = new web3_js_1.PublicKey(p.poolAddress);
597
+ const accountInfo = await connection.getAccountInfo(poolPk);
598
+ if (!accountInfo)
599
+ throw new Error("Pool not found");
600
+ const poolState = deserializePool(accountInfo.data);
601
+ const baseTokenProgram = await detectTokenProgram(poolState.baseMint);
602
+ const quoteTokenProgram = poolState.quoteMint.toBase58() === types_1.WSOL_MINT
603
+ ? spl_token_1.TOKEN_PROGRAM_ID : await detectTokenProgram(poolState.quoteMint);
604
+ const [baseBalance, quoteBalance] = await Promise.all([
605
+ connection.getTokenAccountBalance(poolState.poolBaseTokenAccount),
606
+ connection.getTokenAccountBalance(poolState.poolQuoteTokenAccount),
607
+ ]);
608
+ const quoteAmountIn = BigInt(Math.floor(p.amountSol * web3_js_1.LAMPORTS_PER_SOL));
609
+ const baseAmountOut = calculateBuyBaseOut(BigInt(baseBalance.value.amount), BigInt(quoteBalance.value.amount), quoteAmountIn);
610
+ // 30% slippage buffer on max_quote_amount_in
611
+ const maxQuoteIn = quoteAmountIn + quoteAmountIn * 30n / 100n;
612
+ const buyIx = buildBuyInstruction(poolPk, poolState, wallet.publicKey, new bn_js_1.default(baseAmountOut.toString()), new bn_js_1.default(maxQuoteIn.toString()), baseTokenProgram, quoteTokenProgram);
613
+ return { instructions: [buyIx], signers: [] };
614
+ }
615
+ // ----- getPrice -----
616
+ async getPrice(poolAddress) {
617
+ const connection = (0, config_1.getConnection)();
618
+ const poolPk = new web3_js_1.PublicKey(poolAddress);
619
+ const accountInfo = await connection.getAccountInfo(poolPk);
620
+ if (!accountInfo)
621
+ throw new Error(`Pool not found: ${poolAddress}`);
622
+ const poolState = deserializePool(accountInfo.data);
623
+ // Read pool reserves for price calculation
624
+ const [baseBalance, quoteBalance] = await Promise.all([
625
+ connection.getTokenAccountBalance(poolState.poolBaseTokenAccount),
626
+ connection.getTokenAccountBalance(poolState.poolQuoteTokenAccount),
627
+ ]);
628
+ const baseReserves = Number(baseBalance.value.amount);
629
+ const quoteReserves = Number(quoteBalance.value.amount);
630
+ const baseDecimals = baseBalance.value.decimals;
631
+ const quoteDecimals = quoteBalance.value.decimals;
632
+ // Price = (quoteReserves / 10^quoteDecimals) / (baseReserves / 10^baseDecimals)
633
+ const price = (quoteReserves / Math.pow(10, quoteDecimals)) /
634
+ (baseReserves / Math.pow(10, baseDecimals));
635
+ return {
636
+ price,
637
+ baseMint: poolState.baseMint.toBase58(),
638
+ quoteMint: poolState.quoteMint.toBase58(),
639
+ source: "on-chain",
640
+ poolAddress,
641
+ timestamp: Date.now(),
642
+ };
643
+ }
644
+ // ----- Create pool -----
645
+ /**
646
+ * Create a new PumpSwap AMM pool with initial liquidity.
647
+ *
648
+ * @param baseMint - Base token mint address
649
+ * @param quoteMint - Quote token mint address (usually WSOL)
650
+ * @param baseAmountIn - Amount of base tokens to deposit (human-readable)
651
+ * @param quoteAmountIn - Amount of quote tokens to deposit (human-readable)
652
+ * @param index - Pool index (default: 1; 0 is reserved for canonical pump pools)
653
+ * @returns TxResult with pool address
654
+ */
655
+ async createPool(baseMint, quoteMint, baseAmountIn, quoteAmountIn, index = 1) {
656
+ const connection = (0, config_1.getConnection)();
657
+ const wallet = (0, config_1.getWallet)();
658
+ const baseMintPk = new web3_js_1.PublicKey(baseMint);
659
+ const quoteMintPk = new web3_js_1.PublicKey(quoteMint);
660
+ const baseTokenProgram = await detectTokenProgram(baseMintPk);
661
+ const quoteTokenProgram = quoteMintPk.toBase58() === types_1.WSOL_MINT
662
+ ? spl_token_1.TOKEN_PROGRAM_ID : await detectTokenProgram(quoteMintPk);
663
+ // Get decimals for amount conversion
664
+ const [baseMintInfo, quoteMintInfo] = await Promise.all([
665
+ connection.getTokenSupply(baseMintPk),
666
+ connection.getTokenSupply(quoteMintPk),
667
+ ]);
668
+ const baseRaw = new bn_js_1.default(Math.floor(baseAmountIn * Math.pow(10, baseMintInfo.value.decimals)).toString());
669
+ const quoteRaw = new bn_js_1.default(Math.floor(quoteAmountIn * Math.pow(10, quoteMintInfo.value.decimals)).toString());
670
+ const createPoolIx = buildCreatePoolInstruction(wallet.publicKey, baseMintPk, quoteMintPk, index, baseRaw, quoteRaw, wallet.publicKey, // coin_creator = wallet
671
+ baseTokenProgram, quoteTokenProgram);
672
+ const ixs = [
673
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: types_1.DEFAULT_COMPUTE_UNIT_LIMIT }),
674
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: types_1.DEFAULT_PRIORITY_FEE_MICRO_LAMPORTS }),
675
+ createPoolIx,
676
+ ];
677
+ const result = await (0, send_rpc_1.sendAndConfirmVtx)(connection, ixs, wallet);
678
+ const poolPda = getPoolPda(index, wallet.publicKey, baseMintPk, quoteMintPk);
679
+ return {
680
+ txSignature: result.txSignature,
681
+ confirmed: result.confirmed,
682
+ poolAddress: poolPda.toBase58(),
683
+ dex: this.name,
684
+ };
685
+ }
686
+ }
687
+ exports.PumpFunAmmAdapter = PumpFunAmmAdapter;
688
+ // ---------------------------------------------------------------------------
689
+ // Auto-register
690
+ // ---------------------------------------------------------------------------
691
+ (0, index_1.registerAdapter)(new PumpFunAmmAdapter());
692
+ //# sourceMappingURL=pumpfun-amm.js.map