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") ) 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 }