mirror of
https://github.com/fdundjer/solana-sniper-bot.git
synced 2025-11-10 04:22:05 +10:00
Clean up for merge
This commit is contained in:
115
buy.ts
115
buy.ts
@ -210,13 +210,8 @@ export async function processRaydiumPool(
|
||||
const timeout = parseInt(SELL_DELAY, 10);
|
||||
await new Promise((resolve) => setTimeout(resolve, timeout));
|
||||
|
||||
// log poolstate info
|
||||
// logger.info({ poolState }, `Pool state info`);
|
||||
|
||||
await sell(id, poolState);
|
||||
}
|
||||
|
||||
// await sell(id, poolState);
|
||||
} catch (e) {
|
||||
logger.error({ ...poolState, error: e }, `Failed to process pool`);
|
||||
}
|
||||
@ -311,27 +306,6 @@ async function buy(
|
||||
},
|
||||
'Buy',
|
||||
);
|
||||
|
||||
// post to discord webhook
|
||||
const message = {
|
||||
embeds: [
|
||||
{
|
||||
title: `Bought 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(message),
|
||||
});
|
||||
}
|
||||
|
||||
const maxRetries = 60;
|
||||
@ -353,26 +327,6 @@ async function sell(
|
||||
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,
|
||||
@ -427,28 +381,6 @@ async function sell(
|
||||
},
|
||||
'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) {
|
||||
@ -553,51 +485,4 @@ const runListener = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// runListener();
|
||||
|
||||
// make sure we can send a message on discord if there is an error or the script exits
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
logger.error(reason, 'Unhandled Rejection at:', promise);
|
||||
const message = {
|
||||
embeds: [
|
||||
{
|
||||
title: `Unhandled Rejection: ${reason}`,
|
||||
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(message),
|
||||
});
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
logger.error(err, 'Uncaught Exception thrown');
|
||||
const message = {
|
||||
embeds: [
|
||||
{
|
||||
title: `Uncaught Exception: ${err}`,
|
||||
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(message),
|
||||
});
|
||||
});
|
||||
|
||||
runListener();
|
||||
@ -1,164 +0,0 @@
|
||||
// sellWorker.ts
|
||||
import { parentPort, workerData } from 'worker_threads';
|
||||
import { PublicKey, TokenAmount, Connection, Commitment } from '@solana/web3.js';
|
||||
import { LIQUIDITY_STATE_LAYOUT_V4, Liquidity, SPL_ACCOUNT_LAYOUT, TOKEN_PROGRAM_ID, TokenAccount } from '@raydium-io/raydium-sdk';
|
||||
import { retrieveEnvVariable } from '../utils';
|
||||
import BN from 'bn.js';
|
||||
import pino from 'pino';
|
||||
|
||||
const transport = pino.transport({
|
||||
targets: [
|
||||
{
|
||||
level: 'trace',
|
||||
target: 'pino-pretty',
|
||||
options: {},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const logger = pino(
|
||||
{
|
||||
redact: ['poolKeys'],
|
||||
serializers: {
|
||||
error: pino.stdSerializers.err,
|
||||
},
|
||||
base: undefined,
|
||||
},
|
||||
transport,
|
||||
);
|
||||
|
||||
async function getTokenAccounts(connection: Connection, owner: PublicKey) {
|
||||
const tokenResp = await connection.getTokenAccountsByOwner(owner, {
|
||||
programId: TOKEN_PROGRAM_ID
|
||||
});
|
||||
|
||||
const accounts: TokenAccount[] = [];
|
||||
for (const { pubkey, account } of tokenResp.value) {
|
||||
accounts.push({
|
||||
pubkey,
|
||||
accountInfo: SPL_ACCOUNT_LAYOUT.decode(account.data),
|
||||
programId: new PublicKey(account.owner.toBase58())
|
||||
});
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
|
||||
const SOL_SDC_POOL_ID = "58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2";
|
||||
const OPENBOOK_PROGRAM_ID = new PublicKey(
|
||||
"srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX"
|
||||
);
|
||||
|
||||
async function parsePoolInfo() {
|
||||
const network = 'mainnet-beta';
|
||||
const RPC_ENDPOINT = retrieveEnvVariable('RPC_ENDPOINT', logger);
|
||||
const RPC_WEBSOCKET_ENDPOINT = retrieveEnvVariable(
|
||||
'RPC_WEBSOCKET_ENDPOINT',
|
||||
logger,
|
||||
);
|
||||
|
||||
const connection = new Connection(RPC_ENDPOINT, {
|
||||
wsEndpoint: RPC_WEBSOCKET_ENDPOINT,
|
||||
});
|
||||
const owner = new PublicKey("VnxDzsZ7chE88e9rB6UKztCt2HUwrkgCTx8WieWf5mM");
|
||||
|
||||
const tokenAccounts = await getTokenAccounts(connection, owner);
|
||||
|
||||
// example to get pool info
|
||||
const info = await connection.getAccountInfo(new PublicKey(SOL_SDC_POOL_ID));
|
||||
if (!info) {
|
||||
throw new Error("Pool not found");
|
||||
}
|
||||
|
||||
const poolState = LIQUIDITY_STATE_LAYOUT_V4.decode(info.data);
|
||||
|
||||
const baseDecimal = 10 ** poolState.baseDecimal.toNumber();
|
||||
const quoteDecimal = 10 ** poolState.quoteDecimal.toNumber();
|
||||
|
||||
const baseTokenAmount = await connection.getTokenAccountBalance(
|
||||
poolState.baseVault
|
||||
)
|
||||
|
||||
const quoteTokenAmount = await connection.getTokenAccountBalance(
|
||||
poolState.quoteVault
|
||||
)
|
||||
|
||||
const basePnl = poolState.baseNeedTakePnl.toNumber() / baseDecimal;
|
||||
const quotePnl = poolState.quoteNeedTakePnl.toNumber() / quoteDecimal;
|
||||
|
||||
const base = (baseTokenAmount.value?.uiAmount || 0) - basePnl;
|
||||
const quote = (quoteTokenAmount.value?.uiAmount || 0) - quotePnl;
|
||||
|
||||
const denominator = new BN(10).pow(poolState.baseDecimal);
|
||||
|
||||
const addedLpAccount = tokenAccounts.find((a) => a.accountInfo.mint.equals(poolState.lpMint));
|
||||
|
||||
const message = `
|
||||
SOL - USDC Pool Info:
|
||||
|
||||
Pool total base: ${base},
|
||||
Pool total quote: ${quote},
|
||||
|
||||
Base vault balance: ${baseTokenAmount.value.uiAmount},
|
||||
Quote vault balance: ${quoteTokenAmount.value.uiAmount},
|
||||
|
||||
Base token decimals: ${poolState.baseDecimal.toNumber()},
|
||||
Quote token decimals: ${poolState.quoteDecimal.toNumber()},
|
||||
Total LP: ${poolState.lpReserve.div(denominator).toString()},
|
||||
|
||||
Added LP amount: ${(addedLpAccount?.accountInfo.amount.toNumber() || 0) / baseDecimal},
|
||||
`;
|
||||
|
||||
logger.info(message);
|
||||
|
||||
// send message to discord (embed)
|
||||
// post to discord webhook
|
||||
let embed = {
|
||||
embeds: [
|
||||
{
|
||||
title: "SOL - USDC Pool Info",
|
||||
description: `
|
||||
Pool total base: **${base}**,
|
||||
Pool total quote: **${quote}**,
|
||||
|
||||
Base vault balance: **${baseTokenAmount.value.uiAmount}**,
|
||||
Quote vault balance: **${quoteTokenAmount.value.uiAmount}**,
|
||||
|
||||
Base token decimals:** ${poolState.baseDecimal.toNumber()}**,
|
||||
Quote token decimals:** ${poolState.quoteDecimal.toNumber()}**,
|
||||
|
||||
Total LP: **${poolState.lpReserve.div(denominator).toString()}**,
|
||||
Added LP amount: **${(addedLpAccount?.accountInfo.amount.toNumber() || 0) / baseDecimal}**
|
||||
|
||||
Happy trading! 🚀
|
||||
`
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
};
|
||||
|
||||
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(embed),
|
||||
});
|
||||
|
||||
logger.info("Message sent to Discord");
|
||||
|
||||
}
|
||||
|
||||
// Function to periodically check the pool
|
||||
async function checkPoolPeriodically(interval: number) {
|
||||
while (true) {
|
||||
await parsePoolInfo();
|
||||
await new Promise(resolve => setTimeout(resolve, interval));
|
||||
}
|
||||
}
|
||||
|
||||
// Check pool periodically with a specified interval
|
||||
checkPoolPeriodically(60000); // 1 minute
|
||||
Reference in New Issue
Block a user