package shreder import ( "bytes" "encoding/binary" "fmt" "github.com/gagliardetto/solana-go" ) var binanceWalletProgramID = solana.MustPublicKeyFromBase58("B3111yJCeHBcA1bizdJjUFPALfhAfSRnAbJzGUtnt56A") const ( binanceWalletMinDataLen = 72 binanceWalletSolOffset = 23 binanceWalletTokenOff = 39 binanceWalletSolRepeat = 51 binanceWalletSideOff = 71 binanceWalletPumpBuy = 0x05 binanceWalletPumpSell = 0x06 ) var binanceWalletMarker = []byte{0x13, 0x2c, 0x82, 0x94, 0x48, 0x38, 0x2c, 0xee} func parseBinanceWalletInstruction(tx VersionedTransaction, instructionIndex int) (TxSignalBatch, error) { if instructionIndex >= len(tx.Instructions) { return nil, fmt.Errorf("instruction index out of bounds") } instruction := tx.Instructions[instructionIndex] if len(instruction.Data) < len(binanceWalletMarker) || !bytes.Contains(instruction.Data, binanceWalletMarker) { return nil, nil } if len(instruction.Data) < binanceWalletMinDataLen { return nil, fmt.Errorf("data too short for binance wallet, len=%d", len(instruction.Data)) } side := instruction.Data[binanceWalletSideOff] if side != binanceWalletPumpBuy && side != binanceWalletPumpSell { return nil, nil } if len(instruction.Accounts) <= 8 { return nil, fmt.Errorf("accounts too short") } wsolIdx := 7 tokenIdx := 8 if side == binanceWalletPumpSell { wsolIdx = 8 tokenIdx = 7 } wsolKey, err := tx.GetAccount(int(instruction.Accounts[wsolIdx])) if err != nil { return nil, err } if !wsolKey.Equals(solana.WrappedSol) { return nil, nil } mint, err := tx.GetAccount(int(instruction.Accounts[tokenIdx])) if err != nil { return nil, err } amountA := binary.LittleEndian.Uint64(instruction.Data[binanceWalletSolOffset : binanceWalletSolOffset+8]) if amountA == 0 && len(instruction.Data) >= binanceWalletSolRepeat+8 { repeat := binary.LittleEndian.Uint64(instruction.Data[binanceWalletSolRepeat : binanceWalletSolRepeat+8]) if repeat > 0 { amountA = repeat } } amountB := binary.LittleEndian.Uint64(instruction.Data[binanceWalletTokenOff : binanceWalletTokenOff+8]) solAmount := amountA tokenAmount := amountB if side == binanceWalletPumpSell { solAmount = amountB tokenAmount = amountA } maker := "" if len(tx.StaticAccountKeys) > 0 { maker = tx.StaticAccountKeys[0].String() } else if len(instruction.Accounts) > 0 { key, err := tx.GetAccount(int(instruction.Accounts[0])) if err != nil { return nil, err } maker = key.String() } event := "buy" exactIn := true if side == binanceWalletPumpSell { event = "sell" exactIn = false } return TxSignalBatch{&TxSignal{ TxHash: tx.Signatures[0].String(), Label: "binancewallet", Maker: maker, Token0Address: mint.String(), Token1Address: wsolMint, Token0Amount: formatTokenAmount(tokenAmount), Token1Amount: formatSolAmount(solAmount), Program: "Pump", Event: event, IsToken2022: false, IsMayhemMode: false, ExactSOL: exactIn, Block: tx.Block, Token0AmountUint64: tokenAmount, Token1AmountUint64: solAmount, }}, nil }