123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- // 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
|