package shreder import ( "encoding/binary" "fmt" "github.com/gagliardetto/solana-go" ) var gmgnProgramID = solana.MustPublicKeyFromBase58("GMgnVFR8Jb39LoXsEVzb3DvBy3ywCmdmJquHUy1Lrkqb") var ( gmgnBuyTokensIX = []byte{0x66, 0x06, 0x3d, 0x12, 0x01, 0xda, 0xeb, 0xea} ) func parseGMGNInstruction(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) == 0 { return nil, fmt.Errorf("data is empty") } if len(instruction.Data) < 8 { return nil, nil } var ( err error txSignal *TxSignal ) if matchMethod(instruction.Data, gmgnBuyTokensIX) { txSignal, err = parseGMGNBuy(tx, instruction) } if txSignal != nil { return TxSignalBatch{txSignal}, err } return nil, err } func parseGMGNBuy(tx VersionedTransaction, instruction Instructions) (*TxSignal, error) { if len(instruction.Accounts) < 8 { return nil, fmt.Errorf("accounts too short") } if len(instruction.Data) < 24 { return nil, fmt.Errorf("data too short for gmgn buy args, len=%d", len(instruction.Data)) } mint, err := tx.GetAccount(int(instruction.Accounts[2])) if err != nil { return nil, err } user, err := tx.GetAccount(int(instruction.Accounts[6])) if err != nil { return nil, err } solAmount := binary.LittleEndian.Uint64(instruction.Data[8:16]) tokenAmount := binary.LittleEndian.Uint64(instruction.Data[16:24]) return &TxSignal{ TxHash: tx.Signatures[0].String(), Label: "gmgn", Maker: user.String(), Token0Address: mint.String(), Token1Address: wsolMint, Token0Amount: formatTokenAmount(tokenAmount), Token1Amount: formatSolAmount(solAmount), Program: "Pump", Event: "buy", IsToken2022: false, IsMayhemMode: false, ExactSOL: true, Block: tx.Block, Token0AmountUint64: tokenAmount, Token1AmountUint64: solAmount, }, nil }