Преглед на файлове

Merge pull request #78 from Journeytojah/master

Small improvements
Alexandru Higyedi преди 1 година
родител
ревизия
b13f9864d2
променени са 4 файла, в които са добавени 53 реда и са изтрити 5 реда
  1. 3 1
      .env.copy
  2. 4 1
      .gitignore
  3. 44 2
      buy.ts
  4. 2 1
      constants/constants.ts

+ 3 - 1
.env.copy

@@ -11,4 +11,6 @@ AUTO_SELL=true
 MAX_SELL_RETRIES=5
 AUTO_SELL_DELAY=1000
 LOG_LEVEL=info
-MIN_POOL_SIZE=10
+MIN_POOL_SIZE=10
+MAX_POOL_SIZE=50
+ONE_TOKEN_AT_A_TIME=true

+ 4 - 1
.gitignore

@@ -133,4 +133,7 @@ pnpm-lock.yaml
 .pnp.*
 
 # JetBrains
-.idea
+.idea
+
+# Visual Studio Code 
+*.code-workspace

+ 44 - 2
buy.ts

@@ -48,6 +48,8 @@ import {
   SNIPE_LIST_REFRESH_INTERVAL,
   USE_SNIPE_LIST,
   MIN_POOL_SIZE,
+  MAX_POOL_SIZE,
+  ONE_TOKEN_AT_A_TIME,
 } from './constants';
 
 const solanaConnection = new Connection(RPC_ENDPOINT, {
@@ -70,6 +72,10 @@ let quoteToken: Token;
 let quoteTokenAssociatedAddress: PublicKey;
 let quoteAmount: TokenAmount;
 let quoteMinPoolSizeAmount: TokenAmount;
+let quoteMaxPoolSizeAmount: TokenAmount;
+let processingToken: Boolean = false;
+
+
 
 let snipeList: string[] = [];
 
@@ -86,6 +92,7 @@ async function init(): Promise<void> {
       quoteToken = Token.WSOL;
       quoteAmount = new TokenAmount(Token.WSOL, QUOTE_AMOUNT, false);
       quoteMinPoolSizeAmount = new TokenAmount(quoteToken, MIN_POOL_SIZE, false);
+      quoteMaxPoolSizeAmount = new TokenAmount(quoteToken, MAX_POOL_SIZE, false);
       break;
     }
     case 'USDC': {
@@ -98,6 +105,7 @@ async function init(): Promise<void> {
       );
       quoteAmount = new TokenAmount(quoteToken, QUOTE_AMOUNT, false);
       quoteMinPoolSizeAmount = new TokenAmount(quoteToken, MIN_POOL_SIZE, false);
+      quoteMaxPoolSizeAmount = new TokenAmount(quoteToken, MAX_POOL_SIZE, false);
       break;
     }
     default: {
@@ -110,6 +118,10 @@ async function init(): Promise<void> {
   logger.info(
     `Min pool size: ${quoteMinPoolSizeAmount.isZero() ? 'false' : quoteMinPoolSizeAmount.toFixed()} ${quoteToken.symbol}`,
   );
+  logger.info(
+    `Max pool size: ${quoteMaxPoolSizeAmount.isZero() ? 'false' : quoteMaxPoolSizeAmount.toFixed()} ${quoteToken.symbol}`,
+  );
+  logger.info(`One token at a time: ${ONE_TOKEN_AT_A_TIME}`);
   logger.info(`Buy amount: ${quoteAmount.toFixed()} ${quoteToken.symbol}`);
   logger.info(`Auto sell: ${AUTO_SELL}`);
   logger.info(`Sell delay: ${AUTO_SELL_DELAY === 0 ? 'false' : AUTO_SELL_DELAY}`);
@@ -169,6 +181,24 @@ export async function processRaydiumPool(id: PublicKey, poolState: LiquidityStat
         `Skipping pool, smaller than ${quoteMinPoolSizeAmount.toFixed()} ${quoteToken.symbol}`,
         `Swap quote in amount: ${poolSize.toFixed()}`,
       );
+      logger.info(`-------------------🤖🔧------------------- \n`);
+      return;
+    }
+  }
+
+  if (!quoteMaxPoolSizeAmount.isZero()) {
+    const poolSize = new TokenAmount(quoteToken, poolState.swapQuoteInAmount, true);
+
+    if (poolSize.gt(quoteMaxPoolSizeAmount)) {
+      logger.warn(
+        {
+          mint: poolState.baseMint,
+          pooled: `${poolSize.toFixed()} ${quoteToken.symbol}`,
+        },
+        `Skipping pool, bigger than ${quoteMaxPoolSizeAmount.toFixed()} ${quoteToken.symbol}`,
+        `Swap quote in amount: ${poolSize.toFixed()}`,
+      );
+      logger.info(`-------------------🤖🔧------------------- \n`);
       return;
     }
   }
@@ -265,6 +295,8 @@ async function buy(accountId: PublicKey, accountData: LiquidityStateV4): Promise
       preflightCommitment: COMMITMENT_LEVEL,
     });
     logger.info({ mint: accountData.baseMint, signature }, `Sent buy tx`);
