package shreder import ( "bytes" "fmt" "github.com/gagliardetto/solana-go" "github.com/near/borsh-go" "github.com/shopspring/decimal" ) var boboProgramID = solana.MustPublicKeyFromBase58("BobogA5N2KN2GG4XN3E3rNNRw3L8H1QPXp7QLxGrNHGM") var ( boboBuyPumpTokensIX = []byte{0xff, 0xe7, 0x11, 0x53, 0x15, 0xc5, 0xc3, 0xdf} ) type boboBuyArgs struct { Placeholder1 uint64 Placeholder2 uint64 SolAmount uint64 Placeholder3 uint64 Placeholder4 uint64 Placeholder5 uint64 Placeholder6 uint64 } func parseBoboInstruction(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 || !bytes.Equal(instruction.Data[:8], boboBuyPumpTokensIX) { return nil, nil } if len(instruction.Accounts) < 8 { return nil, fmt.Errorf("accounts too short") } if len(instruction.Data) < 16 { return nil, fmt.Errorf("data too short for bobo 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 } var args boboBuyArgs if err := borsh.Deserialize(&args, instruction.Data[8:]); err != nil { return nil, fmt.Errorf("failed to parse buy tokens args: %w", err) } return TxSignalBatch{&TxSignal{ TxHash: tx.Signatures[0].String(), Label: "bobo", Maker: user.String(), Token0Address: mint.String(), Token1Address: wsolMint, Token0Amount: decimal.NewFromInt(1), Token1Amount: formatSolAmount(args.SolAmount), Program: "Pump", Event: "buy", IsToken2022: false, IsMayhemMode: false, Block: tx.Block, Token0AmountUint64: 1, Token1AmountUint64: args.SolAmount, }}, nil }