mirror of
https://github.com/mortdeus/legacy-cc.git
synced 2026-10-10 12:52:27 +00:00
init
This commit is contained in:
204
2_copy trading bot(node) using gRPC/grpc.js
Normal file
204
2_copy trading bot(node) using gRPC/grpc.js
Normal file
@@ -0,0 +1,204 @@
|
||||
import "dotenv/config";
|
||||
import Client from "@triton-one/yellowstone-grpc";
|
||||
import { CommitmentLevel } from "@triton-one/yellowstone-grpc";
|
||||
import { decodeInstruction } from '@solana/spl-token';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import chalk from "chalk";
|
||||
import { tOutPut } from "./parsingtransaction.js";
|
||||
import { handleNewTokenLaunch } from "./main.js";
|
||||
import dotenv from 'dotenv'
|
||||
dotenv.config();
|
||||
const GRPCTOKEN=process.env.GRPCTOKEN
|
||||
const GRPC_ENDPOINT = process.env.GRPC_ENDPOINT
|
||||
|
||||
// Pre-define constants
|
||||
const SOLANA_TOKEN = "So11111111111111111111111111111111111111112";
|
||||
const RAYDIUM_FEE = "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj"//"7YttLkHDoNj9wyDur5pM1ejNaAvT9X4eqaYcHQqtj2G5";
|
||||
const Raydium_launchpad_authority = "WLHv2UAZm6z4KyaaELi5pjdbJh6RESMva1Rnn8pJVVh"
|
||||
// Create default client
|
||||
const defaultClient = new Client(
|
||||
GRPC_ENDPOINT,
|
||||
GRPCTOKEN
|
||||
);
|
||||
|
||||
export let isNewLaunchRunning = true;
|
||||
export const stopNewLaunch = () => {
|
||||
isNewLaunchRunning = false;
|
||||
console.log(chalk.red("New launch monitoring stopped"));
|
||||
};
|
||||
|
||||
// Default request args
|
||||
const defaultArgs = {
|
||||
accounts: {},
|
||||
slots: {},
|
||||
transactions: {
|
||||
pumpfun: {
|
||||
vote: false,
|
||||
failed: false,
|
||||
signature: undefined,
|
||||
accountInclude: [RAYDIUM_FEE],
|
||||
accountExclude: [],
|
||||
accountRequired: [],
|
||||
},
|
||||
},
|
||||
transactionsStatus: {},
|
||||
entry: {},
|
||||
blocks: {},
|
||||
blocksMeta: {},
|
||||
accountsDataSlice: [],
|
||||
ping: undefined,
|
||||
commitment: CommitmentLevel.PROCESSED,
|
||||
};
|
||||
|
||||
// This function checks for MintTo instructions by comparing with log messages
|
||||
async function checkMintTo(data) {
|
||||
const tx = data.transaction?.transaction;
|
||||
const meta = data.transaction;
|
||||
if (!tx || !meta?.transaction?.meta?.logMessages) return;
|
||||
// Find if MintTo is present in log messages
|
||||
const mintToLog = meta.transaction.meta.logMessages.find((log) =>
|
||||
typeof log === "string" && log.toLowerCase().includes("instruction: mintto")
|
||||
);
|
||||
|
||||
if (mintToLog) {
|
||||
console.log("🩸🩸🩸🩸🩸 MintTo found in logs!");
|
||||
return true
|
||||
} else {
|
||||
// No MintTo found in logs
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function handleStream(client = defaultClient, args = defaultArgs) {
|
||||
const stream = await client.subscribe(args);
|
||||
|
||||
const streamClosed = new Promise((resolve, reject) => {
|
||||
stream.on("error", (error) => {
|
||||
console.error("Stream Error:", error);
|
||||
reject(error);
|
||||
stream.end();
|
||||
});
|
||||
stream.on("end", resolve);
|
||||
stream.on("close", resolve);
|
||||
});
|
||||
|
||||
stream.on("data", async (data) => {
|
||||
// Return early if monitoring is disabled
|
||||
if (!isNewLaunchRunning) {
|
||||
stream.end();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// console.log(chalk.green("start__________new token streaming_________"));
|
||||
if (!data?.transaction?.transaction) {
|
||||
return null;
|
||||
}
|
||||
const mintTo = await checkMintTo(data)
|
||||
if(!mintTo){
|
||||
return null
|
||||
}
|
||||
console.log(`[${new Date().toISOString()}] 🩸🩸🩸🩸🩸 MintTo found in logs!`);
|
||||
|
||||
const preTokenBalances = data?.transaction?.transaction?.meta?.preTokenBalances;
|
||||
const postTokenBalances = data?.transaction?.transaction?.meta?.postTokenBalances;
|
||||
|
||||
if (!preTokenBalances || !postTokenBalances) {
|
||||
console.log("Token balances not found in transaction data");
|
||||
return null;
|
||||
}
|
||||
|
||||
let pre_sol = 0;
|
||||
let post_sol = 0;
|
||||
let pre_token = 0;
|
||||
let post_token = 0;
|
||||
let token_mint = "";
|
||||
let token_owner = "";
|
||||
|
||||
|
||||
for (const balance of postTokenBalances) {
|
||||
if (balance.owner !== Raydium_launchpad_authority) {
|
||||
if (balance.mint !== SOLANA_TOKEN) {
|
||||
post_token = balance.uiTokenAmount.uiAmount || 0;
|
||||
token_mint = balance.mint;
|
||||
token_owner = balance.owner;
|
||||
}
|
||||
} else {
|
||||
post_sol = balance.uiTokenAmount.uiAmount || 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (const balance of preTokenBalances) {
|
||||
if (balance.owner !== Raydium_launchpad_authority) {
|
||||
if (balance.mint !== SOLANA_TOKEN) {
|
||||
pre_token = balance.uiTokenAmount.uiAmount || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const solChanges = post_sol-pre_sol;
|
||||
const tokenChanges = post_token-pre_token;
|
||||
console.log(chalk.bgBlue.bold(`🪙 Token Mint:`), chalk.white(token_mint));
|
||||
console.log(chalk.bgMagenta.bold(`👤 Token Owner:`), chalk.white(token_owner));
|
||||
console.log(chalk.bgYellow.bold(`💸 SOL Balance Change:`), chalk.yellow(`${solChanges > 0 ? "+" : ""}${solChanges}`));
|
||||
console.log(chalk.bgCyan.bold(`🔄 Token Balance Change:`), chalk.cyan(`${tokenChanges > 0 ? "+" : ""}${tokenChanges}`));
|
||||
|
||||
|
||||
if (solChanges> 0.1) {
|
||||
console.log(chalk.bgGreen("Found large SOL transfer:", solChanges));
|
||||
|
||||
// Parse transaction data to get pool information
|
||||
const parsedData = await tOutPut(data);
|
||||
if (parsedData) {
|
||||
console.log(chalk.cyan(`Pool status: Raydium launchpad`));
|
||||
|
||||
// Call the main bot logic to handle the new token launch
|
||||
await handleNewTokenLaunch(token_mint, parsedData.pool_status, parsedData.context);
|
||||
} else {
|
||||
console.log(chalk.yellow("Failed to parse transaction data"));
|
||||
}
|
||||
|
||||
return token_mint;
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error("Error processing transaction data:", error);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await stream.write(args);
|
||||
} catch (error) {
|
||||
console.error("Subscription request failed:", error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
await streamClosed;
|
||||
}
|
||||
|
||||
export async function newlunched_subscribeCommand(client = defaultClient, args = defaultArgs) {
|
||||
// Set monitoring flag to true when starting
|
||||
isNewLaunchRunning = true;
|
||||
console.log(chalk.green("New launch monitoring started"));
|
||||
|
||||
while (isNewLaunchRunning) {
|
||||
try {
|
||||
await handleStream(client, args);
|
||||
} catch (error) {
|
||||
console.error("Stream error, restarting in 1 second...", error);
|
||||
// Only wait and retry if monitoring is still enabled
|
||||
if (isNewLaunchRunning) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log("New launch monitoring stopped");
|
||||
}
|
||||
|
||||
// Export client and args for external use
|
||||
export { defaultClient, defaultArgs };
|
||||
// Remove the auto-execution to prevent conflicts
|
||||
// newlunched_subscribeCommand()
|
||||
Reference in New Issue
Block a user