+    processingToken = true;
+
     const confirmation = await solanaConnection.confirmTransaction(
       {
         signature,
@@ -274,6 +306,7 @@ async function buy(accountId: PublicKey, accountData: LiquidityStateV4): Promise
       COMMITMENT_LEVEL,
     );
     if (!confirmation.value.err) {
+      logger.info(`-------------------🟢------------------- `);
       logger.info(
         {
           mint: accountData.baseMint,
@@ -288,6 +321,7 @@ async function buy(accountId: PublicKey, accountData: LiquidityStateV4): Promise
     }
   } catch (e) {
     logger.debug(e);
+    processingToken = false;
     logger.error({ mint: accountData.baseMint }, `Failed to buy token`);
   }
 }
@@ -369,7 +403,7 @@ async function sell(accountId: PublicKey, mint: PublicKey, amount: BigNumberish)
         logger.info({ mint, signature }, `Error confirming sell tx`);
         continue;
       }
-
+      logger.info(`-------------------🔴------------------- `);
       logger.info(
         {
           dex: `https://dexscreener.com/solana/${mint}?maker=${wallet.publicKey}`,
@@ -380,6 +414,7 @@ async function sell(accountId: PublicKey, mint: PublicKey, amount: BigNumberish)
         `Confirmed sell tx`,
       );
       sold = true;
+      processingToken = false;
     } catch (e: any) {
       // wait for a bit before retrying
       await new Promise((resolve) => setTimeout(resolve, 100));
@@ -388,6 +423,7 @@ async function sell(accountId: PublicKey, mint: PublicKey, amount: BigNumberish)
       logger.error({ mint }, `Failed to sell token, retry: ${retries}/${MAX_SELL_RETRIES}`);
     }
   } while (!sold && retries < MAX_SELL_RETRIES);
+  processingToken = false;
 }
 
 function loadSnipeList() {
@@ -408,7 +444,9 @@ function loadSnipeList() {
 }
 
 function shouldBuy(key: string): boolean {
-  return USE_SNIPE_LIST ? snipeList.includes(key) : true;
+  logger.info(`-------------------🤖🔧------------------- `);
+  logger.info(`Processing token: ${processingToken}`)
+  return USE_SNIPE_LIST ? snipeList.includes(key) : ONE_TOKEN_AT_A_TIME ? !processingToken : true
 }
 
 const runListener = async () => {
@@ -505,6 +543,10 @@ const runListener = async () => {
   logger.info(`Listening for raydium changes: ${raydiumSubscriptionId}`);
   logger.info(`Listening for open book changes: ${openBookSubscriptionId}`);
 
+  logger.info('------------------- 🚀 ---------------------');
+  logger.info('Bot is running! Press CTRL + C to stop it.');
+  logger.info('------------------- 🚀 ---------------------');
+
   if (USE_SNIPE_LIST) {
     setInterval(loadSnipeList, SNIPE_LIST_REFRESH_INTERVAL);
   }

+ 2 - 1
constants/constants.ts

@@ -16,4 +16,5 @@ export const PRIVATE_KEY = retrieveEnvVariable('PRIVATE_KEY', logger);
 export const QUOTE_MINT = retrieveEnvVariable('QUOTE_MINT', logger);
 export const QUOTE_AMOUNT = retrieveEnvVariable('QUOTE_AMOUNT', logger);
 export const MIN_POOL_SIZE = retrieveEnvVariable('MIN_POOL_SIZE', logger);
-
+export const MAX_POOL_SIZE = retrieveEnvVariable('MAX_POOL_SIZE', logger);
+export const ONE_TOKEN_AT_A_TIME = retrieveEnvVariable('ONE_TOKEN_AT_A_TIME', logger) === 'true';