index.ts 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import { MarketCache, PoolCache } from './cache';
  2. import { Listeners } from './listeners';
  3. import { Connection, KeyedAccountInfo, Keypair } from '@solana/web3.js';
  4. import { LIQUIDITY_STATE_LAYOUT_V4, MARKET_STATE_LAYOUT_V3, Token, TokenAmount } from '@raydium-io/raydium-sdk';
  5. import { AccountLayout, getAssociatedTokenAddressSync } from '@solana/spl-token';
  6. import { Bot, BotConfig } from './bot';
  7. import { DefaultTransactionExecutor, TransactionExecutor } from './transactions';
  8. import {
  9. getToken,
  10. getWallet,
  11. logger,
  12. COMMITMENT_LEVEL,
  13. RPC_ENDPOINT,
  14. RPC_WEBSOCKET_ENDPOINT,
  15. PRE_LOAD_EXISTING_MARKETS,
  16. LOG_LEVEL,
  17. CHECK_IF_MUTABLE,
  18. CHECK_IF_MINT_IS_RENOUNCED,
  19. CHECK_IF_FREEZABLE,
  20. CHECK_IF_BURNED,
  21. QUOTE_MINT,
  22. MAX_POOL_SIZE,
  23. MIN_POOL_SIZE,
  24. QUOTE_AMOUNT,
  25. PRIVATE_KEY,
  26. USE_SNIPE_LIST,
  27. ONE_TOKEN_AT_A_TIME,
  28. AUTO_SELL_DELAY,
  29. MAX_SELL_RETRIES,
  30. AUTO_SELL,
  31. MAX_BUY_RETRIES,
  32. AUTO_BUY_DELAY,
  33. COMPUTE_UNIT_LIMIT,
  34. COMPUTE_UNIT_PRICE,
  35. CACHE_NEW_MARKETS,
  36. TAKE_PROFIT,
  37. STOP_LOSS,
  38. BUY_SLIPPAGE,
  39. SELL_SLIPPAGE,
  40. PRICE_CHECK_DURATION,
  41. PRICE_CHECK_INTERVAL,
  42. SNIPE_LIST_REFRESH_INTERVAL,
  43. TRANSACTION_EXECUTOR,
  44. CUSTOM_FEE,
  45. FILTER_CHECK_INTERVAL,
  46. FILTER_CHECK_DURATION,
  47. CONSECUTIVE_FILTER_MATCHES,
  48. } from './helpers';
  49. import { version } from './package.json';
  50. import { WarpTransactionExecutor } from './transactions/warp-transaction-executor';
  51. import { JitoTransactionExecutor } from './transactions/jito-rpc-transaction-executor';
  52. const connection = new Connection(RPC_ENDPOINT, {
  53. wsEndpoint: RPC_WEBSOCKET_ENDPOINT,
  54. commitment: COMMITMENT_LEVEL,
  55. });
  56. function printDetails(wallet: Keypair, quoteToken: Token, bot: Bot) {
  57. logger.info(`
  58. .. :-===++++-
  59. .-==+++++++- =+++++++++-
  60. ..:::--===+=.=: .+++++++++++:=+++++++++:
  61. .==+++++++++++++++=:+++: .+++++++++++.=++++++++-.
  62. .-+++++++++++++++=:=++++- .+++++++++=:.=+++++-::-.
  63. -:+++++++++++++=:+++++++- .++++++++-:- =+++++=-:
  64. -:++++++=++++=:++++=++++= .++++++++++- =+++++:
  65. -:++++-:=++=:++++=:-+++++:+++++====--:::::::.
  66. ::=+-:::==:=+++=::-:--::::::::::---------::.
  67. ::-: .::::::::. --------:::..
  68. :- .:.-:::.
  69. WARP DRIVE ACTIVATED 🚀🐟
  70. Made with ❤️ by humans.
  71. Version: ${version}
  72. `);
  73. const botConfig = bot.config;
  74. logger.info('------- CONFIGURATION START -------');
  75. logger.info(`Wallet: ${wallet.publicKey.toString()}`);
  76. logger.info('- Bot -');
  77. logger.info(
  78. `Using ${TRANSACTION_EXECUTOR} executer: ${bot.isWarp || bot.isJito || (TRANSACTION_EXECUTOR === 'default' ? true : false)}`,
  79. );
  80. if (bot.isWarp || bot.isJito) {
  81. logger.info(`${TRANSACTION_EXECUTOR} fee: ${CUSTOM_FEE}`);
  82. } else {
  83. logger.info(`Compute Unit limit: ${botConfig.unitLimit}`);
  84. logger.info(`Compute Unit price (micro lamports): ${botConfig.unitPrice}`);
  85. }
  86. logger.info(`Single token at the time: ${botConfig.oneTokenAtATime}`);
  87. logger.info(`Pre load existing markets: ${PRE_LOAD_EXISTING_MARKETS}`);
  88. logger.info(`Cache new markets: ${CACHE_NEW_MARKETS}`);
  89. logger.info(`Log level: ${LOG_LEVEL}`);
  90. logger.info('- Buy -');
  91. logger.info(`Buy amount: ${botConfig.quoteAmount.toFixed()} ${botConfig.quoteToken.name}`);
  92. logger.info(`Auto buy delay: ${botConfig.autoBuyDelay} ms`);
  93. logger.info(`Max buy retries: ${botConfig.maxBuyRetries}`);
  94. logger.info(`Buy amount (${quoteToken.symbol}): ${botConfig.quoteAmount.toFixed()}`);
  95. logger.info(`Buy slippage: ${botConfig.buySlippage}%`);
  96. logger.info('- Sell -');
  97. logger.info(`Auto sell: ${AUTO_SELL}`);
  98. logger.info(`Auto sell delay: ${botConfig.autoSellDelay} ms`);
  99. logger.info(`Max sell retries: ${botConfig.maxSellRetries}`);
  100. logger.info(`Sell slippage: ${botConfig.sellSlippage}%`);
  101. logger.info(`Price check interval: ${botConfig.priceCheckInterval} ms`);
  102. logger.info(`Price check duration: ${botConfig.priceCheckDuration} ms`);
  103. logger.info(`Take profit: ${botConfig.takeProfit}%`);
  104. logger.info(`Stop loss: ${botConfig.stopLoss}%`);
  105. logger.info('- Snipe list -');
  106. logger.info(`Snipe list: ${botConfig.useSnipeList}`);
  107. logger.info(`Snipe list refresh interval: ${SNIPE_LIST_REFRESH_INTERVAL} ms`);
  108. if (botConfig.useSnipeList) {
  109. logger.info('- Filters -');
  110. logger.info(`Filters are disabled when snipe list is on`);
  111. } else {
  112. logger.info('- Filters -');
  113. logger.info(`Filter check interval: ${botConfig.filterCheckInterval} ms`);
  114. logger.info(`Filter check duration: ${botConfig.filterCheckDuration} ms`);
  115. logger.info(`Consecutive filter matches: ${botConfig.consecutiveMatchCount}`);
  116. logger.info(`Check renounced: ${botConfig.checkRenounced}`);
  117. logger.info(`Check freezable: ${botConfig.checkFreezable}`);
  118. logger.info(`Check burned: ${botConfig.checkBurned}`);
  119. logger.info(`Min pool size: ${botConfig.minPoolSize.toFixed()}`);
  120. logger.info(`Max pool size: ${botConfig.maxPoolSize.toFixed()}`);
  121. }
  122. logger.info('------- CONFIGURATION END -------');
  123. logger.info('Bot is running! Press CTRL + C to stop it.');
  124. }
  125. const runListener = async () => {
  126. logger.level = LOG_LEVEL;
  127. logger.info('Bot is starting...');
  128. const marketCache = new MarketCache(connection);
  129. const poolCache = new PoolCache();
  130. let txExecutor: TransactionExecutor;
  131. switch (TRANSACTION_EXECUTOR) {
  132. case 'warp': {
  133. txExecutor = new WarpTransactionExecutor(CUSTOM_FEE);
  134. break;
  135. }
  136. case 'jito': {
  137. txExecutor = new JitoTransactionExecutor(CUSTOM_FEE, connection);
  138. break;
  139. }
  140. default: {
  141. txExecutor = new DefaultTransactionExecutor(connection);
  142. break;
  143. }
  144. }
  145. const wallet = getWallet(PRIVATE_KEY.trim());
  146. const quoteToken = getToken(QUOTE_MINT);
  147. const botConfig = <BotConfig>{
  148. wallet,
  149. quoteAta: getAssociatedTokenAddressSync(quoteToken.mint, wallet.publicKey),
  150. checkRenounced: CHECK_IF_MINT_IS_RENOUNCED,
  151. checkFreezable: CHECK_IF_FREEZABLE,
  152. checkBurned: CHECK_IF_BURNED,
  153. minPoolSize: new TokenAmount(quoteToken, MIN_POOL_SIZE, false),
  154. maxPoolSize: new TokenAmount(quoteToken, MAX_POOL_SIZE, false),
  155. quoteToken,
  156. quoteAmount: new TokenAmount(quoteToken, QUOTE_AMOUNT, false),
  157. oneTokenAtATime: ONE_TOKEN_AT_A_TIME,
  158. useSnipeList: USE_SNIPE_LIST,
  159. autoSell: AUTO_SELL,
  160. autoSellDelay: AUTO_SELL_DELAY,
  161. maxSellRetries: MAX_SELL_RETRIES,
  162. autoBuyDelay: AUTO_BUY_DELAY,
  163. maxBuyRetries: MAX_BUY_RETRIES,
  164. unitLimit: COMPUTE_UNIT_LIMIT,
  165. unitPrice: COMPUTE_UNIT_PRICE,
  166. takeProfit: TAKE_PROFIT,
  167. stopLoss: STOP_LOSS,
  168. buySlippage: BUY_SLIPPAGE,
  169. sellSlippage: SELL_SLIPPAGE,
  170. priceCheckInterval: PRICE_CHECK_INTERVAL,
  171. priceCheckDuration: PRICE_CHECK_DURATION,
  172. filterCheckInterval: FILTER_CHECK_INTERVAL,
  173. filterCheckDuration: FILTER_CHECK_DURATION,
  174. consecutiveMatchCount: CONSECUTIVE_FILTER_MATCHES,
  175. };
  176. const bot = new Bot(connection, marketCache, poolCache, txExecutor, botConfig);
  177. const valid = await bot.validate();
  178. if (!valid) {
  179. logger.info('Bot is exiting...');
  180. process.exit(1);
  181. }
  182. if (PRE_LOAD_EXISTING_MARKETS) {
  183. await marketCache.init({ quoteToken });
  184. }
  185. const runTimestamp = Math.floor(new Date().getTime() / 1000);
  186. const listeners = new Listeners(connection);
  187. await listeners.start({
  188. walletPublicKey: wallet.publicKey,
  189. quoteToken,
  190. autoSell: AUTO_SELL,
  191. cacheNewMarkets: CACHE_NEW_MARKETS,
  192. });
  193. listeners.on('market', (updatedAccountInfo: KeyedAccountInfo) => {
  194. const marketState = MARKET_STATE_LAYOUT_V3.decode(updatedAccountInfo.accountInfo.data);
  195. marketCache.save(updatedAccountInfo.accountId.toString(), marketState);
  196. });
  197. listeners.on('pool', async (updatedAccountInfo: KeyedAccountInfo) => {
  198. const poolState = LIQUIDITY_STATE_LAYOUT_V4.decode(updatedAccountInfo.accountInfo.data);
  199. const poolOpenTime = parseInt(poolState.poolOpenTime.toString());
  200. const exists = await poolCache.get(poolState.baseMint.toString());
  201. if (!exists && poolOpenTime > runTimestamp) {
  202. poolCache.save(updatedAccountInfo.accountId.toString(), poolState);
  203. await bot.buy(updatedAccountInfo.accountId, poolState);
  204. }
  205. });
  206. listeners.on('wallet', async (updatedAccountInfo: KeyedAccountInfo) => {
  207. const accountData = AccountLayout.decode(updatedAccountInfo.accountInfo.data);
  208. if (accountData.mint.equals(quoteToken.mint)) {
  209. return;
  210. }
  211. await bot.sell(updatedAccountInfo.accountId, accountData);
  212. });
  213. printDetails(wallet, quoteToken, bot);
  214. };
  215. runListener();