mirror of
https://github.com/mortdeus/legacy-cc.git
synced 2026-10-08 11:52:22 +00:00
267 lines
11 KiB
JavaScript
267 lines
11 KiB
JavaScript
import bs58 from "bs58";
|
|
|
|
// New function to handle parsed transaction data from getDataFromTx
|
|
export async function parseTransactionFromData(parsedTx) {
|
|
if (!parsedTx) return null;
|
|
|
|
const meta = parsedTx.meta;
|
|
// const logs = meta?.logMessages;
|
|
// const logFilter = logs?.some((instruction) => instruction.match(/MintTo/i));
|
|
|
|
const innerInstructions = meta.innerInstructions;
|
|
const flattenedInnerInstructions = (await innerInstructions?.flatMap((ix) => ix.instructions || [])) || [];
|
|
const allInstructions = [...flattenedInnerInstructions];
|
|
// console.log(allInstructions)
|
|
if (allInstructions.length === 0) return null;
|
|
|
|
// Filter out instructions that don't have data property
|
|
const validInstructions = allInstructions.filter((instruction) => instruction && instruction.data);
|
|
|
|
if (validInstructions.length === 0) return null;
|
|
|
|
const largestDataInstruction = await validInstructions.reduce((largest, current) => {
|
|
if (!current || !current.data || !largest || !largest.data) {
|
|
return largest || current;
|
|
}
|
|
return current.data.length > largest.data.length ? current : largest;
|
|
});
|
|
// console.log(largestDataInstruction)
|
|
|
|
if (!largestDataInstruction || !largestDataInstruction.data) {
|
|
return null;
|
|
}
|
|
// console.log(largestDataInstruction.data)
|
|
const rawData = bs58.decode(largestDataInstruction.data);
|
|
const buffer = Buffer.from(rawData);
|
|
// console.log(buffer)
|
|
|
|
const parsedInstructionData = parseTransactionData(buffer);
|
|
// console.log(parsedInstructionData)
|
|
|
|
if (!parsedInstructionData) return null;
|
|
|
|
return {
|
|
solChanges: parseFloat(parsedInstructionData.solchange),
|
|
tokenChanges: parseFloat(parsedInstructionData.tokenchange),
|
|
isBuy: parsedInstructionData.isBuy,
|
|
user: parsedInstructionData.user,
|
|
mint: parsedInstructionData.mint,
|
|
pool: parsedInstructionData.pool,
|
|
liquidity: parsedInstructionData.liquidity,
|
|
coinCreator: parsedInstructionData.coinCreator,
|
|
context: parsedInstructionData.context,
|
|
};
|
|
}
|
|
|
|
export async function tOutPut(data) {
|
|
// Check if this is parsed transaction data from getDataFromTx
|
|
if (data && data.meta && data.transaction) {
|
|
// This is parsed transaction data from getDataFromTx
|
|
return await parseTransactionFromData(data);
|
|
}
|
|
|
|
// Original format handling
|
|
const dataTx = data?.transaction?.transaction;
|
|
if (!dataTx) return;
|
|
const signature = bs58.encode(Buffer.from(dataTx?.transaction.signatures?.[0]));
|
|
// console.log("signature:::", signature);
|
|
|
|
const meta = dataTx?.meta;
|
|
const logs = meta?.logMessages;
|
|
const logFilter = logs?.some((instruction) => instruction.match(instruction.match(/MintTo/i)));
|
|
|
|
const innerInstructions = meta.innerInstructions;
|
|
// console.log(innerInstructions)
|
|
const flattenedInnerInstructions = (await innerInstructions?.flatMap((ix) => ix.instructions || [])) || [];
|
|
// console.log(flattenedInnerInstructions)
|
|
const allInstructions = [...flattenedInnerInstructions];
|
|
// console.log("allInstructions",allInstructions)
|
|
|
|
if (allInstructions.length === 0) return;
|
|
|
|
// Filter out instructions that don't have data property
|
|
const validInstructions = allInstructions.filter((instruction) => instruction && instruction.data);
|
|
|
|
if (validInstructions.length === 0) return null;
|
|
|
|
const largestDataInstruction = await validInstructions.reduce((largest, current) => {
|
|
if (!current || !current.data || !largest || !largest.data) {
|
|
return largest || current;
|
|
}
|
|
return current.data.length > largest.data.length ? current : largest;
|
|
});
|
|
|
|
if (!largestDataInstruction || !largestDataInstruction.data) {
|
|
return null;
|
|
}
|
|
|
|
// console.log("🎈🎈🎈largestDataInstruction:::", largestDataInstruction.data);
|
|
const parsedInstructionData = parseTransactionData(largestDataInstruction.data);
|
|
// console.log("🎈",JSON.stringify(parsedInstructionData,null,2))
|
|
|
|
if (!parsedInstructionData) return null;
|
|
|
|
// console.log(parsedInstructionData);
|
|
// console.log("Mint>>>>>>>>", parsedInstructionData.mint);
|
|
return {
|
|
solChanges: parseFloat(parsedInstructionData.solchange),
|
|
tokenChanges: parseFloat(parsedInstructionData.tokenchange),
|
|
isBuy: parsedInstructionData.isBuy,
|
|
user: parsedInstructionData.user,
|
|
mint: parsedInstructionData.mint,
|
|
pool: parsedInstructionData.pool,
|
|
liquidity: parsedInstructionData.liquidity / 10 ** 9,
|
|
coinCreator: parsedInstructionData.coinCreator,
|
|
pool_status: parsedInstructionData.pool_status,
|
|
signature: signature,
|
|
context: parsedInstructionData.context,
|
|
};
|
|
// console.log("Signature>>>>>>>>", signature);
|
|
}
|
|
|
|
export function parseTransactionData(buffer) {
|
|
try {
|
|
function parsePublicKey(offset) {
|
|
return bs58.encode(buffer.slice(offset, offset + 32)); // Convert 32 bytes to Base58
|
|
}
|
|
|
|
function parseBigInt(offset) {
|
|
return buffer.readBigUInt64LE(offset).toString(); // Read 8 bytes as Little-Endian
|
|
}
|
|
|
|
if (buffer.length == 368) {
|
|
const parsedData_PumpSwap = {
|
|
mint: null,
|
|
timestamp: parseBigInt(16), // 8 bytes (Timestamp)
|
|
baseAmountIn: parseBigInt(24), // 8 bytes (Base amount in)
|
|
minQuoteAmountOut: parseBigInt(32), // 8 bytes (Minimum quote amount out)
|
|
userBaseTokenReserves: parseBigInt(40), // 8 bytes (User base token reserves)
|
|
userQuoteTokenReserves: parseBigInt(48), // 8 bytes (User quote token reserves)
|
|
poolBaseTokenReserves: parseBigInt(56), // 8 bytes (Pool base token reserves)
|
|
poolQuoteTokenReserves: parseBigInt(64), // 8 bytes (Pool quote token reserves)
|
|
quoteAmountOut: parseBigInt(72), // 8 bytes (Quote amount out)
|
|
lpFeeBasisPoints: parseBigInt(80), // 8 bytes (LP fee basis points)
|
|
lpFee: parseBigInt(88), // 8 bytes (LP fee)
|
|
protocolFeeBasisPoints: parseBigInt(96), // 8 bytes (Protocol fee basis points)
|
|
protocolFee: parseBigInt(104), // 8 bytes (Protocol fee)
|
|
quoteAmountOutWithoutLpFee: parseBigInt(112), // 8 bytes (Quote amount out without LP fee)
|
|
userQuoteAmountOut: parseBigInt(120), // 8 bytes (User quote amount out)
|
|
pool: parsePublicKey(128), // 32 bytes (Pool address)
|
|
user: parsePublicKey(160), // 32 bytes (User address)
|
|
userBaseTokenAccount: parsePublicKey(192), // 32 bytes (User base token account)
|
|
userQuoteTokenAccount: parsePublicKey(224), // 32 bytes (User quote token account)
|
|
protocolFeeRecipient: parsePublicKey(256), // 32 bytes (Protocol fee recipient)
|
|
protocolFeeRecipientTokenAccount: parsePublicKey(288), // 32 bytes (Protocol fee recipient token account)
|
|
coinCreator: parsePublicKey(320), // 32 bytes (Coin creator address)
|
|
coinCreatorFeeBasisPoints: parseBigInt(328), // 8 bytes (Coin creator fee basis points)
|
|
coinCreatorFee: parseBigInt(336), // 8 bytes (Coin creator fee)
|
|
};
|
|
// console.log(parsedData_PumpSwap);
|
|
let isBuy = parsedData_PumpSwap.quoteAmountOutWithoutLpFee > parsedData_PumpSwap.quoteAmountOut;
|
|
return {
|
|
solchange: parsedData_PumpSwap.userQuoteAmountOut,
|
|
tokenchange: parsedData_PumpSwap.baseAmountIn,
|
|
isBuy,
|
|
user: parsedData_PumpSwap.user,
|
|
mint: parsedData_PumpSwap.mint,
|
|
pool: parsedData_PumpSwap.pool,
|
|
liquidity: parsedData_PumpSwap.poolQuoteTokenReserves * 2,
|
|
coinCreator: parsedData_PumpSwap.coinCreator,
|
|
pool_status: "pumpswap",
|
|
context: parsedData_PumpSwap,
|
|
};
|
|
} else if (buffer.length == 233) {
|
|
const parsedData_PumpFun = {
|
|
mint: parsePublicKey(16), // 32 bytes (Mint address)
|
|
solAmount: parseBigInt(48), // 8 bytes (Amount in SOL)
|
|
tokenAmount: parseBigInt(56), // 8 bytes (Token amount)
|
|
isBuy: buffer[64] === 1, // 1 byte (Boolean: 0 = Sell, 1 = Buy)
|
|
user: parsePublicKey(65), // 32 bytes (User address)
|
|
timestamp: parseBigInt(97), // 8 bytes (Timestamp - Unix format)
|
|
virtualSolReserves: parseBigInt(105), // 8 bytes (Virtual reserves)
|
|
virtualTokenReserves: parseBigInt(113), // 8 bytes (Virtual token reserves)
|
|
realSolReserves: parseBigInt(121), // 8 bytes (Real reserves)
|
|
realTokenReserves: parseBigInt(129), // 8 bytes (Real token reserves)
|
|
feeRecipient: parsePublicKey(137), // 32 bytes (Fee recipient address)
|
|
feeBasisPoints: parseBigInt(169), // 8 bytes (Fee basis points)
|
|
fee: parseBigInt(177), // 8 bytes (Fee amount)
|
|
creator: parsePublicKey(185), // 32 bytes (Creator address)
|
|
creatorFeeBasisPoints: parseBigInt(217), // 8 bytes (Creator fee basis points)
|
|
creatorFee: parseBigInt(225), // 8 bytes (Creator fee amount)
|
|
};
|
|
// console.log(parsedData_PumpFun);
|
|
|
|
let isBuy = parsedData_PumpFun.isBuy;
|
|
|
|
return {
|
|
solchange: parsedData_PumpFun.solAmount,
|
|
tokenchange: parsedData_PumpFun.tokenAmount,
|
|
isBuy,
|
|
user: parsedData_PumpFun.user,
|
|
mint: parsedData_PumpFun.mint,
|
|
pool: null,
|
|
liquidity: parsedData_PumpFun.virtualSolReserves,
|
|
coinCreator: parsedData_PumpFun.creator,
|
|
pool_status: "pumpfun",
|
|
context: parsedData_PumpFun,
|
|
};
|
|
} else if (buffer.length == 146) {
|
|
const parsedData_Raydium_LaunchLab = {
|
|
poolState: parsePublicKey(16), // 32 bytes (Pool state address)
|
|
totalBaseSell: parseBigInt(48), // 8 bytes (Total base sold)
|
|
virtualBase: parseBigInt(56), // 8 bytes (Virtual base reserves)
|
|
virtualQuote: parseBigInt(64), // 8 bytes (Virtual quote reserves)
|
|
realBaseBefore: parseBigInt(72), // 8 bytes (Real base before)
|
|
realQuoteBefore: parseBigInt(80), // 8 bytes (Real quote before)
|
|
realBaseAfter: parseBigInt(88), // 8 bytes (Real base after)
|
|
realQuoteAfter: parseBigInt(96), // 8 bytes (Real quote after)
|
|
amountIn: parseBigInt(104), // 8 bytes (Amount in)
|
|
amountOut: parseBigInt(112), // 8 bytes (Amount out)
|
|
protocolFee: parseBigInt(120), // 8 bytes (Protocol fee)
|
|
platformFee: parseBigInt(128), // 8 bytes (Platform fee)
|
|
shareFee: parseBigInt(136), // 8 bytes (Share fee)
|
|
tradeDirection: buffer[144] , // 1 byte (1 = sell, 0 = buy)
|
|
poolStatus: buffer[145] === 0 ? { normal: {} } : { fund: {} }, // 1 byte (0 = normal, 1 = fund)
|
|
};
|
|
const isBuy = !parsedData_Raydium_LaunchLab.tradeDirection;
|
|
let solAmount = 0;
|
|
let tokenAmount = 0;
|
|
// console.log("🎈🎈🎈parsedData_Raydium_LaunchLab:::", parsedData_Raydium_LaunchLab);
|
|
if (isBuy){
|
|
solAmount = parsedData_Raydium_LaunchLab.amountIn;
|
|
tokenAmount = parsedData_Raydium_LaunchLab.amountOut;
|
|
}else{
|
|
solAmount = parsedData_Raydium_LaunchLab.amountOut;
|
|
tokenAmount = parsedData_Raydium_LaunchLab.amountIn;
|
|
}
|
|
|
|
return {
|
|
solchange: solAmount,
|
|
tokenchange: tokenAmount,
|
|
isBuy,
|
|
user: null,
|
|
mint: null,
|
|
pool: parsedData_Raydium_LaunchLab.poolState,
|
|
liquidity: 2*parsedData_Raydium_LaunchLab.realQuoteAfter,
|
|
coinCreator: parsedData_Raydium_LaunchLab.poolState,
|
|
pool_status: "raydium_launchlab",
|
|
context: parsedData_Raydium_LaunchLab,
|
|
};
|
|
} else {
|
|
return {
|
|
solchange: 0,
|
|
tokenchange: 0,
|
|
isBuy: false,
|
|
user: null,
|
|
mint: null,
|
|
pool: null,
|
|
liquidity: 0,
|
|
coinCreator: null,
|
|
pool_status: "raydium",
|
|
context: null,
|
|
};
|
|
} }catch (error) {
|
|
console.error("Error parsing transaction data:", error);
|
|
}
|
|
}
|