Files
pump-parser/checking.go

577 lines
15 KiB
Go
Raw Permalink Normal View History

2025-11-20 17:56:45 +08:00
package pump_parser
import (
"log"
"strings"
"github.com/gagliardetto/solana-go"
)
func checkBonkGmgnBuy(rawTx *RawTx) bool {
// 检查交易版本
var version, _ = rawTx.Version.(solana.MessageVersion)
if version != solana.MessageVersionLegacy {
return false
}
// 检查交易指令数量
if len(rawTx.Transaction.Message.Instructions) != 10 && len(rawTx.Transaction.Message.Instructions) != 9 {
return false
}
accountList := rawTx.getAccountList()
// 检查 cu limit
{
instruction := rawTx.Transaction.Message.Instructions[0]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.ComputeBudget {
return false
}
if len(instruction.Accounts) != 1 {
return false
}
accountId := accountList[instruction.Accounts[0]].String()
if !strings.HasPrefix(accountId, "jitodontfront1111111111151111111111111655") {
return false
}
}
// 检查 cu price
{
instruction := rawTx.Transaction.Message.Instructions[1]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.ComputeBudget {
return false
}
}
// 检查 ata.createIdempotent
{
instruction := rawTx.Transaction.Message.Instructions[2]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SPLAssociatedTokenAccountProgramID {
return false
}
if instruction.Data.String() != "2" {
return false
}
if len(instruction.Accounts) < 4 {
return false
}
// gmgn 会先创建 wsol 账户, 而不是 token 账户
accountId := accountList[instruction.Accounts[3]]
if accountId != solana.WrappedSol {
return false
}
}
// 检查 transfer
{
instruction := rawTx.Transaction.Message.Instructions[3]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SystemProgramID {
return false
}
if len(instruction.Data) == 0 || instruction.Data[0] != 2 {
return false
}
}
// 检查 token.syncNative
{
instruction := rawTx.Transaction.Message.Instructions[4]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.TokenProgramID {
return false
}
if instruction.Data.String() != "J" {
return false
}
}
offset := 5
if len(rawTx.Transaction.Message.Instructions) == 10 {
// 检查 ata.create
{
instruction := rawTx.Transaction.Message.Instructions[offset]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SPLAssociatedTokenAccountProgramID {
return false
}
if instruction.Data.String() != "1" {
return false
}
}
offset++
}
// 检查 bonk.buy
{
instruction := rawTx.Transaction.Message.Instructions[offset]
programId := accountList[instruction.ProgramIDIndex]
if programId != raydiumLaunchLabProgramID {
return false
}
}
offset++
// 检查 token.closeAccount
{
instruction := rawTx.Transaction.Message.Instructions[offset]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.TokenProgramID {
return false
}
if instruction.Data.String() != "A" {
return false
}
}
offset++
// 检查 transfer
{
instruction := rawTx.Transaction.Message.Instructions[offset]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SystemProgramID {
return false
}
if len(instruction.Data) == 0 || instruction.Data[0] != 2 {
return false
}
}
offset++
// 检查 transfer
{
instruction := rawTx.Transaction.Message.Instructions[offset]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SystemProgramID {
return false
}
if len(instruction.Data) == 0 || instruction.Data[0] != 2 {
return false
}
}
return true
}
var (
axiomTxLoopupTable = solana.MustPublicKeyFromBase58("7RKtfATWCe98ChuwecNq8XCzAzfoK3DtZTprFsPMGtio")
2026-02-02 14:13:00 +08:00
axiomProgramID = solana.MustPublicKeyFromBase58("AxiomfHaWDemCFBLBayqnEnNwE6b7B2Qz3UmzMpgbMG6")
gmgnProgramID = solana.MustPublicKeyFromBase58("GMgnVFR8Jb39LoXsEVzb3DvBy3ywCmdmJquHUy1Lrkqb")
2025-11-20 17:56:45 +08:00
)
func checkBonkAxiomBuy(rawTx *RawTx) bool {
// 检查交易版本
var version, _ = rawTx.Version.(solana.MessageVersion)
if version == solana.MessageVersionLegacy || len(rawTx.Transaction.Message.AddressTableLookups) != 1 {
log.Printf("CheckBonkAxiomBuy: Invalid transaction version or address table lookups: %v %v %v", rawTx.Transaction.Signatures[0].String(), version, len(rawTx.Transaction.Message.AddressTableLookups))
return false
}
// 检查 addressLookupTable 是否是 Axiom 的
if rawTx.Transaction.Message.AddressTableLookups[0].AccountKey != axiomTxLoopupTable {
log.Printf("CheckBonkAxiomBuy: Invalid address lookup table: %v", rawTx.Transaction.Signatures[0].String())
return false
}
// 检查交易指令数量
if len(rawTx.Transaction.Message.Instructions) != 10 {
return false
}
accountList := rawTx.getAccountList()
// 检查 cu limit
{
instruction := rawTx.Transaction.Message.Instructions[0]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.ComputeBudget {
log.Printf("CheckBonkAxiomBuy: Invalid program ID for ComputeBudget: %v", programId)
return false
}
if len(instruction.Accounts) != 1 {
log.Printf("CheckBonkAxiomBuy: Invalid number of accounts for ComputeBudget: %v", len(instruction.Accounts))
return false
}
accountId := accountList[instruction.Accounts[0]].String()
if !strings.HasPrefix(accountId, "jitodontfront") || !strings.HasSuffix(accountId, "TradeWithAxiomDotTrade") {
log.Printf("CheckBonkAxiomBuy: Invalid account ID for ComputeBudget: %v", accountId)
return false
}
}
// 检查 cu price
{
instruction := rawTx.Transaction.Message.Instructions[1]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.ComputeBudget {
log.Printf("CheckBonkAxiomBuy: Invalid program ID for ComputeBudget: %v", programId)
return false
}
}
// 检查 ata.createIdempotent
{
instruction := rawTx.Transaction.Message.Instructions[2]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SPLAssociatedTokenAccountProgramID {
log.Printf("CheckBonkAxiomBuy: Invalid program ID for SPLAssociatedTokenAccount: %v", programId)
return false
}
if instruction.Data.String() != "2" {
log.Printf("CheckBonkAxiomBuy: Invalid data for SPLAssociatedTokenAccount: %v", instruction.Data.String())
return false
}
if len(instruction.Accounts) < 4 {
log.Printf("CheckBonkAxiomBuy: Invalid number of accounts for SPLAssociatedTokenAccount: %v", len(instruction.Accounts))
return false
}
// axiom 会先创建 token 账户, 而不是 wsol 账户
accountId := accountList[instruction.Accounts[3]]
if accountId == solana.WrappedSol {
log.Printf("CheckBonkAxiomBuy: Invalid account ID for SPLAssociatedTokenAccount, expected token account but got wsol: %v", accountId)
return false
}
}
// 检查 ata.createIdempotent
{
instruction := rawTx.Transaction.Message.Instructions[3]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SPLAssociatedTokenAccountProgramID {
log.Printf("CheckBonkAxiomBuy: Invalid program ID for SPLAssociatedTokenAccount2: %v", programId)
return false
}
if instruction.Data.String() != "2" {
log.Printf("CheckBonkAxiomBuy: Invalid data for SPLAssociatedTokenAccount2: %v", instruction.Data.String())
return false
}
if len(instruction.Accounts) < 4 {
log.Printf("CheckBonkAxiomBuy: Invalid number of accounts for SPLAssociatedTokenAccount2: %v", len(instruction.Accounts))
return false
}
// axiom 会先创建 token 账户, 而不是 wsol 账户
accountId := accountList[instruction.Accounts[3]]
if accountId != solana.WrappedSol {
log.Printf("CheckBonkAxiomBuy: Invalid account ID for SPLAssociatedTokenAccount2, expected wsol but got: %v", accountId)
return false
}
}
// 检查 transfer
{
instruction := rawTx.Transaction.Message.Instructions[4]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SystemProgramID {
log.Printf("CheckBonkAxiomBuy: Invalid program ID for SystemProgram3: %v", programId)
return false
}
if len(instruction.Data) == 0 || instruction.Data[0] != 2 {
log.Printf("CheckBonkAxiomBuy: Invalid data for SystemProgram transfer3: %v", instruction.Data)
return false
}
}
// 检查 token.syncNative
{
instruction := rawTx.Transaction.Message.Instructions[5]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.TokenProgramID {
log.Printf("CheckBonkAxiomBuy: Invalid program ID for TokenProgram3: %v", programId)
return false
}
if instruction.Data.String() != "J" {
log.Printf("CheckBonkAxiomBuy: Invalid data for TokenProgram syncNative3: %v", instruction.Data.String())
return false
}
}
// 检查 bonk.buy
{
instruction := rawTx.Transaction.Message.Instructions[6]
programId := accountList[instruction.ProgramIDIndex]
if programId != raydiumLaunchLabProgramID {
return false
}
}
// 检查 token.closeAccount
{
instruction := rawTx.Transaction.Message.Instructions[7]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.TokenProgramID {
log.Printf("CheckBonkAxiomBuy: Invalid program ID for TokenProgram closeAccount: %v", programId)
return false
}
if instruction.Data.String() != "A" {
log.Printf("CheckBonkAxiomBuy: Invalid data for TokenProgram closeAccount: %v", instruction.Data.String())
return false
}
}
// 检查 transfer
{
instruction := rawTx.Transaction.Message.Instructions[8]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SystemProgramID {
log.Printf("CheckBonkAxiomBuy: Invalid program ID for SystemProgram transfer4: %v", programId)
return false
}
if len(instruction.Data) == 0 || instruction.Data[0] != 2 {
log.Printf("CheckBonkAxiomBuy: Invalid data for SystemProgram transfer4: %v", instruction.Data)
return false
}
}
// 检查 transfer
{
instruction := rawTx.Transaction.Message.Instructions[9]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SystemProgramID {
log.Printf("CheckBonkAxiomBuy: Invalid program ID for SystemProgram transfer5: %v", programId)
return false
}
if len(instruction.Data) == 0 || instruction.Data[0] != 2 {
log.Printf("CheckBonkAxiomBuy: Invalid data for SystemProgram transfer5: %v", instruction.Data)
return false
}
}
return true
}
2026-02-02 14:13:00 +08:00
func checkPumpFunAxiomBuy(rawTx *RawTx) bool {
// 检查交易版本
if rawTx.Version == "legacy" || len(rawTx.Transaction.Message.AddressTableLookups) != 1 {
return false
}
// 检查 addressLookupTable 是否是 Axiom 的
if rawTx.Transaction.Message.AddressTableLookups[0].AccountKey != axiomTxLoopupTable {
return false
}
// 检查交易指令数量
if len(rawTx.Transaction.Message.Instructions) != 6 {
return false
}
accountList := rawTx.getAccountList()
// 检查 cu limit
{
instruction := rawTx.Transaction.Message.Instructions[0]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.ComputeBudget {
return false
}
if len(instruction.Accounts) != 1 {
return false
}
accountId := accountList[instruction.Accounts[0]].String()
if !strings.HasPrefix(accountId, "jitodontfront") || !strings.HasSuffix(accountId, "TradeWithAxiomDotTrade") {
return false
}
}
// 检查 cu price
{
instruction := rawTx.Transaction.Message.Instructions[1]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.ComputeBudget {
return false
}
}
// 检查 ata.createIdempotent
{
instruction := rawTx.Transaction.Message.Instructions[2]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SPLAssociatedTokenAccountProgramID {
return false
}
if instruction.Data.String() != "2" {
return false
}
if len(instruction.Accounts) < 4 {
return false
}
// axiom 会先创建 token 账户, 而不是 wsol 账户
accountId := accountList[instruction.Accounts[3]]
if accountId == solana.WrappedSol {
return false
}
}
// 检查调用axiom合约
{
instruction := rawTx.Transaction.Message.Instructions[3]
programId := accountList[instruction.ProgramIDIndex]
if programId != axiomProgramID {
return false
}
}
// 检查 transfer
{
instruction := rawTx.Transaction.Message.Instructions[4]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SystemProgramID {
return false
}
if len(instruction.Data) == 0 || instruction.Data[0] != 2 {
return false
}
}
// 检查 transfer
{
instruction := rawTx.Transaction.Message.Instructions[5]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SystemProgramID {
return false
}
if len(instruction.Data) == 0 || instruction.Data[0] != 2 {
return false
}
}
return true
}
func checkPumpFunGmgnBuy(rawTx *RawTx) bool {
// 检查交易版本
if rawTx.Version != "legacy" {
return false
}
// 检查交易指令数量
if len(rawTx.Transaction.Message.Instructions) != 6 {
return false
}
accountList := rawTx.getAccountList()
// 检查 cu limit
{
instruction := rawTx.Transaction.Message.Instructions[0]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.ComputeBudget {
return false
}
if len(instruction.Accounts) != 1 {
return false
}
accountId := accountList[instruction.Accounts[0]].String()
if !strings.HasPrefix(accountId, "jitodontfront1111111111151111111111111655") {
return false
}
}
// 检查 cu price
{
instruction := rawTx.Transaction.Message.Instructions[1]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.ComputeBudget {
return false
}
}
// 检查 ata.createIdempotent
{
instruction := rawTx.Transaction.Message.Instructions[2]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SPLAssociatedTokenAccountProgramID {
return false
}
if instruction.Data.String() != "2" {
return false
}
if len(instruction.Accounts) < 4 {
return false
}
accountId := accountList[instruction.Accounts[3]]
if accountId == solana.WrappedSol {
return false
}
}
// 检查调用 gmgn 合约
{
instruction := rawTx.Transaction.Message.Instructions[3]
programId := accountList[instruction.ProgramIDIndex]
if programId != gmgnProgramID {
return false
}
}
// 检查 transfer
{
instruction := rawTx.Transaction.Message.Instructions[4]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SystemProgramID {
return false
}
if len(instruction.Data) == 0 || instruction.Data[0] != 2 {
return false
}
}
// 检查 transfer
{
instruction := rawTx.Transaction.Message.Instructions[5]
programId := accountList[instruction.ProgramIDIndex]
if programId != solana.SystemProgramID {
return false
}
if len(instruction.Data) == 0 || instruction.Data[0] != 2 {
return false
}
}
return true
}