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,735 @@
1
+ "use strict";
2
+ /**
3
+ * Meteora DLMM (Dynamic Liquidity Market Maker) — IDexAdapter Implementation
4
+ *
5
+ * Wraps the @meteora-ag/dlmm SDK for buy/sell/snipe/findPool/getPrice
6
+ * plus LP operations: addLiquidity, removeLiquidity, claimFees, listPositions.
7
+ *
8
+ * Source: 100x-algo-bots/trading-modules/meteora-dlmm/
9
+ *
10
+ * IMPORTANT BUG FIX: Source code hardcodes `swapYtoX = true` which only works
11
+ * when the user is buying (spending Y/quote to get X/base). This adapter
12
+ * dynamically computes the swap direction based on which token is the quote.
13
+ *
14
+ * SDK patterns:
15
+ * // Swaps
16
+ * const dlmmPool = await DLMM.create(connection, poolAddress);
17
+ * const binArrays = await dlmmPool.getBinArrayForSwap(swapYtoX);
18
+ * const quote = await dlmmPool.swapQuote(amount, swapYtoX, slippage, binArrays);
19
+ * const swapTx = await dlmmPool.swap({ inToken, outToken, ... });
20
+ *
21
+ * // LP operations
22
+ * const createTx = await dlmmPool.initializePositionAndAddLiquidityByStrategy({...});
23
+ * const removeTxs = await dlmmPool.removeLiquidity({...});
24
+ * const claimTxs = await dlmmPool.claimSwapFee({...});
25
+ */
26
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
27
+ if (k2 === undefined) k2 = k;
28
+ var desc = Object.getOwnPropertyDescriptor(m, k);
29
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
30
+ desc = { enumerable: true, get: function() { return m[k]; } };
31
+ }
32
+ Object.defineProperty(o, k2, desc);
33
+ }) : (function(o, m, k, k2) {
34
+ if (k2 === undefined) k2 = k;
35
+ o[k2] = m[k];
36
+ }));
37
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
38
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
39
+ }) : function(o, v) {
40
+ o["default"] = v;
41
+ });
42
+ var __importStar = (this && this.__importStar) || (function () {
43
+ var ownKeys = function(o) {
44
+ ownKeys = Object.getOwnPropertyNames || function (o) {
45
+ var ar = [];
46
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
47
+ return ar;
48
+ };
49
+ return ownKeys(o);
50
+ };
51
+ return function (mod) {
52
+ if (mod && mod.__esModule) return mod;
53
+ var result = {};
54
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
55
+ __setModuleDefault(result, mod);
56
+ return result;
57
+ };
58
+ })();
59
+ var __importDefault = (this && this.__importDefault) || function (mod) {
60
+ return (mod && mod.__esModule) ? mod : { "default": mod };
61
+ };
62
+ Object.defineProperty(exports, "__esModule", { value: true });
63
+ exports.MeteoraDlmmAdapter = void 0;
64
+ const bn_js_1 = __importDefault(require("bn.js"));
65
+ const dlmm_1 = __importStar(require("@meteora-ag/dlmm"));
66
+ const web3_js_1 = require("@solana/web3.js");
67
+ const spl_token_1 = require("@solana/spl-token");
68
+ const config_1 = require("../helpers/config");
69
+ const landing_1 = require("../transactions/landing");
70
+ const send_rpc_1 = require("../transactions/send-rpc");
71
+ const types_1 = require("./types");
72
+ const index_1 = require("./index");
73
+ // ---------------------------------------------------------------------------
74
+ // Constants
75
+ // ---------------------------------------------------------------------------
76
+ /** Known stablecoin mints with 6 decimals */
77
+ const SIX_DECIMAL_MINTS = new Set([
78
+ types_1.USDC_MINT,
79
+ types_1.USDT_MINT,
80
+ "USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB",
81
+ ]);
82
+ const WSOL_PK = new web3_js_1.PublicKey(types_1.WSOL_MINT);
83
+ /** Default number of bins for LP positions */
84
+ const DEFAULT_NUM_BINS = 50;
85
+ /** Maximum bins allowed by the DLMM SDK per position */
86
+ const MAX_BINS = 70;
87
+ // ---------------------------------------------------------------------------
88
+ // Helpers
89
+ // ---------------------------------------------------------------------------
90
+ function quoteDecimals(quoteMintStr) {
91
+ return SIX_DECIMAL_MINTS.has(quoteMintStr) ? 6 : 9;
92
+ }
93
+ function amountToLamports(amount, quoteMintStr) {
94
+ const decimals = quoteDecimals(quoteMintStr);
95
+ return new bn_js_1.default(Math.floor(amount * Math.pow(10, decimals)));
96
+ }
97
+ /**
98
+ * Determine swap direction for DLMM pool.
99
+ *
100
+ * DLMM pools have tokenX and tokenY. swapYtoX=true means spending Y to get X.
101
+ * For a buy (spending quote to get base):
102
+ * - If quote == tokenY → swapYtoX = true (spend Y, get X)
103
+ * - If quote == tokenX → swapYtoX = false (spend X, get Y)
104
+ *
105
+ * The source code HARDCODES swapYtoX=true which is WRONG when the quote
106
+ * token is tokenX. This adapter fixes that bug.
107
+ */
108
+ function determineSwapDirection(quoteMintStr, tokenX, tokenY) {
109
+ const quotePk = new web3_js_1.PublicKey(quoteMintStr);
110
+ if (quotePk.equals(tokenY)) {
111
+ // Quote is tokenY → spend Y, get X
112
+ return { swapYtoX: true, inToken: tokenY, outToken: tokenX };
113
+ }
114
+ else if (quotePk.equals(tokenX)) {
115
+ // Quote is tokenX → spend X, get Y
116
+ return { swapYtoX: false, inToken: tokenX, outToken: tokenY };
117
+ }
118
+ else {
119
+ // Fallback: assume tokenY is quote (matches most SOL-paired pools)
120
+ return { swapYtoX: true, inToken: tokenY, outToken: tokenX };
121
+ }
122
+ }
123
+ /**
124
+ * Map our LpStrategy string to the SDK's StrategyType enum.
125
+ * The SDK has: Spot=0, Curve=1, BidAsk=2.
126
+ * One-sided behavior is controlled via the bin range (not a separate enum).
127
+ */
128
+ function toSdkStrategy(strategy) {
129
+ switch (strategy) {
130
+ case "spot":
131
+ return dlmm_1.StrategyType.Spot;
132
+ case "curve":
133
+ return dlmm_1.StrategyType.Curve;
134
+ case "bid-ask":
135
+ return dlmm_1.StrategyType.BidAsk;
136
+ default:
137
+ return dlmm_1.StrategyType.Spot;
138
+ }
139
+ }
140
+ // ---------------------------------------------------------------------------
141
+ // Adapter
142
+ // ---------------------------------------------------------------------------
143
+ class MeteoraDlmmAdapter {
144
+ name = "meteora-dlmm";
145
+ protocol = "dlmm";
146
+ capabilities = (0, types_1.defaultCapabilities)({
147
+ canBuy: true,
148
+ canSell: true,
149
+ canSnipe: true,
150
+ canFindPool: false, // DLMM has no simple PDA derivation
151
+ canGetPrice: true,
152
+ canAddLiquidity: true,
153
+ canRemoveLiquidity: true,
154
+ canClaimFees: true,
155
+ canListPositions: true,
156
+ });
157
+ // ----- Core: buy -----
158
+ async buy(params) {
159
+ const tokenMint = (0, types_1.requireTokenMint)(params, this.name);
160
+ const { amountSol, quoteMint: quoteMintParam, poolAddress, opts } = params;
161
+ const connection = (0, config_1.getConnection)();
162
+ const wallet = (0, config_1.getWallet)();
163
+ const quoteMintStr = quoteMintParam ?? types_1.WSOL_MINT;
164
+ const poolPk = poolAddress
165
+ ? new web3_js_1.PublicKey(poolAddress)
166
+ : await this.resolvePool(tokenMint, quoteMintStr);
167
+ const dlmmPool = await dlmm_1.default.create(connection, poolPk);
168
+ const inputAmount = amountToLamports(amountSol, quoteMintStr);
169
+ // Dynamically determine swap direction (fixes source bug)
170
+ const { swapYtoX, inToken, outToken } = determineSwapDirection(quoteMintStr, dlmmPool.tokenX.publicKey, dlmmPool.tokenY.publicKey);
171
+ const binArrays = await dlmmPool.getBinArrayForSwap(swapYtoX);
172
+ const slippageBps = opts?.slippageBps ?? types_1.DEFAULT_SLIPPAGE_BPS;
173
+ const swapQuote = await dlmmPool.swapQuote(inputAmount, swapYtoX, new bn_js_1.default(slippageBps), binArrays);
174
+ const swapTx = await dlmmPool.swap({
175
+ inToken,
176
+ binArraysPubkey: swapQuote.binArraysPubkey,
177
+ inAmount: inputAmount,
178
+ lbPair: dlmmPool.pubkey,
179
+ user: wallet.publicKey,
180
+ minOutAmount: new bn_js_1.default(0),
181
+ outToken,
182
+ });
183
+ // DLMM SDK already includes ComputeBudget + ATA creation in swapTx.instructions
184
+ const result = await (0, send_rpc_1.sendAndConfirmVtx)(connection, swapTx.instructions, wallet, {
185
+ addressLookupTables: opts?.addressLookupTables,
186
+ });
187
+ return {
188
+ txSignature: result.txSignature,
189
+ confirmed: result.confirmed,
190
+ amountIn: amountSol,
191
+ amountInToken: quoteMintStr,
192
+ dex: this.name,
193
+ poolAddress: poolPk.toBase58(),
194
+ };
195
+ }
196
+ // ----- Core: sell -----
197
+ async sell(params) {
198
+ const tokenMint = (0, types_1.requireTokenMint)(params, this.name);
199
+ const { percentage, quoteMint: quoteMintParam, poolAddress, opts } = params;
200
+ const connection = (0, config_1.getConnection)();
201
+ const wallet = (0, config_1.getWallet)();
202
+ const quoteMintStr = quoteMintParam ?? types_1.WSOL_MINT;
203
+ const poolPk = poolAddress
204
+ ? new web3_js_1.PublicKey(poolAddress)
205
+ : await this.resolvePool(tokenMint, quoteMintStr);
206
+ const dlmmPool = await dlmm_1.default.create(connection, poolPk);
207
+ const baseMintPk = new web3_js_1.PublicKey(tokenMint);
208
+ // Detect base token program
209
+ const baseMintAccInfo = await connection.getAccountInfo(baseMintPk);
210
+ if (!baseMintAccInfo) {
211
+ throw new Error(`Token mint not found: ${tokenMint}`);
212
+ }
213
+ const baseTokenProgram = baseMintAccInfo.owner.equals(spl_token_1.TOKEN_2022_PROGRAM_ID)
214
+ ? spl_token_1.TOKEN_2022_PROGRAM_ID
215
+ : spl_token_1.TOKEN_PROGRAM_ID;
216
+ // Get token balance
217
+ const ata = await (0, spl_token_1.getAssociatedTokenAddress)(baseMintPk, wallet.publicKey, false, baseTokenProgram);
218
+ const tokenAccount = await (0, spl_token_1.getAccount)(connection, ata, "confirmed", baseTokenProgram);
219
+ const balance = tokenAccount.amount;
220
+ // Calculate sell amount based on percentage
221
+ const sellAmount = new bn_js_1.default(Math.floor((Number(balance) * percentage) / 100).toString());
222
+ if (sellAmount.isZero()) {
223
+ throw new Error(`No balance to sell for ${tokenMint}`);
224
+ }
225
+ // Determine swap direction using the base token (being sold) as input
226
+ const { swapYtoX, inToken, outToken } = determineSwapDirection(tokenMint, dlmmPool.tokenX.publicKey, dlmmPool.tokenY.publicKey);
227
+ const binArrays = await dlmmPool.getBinArrayForSwap(swapYtoX);
228
+ const slippageBps = opts?.slippageBps ?? types_1.DEFAULT_SLIPPAGE_BPS;
229
+ const swapQuote = await dlmmPool.swapQuote(sellAmount, swapYtoX, new bn_js_1.default(slippageBps), binArrays);
230
+ const swapTx = await dlmmPool.swap({
231
+ inToken,
232
+ binArraysPubkey: swapQuote.binArraysPubkey,
233
+ inAmount: sellAmount,
234
+ lbPair: dlmmPool.pubkey,
235
+ user: wallet.publicKey,
236
+ minOutAmount: new bn_js_1.default(0),
237
+ outToken,
238
+ });
239
+ // DLMM SDK already includes ComputeBudget + ATA creation in swapTx.instructions
240
+ const rpcResult = await (0, send_rpc_1.sendAndConfirmVtx)(connection, swapTx.instructions, wallet, {
241
+ addressLookupTables: opts?.addressLookupTables,
242
+ });
243
+ // Human-readable sell amount
244
+ let tokenDecimals = 9;
245
+ try {
246
+ const mintData = await connection.getTokenSupply(baseMintPk);
247
+ tokenDecimals = mintData.value.decimals;
248
+ }
249
+ catch { /* fallback to 9 */ }
250
+ const humanAmount = Number(sellAmount.toString()) / Math.pow(10, tokenDecimals);
251
+ return {
252
+ txSignature: rpcResult.txSignature,
253
+ confirmed: rpcResult.confirmed,
254
+ amountIn: humanAmount,
255
+ amountInToken: tokenMint,
256
+ dex: this.name,
257
+ poolAddress: poolPk.toBase58(),
258
+ };
259
+ }
260
+ // ----- Snipe -----
261
+ async snipe(params) {
262
+ const { tokenMint, amountSol, poolAddress, quoteMint: quoteMintParam, tipSol, opts } = params;
263
+ const connection = (0, config_1.getConnection)();
264
+ const wallet = (0, config_1.getWallet)();
265
+ const quoteMintStr = quoteMintParam ?? types_1.WSOL_MINT;
266
+ const poolPk = new web3_js_1.PublicKey(poolAddress);
267
+ const inputAmount = amountToLamports(amountSol, quoteMintStr);
268
+ const dlmmPool = await dlmm_1.default.create(connection, poolPk);
269
+ // Dynamically determine swap direction (fixes source bug)
270
+ const { swapYtoX, inToken, outToken } = determineSwapDirection(quoteMintStr, dlmmPool.tokenX.publicKey, dlmmPool.tokenY.publicKey);
271
+ const binArrays = await dlmmPool.getBinArrayForSwap(swapYtoX);
272
+ const swapQuote = await dlmmPool.swapQuote(inputAmount, swapYtoX, new bn_js_1.default(15 * 100), // 15% slippage for snipe (matches source)
273
+ binArrays);
274
+ const swapTx = await dlmmPool.swap({
275
+ inToken,
276
+ binArraysPubkey: swapQuote.binArraysPubkey,
277
+ inAmount: inputAmount,
278
+ lbPair: dlmmPool.pubkey,
279
+ user: wallet.publicKey,
280
+ minOutAmount: new bn_js_1.default(0), // unlimited slippage for snipe
281
+ outToken,
282
+ });
283
+ const computeLimit = opts?.computeUnitLimit ?? types_1.DEFAULT_COMPUTE_UNIT_LIMIT;
284
+ const priorityFee = opts?.priorityFeeMicroLamports ?? 40_000_000;
285
+ const ixs = [
286
+ web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: computeLimit }),
287
+ web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }),
288
+ ...swapTx.instructions,
289
+ ];
290
+ const blockhash = await connection.getLatestBlockhash();
291
+ const results = await (0, landing_1.landTransaction)(ixs, wallet, blockhash, {
292
+ dex: this.name,
293
+ operation: "snipe",
294
+ tipSol,
295
+ addressLookupTables: opts?.addressLookupTables,
296
+ });
297
+ const accepted = results.find((r) => r.accepted);
298
+ return {
299
+ txSignature: accepted?.signature ?? "",
300
+ confirmed: !!accepted?.accepted,
301
+ amountIn: amountSol,
302
+ amountInToken: quoteMintStr,
303
+ dex: this.name,
304
+ poolAddress,
305
+ };
306
+ }
307
+ // ----- buildSwapIxs -----
308
+ async buildSwapIxs(params) {
309
+ if ("percentage" in params) {
310
+ throw new types_1.UnsupportedOperationError(this.name, "buildSwapIxs(sell)");
311
+ }
312
+ const buyParams = params;
313
+ const tokenMint = (0, types_1.requireTokenMint)(buyParams, this.name);
314
+ const connection = (0, config_1.getConnection)();
315
+ const wallet = (0, config_1.getWallet)();
316
+ const quoteMintStr = buyParams.quoteMint ?? types_1.WSOL_MINT;
317
+ const poolPk = buyParams.poolAddress
318
+ ? new web3_js_1.PublicKey(buyParams.poolAddress)
319
+ : await this.resolvePool(tokenMint, quoteMintStr);
320
+ const dlmmPool = await dlmm_1.default.create(connection, poolPk);
321
+ const inputAmount = amountToLamports(buyParams.amountSol, quoteMintStr);
322
+ const { swapYtoX, inToken, outToken } = determineSwapDirection(quoteMintStr, dlmmPool.tokenX.publicKey, dlmmPool.tokenY.publicKey);
323
+ const binArrays = await dlmmPool.getBinArrayForSwap(swapYtoX);
324
+ const swapQuote = await dlmmPool.swapQuote(inputAmount, swapYtoX, new bn_js_1.default(15 * 100), binArrays);
325
+ const swapTx = await dlmmPool.swap({
326
+ inToken,
327
+ binArraysPubkey: swapQuote.binArraysPubkey,
328
+ inAmount: inputAmount,
329
+ lbPair: dlmmPool.pubkey,
330
+ user: wallet.publicKey,
331
+ minOutAmount: new bn_js_1.default(0),
332
+ outToken,
333
+ });
334
+ return {
335
+ instructions: swapTx.instructions,
336
+ signers: [],
337
+ };
338
+ }
339
+ // ----- findPool -----
340
+ async findPool(baseMint, quoteMint) {
341
+ const connection = (0, config_1.getConnection)();
342
+ const poolPk = new web3_js_1.PublicKey(baseMint); // For DLMM, baseMint is often used to search
343
+ const quoteMintStr = quoteMint ?? types_1.WSOL_MINT;
344
+ // DLMM doesn't have a simple PDA derivation like DAMM.
345
+ // The SDK's DLMM.create() requires a known pool address.
346
+ // For pool discovery, we'd need to use the DLMM program's getLbPairs() which
347
+ // requires anchor setup. Return null — callers should provide poolAddress.
348
+ return null;
349
+ }
350
+ // ----- getPrice -----
351
+ async getPrice(poolAddress) {
352
+ const connection = (0, config_1.getConnection)();
353
+ const poolPk = new web3_js_1.PublicKey(poolAddress);
354
+ const dlmmPool = await dlmm_1.default.create(connection, poolPk);
355
+ const { binId, price: rawPrice } = await dlmmPool.getActiveBin();
356
+ const tokenXDecimals = Number(dlmmPool.tokenX.mint.decimals);
357
+ const tokenYDecimals = Number(dlmmPool.tokenY.mint.decimals);
358
+ const priceFactor = Math.pow(10, tokenYDecimals - tokenXDecimals);
359
+ const adjustedPrice = Number(rawPrice) / priceFactor;
360
+ const price = adjustedPrice;
361
+ return {
362
+ price,
363
+ baseMint: dlmmPool.tokenX.publicKey.toBase58(),
364
+ quoteMint: dlmmPool.tokenY.publicKey.toBase58(),
365
+ source: "on-chain",
366
+ poolAddress,
367
+ timestamp: Date.now(),
368
+ };
369
+ }
370
+ // ----- addLiquidity -----
371
+ /**
372
+ * Add liquidity to a Meteora DLMM pool.
373
+ *
374
+ * Three modes (determined by which amounts are provided):
375
+ *
376
+ * 1. One-sided SOL (amountSol > 0, no amountToken):
377
+ * Bins below active bin, filled with SOL. Most common use case.
378
+ *
379
+ * 2. One-sided token (amountToken > 0, no amountSol):
380
+ * Bins above active bin, filled with the non-SOL token.
381
+ * Useful for DCA-out strategies.
382
+ *
383
+ * 3. Balanced (both amountSol and amountToken > 0):
384
+ * Bins centered around active bin with both tokens.
385
+ *
386
+ * @returns TxResult with positionAddress for the created position.
387
+ */
388
+ async addLiquidity(params) {
389
+ const { poolAddress, opts } = params;
390
+ const strategy = params.strategy ?? "spot";
391
+ const numBins = Math.min(Math.max(params.bins ?? DEFAULT_NUM_BINS, 1), MAX_BINS);
392
+ // Resolve amounts: prefer new fields, fall back to legacy amountA/amountB
393
+ const amountSol = params.amountSol ?? params.amountA ?? 0;
394
+ const amountToken = params.amountToken ?? params.amountB ?? 0;
395
+ const connection = (0, config_1.getConnection)();
396
+ const wallet = (0, config_1.getWallet)();
397
+ const poolPk = new web3_js_1.PublicKey(poolAddress);
398
+ const dlmmPool = await dlmm_1.default.create(connection, poolPk);
399
+ const activeBin = await dlmmPool.getActiveBin();
400
+ // Determine which token is SOL
401
+ const tokenXMint = dlmmPool.tokenX.publicKey;
402
+ const tokenYMint = dlmmPool.tokenY.publicKey;
403
+ const tokenXDecimals = Number(dlmmPool.tokenX.mint.decimals);
404
+ const tokenYDecimals = Number(dlmmPool.tokenY.mint.decimals);
405
+ const xIsSOL = tokenXMint.equals(WSOL_PK);
406
+ const yIsSOL = tokenYMint.equals(WSOL_PK);
407
+ // Calculate amounts in native units
408
+ // SOL goes into whichever side is WSOL; token goes into the other
409
+ let totalXAmount;
410
+ let totalYAmount;
411
+ if (xIsSOL) {
412
+ totalXAmount = new bn_js_1.default(Math.floor(amountSol * 10 ** tokenXDecimals));
413
+ totalYAmount = new bn_js_1.default(Math.floor(amountToken * 10 ** tokenYDecimals));
414
+ }
415
+ else if (yIsSOL) {
416
+ totalXAmount = new bn_js_1.default(Math.floor(amountToken * 10 ** tokenXDecimals));
417
+ totalYAmount = new bn_js_1.default(Math.floor(amountSol * 10 ** tokenYDecimals));
418
+ }
419
+ else {
420
+ // Neither side is SOL — unusual, but handle gracefully
421
+ totalXAmount = new bn_js_1.default(Math.floor(amountSol * 10 ** tokenXDecimals));
422
+ totalYAmount = new bn_js_1.default(Math.floor(amountToken * 10 ** tokenYDecimals));
423
+ }
424
+ const isOneSidedSol = amountSol > 0 && amountToken === 0;
425
+ const isOneSidedToken = amountToken > 0 && amountSol === 0;
426
+ let minBinId;
427
+ let maxBinId;
428
+ let strategyType;
429
+ if (isOneSidedSol) {
430
+ // SOL-only: bins below active bin
431
+ minBinId = activeBin.binId - numBins;
432
+ maxBinId = activeBin.binId;
433
+ strategyType = toSdkStrategy(strategy);
434
+ }
435
+ else if (isOneSidedToken) {
436
+ // Token-only: bins above active bin
437
+ minBinId = activeBin.binId;
438
+ maxBinId = activeBin.binId + numBins;
439
+ strategyType = toSdkStrategy(strategy);
440
+ }
441
+ else {
442
+ // Balanced: center around active bin
443
+ const halfBins = Math.floor(numBins / 2);
444
+ minBinId = activeBin.binId - halfBins;
445
+ maxBinId = activeBin.binId + halfBins;
446
+ strategyType = toSdkStrategy(strategy);
447
+ }
448
+ const newPosition = new web3_js_1.Keypair();
449
+ // Create position and add liquidity in one call
450
+ const createPositionTx = await dlmmPool.initializePositionAndAddLiquidityByStrategy({
451
+ positionPubKey: newPosition.publicKey,
452
+ user: wallet.publicKey,
453
+ totalXAmount,
454
+ totalYAmount,
455
+ strategy: {
456
+ maxBinId,
457
+ minBinId,
458
+ strategyType,
459
+ },
460
+ });
461
+ // Send the SDK's legacy Transaction directly with a fresh blockhash.
462
+ // The SDK call above can take 10-30s, so we must NOT use a stale blockhash.
463
+ try {
464
+ const result = await (0, send_rpc_1.sendAndConfirmLegacyTx)(connection, createPositionTx, wallet, {
465
+ extraSigners: [newPosition],
466
+ });
467
+ return {
468
+ txSignature: result.txSignature,
469
+ confirmed: result.confirmed,
470
+ error: result.error,
471
+ positionAddress: newPosition.publicKey.toBase58(),
472
+ poolAddress,
473
+ dex: this.name,
474
+ };
475
+ }
476
+ catch (error) {
477
+ return {
478
+ txSignature: "",
479
+ confirmed: false,
480
+ error: error instanceof Error ? error.message : String(error),
481
+ positionAddress: newPosition.publicKey.toBase58(),
482
+ poolAddress,
483
+ dex: this.name,
484
+ };
485
+ }
486
+ }
487
+ // ----- removeLiquidity -----
488
+ /**
489
+ * Remove liquidity from a Meteora DLMM pool position.
490
+ *
491
+ * If positionAddress is provided, removes from that specific position.
492
+ * Otherwise, removes from the first position found in the pool.
493
+ *
494
+ * If percentage is 100, also claims fees and closes the position.
495
+ */
496
+ async removeLiquidity(params) {
497
+ const { poolAddress, percentage, positionAddress } = params;
498
+ const connection = (0, config_1.getConnection)();
499
+ const wallet = (0, config_1.getWallet)();
500
+ const poolPk = new web3_js_1.PublicKey(poolAddress);
501
+ const dlmmPool = await dlmm_1.default.create(connection, poolPk);
502
+ // Find user's position in this pool
503
+ const { userPositions } = await dlmmPool.getPositionsByUserAndLbPair(wallet.publicKey);
504
+ if (userPositions.length === 0) {
505
+ return {
506
+ txSignature: "",
507
+ confirmed: false,
508
+ error: `No positions found for user in pool ${poolAddress}`,
509
+ poolAddress,
510
+ dex: this.name,
511
+ };
512
+ }
513
+ // Select position: by address if given, otherwise first found
514
+ let position;
515
+ if (positionAddress) {
516
+ const targetPk = new web3_js_1.PublicKey(positionAddress);
517
+ position = userPositions.find((p) => p.publicKey.equals(targetPk));
518
+ if (!position) {
519
+ return {
520
+ txSignature: "",
521
+ confirmed: false,
522
+ error: `Position ${positionAddress} not found in pool ${poolAddress}`,
523
+ poolAddress,
524
+ dex: this.name,
525
+ };
526
+ }
527
+ }
528
+ else {
529
+ position = userPositions[0];
530
+ }
531
+ // Calculate BPS: 100% = 10000 bps
532
+ const bps = new bn_js_1.default(Math.floor((percentage / 100) * 10000));
533
+ const shouldClaimAndClose = percentage >= 100;
534
+ const removeTxs = await dlmmPool.removeLiquidity({
535
+ position: position.publicKey,
536
+ user: wallet.publicKey,
537
+ fromBinId: position.positionData.lowerBinId,
538
+ toBinId: position.positionData.upperBinId,
539
+ bps,
540
+ shouldClaimAndClose,
541
+ });
542
+ // removeLiquidity returns Transaction | Transaction[], normalize to array
543
+ const txArray = Array.isArray(removeTxs) ? removeTxs : [removeTxs];
544
+ let lastSignature = "";
545
+ try {
546
+ for (const removeTx of txArray) {
547
+ const result = await (0, send_rpc_1.sendAndConfirmLegacyTx)(connection, removeTx, wallet);
548
+ lastSignature = result.txSignature;
549
+ if (!result.confirmed) {
550
+ return {
551
+ txSignature: lastSignature,
552
+ confirmed: false,
553
+ error: result.error,
554
+ positionAddress: position.publicKey.toBase58(),
555
+ poolAddress,
556
+ dex: this.name,
557
+ };
558
+ }
559
+ }
560
+ return {
561
+ txSignature: lastSignature,
562
+ confirmed: true,
563
+ positionAddress: position.publicKey.toBase58(),
564
+ poolAddress,
565
+ dex: this.name,
566
+ };
567
+ }
568
+ catch (error) {
569
+ return {
570
+ txSignature: lastSignature,
571
+ confirmed: false,
572
+ error: error instanceof Error ? error.message : String(error),
573
+ positionAddress: position.publicKey.toBase58(),
574
+ poolAddress,
575
+ dex: this.name,
576
+ };
577
+ }
578
+ }
579
+ // ----- claimFees -----
580
+ /**
581
+ * Claim accumulated swap fees from a DLMM LP position.
582
+ *
583
+ * If positionAddress is provided, claims from that specific position.
584
+ * Otherwise, claims from the first position found in the pool.
585
+ */
586
+ async claimFees(poolAddress, positionAddress) {
587
+ const connection = (0, config_1.getConnection)();
588
+ const wallet = (0, config_1.getWallet)();
589
+ const poolPk = new web3_js_1.PublicKey(poolAddress);
590
+ const dlmmPool = await dlmm_1.default.create(connection, poolPk);
591
+ const { userPositions } = await dlmmPool.getPositionsByUserAndLbPair(wallet.publicKey);
592
+ if (userPositions.length === 0) {
593
+ return {
594
+ txSignature: "",
595
+ confirmed: false,
596
+ error: `No positions found for user in pool ${poolAddress}`,
597
+ poolAddress,
598
+ dex: this.name,
599
+ };
600
+ }
601
+ // Select position
602
+ let position;
603
+ if (positionAddress) {
604
+ const targetPk = new web3_js_1.PublicKey(positionAddress);
605
+ position = userPositions.find((p) => p.publicKey.equals(targetPk));
606
+ if (!position) {
607
+ return {
608
+ txSignature: "",
609
+ confirmed: false,
610
+ error: `Position ${positionAddress} not found in pool ${poolAddress}`,
611
+ poolAddress,
612
+ dex: this.name,
613
+ };
614
+ }
615
+ }
616
+ else {
617
+ position = userPositions[0];
618
+ }
619
+ // claimSwapFee may return null or throw "No fee to claim"
620
+ let claimFeeTx;
621
+ try {
622
+ claimFeeTx = await dlmmPool.claimSwapFee({
623
+ owner: wallet.publicKey,
624
+ position,
625
+ });
626
+ }
627
+ catch (error) {
628
+ const msg = error instanceof Error ? error.message : String(error);
629
+ // "No fee to claim" is expected for fresh positions — not a real error
630
+ return {
631
+ txSignature: "",
632
+ confirmed: true,
633
+ error: msg,
634
+ positionAddress: position.publicKey.toBase58(),
635
+ poolAddress,
636
+ dex: this.name,
637
+ };
638
+ }
639
+ if (!claimFeeTx) {
640
+ return {
641
+ txSignature: "",
642
+ confirmed: true,
643
+ error: "No fees to claim",
644
+ positionAddress: position.publicKey.toBase58(),
645
+ poolAddress,
646
+ dex: this.name,
647
+ };
648
+ }
649
+ try {
650
+ const result = await (0, send_rpc_1.sendAndConfirmLegacyTx)(connection, claimFeeTx, wallet);
651
+ return {
652
+ txSignature: result.txSignature,
653
+ confirmed: result.confirmed,
654
+ error: result.error,
655
+ positionAddress: position.publicKey.toBase58(),
656
+ poolAddress,
657
+ dex: this.name,
658
+ };
659
+ }
660
+ catch (error) {
661
+ return {
662
+ txSignature: "",
663
+ confirmed: false,
664
+ error: error instanceof Error ? error.message : String(error),
665
+ positionAddress: position.publicKey.toBase58(),
666
+ poolAddress,
667
+ dex: this.name,
668
+ };
669
+ }
670
+ }
671
+ // ----- listPositions -----
672
+ /**
673
+ * List user's LP positions in a DLMM pool.
674
+ *
675
+ * Returns position details including bin range, token amounts,
676
+ * unclaimed fees, and whether the position is in range.
677
+ */
678
+ async listPositions(poolAddress) {
679
+ const connection = (0, config_1.getConnection)();
680
+ const wallet = (0, config_1.getWallet)();
681
+ const poolPk = new web3_js_1.PublicKey(poolAddress);
682
+ const dlmmPool = await dlmm_1.default.create(connection, poolPk);
683
+ const activeBin = await dlmmPool.getActiveBin();
684
+ const tokenXMint = dlmmPool.tokenX.publicKey;
685
+ const tokenYMint = dlmmPool.tokenY.publicKey;
686
+ const tokenXDecimals = Number(dlmmPool.tokenX.mint.decimals);
687
+ const tokenYDecimals = Number(dlmmPool.tokenY.mint.decimals);
688
+ const { userPositions } = await dlmmPool.getPositionsByUserAndLbPair(wallet.publicKey);
689
+ return userPositions.map((pos) => {
690
+ const binData = pos.positionData.positionBinData;
691
+ // Sum amounts and fees across all bins
692
+ let totalX = 0;
693
+ let totalY = 0;
694
+ let feeX = 0;
695
+ let feeY = 0;
696
+ for (const bin of binData) {
697
+ totalX += Number(bin.positionXAmount);
698
+ totalY += Number(bin.positionYAmount);
699
+ feeX += Number(bin.positionFeeXAmount);
700
+ feeY += Number(bin.positionFeeYAmount);
701
+ }
702
+ const lowerBinId = pos.positionData.lowerBinId;
703
+ const upperBinId = pos.positionData.upperBinId;
704
+ const inRange = activeBin.binId >= lowerBinId && activeBin.binId <= upperBinId;
705
+ return {
706
+ positionAddress: pos.publicKey.toBase58(),
707
+ poolAddress,
708
+ dex: this.name,
709
+ lowerBinId,
710
+ upperBinId,
711
+ amountX: totalX / 10 ** tokenXDecimals,
712
+ amountY: totalY / 10 ** tokenYDecimals,
713
+ tokenXMint: tokenXMint.toBase58(),
714
+ tokenYMint: tokenYMint.toBase58(),
715
+ feeX: feeX / 10 ** tokenXDecimals,
716
+ feeY: feeY / 10 ** tokenYDecimals,
717
+ inRange,
718
+ };
719
+ });
720
+ }
721
+ // ----- Internal helpers -----
722
+ async resolvePool(baseMint, quoteMint) {
723
+ const pool = await this.findPool(baseMint, quoteMint);
724
+ if (!pool) {
725
+ throw new types_1.PoolNotFoundError(this.name, baseMint, quoteMint);
726
+ }
727
+ return new web3_js_1.PublicKey(pool.address);
728
+ }
729
+ }
730
+ exports.MeteoraDlmmAdapter = MeteoraDlmmAdapter;
731
+ // ---------------------------------------------------------------------------
732
+ // Auto-register
733
+ // ---------------------------------------------------------------------------
734
+ (0, index_1.registerAdapter)(new MeteoraDlmmAdapter());
735
+ //# sourceMappingURL=meteora-dlmm.js.map