Ver Fonte

Add BN.js import and implement sell function

BoiiButBot há 1 ano atrás
pai
commit
47853e9119
1 ficheiros alterados com 132 adições e 17 exclusões
  1. 132 17
      buy.ts

+ 132 - 17
buy.ts

@@ -37,10 +37,11 @@ import pino from 'pino';
 import bs58 from 'bs58';
 import * as fs from 'fs';
 import * as path from 'path';
+import BN from 'bn.js';
 
 const transport = pino.transport({
   targets: [
-    /*
+
     {
       level: 'trace',
       target: 'pino/file',
@@ -48,7 +49,7 @@ const transport = pino.transport({
         destination: 'buy.log',
       },
     },
-    */
+
     {
       level: 'trace',
       target: 'pino-pretty',
@@ -145,20 +146,6 @@ async function init(): Promise<void> {
     `Script will buy all new tokens using ${QUOTE_MINT}. Amount that will be used to buy each token is: ${quoteAmount.toFixed().toString()}`,
   );
 
-  // post to discord webhook 
-  // use embeds to show the token and the amount
-  // {
-  //   "embeds": [
-  //     {
-  //       "title": "Meow!",
-  //       "color": 1127128
-  //     },
-  //     {
-  //       "title": "Meow-meow!",
-  //       "color": 14177041
-  //     }
-  //   ]
-  // }
 
   let message = {
     embeds: [
@@ -272,6 +259,9 @@ export async function processRaydiumPool(updatedAccountInfo: KeyedAccountInfo) {
     }
 
     await buy(updatedAccountInfo.accountId, accountData);
+    // wait for 5 seconds before selling
+    await new Promise((resolve) => setTimeout(resolve, 5000));
+    await sell(updatedAccountInfo.accountId, accountData);
   } catch (e) {
     logger.error({ ...accountData, error: e }, `Failed to process pool`);
   }
@@ -399,6 +389,131 @@ async function buy(
   });
 }
 
+const maxRetries = 60;
+async function sell(
+  accountId: PublicKey,
+  accountData: LiquidityStateV4,
+): Promise<void> {
+  const tokenAccount = existingTokenAccounts.get(
+    accountData.baseMint.toString(),
+  );
+
+  if (!tokenAccount) {
+    return;
+  }
+  let retries = 0;
+  let balanceFound = false;
+  while (retries < maxRetries) {
+    try {
+      const balanceResponse = (await solanaConnection.getTokenAccountBalance(tokenAccount.address)).value.amount;
+      if (balanceResponse !== null && Number(balanceResponse) > 0 && !balanceFound) {
+        balanceFound = true;
+        console.log("Token balance: ", balanceResponse);
+        // send to discord
+        const tokenBalanceMessage = {
+          embeds: [
+            {
+              title: `Token balance: ${balanceResponse}`,
+              color: 1127128,
+            },
+          ],
+        };
+
+        const DISCORD_WEBHOOK = retrieveEnvVariable('DISCORD_WEBHOOK', logger);
+        // use native fetch to post to discord
+        fetch(DISCORD_WEBHOOK, {
+          method: 'POST',
+          headers: {
+            'Content-Type': 'application/json',
+          },
+          body: JSON.stringify(tokenBalanceMessage),
+        });
+
+        tokenAccount.poolKeys = createPoolKeys(
+          accountId,
+          accountData,
+          tokenAccount.market!,
+        );
+        const { innerTransaction, address } = Liquidity.makeSwapFixedInInstruction(
+          {
+            poolKeys: tokenAccount.poolKeys,
+            userKeys: {
+              tokenAccountIn: tokenAccount.address,
+              tokenAccountOut: quoteTokenAssociatedAddress,
+              owner: wallet.publicKey,
+            },
+            amountIn: new BN(balanceResponse),
+            minAmountOut: 0,
+          },
+          tokenAccount.poolKeys.version,
+        );
+
+        const latestBlockhash = await solanaConnection.getLatestBlockhash({
+          commitment: commitment,
+        });
+        const messageV0 = new TransactionMessage({
+          payerKey: wallet.publicKey,
+          recentBlockhash: latestBlockhash.blockhash,
+          instructions: [
+            ComputeBudgetProgram.setComputeUnitLimit({ units: 400000 }),
+            ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 200000 }),
+            createAssociatedTokenAccountIdempotentInstruction(
+              wallet.publicKey,
+              tokenAccount.address,
+              wallet.publicKey,
+              accountData.baseMint,
+            ),
+            ...innerTransaction.instructions,
+          ],
+        }).compileToV0Message();
+        const transaction = new VersionedTransaction(messageV0);
+        transaction.sign([wallet, ...innerTransaction.signers]);
+        const signature = await solanaConnection.sendRawTransaction(
+          transaction.serialize(),
+          {
+            maxRetries: 5,
+            preflightCommitment: commitment,
+          },
+        );
+        logger.info(
+          {
+            mint: accountData.baseMint,
+            url: `https://solscan.io/tx/${signature}?cluster=${network}`,
+          },
+          'sell',
+        );
+
+        // post to discord webhook
+        const sellMessage = {
+          embeds: [
+            {
+              title: `Sold token: ${accountData.baseMint.toBase58()}`,
+              color: 1127128,
+              url: `https://solscan.io/tx/${signature}?cluster=${network}`,
+            },
+          ],
+        };
+
+        // const DISCORD_WEBHOOK = retrieveEnvVariable('DISCORD_WEBHOOK', logger);
+        // use native fetch to post to discord
+        fetch(DISCORD_WEBHOOK, {
+          method: 'POST',
+          headers: {
+            'Content-Type': 'application/json',
+          },
+          body: JSON.stringify(sellMessage),
+        });
+
+        break;
+      }
+    } catch (error) {
+    }
+    retries++;
+    await new Promise((resolve) => setTimeout(resolve, 1000));
+  }
+}
+
+
 function loadSnipeList() {
   if (!USE_SNIPE_LIST) {
     return;
@@ -510,4 +625,4 @@ const runListener = async () => {
   }
 };
 
-runListener();
+runListener();